Skip to content

BridgeJS: Emit static members in declare global class declarations#772

Merged
krodak merged 1 commit into
swiftwasm:mainfrom
PassiveLogic:kr/global-namespace-static-members
Jun 23, 2026
Merged

BridgeJS: Emit static members in declare global class declarations#772
krodak merged 1 commit into
swiftwasm:mainfrom
PassiveLogic:kr/global-namespace-static-members

Conversation

@krodak

@krodak krodak commented Jun 23, 2026

Copy link
Copy Markdown
Member

Overview

Static members of a globally-exposed @JS(namespace:) class were rendered incorrectly in the generated declare global { namespace ... } TypeScript declarations: every method was emitted without static, and properties were filtered to instance-only. As a result a @JS static func was typed as an instance method and a @JS static var was dropped from the .d.ts entirely.

This is a type-only defect. The emitted JavaScript already exposes these members statically (and the class's namespace export entry types them correctly), so the runtime behavior is unaffected and only TypeScript consumers were impacted: static access such as MyNamespace.MyClass.makeDefault() would not type-check even though the call works at runtime. We found it now, as we have tsc --noEmit check over consumer code.

The fix splits static and instance members in this path, emitting static methods with static and including static properties (with static/readonly as appropriate).

Before / after

// before
class Greeter {
    constructor(name: string);
    greet(): string;
    makeDefault(): Greeter;   // wrongly typed as instance, defaultGreeting missing
    release(): void;
}

// after
class Greeter {
    constructor(name: string);
    greet(): string;
    static makeDefault(): Greeter;
    static readonly defaultGreeting: string;
    release(): void;
}

The `declare global { namespace ... }` class stub rendered every method
without `static` and filtered properties to instance-only, so a `@JS static
func` on a namespaced class was typed as an instance method and a `@JS
static var` was omitted from the generated `.d.ts`.

This was a type-only defect: the emitted JavaScript already exposes these
members statically (and the class's namespace export entry types them
correctly), so only TypeScript consumers were affected. Split static and
instance members in this path: emit static methods with `static` and
include static properties.

This has been incorrect since the global namespace class stub was
introduced, not a regression. The `Namespaces.Global` snapshot already
exercises a namespaced class with `static func`/`static var` but had
recorded the wrong output, so it is updated to the corrected declarations.
@krodak krodak self-assigned this Jun 23, 2026
@krodak krodak requested a review from kateinoigakukun June 23, 2026 11:15
@krodak krodak merged commit ebbde04 into swiftwasm:main Jun 23, 2026
10 checks passed
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.

2 participants