Skip to content

Commit

Permalink
feat: debug traceback
Browse files Browse the repository at this point in the history
  • Loading branch information
X3ZvaWQ committed Feb 13, 2024
1 parent 9651244 commit b1e3c90
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 17 deletions.
10 changes: 10 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"chunkname",
"cmodule",
"createtable",
"currentline",
"cwrap",
"emscripten",
"emsdk",
Expand All @@ -48,12 +49,16 @@
"getupvalue",
"GLOBALSINDEX",
"gsub",
"HEAPU",
"IDSIZE",
"iscfunction",
"istable",
"isuserdata",
"lastlinedefined",
"lessthan",
"liblua",
"libname",
"linedefined",
"loadbuffer",
"loadfile",
"loadfilex",
Expand All @@ -65,6 +70,7 @@
"metatable",
"multireturn",
"MULTRET",
"namewhat",
"nargs",
"narr",
"newindex",
Expand All @@ -75,6 +81,7 @@
"nofix",
"nrec",
"nresults",
"nups",
"objindex",
"objlen",
"openlibs",
Expand Down Expand Up @@ -123,7 +130,10 @@
"topointer",
"tothread",
"touserdata",
"traceback",
"tracebacks",
"typerror",
"upvalue",
"upvalueindex",
"wasmoon",
"xmove"
Expand Down
3 changes: 2 additions & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ emcc \
'setValue', \
'lengthBytesUTF8', \
'stringToUTF8', \
'stringToNewUTF8'
'stringToNewUTF8', \
'UTF8ToString'
]" \
-s INCOMING_MODULE_JS_API="[
'locateFile', \
Expand Down
2 changes: 2 additions & 0 deletions src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export const LUA_REGISTRYINDEX = -10000;
export const LUA_ENVIRONINDEX = -10001;
export const LUA_GLOBALSINDEX = -10002;

export const LUA_IDSIZE = 60;

export enum LuaReturn {
Ok = 0,
Yield = 1,
Expand Down
81 changes: 81 additions & 0 deletions src/lua-debug.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { LUA_IDSIZE } from './definitions';

interface LuaDebugTraceback {
event: number;
name: string;
namewhat: string;
what: string;
source: string;
currentline: number | '?';
nups: number;
linedefined: number | '?';
lastlinedefined: number | '?';
short_src: string;
i_ci: number;
}

export class LuaDebug {
public static readonly structSize = 100;
private pointer: number;
private module: LuaEmscriptenModule;
private tracebacks: LuaDebugTraceback[] = [];
private message: string;

constructor(pointer: number, module: LuaEmscriptenModule, message: string) {
this.pointer = pointer;
this.module = module;
this.message = message;
}

public read(): void {
let baseIndex = this.pointer >> 2;
const event = this.module.HEAPU32.at(baseIndex++) as number;
const name = this.readStructString(baseIndex++);
const namewhat = this.readStructString(baseIndex++);
const what = this.readStructString(baseIndex++);
const source = this.readStructString(baseIndex++);
const currentline = this.module.HEAPU32.at(baseIndex++) as number;
const nups = this.module.HEAPU32.at(baseIndex++) as number;
const linedefined = this.module.HEAPU32.at(baseIndex++) as number;
const lastlinedefined = this.module.HEAPU32.at(baseIndex++) as number;
const short_src = this.module.UTF8ToString(baseIndex << 2, 60);
const i_ci = this.module.HEAPU32.at(baseIndex + LUA_IDSIZE / 4) as number;

const traceback: LuaDebugTraceback = {
event,
name: name || '?',
namewhat,
what,
source,
currentline: currentline === 0xffffffff ? '?' : currentline,
nups,
linedefined: linedefined === 0xffffffff ? '?' : linedefined,
lastlinedefined: lastlinedefined === 0xffffffff ? '?' : lastlinedefined,
short_src,
i_ci,
};
this.tracebacks.push(traceback);
}

public getMessage(): string {
const result: string[] = [];
result.push(`${this.tracebacks[0]?.short_src || '?'}:${this.tracebacks[0]?.currentline || '?'}: ${this.message}`);
if (this.tracebacks.length) {
result.push('stack traceback:');
}
for (const traceback of this.tracebacks) {
result.push(
` at ${traceback.name} (${traceback.short_src}:${traceback.currentline}) (${traceback.what}:${traceback.namewhat})`,
);
}
return result.join('\n');
}

public getTracebacks(): LuaDebugTraceback[] {
return this.tracebacks;
}

private readStructString(structPointer: number): string {
return this.module.UTF8ToString(this.module.HEAPU32.at(structPointer) as number);
}
}
19 changes: 19 additions & 0 deletions src/thread.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as lodash from 'lodash';
import { JsType } from './type-bind';
import { LUA_MULTRET, LUA_REGISTRYINDEX, LuaEventMasks, LuaReturn, LuaType, PointerSize } from './definitions';
import { LuaDebug } from './lua-debug';
import { getTable } from './table';
import MultiReturn from './multireturn';
import Pointer from './utils/pointer';
Expand Down Expand Up @@ -430,6 +431,24 @@ export default class LuaThread {
}
}

if (result !== LuaReturn.ErrorMem) {
const pointer = this.luaApi.module._malloc(LuaDebug.structSize);
try {
let level = 0;
const luaDebug = new LuaDebug(pointer, this.luaApi.module, error.message);
while (this.luaApi.lua_getstack(this.address, level, pointer)) {
this.luaApi.lua_getinfo(this.address, 'nSlu', pointer);
luaDebug.read();
level++;
}
error.message = luaDebug.getMessage();
} catch (err) {
console.warn('Error in generate stack trace', err);
} finally {
this.luaApi.module._free(pointer);
}
}

throw error;
}
}
Expand Down
17 changes: 8 additions & 9 deletions test/debug.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ import { Lua } from '../dist/index.js';
// This file was created as a sandbox to test and debug on vscode

