Summary
PR #705 closed #76 by landing a useful WebAssembly host PoC, but the shipped API is still a Perry-specific synchronous subset. Current Node exposes the standard global WebAssembly namespace object, with constructor classes, async compile/instantiate methods, streaming methods, and typed error constructors. Perry currently recognizes a few WebAssembly.* call shapes syntactically instead of exposing a Node-compatible namespace value.
This is observable to packages that feature-detect globalThis.WebAssembly, destructure methods/classes, construct WebAssembly.Module / WebAssembly.Instance, catch WebAssembly.CompileError, or rely on the standard Promise-returning instantiate() shape used by wasm-pack/emscripten glue.
Expected Node behavior
Node's WebAssembly guide says Node provides the necessary APIs via the global WebAssembly object: https://nodejs.org/en/learn/getting-started/nodejs-with-webassembly
A local Node v25.9.0 probe shows the namespace shape:
typeof WebAssembly object
global identity true
keys CompileError,Exception,Global,Instance,JSTag,LinkError,Memory,Module,RuntimeError,SuspendError,Suspending,Table,Tag,compile,compileStreaming,instantiate,instantiateStreaming,promising,validate
Module proto function constructor
Instance proto function constructor,exports
Probe:
console.log("typeof WebAssembly", typeof WebAssembly);
console.log("global identity", globalThis.WebAssembly === WebAssembly);
console.log("keys", Object.getOwnPropertyNames(WebAssembly).sort().join(","));
console.log("Module proto", typeof WebAssembly.Module, Object.getOwnPropertyNames(WebAssembly.Module.prototype).sort().join(","));
console.log("Instance proto", typeof WebAssembly.Instance, Object.getOwnPropertyNames(WebAssembly.Instance.prototype).sort().join(","));
Node's standard WebAssembly.instantiate(bufferSource[, importObject]) returns a Promise for raw bytes and supports new WebAssembly.Module(bytes) plus new WebAssembly.Instance(module, imports) for synchronous construction.
Current Perry evidence
Source inspection against origin/main:
crates/perry-runtime/src/webassembly.rs explicitly documents the current surface as MVP API (Perry-specific, not standard).
- The same comment says the PoC exposes only three synchronous top-level namespace builtins:
WebAssembly.validate(bytes), WebAssembly.instantiate(bytes) returning an opaque handle, and WebAssembly.callExport(handle, name, ...).
crates/perry-hir/src/lower/expr_call/module_static.rs only recognizes validate, instantiate, and the nonstandard callExport when the receiver is the identifier WebAssembly.
crates/perry-runtime/src/object/global_this.rs::GLOBAL_THIS_BUILTIN_NAMESPACES does not include WebAssembly, so globalThis.WebAssembly is not populated through the native global singleton path.
crates/perry-codegen/src/expr/helpers.rs::is_global_this_builtin_name() also omits WebAssembly, so globalThis.WebAssembly reads do not route to a populated namespace object.
test-files/test_wasm_add.ts only covers the PoC flow: WebAssembly.validate(bytes), sync WebAssembly.instantiate(bytes), and inst.exports.add(...); it does not cover globalThis.WebAssembly, constructors, error classes, Promise shape, or imports object behavior.
I did not run a Perry binary because this checkout does not have target/release/perry; this issue is based on committed origin/main source, current Node docs, and a local Node v25.9.0 probe.
Suggested test surface
Add parity tests for the standard namespace shape separately from the existing PoC test:
console.log(typeof globalThis.WebAssembly === "object");
console.log(globalThis.WebAssembly === WebAssembly);
for (const k of [
"validate",
"compile",
"instantiate",
"compileStreaming",
"instantiateStreaming",
"Module",
"Instance",
"Memory",
"Table",
"Global",
"CompileError",
"LinkError",
"RuntimeError",
]) {
console.log(k, typeof WebAssembly[k]);
}
Add behavior tests for:
WebAssembly.instantiate(bytes) returning a Promise resolving to { module, instance } for raw bytes.
new WebAssembly.Module(bytes) and new WebAssembly.Instance(module, imports).
instance.exports.<name> working without compile-time-only local tagging assumptions.
- invalid bytes throwing/rejecting with
WebAssembly.CompileError.
importObject plumbing for numeric host imports once supported.
Scope / non-goals
This issue is a completion follow-up for the standard Node/global WebAssembly API shape after #76/#705. It should not remove the existing PoC helper path unless maintainers decide to deprecate it; WebAssembly.callExport can remain Perry-specific if useful, but it should not be the only way to call exports.
Streaming methods can initially throw or reject with a clear unsupported error if Perry lacks Response body streaming, but the namespace and function/class presence should match Node closely enough for feature detection.
Duplicate search
Checked existing issues and PRs with:
WebAssembly global
WebAssembly validate instantiate globalThis
WebAssembly Module Instance Memory Table
WebAssembly instantiate validate wasmi
The hits were closed #76 and merged #705, both of which explicitly shipped the PoC subset and list the standard async surface, imports, streaming methods, and host passthrough as follow-up work. I did not find an open tracker for the Node-compatible namespace object and standard constructor/method surface.
Summary
PR #705 closed #76 by landing a useful WebAssembly host PoC, but the shipped API is still a Perry-specific synchronous subset. Current Node exposes the standard global
WebAssemblynamespace object, with constructor classes, async compile/instantiate methods, streaming methods, and typed error constructors. Perry currently recognizes a fewWebAssembly.*call shapes syntactically instead of exposing a Node-compatible namespace value.This is observable to packages that feature-detect
globalThis.WebAssembly, destructure methods/classes, constructWebAssembly.Module/WebAssembly.Instance, catchWebAssembly.CompileError, or rely on the standard Promise-returninginstantiate()shape used by wasm-pack/emscripten glue.Expected Node behavior
Node's WebAssembly guide says Node provides the necessary APIs via the global
WebAssemblyobject: https://nodejs.org/en/learn/getting-started/nodejs-with-webassemblyA local Node v25.9.0 probe shows the namespace shape:
Probe:
Node's standard
WebAssembly.instantiate(bufferSource[, importObject])returns a Promise for raw bytes and supportsnew WebAssembly.Module(bytes)plusnew WebAssembly.Instance(module, imports)for synchronous construction.Current Perry evidence
Source inspection against
origin/main:crates/perry-runtime/src/webassembly.rsexplicitly documents the current surface asMVP API (Perry-specific, not standard).WebAssembly.validate(bytes),WebAssembly.instantiate(bytes)returning an opaque handle, andWebAssembly.callExport(handle, name, ...).crates/perry-hir/src/lower/expr_call/module_static.rsonly recognizesvalidate,instantiate, and the nonstandardcallExportwhen the receiver is the identifierWebAssembly.crates/perry-runtime/src/object/global_this.rs::GLOBAL_THIS_BUILTIN_NAMESPACESdoes not includeWebAssembly, soglobalThis.WebAssemblyis not populated through the native global singleton path.crates/perry-codegen/src/expr/helpers.rs::is_global_this_builtin_name()also omitsWebAssembly, soglobalThis.WebAssemblyreads do not route to a populated namespace object.test-files/test_wasm_add.tsonly covers the PoC flow:WebAssembly.validate(bytes), syncWebAssembly.instantiate(bytes), andinst.exports.add(...); it does not coverglobalThis.WebAssembly, constructors, error classes, Promise shape, or imports object behavior.I did not run a Perry binary because this checkout does not have
target/release/perry; this issue is based on committedorigin/mainsource, current Node docs, and a local Node v25.9.0 probe.Suggested test surface
Add parity tests for the standard namespace shape separately from the existing PoC test:
Add behavior tests for:
WebAssembly.instantiate(bytes)returning a Promise resolving to{ module, instance }for raw bytes.new WebAssembly.Module(bytes)andnew WebAssembly.Instance(module, imports).instance.exports.<name>working without compile-time-only local tagging assumptions.WebAssembly.CompileError.importObjectplumbing for numeric host imports once supported.Scope / non-goals
This issue is a completion follow-up for the standard Node/global WebAssembly API shape after #76/#705. It should not remove the existing PoC helper path unless maintainers decide to deprecate it;
WebAssembly.callExportcan remain Perry-specific if useful, but it should not be the only way to call exports.Streaming methods can initially throw or reject with a clear unsupported error if Perry lacks
Responsebody streaming, but the namespace and function/class presence should match Node closely enough for feature detection.Duplicate search
Checked existing issues and PRs with:
WebAssembly globalWebAssembly validate instantiate globalThisWebAssembly Module Instance Memory TableWebAssembly instantiate validate wasmiThe hits were closed #76 and merged #705, both of which explicitly shipped the PoC subset and list the standard async surface, imports, streaming methods, and host passthrough as follow-up work. I did not find an open tracker for the Node-compatible namespace object and standard constructor/method surface.