Node.js运行由Golang生成的WASM时出错,但在浏览器中成功。

huangapple go评论111阅读模式
英文:

Nodejs run WASM generated by Golang error but browser success

问题

我创建了一个名为WASM的Go文件:

package main

func main() {
    println("Hello, world!")
}

然后,执行以下命令生成test.wasm文件:

> GOOS=js GOARCH=wasm go build -o test.wasm ./test.go

我想在Node.js中运行WASM,参考Node.js与WebAssembly

// test.js
const fs = require('fs');

const wasmBuffer = fs.readFileSync('./test.wasm');
WebAssembly.instantiate(wasmBuffer).then((wasmModule) => {
  console.log(wasmBuffer);
});

错误信息:

node:internal/process/promises:279
            triggerUncaughtException(err, true /* fromPromise */);
            ^

[TypeError: WebAssembly.instantiate(): Imports argument must be present and must be an object]

但是,我可以在浏览器中执行:

<html>  
    <head>
        <meta charset="utf-8"/>
        <script src="wasm_exec.js"></script>
        <script>
    if (!WebAssembly.instantiateStreaming) {
      // polyfill
      WebAssembly.instantiateStreaming = async (resp, importObject) => {
            const source = await (await resp).arrayBuffer();
            return await WebAssembly.instantiate(source, importObject);
        };
        }

        const go = new Go();

        let mod, inst;

        WebAssembly.instantiateStreaming(fetch("test.wasm"), go.importObject).then(
        async (result) => {
            mod = result.module;
            inst = result.instance;

            await go.run(inst);
            inst = await WebAssembly.instantiate(mod, go.importObject); // reset instance
        }
        );

        </script>
    </head>
    <body></body>
</html>  

Node.js运行由Golang生成的WASM时出错,但在浏览器中成功。


环境:

  • Node.js: 16.15.1

  • Golang: go1.18.3 darwin/arm64

英文:

I create a go file as WASM:

package main

func main() {
	println(&quot;Hello, world!&quot;)
}

Then, execute following command to generate test.wasm:

&gt; GOOS=js GOARCH=wasm go build -o test.wasm ./test.go

I want run WASM in Node.js, ref Node.js with WebAssembly:

// test.js
const fs = require(&#39;fs&#39;);

const wasmBuffer = fs.readFileSync(&#39;./test.wasm&#39;);
WebAssembly.instantiate(wasmBuffer).then((wasmModule) =&gt; {
  console.log(wasmBuffer);
});

error message:

node:internal/process/promises:279
            triggerUncaughtException(err, true /* fromPromise */);
            ^

[TypeError: WebAssembly.instantiate(): Imports argument must be present and must be an object]

But, I can execute in browser:

&lt;html&gt;  
    &lt;head&gt;
        &lt;meta charset=&quot;utf-8&quot;/&gt;
        &lt;script src=&quot;wasm_exec.js&quot;&gt;&lt;/script&gt;
        &lt;script&gt;
    if (!WebAssembly.instantiateStreaming) {
      // polyfill
      WebAssembly.instantiateStreaming = async (resp, importObject) =&gt; {
            const source = await (await resp).arrayBuffer();
            return await WebAssembly.instantiate(source, importObject);
        };
        }

        const go = new Go();

        let mod, inst;

        WebAssembly.instantiateStreaming(fetch(&quot;test.wasm&quot;), go.importObject).then(
        async (result) =&gt; {
            mod = result.module;
            inst = result.instance;

            await go.run(inst);
            inst = await WebAssembly.instantiate(mod, go.importObject); // reset instance
        }
        );

        &lt;/script&gt;
    &lt;/head&gt;
    &lt;body&gt;&lt;/body&gt;
&lt;/html&gt;  

Node.js运行由Golang生成的WASM时出错,但在浏览器中成功。


environment:

  • Nodejs: 16.15.1

  • Golang: go1.18.3 darwin/arm64

答案1

得分: 4

最后,我找到了一种在Node.js上执行Golang WASM的方法:

// 注释掉这个块以避免死锁
// if (code === 0 &amp;&amp; !go.exited) {
//   // 死锁,使Go打印错误和堆栈跟踪
//   go._pendingEvent = { id: 0 };
//   go._resume();
// }

// 以下代码是为了避免死锁
const result = globalThis[func](...funcArgs);

console.log(result);
process.exit();
  • 代码:https://github.com/riskers/nodejs-exec-go-wasm/blob/main/examples/golang/README.md

或者你可以使用tinyGo编译wasm。

  • 代码:https://github.com/riskers/nodejs-exec-go-wasm/blob/main/examples/tinygo-wasmer/README.md

适用于Node和浏览器的通用cross-wasm

  • 代码:https://github.com/riskers/nodejs-exec-go-wasm/blob/main/packages/cross-wasm/README.md
英文:

Finally, I found a way to execute Golang WASM on Node.js:

// commend the block avoid deadlock
// if (code === 0 &amp;&amp; !go.exited) {
//   // deadlock, make Go print error and stack traces
//   go._pendingEvent = { id: 0 };
//   go._resume();
// }

// below code is to avoid deadlock
const result = globalThis[func](...funcArgs);

console.log(result);
process.exit();

Or you can use tinyGo compile wasm.


Universal cross-wasm for Node and Browsers.

huangapple
  • 本文由 发表于 2022年7月11日 18:38:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/72937239.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定