bytecodealliance / ComponentizeJS

JS -> WebAssembly Component
Apache License 2.0
233 stars 29 forks source link

Unable to call method on resource, works in Rust guest but not JS guest #148

Open lwansbrough opened 2 hours ago

lwansbrough commented 2 hours ago

I've got a bit of a challenging one here. It's hard to trace the issue because I don't have debug information available from SpiderMonkey (will traces from the engine be available via some debug mode at some point?)

I have a repro but it requires my toolchain. Shouldn't take long to set up:

  1. Grab the latest rune-cli release from https://github.com/rune-runtime/rune/releases/tag/v0.1.11 (or use curl -fsSL https://rune.sh/install.sh | bash to install rune locally) -- I think you'll need a Mac for this for the time being.
  2. Create a new directory, ie. test & cd into it
  3. Run rune new game --template cube-js -- this will create a new Rune project in the current directory
  4. Run npm i
  5. Run rune run. Observe that the program crashes with [1]
  6. In game.js, comment out line 194 and rune run again. Observe the program does not crash.

This invocation, pipeline.getBindGroupLayout(0) works in my Rust wasm32-wasip1 guest module (you can try it by doing rune new game --template cube-rust) Because of this, I believe there is a bug in ComponentizeJS. Without better debugging I can't say for certain.

If you need to debug the use of ComponentizeJS in my toolchain, you should refer to the module in node_modules/@bytecodealliance/ComponentizeJS, which is used by the @rune-runtime/rollup-plugin-rune Rollup plugin to build a wasm module for Rune.

[1]

Message:  Game didn't initialize: error while executing at wasm backtrace:
    0: 0x2f363 - <unknown>!<wasm function 451>
    1: 0x2f36c - <unknown>!<wasm function 452>
    2: 0x22ee52 - <unknown>!<wasm function 5253>
    3: 0x7a8ac3 - <unknown>!rune:runtime/guest#init

Caused by:
    wasm trap: wasm `unreachable` instruction executed
Location: crates/rune/src/runtime/mod.rs:97

Guidance is appreciated. Thanks.

lwansbrough commented 2 hours ago

Host code for this method is as follows:

    async fn get_bind_group_layout(
        &mut self,
        pipeline: Resource<GpuRenderPipeline>,
        index: u32,
    ) -> Resource<GpuBindGroupLayout> {
        let pipeline_id = self.table.get(&pipeline).unwrap();
        let bind_group_layout_id = wgpu_id(
            self.instance
                .render_pipeline_get_bind_group_layout(*pipeline_id, index, None),
        )
        .unwrap();
        self.table
            .push_child(bind_group_layout_id, &pipeline)
            .unwrap()
    }

The JS output by SpiderMonkey for this method is as follows:

  getBindGroupLayout(arg0) {
    function helper(arg0, arg1) {
      var handle0 = arg0[symbolRscHandle];
      finalizationRegistry_import$gpu$gpuRenderPipeline.unregister(arg0);
      const ret = $import_gpu$gpuRenderPipeline$method$getBindGroupLayout(handle0, toUint32(arg1));
      var handle2 = ret;
      var rsc1 = new.target === import_gpu$GpuBindGroupLayout ? this : Object.create(import_gpu$GpuBindGroupLayout.prototype);
      Object.defineProperty(rsc1, symbolRscHandle, { writable: true, value: handle2});
      finalizationRegistry_import$gpu$gpuBindGroupLayout.register(rsc1, handle2, rsc1);
      return rsc1;
    }
    return helper(this, arg0);
  }