ReviewOS

zig-utils/zig-js

Wasm: names.wast:630 returns a non-function for an exported name

#879
Closed glennmichael123 opened this 11 days ago ·
11 days ago

One behavioral failure in the pinned wg-1.0 corpus, unrelated to diagnostics.

zig build wasm-spec -Doptimize=ReleaseFast
names.wast:630 [assert_return]
  TypeError: value is not a function

names.wast exercises exported names containing unusual code points (control characters, astral-plane symbols, embedded quotes/backslashes). The assertion resolves an export by name and calls it; we return something that is not callable, which suggests the export is being looked up under a differently-encoded key than the one the JS API surfaces rather than a defect in the call path itself.

Not yet investigated — filed with the reproducer so it is not lost. This is the only non-diagnostic failure in the corpus.

11 days ago

Umbrella: #880. Siblings: #877 (acceptance gap), #878 (diagnostic wording).

11 days ago

Fixed in c67fa08.

Root cause: a wasm name becomes a JS property key, and the interpreter storage-escapes any public key beginning with NUL (value.encodeStringKey prefixes \x00\x00) so it cannot collide with the engine's symbol/internal-slot encodings — which are themselves NUL-led. src/wasm/ had zero call sites for it. The exports object was keyed with the raw module bytes while every JS read escapes first, so the property was stored under bytes no property access can produce. names.wast exports a function named U+0000..U+000F — the only NUL-leading export name in the corpus, and the only behavioural failure left in the suite.

Two things came out of it beyond the reported symptom:

  • Enumeration was broken too. The raw NUL-led key also satisfied value.isSymbolKey, so the export was invisible to Object.keys on the exports object, not merely unreadable by name.
  • The mirror defect on the import side (resolveImports, api.zig:1975/1978) looked up the import object and namespace with raw names, so a JS-authored namespace keyed "\u0000m" raised LinkError: WebAssembly import module is not an object. No upstream case covers that shape, so it had no gate — fixed here because it is the same defect in the other direction.

Only keys are escaped; names used as values (a wrapped function's name, WebAssembly.Module.exports() descriptors) keep exact bytes, and the Module-reflection test covers that distinction.

Corpus, both modes: 18,791 pass / 0 fail / 479 skip / 0 crash.

Sign in to comment on this issue.