Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 4 additions & 24 deletions Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift
Original file line number Diff line number Diff line change
Expand Up @@ -957,18 +957,8 @@ extension BridgeType {
return LoweringParameterInfo(loweredParameters: [("funcRef", .i32)])
case .unsafePointer:
return LoweringParameterInfo(loweredParameters: [("pointer", .pointer)])
case .swiftHeapObject(let className):
switch context {
case .importTS:
throw BridgeJSCoreError(
"""
swiftHeapObject '\(className)' is not supported in TypeScript imports.
Swift classes can only be used in @JS protocols where Swift owns the instance.
"""
)
case .exportSwift:
return LoweringParameterInfo(loweredParameters: [("pointer", .pointer)])
}
case .swiftHeapObject:
return LoweringParameterInfo(loweredParameters: [("pointer", .pointer)])
case .swiftProtocol:
throw BridgeJSCoreError("swiftProtocol is not supported in imported signatures")
case .caseEnum:
Expand Down Expand Up @@ -1038,18 +1028,8 @@ extension BridgeType {
return LiftingReturnInfo(valueToLift: .i32)
case .unsafePointer:
return LiftingReturnInfo(valueToLift: .pointer)
case .swiftHeapObject(let className):
switch context {
case .importTS:
throw BridgeJSCoreError(
"""
swiftHeapObject '\(className)' cannot be returned from imported TypeScript functions.
JavaScript cannot create Swift heap objects.
"""
)
case .exportSwift:
return LiftingReturnInfo(valueToLift: .pointer)
}
case .swiftHeapObject:
return LiftingReturnInfo(valueToLift: .pointer)
case .swiftProtocol:
throw BridgeJSCoreError("swiftProtocol is not supported in imported signatures")
case .caseEnum:
Expand Down
22 changes: 4 additions & 18 deletions Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ struct IntrinsicJSFragment: Sendable {
return IntrinsicJSFragment(
parameters: ["pointer"],
printCode: { arguments, scope, printer, cleanupCode in
return ["\(name).__construct(\(arguments[0]))"]
return ["_exports['\(name)'].__construct(\(arguments[0]))"]
}
)
}
Expand Down Expand Up @@ -1985,14 +1985,7 @@ struct IntrinsicJSFragment: Sendable {
case .jsValue: return .jsValueLiftParameter
case .unsafePointer: return .identity
case .swiftHeapObject(let name):
switch context {
case .importTS:
throw BridgeJSLinkError(
message: "swiftHeapObject '\(name)' can only be used in protocol exports, not in \(context)"
)
case .exportSwift:
return .swiftHeapObjectLiftParameter(name)
}
return .swiftHeapObjectLiftParameter(name)
case .swiftProtocol: return .jsObjectLiftParameter
case .void:
throw BridgeJSLinkError(
Expand Down Expand Up @@ -2074,15 +2067,8 @@ struct IntrinsicJSFragment: Sendable {
case .jsObject: return .jsObjectLowerReturn
case .jsValue: return .jsValueLowerReturn(context: context)
case .unsafePointer: return .identity
case .swiftHeapObject(let name):
switch context {
case .importTS:
throw BridgeJSLinkError(
message: "swiftHeapObject '\(name)' can only be used in protocol exports, not in \(context)"
)
case .exportSwift:
return .swiftHeapObjectLowerReturn
}
case .swiftHeapObject:
return .swiftHeapObjectLowerReturn
case .swiftProtocol: return .jsObjectLowerReturn
case .void: return .void
case .nullable(let wrappedType, let kind):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@

@JS public class PublicGreeter {}
@JS package class PackageGreeter {}

@JSFunction func jsRoundTripGreeter(greeter: Greeter) throws(JSException) -> Greeter
Original file line number Diff line number Diff line change
Expand Up @@ -141,5 +141,34 @@

]
},
"imported" : {
"children" : [
{
"functions" : [
{
"name" : "jsRoundTripGreeter",
"parameters" : [
{
"name" : "greeter",
"type" : {
"swiftHeapObject" : {
"_0" : "Greeter"
}
}
}
],
"returnType" : {
"swiftHeapObject" : {
"_0" : "Greeter"
}
}
}
],
"types" : [

]
}
]
},
"moduleName" : "TestModule"
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,22 @@ fileprivate func _bjs_PackageGreeter_wrap(_ pointer: UnsafeMutableRawPointer) ->
fileprivate func _bjs_PackageGreeter_wrap(_ pointer: UnsafeMutableRawPointer) -> Int32 {
fatalError("Only available on WebAssembly")
}
#endif
#endif

#if arch(wasm32)
@_extern(wasm, module: "TestModule", name: "bjs_jsRoundTripGreeter")
fileprivate func bjs_jsRoundTripGreeter(_ greeter: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer
#else
fileprivate func bjs_jsRoundTripGreeter(_ greeter: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer {
fatalError("Only available on WebAssembly")
}
#endif

func _$jsRoundTripGreeter(_ greeter: Greeter) throws(JSException) -> Greeter {
let greeterPointer = greeter.bridgeJSLowerParameter()
let ret = bjs_jsRoundTripGreeter(greeterPointer)
if let error = _swift_js_take_exception() {
throw error
}
return Greeter.bridgeJSLiftReturn(ret)
}
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ export async function createInstantiator(options, swift) {
}
TestModule["bjs_MyViewControllerDelegate_onHelperUpdated"] = function bjs_MyViewControllerDelegate_onHelperUpdated(self, helper) {
try {
swift.memory.getObject(self).onHelperUpdated(Helper.__construct(helper));
swift.memory.getObject(self).onHelperUpdated(_exports['Helper'].__construct(helper));
} catch (error) {
setException(error);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export type Exports = {
takeGreeter(greeter: Greeter): void;
}
export type Imports = {
jsRoundTripGreeter(greeter: Greeter): Greeter;
}
export function createInstantiator(options: {
imports: Imports;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export async function createInstantiator(options, swift) {
addImports: (importObject, importsContext) => {
bjs = {};
importObject["bjs"] = bjs;
const imports = options.getImports(importsContext);
bjs["swift_js_return_string"] = function(ptr, len) {
const bytes = new Uint8Array(memory.buffer, ptr, len);
tmpRetString = textDecoder.decode(bytes);
Expand Down Expand Up @@ -214,6 +215,16 @@ export async function createInstantiator(options, swift) {
const obj = PublicGreeter.__construct(pointer);
return swift.memory.retain(obj);
};
const TestModule = importObject["TestModule"] = importObject["TestModule"] || {};
TestModule["bjs_jsRoundTripGreeter"] = function bjs_jsRoundTripGreeter(greeter) {
try {
let ret = imports.jsRoundTripGreeter(_exports['Greeter'].__construct(greeter));
return ret.pointer;
} catch (error) {
setException(error);
return 0
}
}
},
setInstance: (i) => {
instance = i;
Expand Down
18 changes: 18 additions & 0 deletions Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10666,4 +10666,22 @@ func _$jsRoundTripOptionalStringUndefined(_ name: JSUndefinedOr<String>) throws(
throw error
}
return JSUndefinedOr<String>.bridgeJSLiftReturnFromSideChannel()
}

#if arch(wasm32)
@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_SwiftClassSupportImports_jsRoundTripGreeter_static")
fileprivate func bjs_SwiftClassSupportImports_jsRoundTripGreeter_static(_ greeter: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer
#else
fileprivate func bjs_SwiftClassSupportImports_jsRoundTripGreeter_static(_ greeter: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer {
fatalError("Only available on WebAssembly")
}
#endif

func _$SwiftClassSupportImports_jsRoundTripGreeter(_ greeter: Greeter) throws(JSException) -> Greeter {
let greeterPointer = greeter.bridgeJSLowerParameter()
let ret = bjs_SwiftClassSupportImports_jsRoundTripGreeter_static(greeterPointer)
if let error = _swift_js_take_exception() {
throw error
}
return Greeter.bridgeJSLiftReturn(ret)
}
39 changes: 39 additions & 0 deletions Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json
Original file line number Diff line number Diff line change
Expand Up @@ -15310,6 +15310,45 @@
"types" : [

]
},
{
"functions" : [

],
"types" : [
{
"getters" : [

],
"methods" : [

],
"name" : "SwiftClassSupportImports",
"setters" : [

],
"staticMethods" : [
{
"name" : "jsRoundTripGreeter",
"parameters" : [
{
"name" : "greeter",
"type" : {
"swiftHeapObject" : {
"_0" : "Greeter"
}
}
}
],
"returnType" : {
"swiftHeapObject" : {
"_0" : "Greeter"
}
}
}
]
}
]
}
]
},
Expand Down
10 changes: 10 additions & 0 deletions Tests/BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* @returns {import('../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Imports["SwiftClassSupportImports"]}
*/
export function getImports(importsContext) {
return {
jsRoundTripGreeter: (greeter) => {
return greeter;
},
};
}
13 changes: 13 additions & 0 deletions Tests/BridgeJSRuntimeTests/SwiftClassSupportTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import XCTest
@_spi(Experimental) import JavaScriptKit

@JSClass struct SwiftClassSupportImports {
@JSFunction static func jsRoundTripGreeter(_ greeter: Greeter) throws(JSException) -> Greeter
}

final class SwiftClassSupportTests: XCTestCase {
func testRoundTripGreeter() throws {
let greeter = try SwiftClassSupportImports.jsRoundTripGreeter(Greeter(name: "Hello"))
XCTAssertEqual(greeter.name, "Hello")
}
}
2 changes: 2 additions & 0 deletions Tests/prelude.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
import { ImportedFoo } from './BridgeJSRuntimeTests/JavaScript/Types.mjs';
import { runJsOptionalSupportTests } from './BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs';
import { getImports as getClosureSupportImports } from './BridgeJSRuntimeTests/JavaScript/ClosureSupportTests.mjs';
import { getImports as getSwiftClassSupportImports } from './BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs';

/** @type {import('../.build/plugins/PackageToJS/outputs/PackageTests/test.d.ts').SetupOptionsFn} */
export async function setupOptions(options, context) {
Expand Down Expand Up @@ -213,6 +214,7 @@ export async function setupOptions(options, context) {
runJsOptionalSupportTests(exports);
},
ClosureSupportImports: getClosureSupportImports(importsContext),
SwiftClassSupportImports: getSwiftClassSupportImports(importsContext),
};
},
addToCoreImports(importObject, importsContext) {
Expand Down