Skip to content
Open
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
15 changes: 12 additions & 3 deletions Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@ struct StackCodegen {
func liftExpression(for type: BridgeType) -> ExprSyntax {
switch type {
case .string, .int, .uint, .bool, .float, .double,
.jsObject(nil), .jsValue, .swiftStruct, .swiftHeapObject, .unsafePointer,
.jsObject(nil), .jsString, .jsValue, .swiftStruct, .swiftHeapObject, .unsafePointer,
.swiftProtocol, .caseEnum, .associatedValueEnum, .rawValueEnum, .array, .dictionary:
return "\(raw: type.swiftType).bridgeJSStackPop()"
case .jsObject(let className?):
Expand All @@ -751,7 +751,7 @@ struct StackCodegen {
private func liftNullableExpression(wrappedType: BridgeType, kind: JSOptionalKind) -> ExprSyntax {
let typeName = kind == .null ? "Optional" : "JSUndefinedOr"
switch wrappedType {
case .string, .int, .uint, .bool, .float, .double, .jsObject(nil), .jsValue,
case .string, .int, .uint, .bool, .float, .double, .jsObject(nil), .jsString, .jsValue,
.swiftStruct, .swiftHeapObject, .caseEnum, .associatedValueEnum, .rawValueEnum,
.array, .dictionary:
return "\(raw: typeName)<\(raw: wrappedType.swiftType)>.bridgeJSStackPop()"
Expand All @@ -775,7 +775,7 @@ struct StackCodegen {
) -> [CodeBlockItemSyntax] {
switch type {
case .string, .int, .uint, .bool, .float, .double, .jsValue,
.jsObject(nil), .swiftHeapObject, .unsafePointer, .closure,
.jsObject(nil), .jsString, .swiftHeapObject, .unsafePointer, .closure,
.caseEnum, .rawValueEnum, .associatedValueEnum, .swiftStruct, .nullable:
return ["\(raw: accessor).bridgeJSStackPush()"]
case .jsObject(_?):
Expand Down Expand Up @@ -1385,6 +1385,7 @@ extension BridgeType {
case .jsValue: return "JSValue"
case .jsObject(nil): return "JSObject"
case .jsObject(let name?): return name
case .jsString: return "JSString"
case .swiftHeapObject(let name): return name
case .unsafePointer(let ptr): return ptr.swiftType
case .swiftProtocol(let name): return "Any\(name)"
Expand Down Expand Up @@ -1431,6 +1432,7 @@ extension BridgeType {
static let double = LiftingIntrinsicInfo(parameters: [("value", .f64)])
static let string = LiftingIntrinsicInfo(parameters: [("bytes", .i32), ("length", .i32)])
static let jsObject = LiftingIntrinsicInfo(parameters: [("value", .i32)])
static let jsString = LiftingIntrinsicInfo(parameters: [("value", .i32)])
static let jsValue = LiftingIntrinsicInfo(parameters: [("kind", .i32), ("payload1", .i32), ("payload2", .f64)])
static let swiftHeapObject = LiftingIntrinsicInfo(parameters: [("value", .pointer)])
static let unsafePointer = LiftingIntrinsicInfo(parameters: [("pointer", .pointer)])
Expand All @@ -1449,11 +1451,14 @@ extension BridgeType {
case .double: return .double
case .string: return .string
case .jsObject: return .jsObject
case .jsString: return .jsString
case .jsValue: return .jsValue
case .swiftHeapObject: return .swiftHeapObject
case .unsafePointer: return .unsafePointer
case .swiftProtocol: return .jsObject
case .void: return .void
case .nullable(.jsString, _):
return .jsString
case .nullable(let wrappedType, _):
let wrappedInfo = try wrappedType.liftParameterInfo()
if wrappedInfo.parameters.isEmpty {
Expand Down Expand Up @@ -1487,6 +1492,7 @@ extension BridgeType {
static let double = LoweringIntrinsicInfo(returnType: .f64)
static let string = LoweringIntrinsicInfo(returnType: nil)
static let jsObject = LoweringIntrinsicInfo(returnType: .i32)
static let jsString = LoweringIntrinsicInfo(returnType: .i32)
static let jsValue = LoweringIntrinsicInfo(returnType: nil)
static let swiftHeapObject = LoweringIntrinsicInfo(returnType: .pointer)
static let unsafePointer = LoweringIntrinsicInfo(returnType: .pointer)
Expand All @@ -1507,11 +1513,14 @@ extension BridgeType {
case .double: return .double
case .string: return .string
case .jsObject: return .jsObject
case .jsString: return .jsString
case .jsValue: return .jsValue
case .swiftHeapObject: return .swiftHeapObject
case .unsafePointer: return .unsafePointer
case .swiftProtocol: return .jsObject
case .void: return .void
case .nullable(.jsString, _):
return .jsString
case .nullable: return .optional
case .caseEnum: return .caseEnum
case .rawValueEnum(_, let rawType):
Expand Down
4 changes: 4 additions & 0 deletions Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,7 @@ extension BridgeType {
case .double: return .double
case .string: return .string
case .jsObject: return .jsObject
case .jsString: return LoweringParameterInfo(loweredParameters: [("value", .i32)], useBorrowing: true)
case .jsValue: return .jsValue
case .void: return .void
case .closure:
Expand Down Expand Up @@ -848,6 +849,8 @@ extension BridgeType {
}
case .namespaceEnum:
throw BridgeJSCoreError("Namespace enums cannot be used as parameters")
case .nullable(.jsString, _):
return LoweringParameterInfo(loweredParameters: [("value", .i32)], useBorrowing: true)
case .nullable(let wrappedType, _):
let wrappedInfo = try wrappedType.loweringParameterInfo(context: context)
var params = [("isSome", WasmCoreType.i32)]
Expand Down Expand Up @@ -881,6 +884,7 @@ extension BridgeType {
case .double: return .double
case .string: return .string
case .jsObject: return .jsObject
case .jsString: return .jsObject
case .jsValue: return .jsValue
case .void: return .void
case .closure:
Expand Down
2 changes: 2 additions & 0 deletions Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3518,6 +3518,8 @@ extension BridgeType {
return "boolean"
case .jsObject(let name):
return name ?? "any"
case .jsString:
return "string"
case .jsValue:
return "any"
case .swiftHeapObject(let name):
Expand Down
137 changes: 134 additions & 3 deletions Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,15 @@ struct IntrinsicJSFragment: Sendable {
kind: JSOptionalKind,
context bridgeContext: BridgeContext = .importTS
) throws -> IntrinsicJSFragment {
if wrappedType == .jsString {
let innerFragment = try liftParameter(type: wrappedType, context: bridgeContext)
return sentinelOptionalLiftSingleValue(
wrappedType: wrappedType,
kind: kind,
innerFragment: { innerFragment }
)
}

if wrappedType.isSingleParamScalar {
let coerce = wrappedType.liftCoerce
return IntrinsicJSFragment(
Expand Down Expand Up @@ -716,6 +725,15 @@ struct IntrinsicJSFragment: Sendable {
wrappedType: BridgeType,
kind: JSOptionalKind
) throws -> IntrinsicJSFragment {
if wrappedType == .jsString {
let innerFragment = try lowerParameter(type: wrappedType)
return sentinelOptionalLowerSingleValue(
wrappedType: wrappedType,
kind: kind,
innerFragment: innerFragment
)
}

if wrappedType.isSingleParamScalar {
let wasmType = wrappedType.wasmParams[0].type
let coerce = wrappedType.lowerCoerce
Expand Down Expand Up @@ -807,6 +825,94 @@ struct IntrinsicJSFragment: Sendable {
)
}

private static func sentinelOptionalLiftSingleValue(
wrappedType: BridgeType,
kind: JSOptionalKind,
innerFragment: @escaping @Sendable () throws -> IntrinsicJSFragment
) -> IntrinsicJSFragment {
let sentinelLiteral = wrappedType.nilSentinel.jsLiteral
let absenceLiteral = kind.absenceLiteral
return IntrinsicJSFragment(
parameters: ["wrappedValue"],
printCode: { arguments, context in
let (scope, printer) = (context.scope, context.printer)
let wrappedValue = arguments[0]

let bufferPrinter = CodeFragmentPrinter()
let innerResults = try innerFragment().printCode(
[wrappedValue],
context.with(\.printer, bufferPrinter)
)
let innerExpr = innerResults.first ?? "undefined"

if bufferPrinter.lines.isEmpty {
return ["\(wrappedValue) === \(sentinelLiteral) ? \(absenceLiteral) : \(innerExpr)"]
}

let resultVar = scope.variable("optResult")
printer.write("let \(resultVar);")
printer.write("if (\(wrappedValue) === \(sentinelLiteral)) {")
printer.indent {
printer.write("\(resultVar) = \(absenceLiteral);")
}
printer.write("} else {")
printer.indent {
for line in bufferPrinter.lines {
printer.write(line)
}
printer.write("\(resultVar) = \(innerExpr);")
}
printer.write("}")
return [resultVar]
}
)
}

private static func sentinelOptionalLowerSingleValue(
wrappedType: BridgeType,
kind: JSOptionalKind,
innerFragment: IntrinsicJSFragment
) -> IntrinsicJSFragment {
let sentinelLiteral = wrappedType.nilSentinel.jsLiteral
return IntrinsicJSFragment(
parameters: ["value"],
printCode: { arguments, context in
let (scope, printer) = (context.scope, context.printer)
let value = arguments[0]
let isSomeVar = scope.variable("isSome")
let presenceExpr = kind.presenceCheck(value: value)
printer.write("const \(isSomeVar) = \(presenceExpr);")

let bufferPrinter = CodeFragmentPrinter()
let innerResults = try innerFragment.printCode(
[value],
context.with(\.printer, bufferPrinter)
)
let innerExpr = innerResults.first ?? sentinelLiteral

if bufferPrinter.lines.isEmpty {
return ["\(isSomeVar) ? \(innerExpr) : \(sentinelLiteral)"]
}

let resultVar = scope.variable("optResult")
printer.write("let \(resultVar);")
printer.write("if (\(isSomeVar)) {")
printer.indent {
for line in bufferPrinter.lines {
printer.write(line)
}
printer.write("\(resultVar) = \(innerExpr);")
}
printer.write("} else {")
printer.indent {
printer.write("\(resultVar) = \(sentinelLiteral);")
}
printer.write("}")
return [resultVar]
}
)
}

private static func optionalLiftReturnFromStorage(storage: String) -> IntrinsicJSFragment {
IntrinsicJSFragment(
parameters: [],
Expand Down Expand Up @@ -934,6 +1040,14 @@ struct IntrinsicJSFragment: Sendable {
wrappedType: BridgeType,
kind: JSOptionalKind
) -> IntrinsicJSFragment {
if wrappedType == .jsString {
return sentinelOptionalLiftSingleValue(
wrappedType: wrappedType,
kind: kind,
innerFragment: { try liftReturn(type: wrappedType) }
)
}

if let scalarKind = wrappedType.optionalScalarKind {
return optionalLiftReturnFromStorage(storage: scalarKind.storageName)
}
Expand Down Expand Up @@ -1068,6 +1182,15 @@ struct IntrinsicJSFragment: Sendable {
)
}

if wrappedType == .jsString {
let innerFragment = try lowerReturn(type: wrappedType, context: .exportSwift)
return sentinelOptionalLowerReturn(
wrappedType: wrappedType,
kind: kind,
innerFragment: innerFragment
)
}

if case .sideChannelReturn(let mode) = wrappedType.optionalConvention {
if mode == .none {
throw BridgeJSLinkError(
Expand Down Expand Up @@ -1249,6 +1372,7 @@ struct IntrinsicJSFragment: Sendable {
return .identity
case .string: return .stringLowerParameter
case .jsObject: return .jsObjectLowerParameter
case .jsString: return .jsObjectLowerParameter
case .jsValue: return .jsValueLower
case .swiftHeapObject: return .swiftHeapObjectLowerParameter
case .swiftProtocol: return .jsObjectLowerParameter
Expand Down Expand Up @@ -1299,6 +1423,7 @@ struct IntrinsicJSFragment: Sendable {
return .identity
case .string: return .stringLiftReturn
case .jsObject: return .jsObjectLiftReturn
case .jsString: return .jsObjectLiftReturn
case .jsValue: return .jsValueLift
case .swiftHeapObject(let name): return .swiftHeapObjectLiftReturn(name)
case .swiftProtocol: return .jsObjectLiftReturn
Expand Down Expand Up @@ -1348,6 +1473,7 @@ struct IntrinsicJSFragment: Sendable {
return .identity
case .string: return .stringLiftParameter
case .jsObject: return .jsObjectLiftParameter
case .jsString: return .jsObjectLiftParameter
case .jsValue: return .jsValueLiftParameter
case .swiftHeapObject(let name):
return .swiftHeapObjectLiftParameter(name)
Expand Down Expand Up @@ -1432,6 +1558,7 @@ struct IntrinsicJSFragment: Sendable {
return .identity
case .string: return .stringLowerReturn
case .jsObject: return .jsObjectLowerReturn
case .jsString: return .jsObjectLowerReturn
case .jsValue: return .jsValueLowerReturn(context: context)
case .swiftHeapObject: return .swiftHeapObjectLowerReturn
case .swiftProtocol: return .jsObjectLowerReturn
Expand Down Expand Up @@ -1986,7 +2113,7 @@ struct IntrinsicJSFragment: Sendable {
return [objVar]
}
)
case .jsObject, .swiftProtocol:
case .jsObject, .jsString, .swiftProtocol:
return IntrinsicJSFragment(
parameters: [],
printCode: { arguments, context in
Expand Down Expand Up @@ -2108,7 +2235,7 @@ struct IntrinsicJSFragment: Sendable {
return []
}
)
case .jsObject, .swiftProtocol:
case .jsObject, .jsString, .swiftProtocol:
return IntrinsicJSFragment(
parameters: ["value"],
printCode: { arguments, context in
Expand Down Expand Up @@ -2587,6 +2714,8 @@ private extension BridgeType {
return .sideChannelReturn(.storage)
case .jsObject:
return .sideChannelReturn(.retainedObject)
case .jsString:
return .sideChannelReturn(.retainedObject)
case .jsValue:
return .inlineFlag
case .swiftHeapObject:
Expand Down Expand Up @@ -2621,7 +2750,7 @@ private extension BridgeType {

var nilSentinel: NilSentinel {
switch self {
case .jsObject, .swiftProtocol:
case .jsObject, .jsString, .swiftProtocol:
return .i32(0)
case .swiftHeapObject:
return .pointer
Expand Down Expand Up @@ -2660,6 +2789,8 @@ private extension BridgeType {
return [("bytes", .i32), ("length", .i32)]
case .jsObject:
return [("value", .i32)]
case .jsString:
return [("value", .i32)]
case .jsValue:
return [("kind", .i32), ("payload1", .i32), ("payload2", .f64)]
case .swiftHeapObject:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ public enum JSOptionalKind: String, Codable, Equatable, Hashable, Sendable {
}

public enum BridgeType: Codable, Equatable, Hashable, Sendable {
case int, uint, float, double, string, bool, jsObject(String?), jsValue, swiftHeapObject(String), void
case int, uint, float, double, string, bool, jsObject(String?), jsString, jsValue, swiftHeapObject(String), void
case unsafePointer(UnsafePointerType)
indirect case nullable(BridgeType, JSOptionalKind)
indirect case array(BridgeType)
Expand Down Expand Up @@ -1074,6 +1074,8 @@ extension BridgeType {
self = .void
case "JSObject":
self = .jsObject(nil)
case "JSString":
self = .jsString
case "UnsafeRawPointer":
self = .unsafePointer(.init(kind: .unsafeRawPointer))
case "UnsafeMutableRawPointer":
Expand All @@ -1093,6 +1095,7 @@ extension BridgeType {
case .float: return .f32
case .double: return .f64
case .string: return nil
case .jsString: return .i32
case .jsObject: return .i32
case .jsValue: return nil
case .swiftHeapObject:
Expand Down Expand Up @@ -1143,6 +1146,7 @@ extension BridgeType {
case .float: return "Sf"
case .double: return "Sd"
case .string: return "SS"
case .jsString: return "8JSStringV"
case .bool: return "Sb"
case .void: return "y"
case .jsObject(let name):
Expand Down
Loading
Loading