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
47 changes: 45 additions & 2 deletions Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,20 @@ struct IntrinsicJSFragment: Sendable {
printer.write("\(JSGlueVariableScope.reservedTmpRetF64s).push(\(payload2Var));")
}
printer.write("\(JSGlueVariableScope.reservedTmpRetInts).push(\(isSomeVar) ? 1 : 0);")
case .array(let elementType):
printer.write("if (\(isSomeVar)) {")
printer.indent {
let arrayLowerFragment = try! arrayLower(elementType: elementType)
let arrayCleanup = CodeFragmentPrinter()
let _ = arrayLowerFragment.printCode([value], scope, printer, arrayCleanup)
if !arrayCleanup.lines.isEmpty {
for line in arrayCleanup.lines {
printer.write(line)
}
}
}
printer.write("}")
printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(isSomeVar) ? 1 : 0);")
case .rawValueEnum(_, let rawType):
switch rawType {
case .string:
Expand Down Expand Up @@ -2613,7 +2627,23 @@ struct IntrinsicJSFragment: Sendable {
private static func stackLiftFragment(elementType: BridgeType) throws -> IntrinsicJSFragment {
switch elementType {
case .jsValue:
throw BridgeJSLinkError(message: "Array of JSValue is not supported yet")
return IntrinsicJSFragment(
parameters: [],
printCode: { _, scope, printer, cleanup in
registerJSValueHelpers(scope: scope)
let payload2Var = scope.variable("jsValuePayload2")
let payload1Var = scope.variable("jsValuePayload1")
let kindVar = scope.variable("jsValueKind")
printer.write("const \(payload2Var) = \(JSGlueVariableScope.reservedTmpRetF64s).pop();")
printer.write("const \(payload1Var) = \(JSGlueVariableScope.reservedTmpRetInts).pop();")
printer.write("const \(kindVar) = \(JSGlueVariableScope.reservedTmpRetInts).pop();")
let resultVar = scope.variable("jsValue")
printer.write(
"const \(resultVar) = \(jsValueLiftHelperName)(\(kindVar), \(payload1Var), \(payload2Var));"
)
return [resultVar]
}
)
case .string:
return IntrinsicJSFragment(
parameters: [],
Expand Down Expand Up @@ -2775,7 +2805,20 @@ struct IntrinsicJSFragment: Sendable {
private static func stackLowerFragment(elementType: BridgeType) throws -> IntrinsicJSFragment {
switch elementType {
case .jsValue:
throw BridgeJSLinkError(message: "Array of JSValue is not supported yet")
return IntrinsicJSFragment(
parameters: ["value"],
printCode: { arguments, scope, printer, cleanup in
registerJSValueHelpers(scope: scope)
let lowered = jsValueLower.printCode([arguments[0]], scope, printer, cleanup)
let kindVar = lowered[0]
let payload1Var = lowered[1]
let payload2Var = lowered[2]
printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(kindVar));")
printer.write("\(JSGlueVariableScope.reservedTmpParamInts).push(\(payload1Var));")
printer.write("\(JSGlueVariableScope.reservedTmpParamF64s).push(\(payload2Var));")
return []
}
)
case .string:
return IntrinsicJSFragment(
parameters: ["value"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
return value
}

@JS func roundTripJSValueArray(_ values: [JSValue]) -> [JSValue] {
return values
}

@JS func roundTripOptionalJSValueArray(_ values: [JSValue]?) -> [JSValue]? {
return values
}

@JS class JSValueHolder {
@JS var value: JSValue
@JS var optionalValue: JSValue?
Expand All @@ -30,3 +38,4 @@
}

@JSFunction func jsEchoJSValue(_ value: JSValue) throws(JSException) -> JSValue
@JSFunction func jsEchoJSValueArray(_ values: [JSValue]) throws(JSException) -> [JSValue]
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,82 @@
"_1" : "null"
}
}
},
{
"abiName" : "bjs_roundTripJSValueArray",
"effects" : {
"isAsync" : false,
"isStatic" : false,
"isThrows" : false
},
"name" : "roundTripJSValueArray",
"parameters" : [
{
"label" : "_",
"name" : "values",
"type" : {
"array" : {
"_0" : {
"jsValue" : {

}
}
}
}
}
],
"returnType" : {
"array" : {
"_0" : {
"jsValue" : {

}
}
}
}
},
{
"abiName" : "bjs_roundTripOptionalJSValueArray",
"effects" : {
"isAsync" : false,
"isStatic" : false,
"isThrows" : false
},
"name" : "roundTripOptionalJSValueArray",
"parameters" : [
{
"label" : "_",
"name" : "values",
"type" : {
"nullable" : {
"_0" : {
"array" : {
"_0" : {
"jsValue" : {

}
}
}
},
"_1" : "null"
}
}
}
],
"returnType" : {
"nullable" : {
"_0" : {
"array" : {
"_0" : {
"jsValue" : {

}
}
}
},
"_1" : "null"
}
}
}
],
"protocols" : [
Expand Down Expand Up @@ -261,6 +337,32 @@

}
}
},
{
"name" : "jsEchoJSValueArray",
"parameters" : [
{
"name" : "values",
"type" : {
"array" : {
"_0" : {
"jsValue" : {

}
}
}
}
}
],
"returnType" : {
"array" : {
"_0" : {
"jsValue" : {

}
}
}
}
}
],
"types" : [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,37 @@ public func _bjs_roundTripOptionalJSValue(_ valueIsSome: Int32, _ valueKind: Int
#endif
}

@_expose(wasm, "bjs_roundTripJSValueArray")
@_cdecl("bjs_roundTripJSValueArray")
public func _bjs_roundTripJSValueArray() -> Void {
#if arch(wasm32)
let ret = roundTripJSValueArray(_: [JSValue].bridgeJSLiftParameter())
ret.bridgeJSLowerReturn()
#else
fatalError("Only available on WebAssembly")
#endif
}

@_expose(wasm, "bjs_roundTripOptionalJSValueArray")
@_cdecl("bjs_roundTripOptionalJSValueArray")
public func _bjs_roundTripOptionalJSValueArray(_ values: Int32) -> Void {
#if arch(wasm32)
let ret = roundTripOptionalJSValueArray(_: {
if values == 0 {
return Optional<[JSValue]>.none
} else {
return [JSValue].bridgeJSLiftParameter()
}
}())
let __bjs_isSome_ret = ret != nil
if let __bjs_unwrapped_ret = ret {
__bjs_unwrapped_ret.bridgeJSLowerReturn()}
_swift_js_push_i32(__bjs_isSome_ret ? 1 : 0)
#else
fatalError("Only available on WebAssembly")
#endif
}

@_expose(wasm, "bjs_JSValueHolder_init")
@_cdecl("bjs_JSValueHolder_init")
public func _bjs_JSValueHolder_init(_ valueKind: Int32, _ valuePayload1: Int32, _ valuePayload2: Float64, _ optionalValueIsSome: Int32, _ optionalValueKind: Int32, _ optionalValuePayload1: Int32, _ optionalValuePayload2: Float64) -> UnsafeMutableRawPointer {
Expand Down Expand Up @@ -146,4 +177,22 @@ func _$jsEchoJSValue(_ value: JSValue) throws(JSException) -> JSValue {
throw error
}
return JSValue.bridgeJSLiftReturn()
}

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

func _$jsEchoJSValueArray(_ values: [JSValue]) throws(JSException) -> [JSValue] {
let _ = values.bridgeJSLowerParameter()
bjs_jsEchoJSValueArray()
if let error = _swift_js_take_exception() {
throw error
}
return [JSValue].bridgeJSLiftReturn()
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@ export type Exports = {
}
roundTripJSValue(value: any): any;
roundTripOptionalJSValue(value: any | null): any | null;
roundTripJSValueArray(values: any[]): any[];
roundTripOptionalJSValueArray(values: any[] | null): any[] | null;
}
export type Imports = {
jsEchoJSValue(value: any): any;
jsEchoJSValueArray(values: any[]): any[];
}
export function createInstantiator(options: {
imports: Imports;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,31 @@ export async function createInstantiator(options, swift) {
setException(error);
}
}
TestModule["bjs_jsEchoJSValueArray"] = function bjs_jsEchoJSValueArray() {
try {
const arrayLen = tmpRetInts.pop();
const arrayResult = [];
for (let i = 0; i < arrayLen; i++) {
const jsValuePayload2 = tmpRetF64s.pop();
const jsValuePayload1 = tmpRetInts.pop();
const jsValueKind = tmpRetInts.pop();
const jsValue = __bjs_jsValueLift(jsValueKind, jsValuePayload1, jsValuePayload2);
arrayResult.push(jsValue);
}
arrayResult.reverse();
let ret = imports.jsEchoJSValueArray(arrayResult);
const arrayCleanups = [];
for (const elem of ret) {
const [elemKind, elemPayload1, elemPayload2] = __bjs_jsValueLower(elem);
tmpParamInts.push(elemKind);
tmpParamInts.push(elemPayload1);
tmpParamF64s.push(elemPayload2);
}
tmpParamInts.push(ret.length);
} catch (error) {
setException(error);
}
}
},
setInstance: (i) => {
instance = i;
Expand Down Expand Up @@ -448,6 +473,64 @@ export async function createInstantiator(options, swift) {
}
return optResult;
},
roundTripJSValueArray: function bjs_roundTripJSValueArray(values) {
const arrayCleanups = [];
for (const elem of values) {
const [elemKind, elemPayload1, elemPayload2] = __bjs_jsValueLower(elem);
tmpParamInts.push(elemKind);
tmpParamInts.push(elemPayload1);
tmpParamF64s.push(elemPayload2);
}
tmpParamInts.push(values.length);
instance.exports.bjs_roundTripJSValueArray();
const arrayLen = tmpRetInts.pop();
const arrayResult = [];
for (let i = 0; i < arrayLen; i++) {
const jsValuePayload2 = tmpRetF64s.pop();
const jsValuePayload1 = tmpRetInts.pop();
const jsValueKind = tmpRetInts.pop();
const jsValue = __bjs_jsValueLift(jsValueKind, jsValuePayload1, jsValuePayload2);
arrayResult.push(jsValue);
}
arrayResult.reverse();
for (const cleanup of arrayCleanups) { cleanup(); }
return arrayResult;
},
roundTripOptionalJSValueArray: function bjs_roundTripOptionalJSValueArray(values) {
const isSome = values != null;
const valuesCleanups = [];
if (isSome) {
const arrayCleanups = [];
for (const elem of values) {
const [elemKind, elemPayload1, elemPayload2] = __bjs_jsValueLower(elem);
tmpParamInts.push(elemKind);
tmpParamInts.push(elemPayload1);
tmpParamF64s.push(elemPayload2);
}
tmpParamInts.push(values.length);
valuesCleanups.push(() => { for (const cleanup of arrayCleanups) { cleanup(); } });
}
instance.exports.bjs_roundTripOptionalJSValueArray(+isSome);
const isSome1 = tmpRetInts.pop();
let optResult;
if (isSome1) {
const arrayLen = tmpRetInts.pop();
const arrayResult = [];
for (let i = 0; i < arrayLen; i++) {
const jsValuePayload2 = tmpRetF64s.pop();
const jsValuePayload1 = tmpRetInts.pop();
const jsValueKind = tmpRetInts.pop();
const jsValue = __bjs_jsValueLift(jsValueKind, jsValuePayload1, jsValuePayload2);
arrayResult.push(jsValue);
}
arrayResult.reverse();
optResult = arrayResult;
} else {
optResult = null;
}
for (const cleanup of valuesCleanups) { cleanup(); }
return optResult;
},
};
_exports = exports;
return exports;
Expand Down
Loading