Skip to content

BridgeJS: Fix JSValue reference ownership across the bridge - #31

Closed
krodak wants to merge 3 commits into
mainfrom
kr/bridgejs-jsvalue-return-lifetime
Closed

krodak wants to merge 3 commits into
mainfrom
kr/bridgejs-jsvalue-return-lifetime

Conversation

@krodak

@krodak krodak commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Overview

Returning a JSValue that Swift created crashed:

@JS func makeOptions() -> JSValue {
    let options = JSObject()
    options["method"] = .string("POST")
    return .object(options)
}
exports.makeOptions(); // ReferenceError: Attempted to use invalid reference ...

JSValue.bridgeJSStackPush consumed self before it retained the payload, so the last reference was already released. The retain now runs inside withRawJSValue.

Values that came from JavaScript did not crash, because they leaked. The JS lower retained the payload and JSValue.bridgeJSLiftParameter retained it again. In the other direction, Swift retained a returned payload and the JS lift never released it. JSValue now follows the JSObject rule: the sender retains and the receiver takes ownership. The Swift lift no longer retains, and the JS lift of returned and container values releases through a new __bjs_jsValueTake helper. Direct Swift-to-JS parameters stay borrowed. A private JSValueKind enum now holds the kind tags, so the glue no longer repeats which kinds carry a reference.

Testing

Added makeJSValueString and makeJSValueObject, and asserts that no reference stays in the JS heap after roundTripJSValue and roundTripOptionalJSValueArray. Snapshot tests and make unittest pass.

@krodak krodak changed the title BridgeJS: Retain JSValue return payloads before releasing the value BridgeJS: Fix JSValue reference ownership across the bridge Nov 3, 2026
@krodak
krodak force-pushed the kr/bridgejs-jsvalue-return-lifetime branch from 6debac7 to d9e038b Compare November 3, 2026 06:41
@krodak
krodak force-pushed the kr/bridgejs-jsvalue-return-lifetime branch from d9e038b to 5e27587 Compare November 3, 2026 10:55
@krodak
krodak force-pushed the kr/bridgejs-jsvalue-return-lifetime branch from 5e27587 to f1d5c94 Compare November 3, 2026 11:17
@krodak krodak closed this Nov 3, 2026
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.

1 participant