ceifa / wasmoon

A real lua 5.4 VM with JS bindings made with webassembly
MIT License
495 stars 32 forks source link

How to use `lua_dump`? #95

Closed paulyoung closed 12 months ago

paulyoung commented 1 year ago

I've been struggling to figure out how to call lua_dump properly. Please could you provide an example?

I think I have all of the arguments figured out except for the data argument, but my writer function isn't being called.

Calling lua_dump returns LuaReturn.Yield so I'm not sure if that's an indicator of something waiting to be resumed.

Thanks.

tims-bsquare commented 1 year ago

First define a writer function to be passed to the lua_dump function.

    // The lua_dump function requires a writer callback in C that gets passed a pointer to
    // data and the size.
    let writtenBuffers: Buffer[] = [];
    const writerFunctionPointer = luaModule.module.addFunction(
      (_luaState: number, pointer: number, size: number): number => {
        if (size <= 0 || pointer === 0) {
          return 0;
        }
        // Buffer extends uint8array.
        const buffer = Buffer.alloc(size);
        // Needs to be copied because the data may change in the heap.
        // .set copies the data from the heap to the output buffer.
        // It's important that we don't use Buffer.from on the heap because it
        // copies the whole heap which is utterly insane.
        buffer.set(luaModule.module.HEAPU8.subarray(pointer, pointer + size));
        writtenBuffers.push(buffer);
        return 0;
      },
      'iiiii',
    );

Load your function and then call lua_dump, it should always return LuaReturn.Ok unless there's an error, might have returned yield because of the writer function for you?

        if (LuaReturn.Ok === luaModule.lua_dump(address, writerFunctionPointer, 0, 0)) {
            const data = Buffer.concat(writtenBuffers)
              // TODO Use buffer
          } else {
            // TODO Deal with error
          }

Loading it is equally as annoying. Fist you need to copy the buffer onto the heap, something like:

const mem = thread.lua.module._realloc(0, script.length);
if (!mem) {
  throw new Error('failed to allocate memory for script');
}
// Where script is a Buffer
script.copy(thread.lua.module.HEAPU8, mem, 0, script.length);

thread.assertOk(
  thread.lua.luaL_loadbufferx_raw(
    thread.address,
    mem,
    script.length,
    "name of loaded file for debug purposes",
    null,
  )
);