Skip to content

Commit 83098c2

Browse files
committed
BridgeJS: Pass optional jsObject import parameters via direct ABI
1 parent c93a031 commit 83098c2

6 files changed

Lines changed: 77 additions & 26 deletions

File tree

Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -669,7 +669,7 @@ struct IntrinsicJSFragment: Sendable {
669669
}
670670

671671
let innerFragment =
672-
if wrappedType.optionalConvention == .stackABI {
672+
if wrappedType.optionalParameterUsesStackABI {
673673
try stackLiftFragment(elementType: wrappedType)
674674
} else {
675675
try liftParameter(type: wrappedType, context: bridgeContext)
@@ -686,7 +686,7 @@ struct IntrinsicJSFragment: Sendable {
686686
kind: JSOptionalKind,
687687
innerFragment: IntrinsicJSFragment
688688
) -> IntrinsicJSFragment {
689-
let isStackConvention = wrappedType.optionalConvention == .stackABI
689+
let isStackConvention = wrappedType.optionalParameterUsesStackABI
690690
let absenceLiteral = kind.absenceLiteral
691691

692692
let outerParams: [String]

Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -387,18 +387,9 @@ export async function createInstantiator(options, swift) {
387387
setException(error);
388388
}
389389
}
390-
TestModule["bjs_WithOptionalJSClass_childOrNull_set"] = function bjs_WithOptionalJSClass_childOrNull_set(self, newValue) {
390+
TestModule["bjs_WithOptionalJSClass_childOrNull_set"] = function bjs_WithOptionalJSClass_childOrNull_set(self, newValueIsSome, newValueObjectId) {
391391
try {
392-
let optResult;
393-
if (newValue) {
394-
const objId = i32Stack.pop();
395-
const obj = swift.memory.getObject(objId);
396-
swift.memory.release(objId);
397-
optResult = obj;
398-
} else {
399-
optResult = null;
400-
}
401-
swift.memory.getObject(self).childOrNull = optResult;
392+
swift.memory.getObject(self).childOrNull = newValueIsSome ? swift.memory.getObject(newValueObjectId) : null;
402393
} catch (error) {
403394
setException(error);
404395
}
@@ -489,22 +480,13 @@ export async function createInstantiator(options, swift) {
489480
setException(error);
490481
}
491482
}
492-
TestModule["bjs_WithOptionalJSClass_roundTripChildOrNull"] = function bjs_WithOptionalJSClass_roundTripChildOrNull(self, value) {
483+
TestModule["bjs_WithOptionalJSClass_roundTripChildOrNull"] = function bjs_WithOptionalJSClass_roundTripChildOrNull(self, valueIsSome, valueObjectId) {
493484
try {
494-
let optResult;
495-
if (value) {
496-
const objId = i32Stack.pop();
497-
const obj = swift.memory.getObject(objId);
498-
swift.memory.release(objId);
499-
optResult = obj;
500-
} else {
501-
optResult = null;
502-
}
503-
let ret = swift.memory.getObject(self).roundTripChildOrNull(optResult);
485+
let ret = swift.memory.getObject(self).roundTripChildOrNull(valueIsSome ? swift.memory.getObject(valueObjectId) : null);
504486
const isSome = ret != null;
505487
if (isSome) {
506-
const objId1 = swift.memory.retain(ret);
507-
i32Stack.push(objId1);
488+
const objId = swift.memory.retain(ret);
489+
i32Stack.push(objId);
508490
}
509491
i32Stack.push(isSome ? 1 : 0);
510492
} catch (error) {

Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14087,6 +14087,18 @@ fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringToStringDic
1408714087
return bjs_OptionalSupportImports_jsRoundTripOptionalStringToStringDictionaryUndefined_static_extern(v)
1408814088
}
1408914089

14090+
#if arch(wasm32)
14091+
@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_OptionalSupportImports_jsRoundTripOptionalJSObjectNull_static")
14092+
fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalJSObjectNull_static_extern(_ valueIsSome: Int32, _ valueValue: Int32) -> Void
14093+
#else
14094+
fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalJSObjectNull_static_extern(_ valueIsSome: Int32, _ valueValue: Int32) -> Void {
14095+
fatalError("Only available on WebAssembly")
14096+
}
14097+
#endif
14098+
@inline(never) fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalJSObjectNull_static(_ valueIsSome: Int32, _ valueValue: Int32) -> Void {
14099+
return bjs_OptionalSupportImports_jsRoundTripOptionalJSObjectNull_static_extern(valueIsSome, valueValue)
14100+
}
14101+
1409014102
#if arch(wasm32)
1409114103
@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_OptionalSupportImports_runJsOptionalSupportTests_static")
1409214104
fileprivate func bjs_OptionalSupportImports_runJsOptionalSupportTests_static_extern() -> Void
@@ -14173,6 +14185,15 @@ func _$OptionalSupportImports_jsRoundTripOptionalStringToStringDictionaryUndefin
1417314185
return JSUndefinedOr<[String: String]>.bridgeJSLiftReturn()
1417414186
}
1417514187

14188+
func _$OptionalSupportImports_jsRoundTripOptionalJSObjectNull(_ value: Optional<JSObject>) throws(JSException) -> Optional<JSObject> {
14189+
let (valueIsSome, valueValue) = value.bridgeJSLowerParameter()
14190+
bjs_OptionalSupportImports_jsRoundTripOptionalJSObjectNull_static(valueIsSome, valueValue)
14191+
if let error = _swift_js_take_exception() {
14192+
throw error
14193+
}
14194+
return Optional<JSObject>.bridgeJSLiftReturn()
14195+
}
14196+
1417614197
func _$OptionalSupportImports_runJsOptionalSupportTests() throws(JSException) -> Void {
1417714198
bjs_OptionalSupportImports_runJsOptionalSupportTests_static()
1417814199
if let error = _swift_js_take_exception() {

Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21047,6 +21047,40 @@
2104721047
}
2104821048
}
2104921049
},
21050+
{
21051+
"accessLevel" : "internal",
21052+
"effects" : {
21053+
"isAsync" : false,
21054+
"isStatic" : false,
21055+
"isThrows" : true
21056+
},
21057+
"name" : "jsRoundTripOptionalJSObjectNull",
21058+
"parameters" : [
21059+
{
21060+
"name" : "value",
21061+
"type" : {
21062+
"nullable" : {
21063+
"_0" : {
21064+
"jsObject" : {
21065+
21066+
}
21067+
},
21068+
"_1" : "null"
21069+
}
21070+
}
21071+
}
21072+
],
21073+
"returnType" : {
21074+
"nullable" : {
21075+
"_0" : {
21076+
"jsObject" : {
21077+
21078+
}
21079+
},
21080+
"_1" : "null"
21081+
}
21082+
}
21083+
},
2105021084
{
2105121085
"accessLevel" : "internal",
2105221086
"effects" : {

Tests/BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ export function getImports(importsContext) {
4646
jsRoundTripOptionalStringToStringDictionaryUndefined: (v) => {
4747
return v === undefined ? undefined : v;
4848
},
49+
jsRoundTripOptionalJSObjectNull: (v) => {
50+
return v ?? null;
51+
},
4952
runJsOptionalSupportTests: () => {
5053
const exports = importsContext.getExports();
5154
if (!exports) { throw new Error("No exports!?"); }

Tests/BridgeJSRuntimeTests/OptionalSupportTests.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import JavaScriptEventLoop
2424
_ v: JSUndefinedOr<[String: String]>
2525
) throws(JSException) -> JSUndefinedOr<[String: String]>
2626

27+
@JSFunction static func jsRoundTripOptionalJSObjectNull(_ value: JSObject?) throws(JSException) -> JSObject?
28+
2729
@JSFunction static func runJsOptionalSupportTests() throws(JSException)
2830
}
2931

@@ -84,6 +86,15 @@ final class OptionalSupportTests: XCTestCase {
8486
func testRoundTripOptionalStringToStringDictionaryUndefined() throws {
8587
try roundTripTest(OptionalSupportImports.jsRoundTripOptionalStringToStringDictionaryUndefined, ["key": "value"])
8688
}
89+
90+
func testRoundTripOptionalJSObjectNull() throws {
91+
try XCTAssertNil(OptionalSupportImports.jsRoundTripOptionalJSObjectNull(nil))
92+
93+
let object = JSObject.global.Object.function!.new()
94+
object.testProp = "hello"
95+
let result = try OptionalSupportImports.jsRoundTripOptionalJSObjectNull(object)
96+
XCTAssertEqual(result?.testProp.string, "hello")
97+
}
8798
}
8899

89100
@JS enum OptionalSupportExports {

0 commit comments

Comments
 (0)