◐ Shell
clean mode source ↗

Support JSString in BridgeJS interop by sliemeobn · Pull Request #700 · swiftwasm/JavaScriptKit

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