const lua = await Lua.create();

const obj = {};
lua.ctx.obj = obj;

const o = lua.ctx.obj;
o.name = 23333;
console.log(o.name);

lua.doStringSync('print(obj.name)');
await lua.doString(
`local function a()
error("function a threw error")
end
local function b() a() end
local function c() b() end
c()`,
);
13 changes: 6 additions & 7 deletions test/engine.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -613,13 +613,12 @@ describe('Engine', () => {
`);
throw new Error('should not be reached');
} catch (err) {
expect(err.message).to.includes('[string "..."]:3: function a threw error');
// TODO: stack traceback
// expect(err.message).to.includes('stack traceback:');
// expect(err.message).to.includes(`[string "..."]:3: in upvalue 'a'`);
// expect(err.message).to.includes(`[string "..."]:5: in upvalue 'b'`);
// expect(err.message).to.includes(`[string "..."]:6: in local 'c'`);
// expect(err.message).to.includes(`[string "..."]:7: in main chunk`);
expect(err.message).to.includes('at error ([C]:?) (C:global)');
expect(err.message).to.includes('stack traceback:');
expect(err.message).to.includes(`at a ([string "..."]:3) (Lua:upvalue)`);
expect(err.message).to.includes(`at b ([string "..."]:5) (Lua:upvalue)`);
expect(err.message).to.includes(`at c ([string "..."]:6) (Lua:local)`);
expect(err.message).to.includes(`at ? ([string "..."]:7) (main:)`);
}
});

Expand Down
2 changes: 2 additions & 0 deletions types/wasm.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ interface LuaEmscriptenModule extends EmscriptenModule {
stringToNewUTF8: typeof allocateUTF8;
lengthBytesUTF8: typeof lengthBytesUTF8;
stringToUTF8: typeof stringToUTF8;
UTF8ToString: typeof UTF8ToString;
ENV: EnvironmentVariables;
_realloc: (pointer: number, size: number) => number;
_malloc: (size: number) => number;
}

interface ReferenceMetadata {
Expand Down

0 comments on commit b1e3c90

Please sign in to comment.