Skip to content

Commit

Permalink
feat: getTable support specify dictType
Browse files Browse the repository at this point in the history
  • Loading branch information
X3ZvaWQ committed Jan 30, 2024
1 parent 02a5f49 commit 24d089b
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 32 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "wasmoon-lua5.1",
"version": "1.17.0",
"version": "1.17.1",
"description": "A real lua 5.1 VM with JS bindings made with webassembly",
"main": "dist/index.js",
"scripts": {
Expand Down
4 changes: 4 additions & 0 deletions src/lua.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ export default class Lua {

// 构造方法
constructor(luaApi: LuaApi, options: LuaCreateOptions) {
if (!options) {
// 必须通过静态方法创建,不允许直接new
throw new Error('Lua.create(options) must be used to create a Lua instance');
}
this.luaApi = luaApi;
this.global = new LuaGlobal(this.luaApi, options.traceAllocations);

Expand Down
9 changes: 5 additions & 4 deletions src/thread.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as lodash from 'lodash';
import { DictType, mapTransform } from './utils/map-transform';
import { JsType } from './type-bind';
import { LUA_MULTRET, LUA_REGISTRYINDEX, LuaEventMasks, LuaReturn, LuaTimeoutError, LuaType, PointerSize } from './definitions';
import { mapTransform } from './utils/map';
import MultiReturn from './multireturn';
import Pointer from './utils/pointer';
import type LuaApi from './api';
Expand Down Expand Up @@ -339,8 +339,10 @@ export default class LuaThread {

// lua的table太奔放了 甚至键可以是自身 js里可以匹配的数据结构只有Map
public getTable(index: number, options: GetValueOptions = {}): Record<string | number, any> {
const table = new Map();
const needTransform = !options.refs;
const dictType = options.dictType as DictType;

const table = new Map();
if (!options.refs) {
options.refs = new Map<number, any>();
}
Expand All @@ -361,8 +363,7 @@ export default class LuaThread {
table.set(key, value);
this.pop();
}

return needTransform ? mapTransform(table) : table;
return needTransform ? mapTransform(table, { dictType }) : table;
}

public call(name: string, ...args: any[]): MultiReturn {
Expand Down
3 changes: 3 additions & 0 deletions src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,7 @@ declare interface PushValueOptions {
declare interface GetValueOptions {
refs?: Map<number, any>;
type?: LuaType;

// used for table
dictType?: DictType;
}
60 changes: 60 additions & 0 deletions src/utils/map-transform.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
export enum DictType {
Array,
Object,
Map,
}

declare interface MapTransformOptions {
refs?: Map<any, any>;
dictType?: DictType;
}

const detectDuplicateKeys = (keys: any[]): boolean => {
const set = new Set();
for (const _key of keys) {
const key = String(_key);
if (set.has(key)) {
return true;
}
set.add(key);
}
return false;
};

const detectDictType = (keys: any[]): DictType => {
if (keys.some((key) => !['number', 'string'].includes(typeof key)) || detectDuplicateKeys(keys)) {
return DictType.Map;
} else if (keys.some((key) => typeof key === 'number')) {
return DictType.Array;
} else {
return DictType.Object;
}
};

export const mapTransform = (map: Map<any, any>, options: MapTransformOptions = {}): Record<string, any> | any[] | Map<any, any> => {
if (!options.refs) {
options.refs = new Map();
}
if (options.refs.has(map)) {
return options.refs.get(map);
}
const keys = [...map.keys()];

// detect output type
const dictType = options.dictType ? options.dictType : detectDictType(keys);
if (dictType === DictType.Map) {
return map;
}
const result: Record<any, any> = dictType === DictType.Array ? [] : {};
options.refs.set(map, result);

for (const key of keys) {
const value = map.get(key);
if (value instanceof Map) {
result[key] = mapTransform(value, options);
continue;
}
result[key] = value;
}
return result;
};
26 changes: 0 additions & 26 deletions src/utils/map.ts

This file was deleted.

30 changes: 29 additions & 1 deletion test/debug.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,33 @@
import { Lua } from '../dist/index.js';
import fs from 'fs';

// This file was created as a sandbox to test and debug on vscode
const std = '/home/x3zvawq/workspace/JX3BOX/jx3-raw/unpack/std/scripts/include/CustomFunction.lua';
const origin = '/home/x3zvawq/workspace/JX3BOX/jx3-raw/unpack/origin/scripts/include/CustomFunction.lua';

const std_buffer = new Uint8Array(fs.readFileSync(std).buffer);
const origin_buffer = new Uint8Array(fs.readFileSync(origin).buffer);

const lua = await Lua.create();
await lua.doString(`print('Hello World!')`);
lua.mountFile('/std', std_buffer);
lua.mountFile('/origin', origin_buffer);

await lua.doString(`
function expose_locals()
local i = 1
while true do
local name, value = debug.getlocal(2, i)
print(name, value)
if not name then break end
-- 将local变量设置为全局变量
_G[name] = value
i = i + 1
end
end
`);
await lua.doString(`
local x = 1
expose_locals()
`);
await lua.doString(`expose_locals()`);
await lua.doString('print(x)');

0 comments on commit 24d089b

Please sign in to comment.