Skip to content

Commit

Permalink
auto-convert lua arrays to JS arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
Doridian committed Dec 3, 2023
1 parent 290a1b1 commit 36ee929
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 13 deletions.
65 changes: 53 additions & 12 deletions src/lua_interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ declare var global: unknown;
_GLOBAL = global;
}

const UNKNOWN_LUA_REFERENCE = Symbol("UNKNOWN_LUA_REFERENCE");

function mustMalloc(size: number): EmscriptenPointer {
const ptr = Module._malloc(size);
if (!ptr) {
Expand Down Expand Up @@ -439,33 +441,72 @@ declare var global: unknown;
toObject(recurse: boolean, unrefAll: boolean, maxDepth: number = 10) {
this.push();
luaNative!.lua_pushnil(this.state);
const ret: Record<string, unknown> = {};

let isArray = true;
const retObj: Record<string, unknown> = {};
const retArray: unknown[] = [];

while (luaNative!.lua_next(this.state, -2)) {
luaNative!.lua_pushvalue(this.state, -2);
const key = luaNative!.js_tostring(this.state, -1);

const value = decodeSingle(this.state, -2);
ret[key] = value;

if (isArray) {
const keyNumeric = luaNative!.lua_tonumberx(this.state, -1, 0);
if (keyNumeric > 0) {
retArray[keyNumeric - 1] = value;
luaNative!.js_drop(this.state, 2);
continue;
} else {
isArray = false;
}
}

const key = luaNative!.js_tostring(this.state, -1);
retObj[key] = value;
luaNative!.js_drop(this.state, 2);
}

luaNative!.js_drop(this.state, 1);


if (recurse) {
maxDepth--;

for (const idx of Object.keys(ret)) {
const val = ret[idx];
if (val instanceof LuaTable && maxDepth > 0) {
ret[idx] = val.toObject(true, unrefAll, maxDepth);
val.unref();
} else if (unrefAll && val instanceof LuaReference) {
val.unref();
delete ret[idx];
if (isArray) {
for (let i = 0; i < retArray.length; i++) {
const val = retArray[i];
if (val instanceof LuaTable && maxDepth > 0) {
retArray[i] = val.toObject(true, unrefAll, maxDepth);
val.unref();
} else if (unrefAll && val instanceof LuaReference) {
val.unref();
retArray[i] = UNKNOWN_LUA_REFERENCE;
}
}
} else {
for (const idx of Object.keys(retObj)) {
if (!retObj.hasOwnProperty(idx)) {
continue;
}

const val = retObj[idx];
if (val instanceof LuaTable && maxDepth > 0) {
retObj[idx] = val.toObject(true, unrefAll, maxDepth);
val.unref();
} else if (unrefAll && val instanceof LuaReference) {
val.unref();
retObj[idx] = UNKNOWN_LUA_REFERENCE;
}
}
}
}

return ret;
if (isArray) {
return retArray;
}

return retObj;
}
}

Expand Down
2 changes: 1 addition & 1 deletion test/basics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ test('Can pass JS types to Lua correctly', async () => {
assert.deepEqual(await func(13), ['number', 13]);
assert.deepEqual(await func([1,2,3]), ['userdata', [1,2,3]]);

//assert.deepEqual(convertBack(await funcConvert([1,2,3])), ['table', { '1': 1, '2': 2, '3': 3 }]);
assert.deepEqual(convertBack(await funcConvert([1,2,3])), ['table', [1,2,3]]);
assert.deepEqual(convertBack(await funcConvert({'a': 1, 'b': '2', 'c': true})), ['table', {'a': 1, 'b': '2', 'c': true}]);
});

0 comments on commit 36ee929

Please sign in to comment.