moonbitlang / moonbit-docs

The docs of MoonBit programming language
https://moonbitlang.com/docs/syntax
871 stars 40 forks source link

WebAssembly.instantiate(): Import #0 module="spectest": module is not an object or function #213

Closed 1226085293 closed 1 month ago

1226085293 commented 1 month ago

Running a compiled WASM reports an error: WebAssembly.instantiate(): Import #0 module="spectest": module is not an object or function

node version: v22.2.0 System version: win11 professional version

main.mbt

fn main {
  let mut value = 0
  for index = 0; index < 10000000; index = index + 1 {
    value = value + 1;
  }
  println(123)
}

moon.pkg.json

{
    "is-main": true
}

main.ts

import fs from "fs";

(async () => {
    try {
        // 读取 WebAssembly 文件
        const wasmBuffer = fs.readFileSync("./wasm/main2.wasm");

        // 使用 WebAssembly.instantiate 直接实例化
        //@ts-ignore
        const wasmModule = await WebAssembly.instantiate(wasmBuffer, {
            Date: {
                now: () => Date.now(),
            },
        });

        // 调用 _start 函数来初始化环境
        // 类型断言以确保类型安全
        //@ts-ignore
        const instance = wasmModule.instance as WebAssembly.Instance & {
            exports: { _start: () => void };
        };
        instance.exports._start();

        console.log("WebAssembly module initialized successfully.");
    } catch (error) {
        console.error(error);
        debugger;
    }
})();
1226085293 commented 1 month ago

I used node20 version before. This script does not use external interfaces. For example, pub fn now() -> Int = "Date" "now" compiled WASM can run successfully. However, after I upgraded to Node22, it did not use external interfaces. WASM also doesn't work properly

peter-jerry-ye commented 1 month ago

println is the external interface. You'll need:

const [log, flush] = (() => {
  var buffer = [];
  function flush() {
    if (buffer.length > 0) {
      console.log(new TextDecoder("utf-16").decode(new Uint16Array(buffer).valueOf()));
      buffer = [];
    }
  }
  function log(ch) {
    if (ch == '\n'.charCodeAt(0)) { flush(); }
    else if (ch == '\r'.charCodeAt(0)) { /* noop */ }
    else { buffer.push(ch); }
  }
  return [log, flush]
})();

const importObject = {
  // ...
  spectest: {
    print_char: log
  },
}