Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
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
14 changes: 2 additions & 12 deletions 14 Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift
Original file line number Diff line number Diff line change
Expand Up @@ -936,12 +936,7 @@ extension BridgeType {
let wasmType = rawType.wasmCoreType ?? .i32
return LoweringParameterInfo(loweredParameters: [("value", wasmType)])
case .associatedValueEnum:
switch context {
case .importTS:
throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports")
case .exportSwift:
return LoweringParameterInfo(loweredParameters: [("caseId", .i32)])
}
return LoweringParameterInfo(loweredParameters: [("caseId", .i32)])
case .swiftStruct:
switch context {
case .importTS:
Expand Down Expand Up @@ -1011,12 +1006,7 @@ extension BridgeType {
let wasmType = rawType.wasmCoreType ?? .i32
return LiftingReturnInfo(valueToLift: wasmType)
case .associatedValueEnum:
switch context {
case .importTS:
throw BridgeJSCoreError("Enum types are not yet supported in TypeScript imports")
case .exportSwift:
return LiftingReturnInfo(valueToLift: .i32)
}
return LiftingReturnInfo(valueToLift: .i32)
case .swiftStruct:
switch context {
case .importTS:
Expand Down
44 changes: 14 additions & 30 deletions 44 Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1422,27 +1422,19 @@ struct IntrinsicJSFragment: Sendable {
return try .optionalLiftParameter(wrappedType: wrappedType, kind: kind, context: context)
case .rawValueEnum(_, .string): return .stringLiftParameter
case .associatedValueEnum(let fullName):
switch context {
case .importTS:
throw BridgeJSLinkError(
message:
"Associated value enums are not supported to be passed as parameters to imported JS functions: \(fullName)"
)
case .exportSwift:
let base = fullName.components(separatedBy: ".").last ?? fullName
return IntrinsicJSFragment(
parameters: ["caseId"],
printCode: { arguments, context in
let (scope, printer) = (context.scope, context.printer)
let caseId = arguments[0]
let resultVar = scope.variable("enumValue")
printer.write(
"const \(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(caseId));"
)
return [resultVar]
}
)
}
let base = fullName.components(separatedBy: ".").last ?? fullName
return IntrinsicJSFragment(
parameters: ["caseId"],
printCode: { arguments, context in
let (scope, printer) = (context.scope, context.printer)
let caseId = arguments[0]
let resultVar = scope.variable("enumValue")
printer.write(
"const \(resultVar) = \(JSGlueVariableScope.reservedEnumHelpers).\(base).lift(\(caseId));"
)
return [resultVar]
}
)
case .swiftStruct(let fullName):
switch context {
case .importTS:
Expand Down Expand Up @@ -1502,15 +1494,7 @@ struct IntrinsicJSFragment: Sendable {
return try .optionalLowerReturn(wrappedType: wrappedType, kind: kind)
case .rawValueEnum(_, .string): return .stringLowerReturn
case .associatedValueEnum(let fullName):
switch context {
case .importTS:
throw BridgeJSLinkError(
message:
"Associated value enums are not supported to be returned from imported JS functions: \(fullName)"
)
case .exportSwift:
return associatedValueLowerReturn(fullName: fullName)
}
return associatedValueLowerReturn(fullName: fullName)
case .swiftStruct(let fullName):
switch context {
case .importTS:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1611,10 +1611,10 @@ extension BridgeType {
/// Whether a value of this type can be passed to a generated `Promise_resolve_<mangled>`
/// settlement helper, i.e. lowered through the imported-parameter ABI. Every `async`
/// exported return settles through `_bjs_makePromise`; the few types that cannot be lowered
/// (associated-value enums, protocols, namespace enums, and their compositions) are diagnosed.
/// (protocols, namespace enums, and their compositions) are diagnosed.
public var isAsyncResolvable: Bool {
switch self {
case .associatedValueEnum, .swiftProtocol, .namespaceEnum:
case .swiftProtocol, .namespaceEnum:
return false
case .nullable(let wrapped, _):
return wrapped.isAsyncResolvable
Expand Down
13 changes: 6 additions & 7 deletions 13 Plugins/BridgeJS/Tests/BridgeJSToolTests/DiagnosticsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -309,15 +309,14 @@ import Testing

@Test
func asyncReturnOfUnsupportedTypeIsDiagnosed() throws {
// An associated-value enum can be neither lowered through the imported-parameter ABI
// nor settled via `_bjs_makePromise`, so an async return of one must be diagnosed.
// Protocol existentials still can't be lowered through the imported-parameter ABI, so
// an async return of one must still be diagnosed.
let source = """
@JS enum Payload {
case text(String)
case number(Int)
@JS protocol PayloadDelegate {
func notify()
}
@JS func loadPayload() async -> Payload {
.number(1)
@JS func loadPayload() async -> PayloadDelegate {
fatalError()
}
"""
let swiftAPI = SwiftToSkeleton(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@JS enum AsyncPayloadResult {
case success(String)
case failure(Int)
case idle
}

@JS func asyncRoundTripAssociatedValueEnum(_ value: AsyncPayloadResult) async -> AsyncPayloadResult {
return value
}

@JS func asyncRoundTripOptionalAssociatedValueEnum(_ value: AsyncPayloadResult?) async -> AsyncPayloadResult? {
return value
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@JS enum PayloadSignal {
case start(String)
case stop(Int)
case idle
}

// Associated-value enums bridge as their `Int32` case ID plus stack payload in imported
// function parameters and return values.
@JSClass struct PayloadSignalControls {
@JSFunction func send(_ signal: PayloadSignal) throws(JSException)
@JSFunction func current() throws(JSException) -> PayloadSignal
@JSFunction static func roundTrip(_ signal: PayloadSignal) throws(JSException) -> PayloadSignal
@JSFunction func roundTripOptional(_ signal: PayloadSignal?) throws(JSException) -> PayloadSignal?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
{
"exported" : {
"classes" : [

],
"enums" : [
{
"cases" : [
{
"associatedValues" : [
{
"type" : {
"string" : {

}
}
}
],
"name" : "success"
},
{
"associatedValues" : [
{
"type" : {
"integer" : {
"_0" : {
"isSigned" : true,
"width" : "word"
}
}
}
}
],
"name" : "failure"
},
{
"associatedValues" : [

],
"name" : "idle"
}
],
"emitStyle" : "const",
"name" : "AsyncPayloadResult",
"staticMethods" : [

],
"staticProperties" : [

],
"swiftCallName" : "AsyncPayloadResult",
"tsFullPath" : "AsyncPayloadResult"
}
],
"exposeToGlobal" : false,
"functions" : [
{
"abiName" : "bjs_asyncRoundTripAssociatedValueEnum",
"effects" : {
"isAsync" : true,
"isStatic" : false,
"isThrows" : false
},
"name" : "asyncRoundTripAssociatedValueEnum",
"parameters" : [
{
"label" : "_",
"name" : "value",
"type" : {
"associatedValueEnum" : {
"_0" : "AsyncPayloadResult"
}
}
}
],
"returnType" : {
"associatedValueEnum" : {
"_0" : "AsyncPayloadResult"
}
}
},
{
"abiName" : "bjs_asyncRoundTripOptionalAssociatedValueEnum",
"effects" : {
"isAsync" : true,
"isStatic" : false,
"isThrows" : false
},
"name" : "asyncRoundTripOptionalAssociatedValueEnum",
"parameters" : [
{
"label" : "_",
"name" : "value",
"type" : {
"nullable" : {
"_0" : {
"associatedValueEnum" : {
"_0" : "AsyncPayloadResult"
}
},
"_1" : "null"
}
}
}
],
"returnType" : {
"nullable" : {
"_0" : {
"associatedValueEnum" : {
"_0" : "AsyncPayloadResult"
}
},
"_1" : "null"
}
}
}
],
"protocols" : [

],
"structs" : [

]
},
"moduleName" : "TestModule",
"usedExternalModules" : [

]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
extension AsyncPayloadResult: _BridgedSwiftAssociatedValueEnum {
@_spi(BridgeJS) @_transparent public static func bridgeJSStackPopPayload(_ caseId: Int32) -> AsyncPayloadResult {
switch caseId {
case 0:
return .success(String.bridgeJSStackPop())
case 1:
return .failure(Int.bridgeJSStackPop())
case 2:
return .idle
default:
fatalError("Unknown AsyncPayloadResult case ID: \(caseId)")
}
}

@_spi(BridgeJS) @_transparent public consuming func bridgeJSStackPushPayload() -> Int32 {
switch self {
case .success(let param0):
param0.bridgeJSStackPush()
return Int32(0)
case .failure(let param0):
param0.bridgeJSStackPush()
return Int32(1)
case .idle:
return Int32(2)
}
}
}

@_expose(wasm, "bjs_asyncRoundTripAssociatedValueEnum")
@_cdecl("bjs_asyncRoundTripAssociatedValueEnum")
public func _bjs_asyncRoundTripAssociatedValueEnum(_ value: Int32) -> Int32 {
#if arch(wasm32)
let _tmp_value = AsyncPayloadResult.bridgeJSLiftParameter(value)
return _bjs_makePromise(resolve: Promise_resolve_18AsyncPayloadResultO, reject: Promise_reject) {
return await asyncRoundTripAssociatedValueEnum(_: _tmp_value)
}
#else
fatalError("Only available on WebAssembly")
#endif
}

@_expose(wasm, "bjs_asyncRoundTripOptionalAssociatedValueEnum")
@_cdecl("bjs_asyncRoundTripOptionalAssociatedValueEnum")
public func _bjs_asyncRoundTripOptionalAssociatedValueEnum(_ valueIsSome: Int32, _ valueCaseId: Int32) -> Int32 {
#if arch(wasm32)
let _tmp_value = Optional<AsyncPayloadResult>.bridgeJSLiftParameter(valueIsSome, valueCaseId)
return _bjs_makePromise(resolve: Promise_resolve_Sq18AsyncPayloadResultO, reject: Promise_reject) {
return await asyncRoundTripOptionalAssociatedValueEnum(_: _tmp_value)
}
#else
fatalError("Only available on WebAssembly")
#endif
}

@JSFunction func Promise_reject(_ promise: JSObject, _ value: JSValue) throws(JSException)

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "promise_reject_TestModule")
fileprivate func promise_reject_TestModule_extern(_ promise: Int32, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void
#else
fileprivate func promise_reject_TestModule_extern(_ promise: Int32, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void {
fatalError("Only available on WebAssembly")
}
#endif
@inline(never) fileprivate func promise_reject_TestModule(_ promise: Int32, _ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64) -> Void {
return promise_reject_TestModule_extern(promise, valueKind, valuePayload1, valuePayload2)
}

func _$Promise_reject(_ promise: JSObject, _ value: JSValue) throws(JSException) -> Void {
let promiseValue = promise.bridgeJSLowerParameter()
let (valueKind, valuePayload1, valuePayload2) = value.bridgeJSLowerParameter()
promise_reject_TestModule(promiseValue, valueKind, valuePayload1, valuePayload2)
if let error = _swift_js_take_exception() { throw error }
}

@JSFunction func Promise_resolve_18AsyncPayloadResultO(_ promise: JSObject, _ value: AsyncPayloadResult) throws(JSException)

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_18AsyncPayloadResultO")
fileprivate func promise_resolve_TestModule_18AsyncPayloadResultO_extern(_ promise: Int32, _ value: Int32) -> Void
#else
fileprivate func promise_resolve_TestModule_18AsyncPayloadResultO_extern(_ promise: Int32, _ value: Int32) -> Void {
fatalError("Only available on WebAssembly")
}
#endif
@inline(never) fileprivate func promise_resolve_TestModule_18AsyncPayloadResultO(_ promise: Int32, _ value: Int32) -> Void {
return promise_resolve_TestModule_18AsyncPayloadResultO_extern(promise, value)
}

func _$Promise_resolve_18AsyncPayloadResultO(_ promise: JSObject, _ value: AsyncPayloadResult) throws(JSException) -> Void {
let promiseValue = promise.bridgeJSLowerParameter()
let valueCaseId = value.bridgeJSLowerParameter()
promise_resolve_TestModule_18AsyncPayloadResultO(promiseValue, valueCaseId)
if let error = _swift_js_take_exception() { throw error }
}

@JSFunction func Promise_resolve_Sq18AsyncPayloadResultO(_ promise: JSObject, _ value: Optional<AsyncPayloadResult>) throws(JSException)

#if arch(wasm32)
@_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_Sq18AsyncPayloadResultO")
fileprivate func promise_resolve_TestModule_Sq18AsyncPayloadResultO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueCaseId: Int32) -> Void
#else
fileprivate func promise_resolve_TestModule_Sq18AsyncPayloadResultO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueCaseId: Int32) -> Void {
fatalError("Only available on WebAssembly")
}
#endif
@inline(never) fileprivate func promise_resolve_TestModule_Sq18AsyncPayloadResultO(_ promise: Int32, _ valueIsSome: Int32, _ valueCaseId: Int32) -> Void {
return promise_resolve_TestModule_Sq18AsyncPayloadResultO_extern(promise, valueIsSome, valueCaseId)
}

func _$Promise_resolve_Sq18AsyncPayloadResultO(_ promise: JSObject, _ value: Optional<AsyncPayloadResult>) throws(JSException) -> Void {
let promiseValue = promise.bridgeJSLowerParameter()
let (valueIsSome, valueCaseId) = value.bridgeJSLowerParameter()
promise_resolve_TestModule_Sq18AsyncPayloadResultO(promiseValue, valueIsSome, valueCaseId)
if let error = _swift_js_take_exception() { throw error }
}
Loading
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.