Skip to content

Commit

Permalink
fix for script finalizers
Browse files Browse the repository at this point in the history
  • Loading branch information
bendmorris committed Jul 15, 2021
1 parent e6328eb commit 9c48433
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 61 deletions.
File renamed without changes.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ add_definitions(
file(GLOB_RECURSE KRIT_SRC_FILES
CONFIGURE_DEPENDS
src/krit/*.cpp
)
file(GLOB_RECURSE KRIT_THIRDPARTY_FILES
CONFIGURE_DEPENDS
spine-runtimes/spine-cpp/spine-cpp/src/spine/*.cpp
imgui/*.cpp
)
Expand All @@ -40,6 +43,7 @@ add_library(${PROJECT_NAME} STATIC
${CMAKE_CURRENT_BINARY_DIR}/script/ScriptBridge.cpp
${KRIT_GENERATED_SCRIPT_FILES}
${KRIT_SRC_FILES}
${KRIT_THIRDPARTY_FILES}
)
target_link_libraries(${PROJECT_NAME}
PUBLIC
Expand Down
10 changes: 10 additions & 0 deletions script/sprites.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
declare const enum BlendMode {
Alpha,
Add,
Subtract,
Multiply,
BlendScreen,
}

/**
* @namespace krit
* @import krit/Sprite.h
Expand All @@ -19,6 +27,7 @@ declare class VisibleSprite extends Sprite {
/** @readonly */ dimensions: Dimensions;
/** @readonly */ scale: ScaleFactor;
color: Color;
/** @cast BlendMode */ blendMode: BlendMode;
}

/**
Expand Down Expand Up @@ -55,6 +64,7 @@ declare class BitmapText extends VisibleSprite {
/** @readonly */ text: string;
baseColor: Color;
/** @readonly */ textDimensions: Dimensions;
allowPixelPerfect: boolean;

refresh(): void;
setText(s: string): void;
Expand Down
4 changes: 2 additions & 2 deletions src/krit/script/ScriptEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ struct ScriptEngine {
static JSRuntime *rt;

JSContext *ctx = nullptr;
JSValue exports;
JSValue exports = JS_UNDEFINED;
void *userData;
JSValue finalizerSymbol;
JSValue finalizerSymbol = JS_UNDEFINED;

ScriptEngine();
~ScriptEngine();
Expand Down
2 changes: 2 additions & 0 deletions src/krit/script/ScriptFinalizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ void ScriptFinalizer::init(ScriptEngine *engine) {
JS_FreeValue(ctx, finalizerName);
JS_FreeValue(ctx, symbol);
JS_FreeValue(ctx, globalObj);

engine->finalizerSymbol = finalizerSymbol;
}

void ScriptEngine::addFinalizer(JSValue obj, ScriptClass classId) {
Expand Down
2 changes: 2 additions & 0 deletions src/krit/sprites/Layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,8 @@ SpriteStyle LayoutRoot::parseStyle(std::string &s) {
style.color = ParseUtil::parseColor(value);
} else if (key == "alpha") {
style.color.a = ParseUtil::parseFloat(value);
} else if (key == "scale") {
style.scale.x = style.scale.y = ParseUtil::parseFloat(value);
} else if (key == "scaleX") {
style.scale.x = ParseUtil::parseFloat(value);
} else if (key == "scaleY") {
Expand Down
2 changes: 1 addition & 1 deletion src/krit/sprites/Text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ void Text::render(RenderContext &ctx) {
float cameraScale = std::max(ctx.camera->scale.x, ctx.camera->scale.y);
float size = this->size * cameraScale;
float fontScale = std::floor(size) / cameraScale / 64.0;
bool pixelPerfect = fontScale < 20;
bool pixelPerfect = allowPixelPerfect && fontScale < 20;

for (TextOpcode &op : this->opcodes) {
switch (op.type) {
Expand Down
1 change: 1 addition & 0 deletions src/krit/sprites/Text.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ struct Text : public VisibleSprite, public TextOptions {
Color baseColor = Color::white();
std::string text;
Dimensions textDimensions;
bool allowPixelPerfect = true;

Text() = default;
Text(const TextOptions &options);
Expand Down
134 changes: 78 additions & 56 deletions tools/bridge_generator/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,25 @@ const fs = require('fs');
const path = require('path');
const nunjucks = require('nunjucks');

const typeMap = new Map(Object.entries({
'void': undefined,
'boolean': { type: 'bool', pointer: 0 },
'number': { type: 'double', pointer: 0 },
'integer': { type: 'int', pointer: 0 },
'float': { type: 'float', pointer: 0 },
'size_t': { type: 'size_t', pointer: 0 },
// 'cstring': { type: 'const char', pointer: 1 },
'string_view': { type: 'std::string_view', pointer: 0 },
'string': { type: 'std::string', pointer: 0 },
'any': { type: 'JSValue', pointer: 0 },
}));
const typeMap = new Map(
Object.entries({
void: undefined,
boolean: { type: 'bool', pointer: 0 },
number: { type: 'double', pointer: 0 },
integer: { type: 'int', pointer: 0 },
float: { type: 'float', pointer: 0 },
size_t: { type: 'size_t', pointer: 0 },
// 'cstring': { type: 'const char', pointer: 1 },
string_view: { type: 'std::string_view', pointer: 0 },
string: { type: 'std::string', pointer: 0 },
any: { type: 'JSValue', pointer: 0 },
}),
);

const [_, __, bridgePath, outputDir] = process.argv;

if (!outputDir) {
console.log("usage: node bridge_generator.js <path> <outputDir>");
console.log('usage: node bridge_generator.js <path> <outputDir>');
process.exit(1);
}

Expand All @@ -28,34 +30,40 @@ if (bridgePath) {
basePaths.push(bridgePath);
}

const filePaths = [].concat(...basePaths.map(function walk(dir) {
var results = [];
var list = fs.readdirSync(dir);
list.forEach(function(file) {
if (file === 'node_modules') {
return;
}
file = path.join(dir, file);
var stat = fs.statSync(file);
if (stat && stat.isDirectory()) {
/* Recurse into a subdirectory */
results = results.concat(walk(file));
} else {
/* Is a file */
if (file.endsWith('.d.ts')) {
results.push(file);
const filePaths = [].concat(
...basePaths.map(function walk(dir) {
var results = [];
var list = fs.readdirSync(dir);
list.forEach(function (file) {
if (file === 'node_modules') {
return;
}
}
});
return results;
}));
file = path.join(dir, file);
var stat = fs.statSync(file);
if (stat && stat.isDirectory()) {
/* Recurse into a subdirectory */
results = results.concat(walk(file));
} else {
/* Is a file */
if (file.endsWith('.d.ts')) {
results.push(file);
}
}
});
return results;
}),
);

const program = ts.createProgram(filePaths, { typeRoots: basePaths });
const program = ts.createProgram(filePaths, {
target: 'es2020',
typeRoots: basePaths,
lib: ['lib.es2020.d.ts'],
moduleResolution: 'node',
});
let checker = program.getTypeChecker();

function cppType(t) {
if (t.intrinsicName === 'error') {
console.log(t);
throw new Error('unrecognized type');
}
// const enums are integers
Expand Down Expand Up @@ -104,7 +112,7 @@ function tagify(v) {
const functions = [];
const wrappers = [];

function defineFunction(node, functionType, namespace=[]) {
function defineFunction(node, functionType, namespace = []) {
const name = node.name.text;
const returnType = functionType.getReturnType();
const type = cppType(returnType);
Expand Down Expand Up @@ -259,11 +267,13 @@ for (const f of functions) {
}
}
if (!existing) {
bridge.namespaces.push(existing = {
bridgeNamespace: name,
functions: [],
namespaces: [],
});
bridge.namespaces.push(
(existing = {
bridgeNamespace: name,
functions: [],
namespaces: [],
}),
);
}
bridge = existing;
}
Expand All @@ -276,10 +286,10 @@ if (!fs.existsSync(scriptDir)) {
}

var env = nunjucks.configure({ autoescape: false });
env.addFilter('repeat', function(str, count) {
env.addFilter('repeat', function (str, count) {
return str.repeat(count || 0);
});
env.addFilter('escapeName', function(str) {
env.addFilter('escapeName', function (str) {
return str.replace('$', '__dollar__');
});

Expand All @@ -295,25 +305,37 @@ function replaceIfDifferent(path, content) {
}

// generate native function declarations
replaceIfDifferent(path.join(scriptDir, 'ScriptBridge.h'), env.render('templates/ScriptBridge.h.nj', {
bridgeFuncs: functions,
}));
replaceIfDifferent(
path.join(scriptDir, 'ScriptBridge.h'),
env.render('templates/ScriptBridge.h.nj', {
bridgeFuncs: functions,
}),
);

// generate script engine init function implementation to define all bridges
replaceIfDifferent(path.join(scriptDir, 'ScriptBridge.cpp'), env.render('templates/ScriptBridge.cpp.nj', {
bridgeFuncs: functions,
bridges,
}));
replaceIfDifferent(
path.join(scriptDir, 'ScriptBridge.cpp'),
env.render('templates/ScriptBridge.cpp.nj', {
bridgeFuncs: functions,
bridges,
}),
);

// generate ScriptClass declaration
replaceIfDifferent(path.join(scriptDir, 'ScriptClass.h'), env.render('templates/ScriptClass.h.nj', {
wrappers,
}));
replaceIfDifferent(
path.join(scriptDir, 'ScriptClass.h'),
env.render('templates/ScriptClass.h.nj', {
wrappers,
}),
);

// generate script classes

for (const wrapper of wrappers) {
replaceIfDifferent(path.join(scriptDir, `ScriptClass.${wrapper.namespace.replace('::', '.')}.${wrapper.name}.cpp`), env.render('templates/ScriptClass.cpp.nj', {
wrapper,
}));
replaceIfDifferent(
path.join(scriptDir, `ScriptClass.${wrapper.namespace.replace('::', '.')}.${wrapper.name}.cpp`),
env.render('templates/ScriptClass.cpp.nj', {
wrapper,
}),
);
}
5 changes: 3 additions & 2 deletions tools/bridge_generator/templates/ScriptClass.cpp.nj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <string>
#include "krit/script/ScriptClass.h"
#include "krit/script/ScriptEngine.h"
#include "krit/script/ScriptValue.h"
#include "krit/utils/Log.h"
#include "quickjs.h"

{% for import in wrapper.import %}
Expand Down Expand Up @@ -79,6 +81,7 @@ JS_FUNC({{wrapper.name}}___from__) {
bool owned = false;
if (!JS_IsUndefined(finalizerSymbol) && JS_HasProperty(ctx, argv[0], atom)) {
// if this was owned, we'll transfer ownership to the return value
Log::debug("transfer finalizer: {{wrapper.name}}");
owned = true;
JSValue finalizer = JS_GetProperty(ctx, argv[0], atom);
JS_SetOpaque(finalizer, nullptr);
Expand Down Expand Up @@ -151,8 +154,6 @@ static void finalize{{wrapper.name}}(JSRuntime *rt, JSValue val) {
}
}

static const JSCFunctionListEntry protoFuncs{{ wrapper.name }}Finalizer[] = {};

static JSClassDef classDef{{wrapper.name}}Finalizer = {
"{{ wrapper.name }}Finalizer",
.finalizer = finalize{{wrapper.name}},
Expand Down

0 comments on commit 9c48433

Please sign in to comment.