Closed kennu closed 2 years ago
Could you elaborate "Build simple wasm that just prints hello world." more to reproduce your problem on my side? Also please report the JS harness script for launching your wasi app.
The hello world .swift program that I tried to execute looks like this, using only print() functions:
It is built with docker run --rm -it -v $PWD:/app -w /app ghcr.io/swiftwasm/swift:5.6 swiftc -target wasm32-unknown-wasi demo-swift.swift -o demo-swift.wasm
demo-swift.swift:
print("{")
print(" \"statusCode\": \"200\",")
print(" \"headers\": {")
print(" \"Content-Type\":\"application/json\"")
print(" },")
print(" \"body\": \"{ \\\"message\\\": \\\"Hello world from Swift application!\\\" }\"")
print("}")
The Node.js WebAssembly loader code looks like this:
import { join } from 'path'
import { openSync, closeSync, readFileSync } from 'fs'
// @ts-ignore
import { WASI } from 'wasi'
async function runWasm(): Promise<Buffer> {
const wasmPath = join(__dirname, 'main.wasm')
const wasmContent = readFileSync(wasmPath)
const wasmLength = wasmContent.length
console.log('Executing WASM file at', wasmPath, 'with', wasmLength, 'bytes')
// Capture output to a temporary file
const tempFileName = `/tmp/output-${process.env.AWS_LAMBDA_LOG_STREAM_NAME?.replace(/[^a-z0-9]/g, '')}.txt`
const tempFileFd = openSync(tempFileName, 'w+', 0o666)
const wasi = new WASI({
args: [],
env: {}, // process.env,
preopens: {
// '/': '/',
},
returnOnExit: true,
stdout: tempFileFd,
})
// @ts-ignore
const wasm = await WebAssembly.compile(wasmContent)
// @ts-ignore
const instance = await WebAssembly.instantiate(wasm, {
wasi_snapshot_preview1: wasi.wasiImport,
})
const exitCode = wasi.start(instance)
console.log('WebAssembly exit code:', exitCode)
closeSync(tempFileFd)
const output = readFileSync(tempFileName)
console.log('WebAssembly output (', output?.length, '):', output?.toString())
return output
}
Here is a simpler Node.js 16.x loader that works from command line as
node --experimental-wasi-unstable-preview1 loader.js ../wasm/swift/demo-swift.wasm
With the SwiftWasm-compiled wasm, I get exit code 71. With e.g. AssemblyScript compiled wasm, I get expected output and exit code 0.
loader.js:
const fs = require('fs')
const wasiMod = require('wasi')
async function main() {
const wasmPath = process.argv[2]
const wasmContent = fs.readFileSync(wasmPath)
const wasmLength = wasmContent.length
console.log('Executing WASM file at', wasmPath, 'with', wasmLength, 'bytes')
const wasi = new wasiMod.WASI({
args: [],
env: {},
preopens: {},
returnOnExit: true,
})
const wasm = await WebAssembly.compile(wasmContent)
const instance = await WebAssembly.instantiate(wasm, {
wasi_snapshot_preview1: wasi.wasiImport,
})
const exitCode = wasi.start(instance)
console.log('WebAssembly exit code:', exitCode)
}
main().then(console.log).catch(console.error)
Thank you for your info. I could reproduce your issue.
The root cause of this issue is you didn't pass "program name" as args[0]
and wasi-libc requires to have it. (so C code compiled with WASI SDK also results the same result)
So passing args: ["main"]
to WASI constructor would solve your issue. I will note this on our documentation.
Thank you.
Awesome @kateinoigakukun thanks! I never thought of it. After adding args[0] it works fine.
Node.js docs/default are a little conflicting, saying "The first argument is the virtual path to the WASI command itself. Default: []". I guess many languages ignore argv[0] until you use it, but now I know to always include it.
Describe the bug When I load and execute a simple helloworld.wasm file, built with SwiftWasm, in Node.js 16, it terminates with exit code 71 before outputting anything.
Steps To Reproduce Steps to reproduce the behavior:
Expected behavior Program should print hello world and exit with code 0.
Environment (please fill out the following information)
Additional context Many other wasm compilers work fine with the same setup (Clang, Rust, Go, Grain, Zig, AssemlyScript) so I'm trying to figure out what is different in SwiftWasm.