swiftwasm / swiftwasm/JavaScriptKit
BridgeJS: Same-named `@JS` types across modules collide silently in generated glue
@krodak 已經在處理了。
開始於 2026年7月6日。
- 主要語言
- Swift
- 星號
- 986
- 分支
- 76
- 平均合併
- 21 小時 11 分鐘
- 30 天內合併 PR
- 4
描述
Overview
Since #730, @JS types defined in one module can be referenced from @JS APIs in other modules within the same package. However, type identity in the skeleton and in the generated glue is the unqualified type name — abiName carries the namespace but not the module. When two linked modules define @JS types with the same name (e.g. @JS struct Point in both ModuleA and ModuleB), several generated-name surfaces collide:
Stack ABI intrinsics (silent data corruption): Both modules' generated Swift declares
@_extern(wasm, module: "bjs", name: "swift_js_struct_lower_Point")
WebAssembly imports with the same module + name unify, and the linker assigns bjs["swift_js_struct_lower_Point"] twice — last one wins. Both modules end up calling the same handler, so one module's structs are encoded/decoded with the other's field layout. No diagnostic at build time or runtime.
JS helper tables: structHelpers / enum helper factories are keyed by unqualified name inside createInstantiator — same last-wins behavior.
Exposed thunks: @_expose(wasm, "bjs_Point_init") (and method/deinit thunks) are emitted by both modules, producing duplicate export names.
TypeScript declarations: two interface Point declarations in one bridge-js.d.ts — TypeScript declaration-merges them, which is silent when the field sets are compatible and produces confusing errors when they are not.
Reference resolution: independent of naming, a skeleton reference like .swiftStruct("Point") is unqualified, so the linker resolves it by name-matching across all skeletons — with two candidates the choice is arbitrary. Renaming the ABI surfaces alone is not sufficient; the reference side needs the defining module too.
Public JS declarations (fails loudly, related): even when the colliding types live under different @JS(namespace:) paths — where no public-surface conflict exists — the generated JS still declares classes and enum value objects with flat top-level identifiers (class Point { … }, const PointValues = …) before wiring them into their namespace objects, and bridge-js.d.ts emits the corresponding declarations unscoped. Two same-named types in different namespaces therefore produce duplicate declarations in one scope: a load-time SyntaxError on the JS side and duplicate-identifier errors in the .d.ts. Unlike the ABI surfaces above this fails loudly rather than corrupting data, but it makes same-named types unusable across modules even when their public paths don't overlap.
Possible direction
- Make type identity in the skeleton module-aware (defining module + name). #730 already established that the skeleton format does not need to stay backward compatible.
- Module-qualify the internal ABI names (
swift_js_struct_lower_<Module>_<Name>,bjs_<Module>_…). Newer name families already follow this pattern — closure invokes (invoke_js_callback_<module>_<mangleName>) and promise settlement helpers (promise_resolve_<module>_<mangled>) — it is only the older core names that predate it. - Keep the public JS access paths flat (
exports.Point, namespace objects, TS types) and emit a build-time linker diagnostic when two modules expose the identical public name at the same namespace path, mirroring how #730 handles Swift-side ambiguity with a diagnostic that asks for explicit qualification. - For the declaration surface: declare classes and enum value objects under unique internal identifiers (the module-qualified ABI name is a natural choice), bind public names only through namespace objects /
exports, and scope.d.tsdeclarations for namespaced types insidedeclare namespaceblocks. Public access paths stay exactly as today; only the internal declaration identifiers change, so same-named types in different namespaces become fully usable.
貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
評估
這個 Issue 還沒有評估資料。