Latest Results
Fix invalid TS emission for namespaced (js_namespace) emscripten exports
The emscripten .d.ts emission produced three TS-invalid forms for
namespaced struct/impl, enum, and free-function exports:
1. The mangled identifier (e.g. app__math__Calc) leaked publicly because
the class/enum/function were emitted as `export class` and the file
was script-scoped (so even `declare class` would have leaked as a
global). Consumers could write `const c: app__math__Calc = ...` and
pin to an internal implementation detail.
2. An unqualified `Calc: typeof app__math__Calc` property was added to
`interface BindgenModule` alongside the namespace entry, lying about
the runtime shape (`m.Calc` is undefined) and duplicating the
namespace path. The same bug applied to namespaced enums and
functions which additionally emitted full declarations inside the
interface body (`enum X { ... }` and `<mangled>(): T;` are not
valid interface members).
3. The namespace shape landed as `export let app: { math: { Calc:
typeof app__math__Calc }, };` inside the interface body, producing
TS1131 (Property or signature expected) because `export let` is
illegal in an interface.
Fixes, scoped to the emscripten code path:
* class/enum/function declarations for namespaced items lift to a
pre-BindgenModule `declare ...` (module-internal). Drops the
`export ` prefix on the class prelude and adds the same `declare`
treatment for namespaced enums and functions, which previously
emitted directly into the BindgenModule body.
* the unqualified `<js_name>: typeof <mangled>;` interface entry is
skipped when the item is namespaced; the namespace shape covers it.
* the namespace shape emits as a plain interface member (`app: {
math: { Calc: typeof app__math__Calc } };`) bypassing the
`export let ` form `export_def` would otherwise produce.
* the .d.ts now ends with `export { BindgenModule };` so the file is
an ES module — the `declare ...` declarations become module-scoped
rather than global, closing the mangled-identifier leak.
Test:
* `emscripten_namespaced_exports_valid_ts` covers the original deep-
namespace repro (`js_namespace = ["app", "math"]` on a struct +
impl with constructor and method), same-`js_name` collisions across
namespaces (which require the mangled identifier as the
disambiguator inside the shape), namespaced enums and free
functions, and runs `tsc --noEmit --strict` on the output as the
canonical validity check. CI installs typescript globally before
`cargo test -p wasm-bindgen-cli` so tsc is on PATH; the test skips
gracefully when tsc isn't available locally. Latest Branches
-11%
-23%
+11%
ZhaoXiangXML:fix/require-class-js-name-lookup © 2026 CodSpeed Technology