Skip to content

BridgeJS: Fix name collision for same-named nested structs#744

Open
krodak wants to merge 1 commit into
swiftwasm:mainfrom
PassiveLogic:kr/fix-nested-struct-name-collision
Open

BridgeJS: Fix name collision for same-named nested structs#744
krodak wants to merge 1 commit into
swiftwasm:mainfrom
PassiveLogic:kr/fix-nested-struct-name-collision

Conversation

@krodak
Copy link
Copy Markdown
Member

@krodak krodak commented May 11, 2026

Overview

Follow-up to #735. When two different parent types both have a nested struct with the same short name (e.g., User.Stats and Player.Stats), the generated JavaScript produces duplicate const declarations and overwrites the same structHelpers.Stats key, causing a SyntaxError at parse time.

The fix uses abiName (which joins namespace + name with _, e.g., User_Stats) instead of the short name for all JS-side struct identifiers - helper keys, factory names, and TypeScript interface names.

Non-nested structs are unaffected since abiName returns the plain name when there is no namespace.

@krodak krodak force-pushed the kr/fix-nested-struct-name-collision branch from adf1074 to d0939f0 Compare May 11, 2026 16:08
@krodak krodak self-assigned this May 11, 2026
@krodak krodak requested a review from kateinoigakukun May 11, 2026 16:50
// `swift package bridge-js`.

export interface Stats {
export interface User_Stats {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if UserStats would be more aesthetically pleasing? I guess this could conflict with a separate struct just called UserStats in Swift.

More work but I think we could use TS namespaces here as well:

export namespace User {
    export interface Stats {
    }
}

I believe that this will automatically merge with the interface Player, if it exists.

Copy link
Copy Markdown
Member Author

@krodak krodak May 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey William, on the naming - yeah, UserStats would read nicer, but as you noted it could collide with an actual UserStats struct. The underscore keeps it unambiguous and mirrors the internal ABI name and aligns with current approach elsewhere in the code.

As for TS namespace idea - we do already emit namespace blocks in the declare global path (for exposeToGlobal: true), so the mechanism exists and could be reused. Current approach aligns with use of underscore in other places, but that could be considered, depending on @kateinoigakukun preference.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes more sense to use TS-namespace to represent the hierarchical types for public user-facing APIs.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated - nested struct interfaces now use TS namespaces. User.Stats and Player.Stats generate:

export namespace User {
    export interface Stats {
        health: number;
        score: number;
    }
}
export namespace Player {
    export interface Stats {
        level: number;
        rating: string;
    }
}

Internal JS struct helpers still use underscore-separated keys (structHelpers.User_Stats) since those aren't user-facing.

@krodak krodak force-pushed the kr/fix-nested-struct-name-collision branch from d0939f0 to 871815e Compare May 13, 2026 09:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants