From da29eaa2d7a003f8064c4fc6b7c9a03e6f3e440c Mon Sep 17 00:00:00 2001 From: Simon Leeb <52261246+sliemeobn@users.noreply.github.com> Date: Sun, 4 Oct 2026 21:27:15 +0200 Subject: [PATCH 1/3] fast-pass string with native representation --- Benchmarks/Sources/Generated/BridgeJS.swift | 12 +- .../PlayBridgeJS/Generated/BridgeJS.swift | 12 +- Plugins/BridgeJS/README.md | 5 +- .../Sources/BridgeJSCore/ExportSwift.swift | 4 +- .../Sources/BridgeJSCore/ImportTS.swift | 2 +- .../Sources/BridgeJSLink/BridgeJSLink.swift | 104 ++- .../Sources/BridgeJSLink/JSGlueGen.swift | 13 +- .../BridgeJSCodegenTests/Alias.swift | 36 +- .../BridgeJSCodegenTests/Async.swift | 36 +- .../BridgeJSCodegenTests/AsyncImport.swift | 24 +- .../BridgeJSCodegenTests/EnumRawType.swift | 12 +- .../BridgeJSCodegenTests/GenericImports.swift | 24 +- .../BridgeJSCodegenTests/GlobalGetter.swift | 12 +- .../GlobalThisImports.swift | 36 +- .../BridgeJSCodegenTests/ImportArray.swift | 12 +- .../InvalidPropertyNames.swift | 60 +- .../BridgeJSCodegenTests/JSClass.swift | 36 +- .../JSImportBareModule.swift | 24 +- .../JSImportBareModuleFallback.swift | 14 +- .../BridgeJSCodegenTests/Optionals.swift | 62 +- .../BridgeJSCodegenTests/Protocol.swift | 62 +- .../StringParameter.swift | 24 +- .../BridgeJSCodegenTests/SwiftClosure.swift | 132 +-- .../SwiftClosureImports.swift | 48 +- .../__Snapshots__/BridgeJSLinkTests/Alias.js | 93 ++- .../BridgeJSLinkTests/AliasInClosure.js | 83 +- .../BridgeJSLinkTests/ArrayTypes.js | 81 +- .../__Snapshots__/BridgeJSLinkTests/Async.js | 93 ++- .../AsyncAssociatedValueEnum.js | 81 +- .../BridgeJSLinkTests/AsyncImport.js | 91 +- .../BridgeJSLinkTests/AsyncStaticImport.js | 83 +- .../BridgeJSLinkTests/ClassWithNestedTypes.js | 81 +- .../BridgeJSLinkTests/DefaultParameters.js | 81 +- .../BridgeJSLinkTests/DictionaryTypes.js | 81 +- .../BridgeJSLinkTests/DocComments.js | 81 +- .../BridgeJSLinkTests/EnumAlias.js | 81 +- .../BridgeJSLinkTests/EnumAssociatedValue.js | 81 +- .../EnumAssociatedValueImport.js | 81 +- .../BridgeJSLinkTests/EnumCase.js | 81 +- .../BridgeJSLinkTests/EnumCaseImport.js | 81 +- .../BridgeJSLinkTests/EnumNamespace.Global.js | 81 +- .../BridgeJSLinkTests/EnumNamespace.js | 81 +- .../BridgeJSLinkTests/EnumRawType.js | 85 +- .../BridgeJSLinkTests/ExtensionNestedTypes.js | 81 +- .../ExtensionOrderIndependence.js | 81 +- .../BridgeJSLinkTests/ExtensionScopeParity.js | 81 +- .../BridgeJSLinkTests/FixedWidthIntegers.js | 81 +- .../BridgeJSLinkTests/GenericImports.js | 89 +- .../BridgeJSLinkTests/GlobalGetter.js | 85 +- .../BridgeJSLinkTests/GlobalThisImports.js | 93 ++- .../IdentityModeClass.ConfigPointer.js | 81 +- .../IdentityModeClass.PerClass.js | 81 +- .../BridgeJSLinkTests/IdentityModeClass.js | 81 +- .../BridgeJSLinkTests/ImportArray.js | 85 +- .../ImportedTypeInExportedInterface.js | 81 +- .../BridgeJSLinkTests/InvalidPropertyNames.js | 101 ++- .../BridgeJSLinkTests/JSClass.js | 93 ++- .../JSClassStaticFunctions.js | 81 +- .../BridgeJSLinkTests/JSImportBareModule.js | 89 +- .../JSImportBareModuleFallback.js | 87 +- .../BridgeJSLinkTests/JSImportModule.js | 81 +- .../BridgeJSLinkTests/JSNameOverride.js | 81 +- .../BridgeJSLinkTests/JSNameTypes.js | 81 +- .../BridgeJSLinkTests/JSTypedArrayTypes.js | 81 +- .../BridgeJSLinkTests/JSValue.js | 81 +- .../BridgeJSLinkTests/MixedGlobal.js | 81 +- .../BridgeJSLinkTests/MixedModules.js | 81 +- .../BridgeJSLinkTests/MixedPrivate.js | 81 +- .../NamespacedClassSignature.js | 83 +- .../BridgeJSLinkTests/Namespaces.Global.js | 81 +- .../BridgeJSLinkTests/Namespaces.js | 81 +- .../BridgeJSLinkTests/NestedType.js | 81 +- .../NestedTypeNameCollision.js | 81 +- .../BridgeJSLinkTests/Optionals.js | 103 ++- .../BridgeJSLinkTests/PrimitiveParameters.js | 81 +- .../BridgeJSLinkTests/PrimitiveReturn.js | 81 +- .../BridgeJSLinkTests/PropertyTypes.js | 81 +- .../BridgeJSLinkTests/Protocol.js | 103 ++- .../BridgeJSLinkTests/ProtocolInClosure.js | 83 +- .../RelativeQualifiedTypes.js | 81 +- .../StaticFunctions.Global.js | 81 +- .../BridgeJSLinkTests/StaticFunctions.js | 81 +- .../StaticProperties.Global.js | 81 +- .../BridgeJSLinkTests/StaticProperties.js | 81 +- .../BridgeJSLinkTests/StringParameter.js | 89 +- .../BridgeJSLinkTests/StringReturn.js | 81 +- .../StructWithNestedTypes.js | 81 +- .../BridgeJSLinkTests/SwiftClass.js | 81 +- .../BridgeJSLinkTests/SwiftClosure.js | 127 ++- .../BridgeJSLinkTests/SwiftClosureImports.js | 99 ++- .../BridgeJSLinkTests/SwiftStruct.js | 81 +- .../BridgeJSLinkTests/SwiftStructImports.js | 81 +- .../SwiftTypedClosureAccess.js | 83 +- .../__Snapshots__/BridgeJSLinkTests/Throws.js | 81 +- .../BridgeJSLinkTests/UnsafePointer.js | 81 +- .../VoidParameterVoidReturn.js | 81 +- .../JavaScriptKit/BridgeJSIntrinsics.swift | 97 ++- .../Generated/BridgeJS.swift | 779 +++++++++++------- .../Generated/JavaScript/BridgeJS.json | 421 ++++++++++ .../JavaScript/StringABITests.mjs | 40 + .../BridgeJSRuntimeTests/StringABITests.swift | 62 ++ Tests/prelude.mjs | 8 + 102 files changed, 6825 insertions(+), 1458 deletions(-) create mode 100644 Tests/BridgeJSRuntimeTests/JavaScript/StringABITests.mjs create mode 100644 Tests/BridgeJSRuntimeTests/StringABITests.swift diff --git a/Benchmarks/Sources/Generated/BridgeJS.swift b/Benchmarks/Sources/Generated/BridgeJS.swift index 86f2516e6..fc46623f2 100644 --- a/Benchmarks/Sources/Generated/BridgeJS.swift +++ b/Benchmarks/Sources/Generated/BridgeJS.swift @@ -2429,20 +2429,20 @@ func _$benchmarkHelperNoopWithNumber(_ n: Double) throws(JSException) -> Void { #if arch(wasm32) @_extern(wasm, module: "Benchmarks", name: "bjs_benchmarkRunner") -fileprivate func bjs_benchmarkRunner_extern(_ nameBytes: Int32, _ nameLength: Int32, _ body: Int32) -> Void +fileprivate func bjs_benchmarkRunner_extern(_ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32, _ body: Int32) -> Void #else -fileprivate func bjs_benchmarkRunner_extern(_ nameBytes: Int32, _ nameLength: Int32, _ body: Int32) -> Void { +fileprivate func bjs_benchmarkRunner_extern(_ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32, _ body: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_benchmarkRunner(_ nameBytes: Int32, _ nameLength: Int32, _ body: Int32) -> Void { - return bjs_benchmarkRunner_extern(nameBytes, nameLength, body) +@inline(never) fileprivate func bjs_benchmarkRunner(_ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32, _ body: Int32) -> Void { + return bjs_benchmarkRunner_extern(nameWord0, nameWord1, nameWord2, body) } func _$benchmarkRunner(_ name: String, _ body: JSObject) throws(JSException) -> Void { - name.bridgeJSWithLoweredParameter { (nameBytes, nameLength) in + name.bridgeJSWithLoweredParameter { (nameWord0, nameWord1, nameWord2) in let bodyValue = body.bridgeJSLowerParameter() - bjs_benchmarkRunner(nameBytes, nameLength, bodyValue) + bjs_benchmarkRunner(nameWord0, nameWord1, nameWord2, bodyValue) } if let error = _swift_js_take_exception() { throw error diff --git a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.swift b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.swift index eed55bdea..ee8b1f436 100644 --- a/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.swift +++ b/Examples/PlayBridgeJS/Sources/PlayBridgeJS/Generated/BridgeJS.swift @@ -268,20 +268,20 @@ func _$createTS2Swift() throws(JSException) -> TS2Swift { #if arch(wasm32) @_extern(wasm, module: "PlayBridgeJS", name: "bjs_TS2Swift_convert") -fileprivate func bjs_TS2Swift_convert_extern(_ self: Int32, _ tsBytes: Int32, _ tsLength: Int32) -> Int32 +fileprivate func bjs_TS2Swift_convert_extern(_ self: Int32, _ tsWord0: Int32, _ tsWord1: Int32, _ tsWord2: Int32) -> Int32 #else -fileprivate func bjs_TS2Swift_convert_extern(_ self: Int32, _ tsBytes: Int32, _ tsLength: Int32) -> Int32 { +fileprivate func bjs_TS2Swift_convert_extern(_ self: Int32, _ tsWord0: Int32, _ tsWord1: Int32, _ tsWord2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_TS2Swift_convert(_ self: Int32, _ tsBytes: Int32, _ tsLength: Int32) -> Int32 { - return bjs_TS2Swift_convert_extern(self, tsBytes, tsLength) +@inline(never) fileprivate func bjs_TS2Swift_convert(_ self: Int32, _ tsWord0: Int32, _ tsWord1: Int32, _ tsWord2: Int32) -> Int32 { + return bjs_TS2Swift_convert_extern(self, tsWord0, tsWord1, tsWord2) } func _$TS2Swift_convert(_ self: JSObject, _ ts: String) throws(JSException) -> String { - let ret0 = ts.bridgeJSWithLoweredParameter { (tsBytes, tsLength) in + let ret0 = ts.bridgeJSWithLoweredParameter { (tsWord0, tsWord1, tsWord2) in let selfValue = self.bridgeJSLowerParameter() - let ret = bjs_TS2Swift_convert(selfValue, tsBytes, tsLength) + let ret = bjs_TS2Swift_convert(selfValue, tsWord0, tsWord1, tsWord2) return ret } let ret = ret0 diff --git a/Plugins/BridgeJS/README.md b/Plugins/BridgeJS/README.md index 0905695c5..4d93dc875 100644 --- a/Plugins/BridgeJS/README.md +++ b/Plugins/BridgeJS/README.md @@ -139,7 +139,8 @@ The ABI will not be stable, and not meant to be interposed by other tools. Parameter passing follows Wasm calling conventions, with custom handling for complex types: - **Primitives**: Passed directly as Wasm arguments (`i32`, `i64`, `f32`, `f64`) -- **Strings**: UTF-8 bytes stored in `swift.memory`, ID + length passed as Wasm arguments +- **Strings (JS → Swift)**: UTF-8 bytes stored in `swift.memory`, ID + length passed as Wasm arguments +- **Strings (Swift → JS)**: the wasm32 12-byte `String` layout passed as three `i32` words. JS fast-decodes small strings, caches large immortals by a 53-bit `ptr + len` pack when `len < 2**21`, and otherwise reads UTF-8 at `word1 + 20` (`nativeBias`). This layout is a Swift stdlib implementation detail and can change with the toolchain. - **Swift Classes**: Raw Swift heap pointer passed as `i32` - **JSObjects**: Object stored in `swift.memory.heap`, object ID passed as `i32` - **Structs/Arrays**: Fields/elements pushed to type-specific stacks, Swift pops in reverse order @@ -150,7 +151,7 @@ Parameter passing follows Wasm calling conventions, with custom handling for com Return values use direct Wasm returns for primitives, and imported intrinsic functions for complex types: - **Primitives**: Returned directly via Wasm return value -- **Strings**: Swift writes UTF-8 bytes to shared memory, JS decodes +- **Strings**: Swift passes the 12-byte `String` layout; JS decodes (small / immortal-cached / UTF-8) - **Swift Classes**: Pointer returned directly, JS wraps in `SwiftHeapObject` with `FinalizationRegistry` - **Structs/Arrays**: Swift pushes fields/elements to type-specific stacks, JS reconstructs diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift index 6b5d3ef76..df8c589ea 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ExportSwift.swift @@ -744,9 +744,7 @@ public class ExportSwift { /// public func _bjs_Greeter_greet(pointer: UnsafeMutableRawPointer) -> Void { /// let _self = Unmanaged.fromOpaque(pointer).takeUnretainedValue() /// var ret = _self.greet() - /// return ret.withUTF8 { ptr in - /// _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) - /// } + /// return ret.bridgeJSLowerReturn() /// } /// @_expose(wasm, "bjs_Greeter_deinit") /// @_cdecl("bjs_Greeter_deinit") diff --git a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift index 378fe2012..841c0409c 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSCore/ImportTS.swift @@ -927,7 +927,7 @@ extension BridgeType { static let float = LoweringParameterInfo(loweredParameters: [("value", .f32)]) static let double = LoweringParameterInfo(loweredParameters: [("value", .f64)]) static let string = LoweringParameterInfo( - loweredParameters: [("bytes", .i32), ("length", .i32)], + loweredParameters: [("word0", .i32), ("word1", .i32), ("word2", .i32)], useBorrowing: true ) static let jsObject = LoweringParameterInfo(loweredParameters: [("value", .i32)]) diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index 40b1c13c3..d12749e0e 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -313,12 +313,91 @@ public struct BridgeJSLink { return data } + /// Emits `decodeString`, including small-string helpers used only by it. + /// + /// The wasm32 12-byte Swift `String` layout is a standard-library + /// implementation detail, not a stable ABI. Small strings (`word2 & 0x2000`) + /// store up to 10 UTF-8 bytes inline. Large strings store the UTF-8 count in + /// `word0` and a storage pointer in `word1` already biased by `nativeBias` + /// (20), so UTF-8 starts at `word1 + 20`. Immortal large strings + /// (`word2 & 0x8000`) are cached by a 53-bit `ptr + len * 2**32` key when + /// `len < 2**21`; longer immortals skip the cache. + private func emitDecodeString(_ printer: CodeFragmentPrinter) { + printer.write( + multilineString: """ + \(JSGlueVariableScope.reservedDecodeString) = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return \(JSGlueVariableScope.reservedDecodeUTF8)(ptr, len); + const key = ptr + len * 0x100000000; + const cached = \(JSGlueVariableScope.reservedImmortalStrings).get(key); + if (cached !== undefined) return cached; + const value = \(JSGlueVariableScope.reservedDecodeUTF8)(ptr, len); + \(JSGlueVariableScope.reservedImmortalStrings).set(key, value); + return value; + }; + })(); + """ + ) + } + private func generateVariableDeclarations() -> [String] { var declarations: [String] = [ "let \(JSGlueVariableScope.reservedInstance);", "let \(JSGlueVariableScope.reservedMemory);", "let \(JSGlueVariableScope.reservedSetException);", "let \(JSGlueVariableScope.reservedDecodeString);", + "let \(JSGlueVariableScope.reservedDecodeUTF8);", + "const \(JSGlueVariableScope.reservedImmortalStrings) = new Map();", "const \(JSGlueVariableScope.reservedTextDecoder) = new TextDecoder(\"utf-8\");", "const \(JSGlueVariableScope.reservedTextEncoder) = new TextEncoder(\"utf-8\");", "let \(JSGlueVariableScope.reservedStorageToReturnString);", @@ -495,10 +574,10 @@ public struct BridgeJSLink { "const imports = options.getImports(importsContext);" ]) } - printer.write("bjs[\"swift_js_return_string\"] = function(ptr, len) {") + printer.write("bjs[\"swift_js_return_string\"] = function(word0, word1, word2) {") printer.indent { printer.write( - "\(JSGlueVariableScope.reservedStorageToReturnString) = \(JSGlueVariableScope.reservedDecodeString)(ptr, len);" + "\(JSGlueVariableScope.reservedStorageToReturnString) = \(JSGlueVariableScope.reservedDecodeString)(word0, word1, word2);" ) } printer.write("}") @@ -516,10 +595,10 @@ public struct BridgeJSLink { printer.write("bytes.set(source);") } printer.write("}") - printer.write("bjs[\"swift_js_make_js_string\"] = function(ptr, len) {") + printer.write("bjs[\"swift_js_make_js_string\"] = function(word0, word1, word2) {") printer.indent { printer.write( - "return \(JSGlueVariableScope.reservedSwift).\(JSGlueVariableScope.reservedMemory).retain(\(JSGlueVariableScope.reservedDecodeString)(ptr, len));" + "return \(JSGlueVariableScope.reservedSwift).\(JSGlueVariableScope.reservedMemory).retain(\(JSGlueVariableScope.reservedDecodeString)(word0, word1, word2));" ) } printer.write("}") @@ -566,9 +645,11 @@ public struct BridgeJSLink { printer.write("\(JSGlueVariableScope.reservedF64Stack).push(v);") } printer.write("}") - printer.write("bjs[\"swift_js_push_string\"] = function(ptr, len) {") + printer.write("bjs[\"swift_js_push_string\"] = function(word0, word1, word2) {") printer.indent { - printer.write("const value = \(JSGlueVariableScope.reservedDecodeString)(ptr, len);") + printer.write( + "const value = \(JSGlueVariableScope.reservedDecodeString)(word0, word1, word2);" + ) printer.write("\(JSGlueVariableScope.reservedStringStack).push(value);") } printer.write("}") @@ -732,7 +813,7 @@ public struct BridgeJSLink { printer.write("}") } printer.write("}") - printer.write("bjs[\"swift_js_return_optional_string\"] = function(isSome, ptr, len) {") + printer.write("bjs[\"swift_js_return_optional_string\"] = function(isSome, word0, word1, word2) {") printer.indent { printer.write("if (isSome === 0) {") printer.indent { @@ -741,7 +822,7 @@ public struct BridgeJSLink { printer.write("} else {") printer.indent { printer.write(lines: [ - "\(JSGlueVariableScope.reservedStorageToReturnString) = \(JSGlueVariableScope.reservedDecodeString)(ptr, len);" + "\(JSGlueVariableScope.reservedStorageToReturnString) = \(JSGlueVariableScope.reservedDecodeString)(word0, word1, word2);" ]) } printer.write("}") @@ -879,7 +960,7 @@ public struct BridgeJSLink { helperPrinter.write("let length = 0;") helperPrinter.write("while (bytes[length] !== 0) { length += 1; }") helperPrinter.write( - "const fileID = \(JSGlueVariableScope.reservedDecodeString)(state.file, length);" + "const fileID = \(JSGlueVariableScope.reservedDecodeUTF8)(state.file, length);" ) helperPrinter.write( "throw new Error(`Attempted to call a released JSTypedClosure created at ${fileID}:${state.line}`);" @@ -1295,13 +1376,14 @@ public struct BridgeJSLink { printer.nextLine() if sharedMemory { printer.write( - "\(JSGlueVariableScope.reservedDecodeString) = (ptr, len) => { const bytes = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, ptr >>> 0, len >>> 0).slice(); return \(JSGlueVariableScope.reservedTextDecoder).decode(bytes); }" + "\(JSGlueVariableScope.reservedDecodeUTF8) = (ptr, len) => { const bytes = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, ptr >>> 0, len >>> 0).slice(); return \(JSGlueVariableScope.reservedTextDecoder).decode(bytes); }" ) } else { printer.write( - "\(JSGlueVariableScope.reservedDecodeString) = (ptr, len) => { const bytes = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, ptr >>> 0, len >>> 0); return \(JSGlueVariableScope.reservedTextDecoder).decode(bytes); }" + "\(JSGlueVariableScope.reservedDecodeUTF8) = (ptr, len) => { const bytes = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, ptr >>> 0, len >>> 0); return \(JSGlueVariableScope.reservedTextDecoder).decode(bytes); }" ) } + emitDecodeString(printer) printer.nextLine() // Error handling printer.write("\(JSGlueVariableScope.reservedSetException) = (error) => {") diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index 747c9f532..2da07f2be 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -14,6 +14,8 @@ final class JSGlueVariableScope { static let reservedMemory = "memory" static let reservedSetException = "setException" static let reservedDecodeString = "decodeString" + static let reservedDecodeUTF8 = "decodeUTF8" + static let reservedImmortalStrings = "immortalStrings" static let reservedStorageToReturnString = "tmpRetString" static let reservedStorageToReturnBytes = "tmpRetBytes" static let reservedStorageToReturnException = "tmpRetException" @@ -49,6 +51,8 @@ final class JSGlueVariableScope { reservedMemory, reservedSetException, reservedDecodeString, + reservedDecodeUTF8, + reservedImmortalStrings, reservedStorageToReturnString, reservedStorageToReturnBytes, reservedStorageToReturnException, @@ -678,14 +682,15 @@ struct IntrinsicJSFragment: Sendable { } ) static let stringLiftParameter = IntrinsicJSFragment( - parameters: ["bytes", "count"], + parameters: ["word0", "word1", "word2"], printCode: { arguments, context in let (scope, printer) = (context.scope, context.printer) - let bytesExpr = arguments[0] - let countExpr = arguments[1] + let word0Expr = arguments[0] + let word1Expr = arguments[1] + let word2Expr = arguments[2] let stringLabel = scope.variable("string") printer.write( - "const \(stringLabel) = \(JSGlueVariableScope.reservedDecodeString)(\(bytesExpr), \(countExpr));" + "const \(stringLabel) = \(JSGlueVariableScope.reservedDecodeString)(\(word0Expr), \(word1Expr), \(word2Expr));" ) return [stringLabel] } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Alias.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Alias.swift index 2529f22d3..7f8b3750d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Alias.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Alias.swift @@ -297,19 +297,19 @@ extension UserId: _BridgedSwiftAlias, _BridgedSwiftStackType {} #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_acceptTagged") -fileprivate func bjs_acceptTagged_extern(_ taggedBytes: Int32, _ taggedLength: Int32) -> Void +fileprivate func bjs_acceptTagged_extern(_ taggedWord0: Int32, _ taggedWord1: Int32, _ taggedWord2: Int32) -> Void #else -fileprivate func bjs_acceptTagged_extern(_ taggedBytes: Int32, _ taggedLength: Int32) -> Void { +fileprivate func bjs_acceptTagged_extern(_ taggedWord0: Int32, _ taggedWord1: Int32, _ taggedWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_acceptTagged(_ taggedBytes: Int32, _ taggedLength: Int32) -> Void { - return bjs_acceptTagged_extern(taggedBytes, taggedLength) +@inline(never) fileprivate func bjs_acceptTagged(_ taggedWord0: Int32, _ taggedWord1: Int32, _ taggedWord2: Int32) -> Void { + return bjs_acceptTagged_extern(taggedWord0, taggedWord1, taggedWord2) } func _$acceptTagged(_ tagged: Tagged) throws(JSException) -> Void { - tagged.bridgeJSWithLoweredParameter { (taggedBytes, taggedLength) in - bjs_acceptTagged(taggedBytes, taggedLength) + tagged.bridgeJSWithLoweredParameter { (taggedWord0, taggedWord1, taggedWord2) in + bjs_acceptTagged(taggedWord0, taggedWord1, taggedWord2) } if let error = _swift_js_take_exception() { throw error @@ -318,19 +318,19 @@ func _$acceptTagged(_ tagged: Tagged) throws(JSException) -> Void { #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_acceptOptionalTagged") -fileprivate func bjs_acceptOptionalTagged_extern(_ taggedIsSome: Int32, _ taggedBytes: Int32, _ taggedLength: Int32) -> Void +fileprivate func bjs_acceptOptionalTagged_extern(_ taggedIsSome: Int32, _ taggedWord0: Int32, _ taggedWord1: Int32, _ taggedWord2: Int32) -> Void #else -fileprivate func bjs_acceptOptionalTagged_extern(_ taggedIsSome: Int32, _ taggedBytes: Int32, _ taggedLength: Int32) -> Void { +fileprivate func bjs_acceptOptionalTagged_extern(_ taggedIsSome: Int32, _ taggedWord0: Int32, _ taggedWord1: Int32, _ taggedWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_acceptOptionalTagged(_ taggedIsSome: Int32, _ taggedBytes: Int32, _ taggedLength: Int32) -> Void { - return bjs_acceptOptionalTagged_extern(taggedIsSome, taggedBytes, taggedLength) +@inline(never) fileprivate func bjs_acceptOptionalTagged(_ taggedIsSome: Int32, _ taggedWord0: Int32, _ taggedWord1: Int32, _ taggedWord2: Int32) -> Void { + return bjs_acceptOptionalTagged_extern(taggedIsSome, taggedWord0, taggedWord1, taggedWord2) } func _$acceptOptionalTagged(_ tagged: Optional) throws(JSException) -> Void { - tagged.bridgeJSWithLoweredParameter { (taggedIsSome, taggedBytes, taggedLength) in - bjs_acceptOptionalTagged(taggedIsSome, taggedBytes, taggedLength) + tagged.bridgeJSWithLoweredParameter { (taggedIsSome, taggedWord0, taggedWord1, taggedWord2) in + bjs_acceptOptionalTagged(taggedIsSome, taggedWord0, taggedWord1, taggedWord2) } if let error = _swift_js_take_exception() { throw error @@ -339,19 +339,19 @@ func _$acceptOptionalTagged(_ tagged: Optional) throws(JSException) -> V #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_roundtripTagged") -fileprivate func bjs_roundtripTagged_extern(_ taggedBytes: Int32, _ taggedLength: Int32) -> Int32 +fileprivate func bjs_roundtripTagged_extern(_ taggedWord0: Int32, _ taggedWord1: Int32, _ taggedWord2: Int32) -> Int32 #else -fileprivate func bjs_roundtripTagged_extern(_ taggedBytes: Int32, _ taggedLength: Int32) -> Int32 { +fileprivate func bjs_roundtripTagged_extern(_ taggedWord0: Int32, _ taggedWord1: Int32, _ taggedWord2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_roundtripTagged(_ taggedBytes: Int32, _ taggedLength: Int32) -> Int32 { - return bjs_roundtripTagged_extern(taggedBytes, taggedLength) +@inline(never) fileprivate func bjs_roundtripTagged(_ taggedWord0: Int32, _ taggedWord1: Int32, _ taggedWord2: Int32) -> Int32 { + return bjs_roundtripTagged_extern(taggedWord0, taggedWord1, taggedWord2) } func _$roundtripTagged(_ tagged: Tagged) throws(JSException) -> Tagged { - let ret0 = tagged.bridgeJSWithLoweredParameter { (taggedBytes, taggedLength) in - let ret = bjs_roundtripTagged(taggedBytes, taggedLength) + let ret0 = tagged.bridgeJSWithLoweredParameter { (taggedWord0, taggedWord1, taggedWord2) in + let ret = bjs_roundtripTagged(taggedWord0, taggedWord1, taggedWord2) return ret } let ret = ret0 diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Async.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Async.swift index ae03fc475..2d0143ea9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Async.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Async.swift @@ -423,20 +423,20 @@ func _$Promise_resolve_Si(_ promise: JSObject, _ value: Int) throws(JSException) #if arch(wasm32) @_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_SS") -fileprivate func promise_resolve_TestModule_SS_extern(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void +fileprivate func promise_resolve_TestModule_SS_extern(_ promise: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void #else -fileprivate func promise_resolve_TestModule_SS_extern(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { +fileprivate func promise_resolve_TestModule_SS_extern(_ promise: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func promise_resolve_TestModule_SS(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { - return promise_resolve_TestModule_SS_extern(promise, valueBytes, valueLength) +@inline(never) fileprivate func promise_resolve_TestModule_SS(_ promise: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { + return promise_resolve_TestModule_SS_extern(promise, valueWord0, valueWord1, valueWord2) } func _$Promise_resolve_SS(_ promise: JSObject, _ value: String) throws(JSException) -> Void { - value.bridgeJSWithLoweredParameter { (valueBytes, valueLength) in + value.bridgeJSWithLoweredParameter { (valueWord0, valueWord1, valueWord2) in let promiseValue = promise.bridgeJSLowerParameter() - promise_resolve_TestModule_SS(promiseValue, valueBytes, valueLength) + promise_resolve_TestModule_SS(promiseValue, valueWord0, valueWord1, valueWord2) } if let error = _swift_js_take_exception() { throw error } } @@ -571,20 +571,20 @@ func _$Promise_resolve_14AsyncDirectionO(_ promise: JSObject, _ value: AsyncDire #if arch(wasm32) @_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_10AsyncThemeO") -fileprivate func promise_resolve_TestModule_10AsyncThemeO_extern(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void +fileprivate func promise_resolve_TestModule_10AsyncThemeO_extern(_ promise: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void #else -fileprivate func promise_resolve_TestModule_10AsyncThemeO_extern(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { +fileprivate func promise_resolve_TestModule_10AsyncThemeO_extern(_ promise: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func promise_resolve_TestModule_10AsyncThemeO(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { - return promise_resolve_TestModule_10AsyncThemeO_extern(promise, valueBytes, valueLength) +@inline(never) fileprivate func promise_resolve_TestModule_10AsyncThemeO(_ promise: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { + return promise_resolve_TestModule_10AsyncThemeO_extern(promise, valueWord0, valueWord1, valueWord2) } func _$Promise_resolve_10AsyncThemeO(_ promise: JSObject, _ value: AsyncTheme) throws(JSException) -> Void { - value.bridgeJSWithLoweredParameter { (valueBytes, valueLength) in + value.bridgeJSWithLoweredParameter { (valueWord0, valueWord1, valueWord2) in let promiseValue = promise.bridgeJSLowerParameter() - promise_resolve_TestModule_10AsyncThemeO(promiseValue, valueBytes, valueLength) + promise_resolve_TestModule_10AsyncThemeO(promiseValue, valueWord0, valueWord1, valueWord2) } if let error = _swift_js_take_exception() { throw error } } @@ -614,20 +614,20 @@ func _$Promise_resolve_Sq14AsyncDirectionO(_ promise: JSObject, _ value: Optiona #if arch(wasm32) @_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_Sq10AsyncThemeO") -fileprivate func promise_resolve_TestModule_Sq10AsyncThemeO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void +fileprivate func promise_resolve_TestModule_Sq10AsyncThemeO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void #else -fileprivate func promise_resolve_TestModule_Sq10AsyncThemeO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { +fileprivate func promise_resolve_TestModule_Sq10AsyncThemeO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func promise_resolve_TestModule_Sq10AsyncThemeO(_ promise: Int32, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { - return promise_resolve_TestModule_Sq10AsyncThemeO_extern(promise, valueIsSome, valueBytes, valueLength) +@inline(never) fileprivate func promise_resolve_TestModule_Sq10AsyncThemeO(_ promise: Int32, _ valueIsSome: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { + return promise_resolve_TestModule_Sq10AsyncThemeO_extern(promise, valueIsSome, valueWord0, valueWord1, valueWord2) } func _$Promise_resolve_Sq10AsyncThemeO(_ promise: JSObject, _ value: Optional) throws(JSException) -> Void { - value.bridgeJSWithLoweredParameter { (valueIsSome, valueBytes, valueLength) in + value.bridgeJSWithLoweredParameter { (valueIsSome, valueWord0, valueWord1, valueWord2) in let promiseValue = promise.bridgeJSLowerParameter() - promise_resolve_TestModule_Sq10AsyncThemeO(promiseValue, valueIsSome, valueBytes, valueLength) + promise_resolve_TestModule_Sq10AsyncThemeO(promiseValue, valueIsSome, valueWord0, valueWord1, valueWord2) } if let error = _swift_js_take_exception() { throw error } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncImport.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncImport.swift index 509f79578..42cb4f52b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncImport.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/AsyncImport.swift @@ -124,14 +124,14 @@ public func _invoke_swift_closure_TestModule_10TestModules8JSObjectC_y(_ boxPtr: #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModulesSS_y") -fileprivate func invoke_js_callback_TestModule_10TestModulesSS_y_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void +fileprivate func invoke_js_callback_TestModule_10TestModulesSS_y_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void #else -fileprivate func invoke_js_callback_TestModule_10TestModulesSS_y_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { +fileprivate func invoke_js_callback_TestModule_10TestModulesSS_y_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModulesSS_y(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { - return invoke_js_callback_TestModule_10TestModulesSS_y_extern(callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModulesSS_y(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { + return invoke_js_callback_TestModule_10TestModulesSS_y_extern(callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -151,9 +151,9 @@ private enum _BJS_Closure_10TestModulesSS_y { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) - param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - invoke_js_callback_TestModule_10TestModulesSS_y(callbackValue, param0Bytes, param0Length) + invoke_js_callback_TestModule_10TestModulesSS_y(callbackValue, param0Word0, param0Word1, param0Word2) } #else fatalError("Only available on WebAssembly") @@ -479,14 +479,14 @@ func _$asyncRoundTripInt(_ v: Int) async throws(JSException) -> Int { #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_asyncRoundTripString") -fileprivate func bjs_asyncRoundTripString_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ vBytes: Int32, _ vLength: Int32) -> Void +fileprivate func bjs_asyncRoundTripString_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ vWord0: Int32, _ vWord1: Int32, _ vWord2: Int32) -> Void #else -fileprivate func bjs_asyncRoundTripString_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ vBytes: Int32, _ vLength: Int32) -> Void { +fileprivate func bjs_asyncRoundTripString_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ vWord0: Int32, _ vWord1: Int32, _ vWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_asyncRoundTripString(_ resolveRef: Int32, _ rejectRef: Int32, _ vBytes: Int32, _ vLength: Int32) -> Void { - return bjs_asyncRoundTripString_extern(resolveRef, rejectRef, vBytes, vLength) +@inline(never) fileprivate func bjs_asyncRoundTripString(_ resolveRef: Int32, _ rejectRef: Int32, _ vWord0: Int32, _ vWord1: Int32, _ vWord2: Int32) -> Void { + return bjs_asyncRoundTripString_extern(resolveRef, rejectRef, vWord0, vWord1, vWord2) } func _$asyncRoundTripString(_ v: String) async throws(JSException) -> String { @@ -495,8 +495,8 @@ func _$asyncRoundTripString(_ v: String) async throws(JSException) -> String { }, makeRejectClosure: { JSTypedClosure<(sending JSValue) -> Void>.sending($0) }) { resolveRef, rejectRef in - v.bridgeJSWithLoweredParameter { (vBytes, vLength) in - bjs_asyncRoundTripString(resolveRef, rejectRef, vBytes, vLength) + v.bridgeJSWithLoweredParameter { (vWord0, vWord1, vWord2) in + bjs_asyncRoundTripString(resolveRef, rejectRef, vWord0, vWord1, vWord2) } } return resolved diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumRawType.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumRawType.swift index 2cee26721..da2e3916f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumRawType.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/EnumRawType.swift @@ -528,19 +528,19 @@ extension Ratio: BridgedSwiftGenericBridgeable { #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_takesFeatureFlag") -fileprivate func bjs_takesFeatureFlag_extern(_ flagBytes: Int32, _ flagLength: Int32) -> Void +fileprivate func bjs_takesFeatureFlag_extern(_ flagWord0: Int32, _ flagWord1: Int32, _ flagWord2: Int32) -> Void #else -fileprivate func bjs_takesFeatureFlag_extern(_ flagBytes: Int32, _ flagLength: Int32) -> Void { +fileprivate func bjs_takesFeatureFlag_extern(_ flagWord0: Int32, _ flagWord1: Int32, _ flagWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_takesFeatureFlag(_ flagBytes: Int32, _ flagLength: Int32) -> Void { - return bjs_takesFeatureFlag_extern(flagBytes, flagLength) +@inline(never) fileprivate func bjs_takesFeatureFlag(_ flagWord0: Int32, _ flagWord1: Int32, _ flagWord2: Int32) -> Void { + return bjs_takesFeatureFlag_extern(flagWord0, flagWord1, flagWord2) } func _$takesFeatureFlag(_ flag: FeatureFlag) throws(JSException) -> Void { - flag.bridgeJSWithLoweredParameter { (flagBytes, flagLength) in - bjs_takesFeatureFlag(flagBytes, flagLength) + flag.bridgeJSWithLoweredParameter { (flagWord0, flagWord1, flagWord2) in + bjs_takesFeatureFlag(flagWord0, flagWord1, flagWord2) } if let error = _swift_js_take_exception() { throw error diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GenericImports.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GenericImports.swift index ecb1512cf..8a9a11197 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GenericImports.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GenericImports.swift @@ -321,19 +321,19 @@ func _$genericRoundTrip(_ value: T) throws(JSE #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_genericParse") -fileprivate func bjs_genericParse_extern(_ jsonBytes: Int32, _ jsonLength: Int32, _ _generic0TypeId: Int32) -> Void +fileprivate func bjs_genericParse_extern(_ jsonWord0: Int32, _ jsonWord1: Int32, _ jsonWord2: Int32, _ _generic0TypeId: Int32) -> Void #else -fileprivate func bjs_genericParse_extern(_ jsonBytes: Int32, _ jsonLength: Int32, _ _generic0TypeId: Int32) -> Void { +fileprivate func bjs_genericParse_extern(_ jsonWord0: Int32, _ jsonWord1: Int32, _ jsonWord2: Int32, _ _generic0TypeId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_genericParse(_ jsonBytes: Int32, _ jsonLength: Int32, _ _generic0TypeId: Int32) -> Void { - return bjs_genericParse_extern(jsonBytes, jsonLength, _generic0TypeId) +@inline(never) fileprivate func bjs_genericParse(_ jsonWord0: Int32, _ jsonWord1: Int32, _ jsonWord2: Int32, _ _generic0TypeId: Int32) -> Void { + return bjs_genericParse_extern(jsonWord0, jsonWord1, jsonWord2, _generic0TypeId) } func _$genericParse(_ json: String) throws(JSException) -> T { - json.bridgeJSWithLoweredParameter { (jsonBytes, jsonLength) in - bjs_genericParse(jsonBytes, jsonLength, T.bridgeJSTypeID) + json.bridgeJSWithLoweredParameter { (jsonWord0, jsonWord1, jsonWord2) in + bjs_genericParse(jsonWord0, jsonWord1, jsonWord2, T.bridgeJSTypeID) } if let error = _swift_js_take_exception() { throw error @@ -514,21 +514,21 @@ func _$constrainedComposition Int32 +fileprivate func bjs_GenericPairFactory_init_extern(_ tagWord0: Int32, _ tagWord1: Int32, _ tagWord2: Int32, _ _generic0TypeId: Int32, _ _generic1TypeId: Int32) -> Int32 #else -fileprivate func bjs_GenericPairFactory_init_extern(_ tagBytes: Int32, _ tagLength: Int32, _ _generic0TypeId: Int32, _ _generic1TypeId: Int32) -> Int32 { +fileprivate func bjs_GenericPairFactory_init_extern(_ tagWord0: Int32, _ tagWord1: Int32, _ tagWord2: Int32, _ _generic0TypeId: Int32, _ _generic1TypeId: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_GenericPairFactory_init(_ tagBytes: Int32, _ tagLength: Int32, _ _generic0TypeId: Int32, _ _generic1TypeId: Int32) -> Int32 { - return bjs_GenericPairFactory_init_extern(tagBytes, tagLength, _generic0TypeId, _generic1TypeId) +@inline(never) fileprivate func bjs_GenericPairFactory_init(_ tagWord0: Int32, _ tagWord1: Int32, _ tagWord2: Int32, _ _generic0TypeId: Int32, _ _generic1TypeId: Int32) -> Int32 { + return bjs_GenericPairFactory_init_extern(tagWord0, tagWord1, tagWord2, _generic0TypeId, _generic1TypeId) } func _$GenericPairFactory_init(_ tag: String, _ first: T, _ second: U) throws(JSException) -> JSObject { - let ret0 = tag.bridgeJSWithLoweredParameter { (tagBytes, tagLength) in + let ret0 = tag.bridgeJSWithLoweredParameter { (tagWord0, tagWord1, tagWord2) in second.bridgeJSStackPush() first.bridgeJSStackPush() - let ret = bjs_GenericPairFactory_init(tagBytes, tagLength, T.bridgeJSTypeID, U.bridgeJSTypeID) + let ret = bjs_GenericPairFactory_init(tagWord0, tagWord1, tagWord2, T.bridgeJSTypeID, U.bridgeJSTypeID) return ret } let ret = ret0 diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalGetter.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalGetter.swift index 68afce080..14d4b1907 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalGetter.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalGetter.swift @@ -20,20 +20,20 @@ func _$console_get() throws(JSException) -> JSConsole { #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_JSConsole_log") -fileprivate func bjs_JSConsole_log_extern(_ self: Int32, _ messageBytes: Int32, _ messageLength: Int32) -> Void +fileprivate func bjs_JSConsole_log_extern(_ self: Int32, _ messageWord0: Int32, _ messageWord1: Int32, _ messageWord2: Int32) -> Void #else -fileprivate func bjs_JSConsole_log_extern(_ self: Int32, _ messageBytes: Int32, _ messageLength: Int32) -> Void { +fileprivate func bjs_JSConsole_log_extern(_ self: Int32, _ messageWord0: Int32, _ messageWord1: Int32, _ messageWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_JSConsole_log(_ self: Int32, _ messageBytes: Int32, _ messageLength: Int32) -> Void { - return bjs_JSConsole_log_extern(self, messageBytes, messageLength) +@inline(never) fileprivate func bjs_JSConsole_log(_ self: Int32, _ messageWord0: Int32, _ messageWord1: Int32, _ messageWord2: Int32) -> Void { + return bjs_JSConsole_log_extern(self, messageWord0, messageWord1, messageWord2) } func _$JSConsole_log(_ self: JSObject, _ message: String) throws(JSException) -> Void { - message.bridgeJSWithLoweredParameter { (messageBytes, messageLength) in + message.bridgeJSWithLoweredParameter { (messageWord0, messageWord1, messageWord2) in let selfValue = self.bridgeJSLowerParameter() - bjs_JSConsole_log(selfValue, messageBytes, messageLength) + bjs_JSConsole_log(selfValue, messageWord0, messageWord1, messageWord2) } if let error = _swift_js_take_exception() { throw error diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalThisImports.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalThisImports.swift index 4ba7a26fe..896c4e36d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalThisImports.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/GlobalThisImports.swift @@ -20,19 +20,19 @@ func _$console_get() throws(JSException) -> JSConsole { #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_parseInt") -fileprivate func bjs_parseInt_extern(_ stringBytes: Int32, _ stringLength: Int32) -> Float64 +fileprivate func bjs_parseInt_extern(_ stringWord0: Int32, _ stringWord1: Int32, _ stringWord2: Int32) -> Float64 #else -fileprivate func bjs_parseInt_extern(_ stringBytes: Int32, _ stringLength: Int32) -> Float64 { +fileprivate func bjs_parseInt_extern(_ stringWord0: Int32, _ stringWord1: Int32, _ stringWord2: Int32) -> Float64 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_parseInt(_ stringBytes: Int32, _ stringLength: Int32) -> Float64 { - return bjs_parseInt_extern(stringBytes, stringLength) +@inline(never) fileprivate func bjs_parseInt(_ stringWord0: Int32, _ stringWord1: Int32, _ stringWord2: Int32) -> Float64 { + return bjs_parseInt_extern(stringWord0, stringWord1, stringWord2) } func _$parseInt(_ string: String) throws(JSException) -> Double { - let ret0 = string.bridgeJSWithLoweredParameter { (stringBytes, stringLength) in - let ret = bjs_parseInt(stringBytes, stringLength) + let ret0 = string.bridgeJSWithLoweredParameter { (stringWord0, stringWord1, stringWord2) in + let ret = bjs_parseInt(stringWord0, stringWord1, stringWord2) return ret } let ret = ret0 @@ -44,20 +44,20 @@ func _$parseInt(_ string: String) throws(JSException) -> Double { #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_JSConsole_log") -fileprivate func bjs_JSConsole_log_extern(_ self: Int32, _ messageBytes: Int32, _ messageLength: Int32) -> Void +fileprivate func bjs_JSConsole_log_extern(_ self: Int32, _ messageWord0: Int32, _ messageWord1: Int32, _ messageWord2: Int32) -> Void #else -fileprivate func bjs_JSConsole_log_extern(_ self: Int32, _ messageBytes: Int32, _ messageLength: Int32) -> Void { +fileprivate func bjs_JSConsole_log_extern(_ self: Int32, _ messageWord0: Int32, _ messageWord1: Int32, _ messageWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_JSConsole_log(_ self: Int32, _ messageBytes: Int32, _ messageLength: Int32) -> Void { - return bjs_JSConsole_log_extern(self, messageBytes, messageLength) +@inline(never) fileprivate func bjs_JSConsole_log(_ self: Int32, _ messageWord0: Int32, _ messageWord1: Int32, _ messageWord2: Int32) -> Void { + return bjs_JSConsole_log_extern(self, messageWord0, messageWord1, messageWord2) } func _$JSConsole_log(_ self: JSObject, _ message: String) throws(JSException) -> Void { - message.bridgeJSWithLoweredParameter { (messageBytes, messageLength) in + message.bridgeJSWithLoweredParameter { (messageWord0, messageWord1, messageWord2) in let selfValue = self.bridgeJSLowerParameter() - bjs_JSConsole_log(selfValue, messageBytes, messageLength) + bjs_JSConsole_log(selfValue, messageWord0, messageWord1, messageWord2) } if let error = _swift_js_take_exception() { throw error @@ -66,14 +66,14 @@ func _$JSConsole_log(_ self: JSObject, _ message: String) throws(JSException) -> #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_WebSocket_init") -fileprivate func bjs_WebSocket_init_extern(_ urlBytes: Int32, _ urlLength: Int32) -> Int32 +fileprivate func bjs_WebSocket_init_extern(_ urlWord0: Int32, _ urlWord1: Int32, _ urlWord2: Int32) -> Int32 #else -fileprivate func bjs_WebSocket_init_extern(_ urlBytes: Int32, _ urlLength: Int32) -> Int32 { +fileprivate func bjs_WebSocket_init_extern(_ urlWord0: Int32, _ urlWord1: Int32, _ urlWord2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_WebSocket_init(_ urlBytes: Int32, _ urlLength: Int32) -> Int32 { - return bjs_WebSocket_init_extern(urlBytes, urlLength) +@inline(never) fileprivate func bjs_WebSocket_init(_ urlWord0: Int32, _ urlWord1: Int32, _ urlWord2: Int32) -> Int32 { + return bjs_WebSocket_init_extern(urlWord0, urlWord1, urlWord2) } #if arch(wasm32) @@ -89,8 +89,8 @@ fileprivate func bjs_WebSocket_close_extern(_ self: Int32) -> Void { } func _$WebSocket_init(_ url: String) throws(JSException) -> JSObject { - let ret0 = url.bridgeJSWithLoweredParameter { (urlBytes, urlLength) in - let ret = bjs_WebSocket_init(urlBytes, urlLength) + let ret0 = url.bridgeJSWithLoweredParameter { (urlWord0, urlWord1, urlWord2) in + let ret = bjs_WebSocket_init(urlWord0, urlWord1, urlWord2) return ret } let ret = ret0 diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportArray.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportArray.swift index 12abbd1e6..a501dd2f5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportArray.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/ImportArray.swift @@ -63,21 +63,21 @@ func _$optionalArrayThenArray(_ a: Optional<[Int]>, _ b: [Int]) throws(JSExcepti #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_borrowedStringAroundStackParams") -fileprivate func bjs_borrowedStringAroundStackParams_extern(_ sBytes: Int32, _ sLength: Int32) -> Int32 +fileprivate func bjs_borrowedStringAroundStackParams_extern(_ sWord0: Int32, _ sWord1: Int32, _ sWord2: Int32) -> Int32 #else -fileprivate func bjs_borrowedStringAroundStackParams_extern(_ sBytes: Int32, _ sLength: Int32) -> Int32 { +fileprivate func bjs_borrowedStringAroundStackParams_extern(_ sWord0: Int32, _ sWord1: Int32, _ sWord2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_borrowedStringAroundStackParams(_ sBytes: Int32, _ sLength: Int32) -> Int32 { - return bjs_borrowedStringAroundStackParams_extern(sBytes, sLength) +@inline(never) fileprivate func bjs_borrowedStringAroundStackParams(_ sWord0: Int32, _ sWord1: Int32, _ sWord2: Int32) -> Int32 { + return bjs_borrowedStringAroundStackParams_extern(sWord0, sWord1, sWord2) } func _$borrowedStringAroundStackParams(_ s: String, _ a: Optional<[Int]>, _ b: [Int]) throws(JSException) -> Int { - let ret0 = s.bridgeJSWithLoweredParameter { (sBytes, sLength) in + let ret0 = s.bridgeJSWithLoweredParameter { (sWord0, sWord1, sWord2) in let _ = b.bridgeJSLowerParameter() let _ = a.bridgeJSLowerParameter() - let ret = bjs_borrowedStringAroundStackParams(sBytes, sLength) + let ret = bjs_borrowedStringAroundStackParams(sWord0, sWord1, sWord2) return ret } let ret = ret0 diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/InvalidPropertyNames.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/InvalidPropertyNames.swift index f82632737..3adaeb88f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/InvalidPropertyNames.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/InvalidPropertyNames.swift @@ -136,14 +136,14 @@ fileprivate func bjs_WeirdNaming_Any_get_extern(_ self: Int32) -> Int32 { #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_WeirdNaming_normalProperty_set") -fileprivate func bjs_WeirdNaming_normalProperty_set_extern(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void +fileprivate func bjs_WeirdNaming_normalProperty_set_extern(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void #else -fileprivate func bjs_WeirdNaming_normalProperty_set_extern(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { +fileprivate func bjs_WeirdNaming_normalProperty_set_extern(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_WeirdNaming_normalProperty_set(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { - return bjs_WeirdNaming_normalProperty_set_extern(self, newValueBytes, newValueLength) +@inline(never) fileprivate func bjs_WeirdNaming_normalProperty_set(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { + return bjs_WeirdNaming_normalProperty_set_extern(self, newValueWord0, newValueWord1, newValueWord2) } #if arch(wasm32) @@ -172,14 +172,14 @@ fileprivate func bjs_WeirdNaming__123invalidStart_set_extern(_ self: Int32, _ ne #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_WeirdNaming_property_with_spaces_set") -fileprivate func bjs_WeirdNaming_property_with_spaces_set_extern(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void +fileprivate func bjs_WeirdNaming_property_with_spaces_set_extern(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void #else -fileprivate func bjs_WeirdNaming_property_with_spaces_set_extern(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { +fileprivate func bjs_WeirdNaming_property_with_spaces_set_extern(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_WeirdNaming_property_with_spaces_set(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { - return bjs_WeirdNaming_property_with_spaces_set_extern(self, newValueBytes, newValueLength) +@inline(never) fileprivate func bjs_WeirdNaming_property_with_spaces_set(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { + return bjs_WeirdNaming_property_with_spaces_set_extern(self, newValueWord0, newValueWord1, newValueWord2) } #if arch(wasm32) @@ -196,38 +196,38 @@ fileprivate func bjs_WeirdNaming__specialChar_set_extern(_ self: Int32, _ newVal #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_WeirdNaming_constructor_set") -fileprivate func bjs_WeirdNaming_constructor_set_extern(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void +fileprivate func bjs_WeirdNaming_constructor_set_extern(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void #else -fileprivate func bjs_WeirdNaming_constructor_set_extern(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { +fileprivate func bjs_WeirdNaming_constructor_set_extern(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_WeirdNaming_constructor_set(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { - return bjs_WeirdNaming_constructor_set_extern(self, newValueBytes, newValueLength) +@inline(never) fileprivate func bjs_WeirdNaming_constructor_set(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { + return bjs_WeirdNaming_constructor_set_extern(self, newValueWord0, newValueWord1, newValueWord2) } #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_WeirdNaming_for_set") -fileprivate func bjs_WeirdNaming_for_set_extern(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void +fileprivate func bjs_WeirdNaming_for_set_extern(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void #else -fileprivate func bjs_WeirdNaming_for_set_extern(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { +fileprivate func bjs_WeirdNaming_for_set_extern(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_WeirdNaming_for_set(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { - return bjs_WeirdNaming_for_set_extern(self, newValueBytes, newValueLength) +@inline(never) fileprivate func bjs_WeirdNaming_for_set(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { + return bjs_WeirdNaming_for_set_extern(self, newValueWord0, newValueWord1, newValueWord2) } #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_WeirdNaming_any_set") -fileprivate func bjs_WeirdNaming_any_set_extern(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void +fileprivate func bjs_WeirdNaming_any_set_extern(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void #else -fileprivate func bjs_WeirdNaming_any_set_extern(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { +fileprivate func bjs_WeirdNaming_any_set_extern(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_WeirdNaming_any_set(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { - return bjs_WeirdNaming_any_set_extern(self, newValueBytes, newValueLength) +@inline(never) fileprivate func bjs_WeirdNaming_any_set(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { + return bjs_WeirdNaming_any_set_extern(self, newValueWord0, newValueWord1, newValueWord2) } #if arch(wasm32) @@ -327,9 +327,9 @@ func _$WeirdNaming_Any_get(_ self: JSObject) throws(JSException) -> String { } func _$WeirdNaming_normalProperty_set(_ self: JSObject, _ newValue: String) throws(JSException) -> Void { - newValue.bridgeJSWithLoweredParameter { (newValueBytes, newValueLength) in + newValue.bridgeJSWithLoweredParameter { (newValueWord0, newValueWord1, newValueWord2) in let selfValue = self.bridgeJSLowerParameter() - bjs_WeirdNaming_normalProperty_set(selfValue, newValueBytes, newValueLength) + bjs_WeirdNaming_normalProperty_set(selfValue, newValueWord0, newValueWord1, newValueWord2) } if let error = _swift_js_take_exception() { throw error @@ -355,9 +355,9 @@ func _$WeirdNaming__123invalidStart_set(_ self: JSObject, _ newValue: Bool) thro } func _$WeirdNaming_property_with_spaces_set(_ self: JSObject, _ newValue: String) throws(JSException) -> Void { - newValue.bridgeJSWithLoweredParameter { (newValueBytes, newValueLength) in + newValue.bridgeJSWithLoweredParameter { (newValueWord0, newValueWord1, newValueWord2) in let selfValue = self.bridgeJSLowerParameter() - bjs_WeirdNaming_property_with_spaces_set(selfValue, newValueBytes, newValueLength) + bjs_WeirdNaming_property_with_spaces_set(selfValue, newValueWord0, newValueWord1, newValueWord2) } if let error = _swift_js_take_exception() { throw error @@ -374,9 +374,9 @@ func _$WeirdNaming__specialChar_set(_ self: JSObject, _ newValue: Double) throws } func _$WeirdNaming_constructor_set(_ self: JSObject, _ newValue: String) throws(JSException) -> Void { - newValue.bridgeJSWithLoweredParameter { (newValueBytes, newValueLength) in + newValue.bridgeJSWithLoweredParameter { (newValueWord0, newValueWord1, newValueWord2) in let selfValue = self.bridgeJSLowerParameter() - bjs_WeirdNaming_constructor_set(selfValue, newValueBytes, newValueLength) + bjs_WeirdNaming_constructor_set(selfValue, newValueWord0, newValueWord1, newValueWord2) } if let error = _swift_js_take_exception() { throw error @@ -384,9 +384,9 @@ func _$WeirdNaming_constructor_set(_ self: JSObject, _ newValue: String) throws( } func _$WeirdNaming_for_set(_ self: JSObject, _ newValue: String) throws(JSException) -> Void { - newValue.bridgeJSWithLoweredParameter { (newValueBytes, newValueLength) in + newValue.bridgeJSWithLoweredParameter { (newValueWord0, newValueWord1, newValueWord2) in let selfValue = self.bridgeJSLowerParameter() - bjs_WeirdNaming_for_set(selfValue, newValueBytes, newValueLength) + bjs_WeirdNaming_for_set(selfValue, newValueWord0, newValueWord1, newValueWord2) } if let error = _swift_js_take_exception() { throw error @@ -394,9 +394,9 @@ func _$WeirdNaming_for_set(_ self: JSObject, _ newValue: String) throws(JSExcept } func _$WeirdNaming_any_set(_ self: JSObject, _ newValue: String) throws(JSException) -> Void { - newValue.bridgeJSWithLoweredParameter { (newValueBytes, newValueLength) in + newValue.bridgeJSWithLoweredParameter { (newValueWord0, newValueWord1, newValueWord2) in let selfValue = self.bridgeJSLowerParameter() - bjs_WeirdNaming_any_set(selfValue, newValueBytes, newValueLength) + bjs_WeirdNaming_any_set(selfValue, newValueWord0, newValueWord1, newValueWord2) } if let error = _swift_js_take_exception() { throw error diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSClass.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSClass.swift index 37009f318..95e020b23 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSClass.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSClass.swift @@ -20,14 +20,14 @@ func _$returnAnimatable() throws(JSException) -> Animatable { #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_Greeter_init") -fileprivate func bjs_Greeter_init_extern(_ nameBytes: Int32, _ nameLength: Int32) -> Int32 +fileprivate func bjs_Greeter_init_extern(_ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32) -> Int32 #else -fileprivate func bjs_Greeter_init_extern(_ nameBytes: Int32, _ nameLength: Int32) -> Int32 { +fileprivate func bjs_Greeter_init_extern(_ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_Greeter_init(_ nameBytes: Int32, _ nameLength: Int32) -> Int32 { - return bjs_Greeter_init_extern(nameBytes, nameLength) +@inline(never) fileprivate func bjs_Greeter_init(_ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32) -> Int32 { + return bjs_Greeter_init_extern(nameWord0, nameWord1, nameWord2) } #if arch(wasm32) @@ -56,14 +56,14 @@ fileprivate func bjs_Greeter_age_get_extern(_ self: Int32) -> Float64 { #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_Greeter_name_set") -fileprivate func bjs_Greeter_name_set_extern(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void +fileprivate func bjs_Greeter_name_set_extern(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void #else -fileprivate func bjs_Greeter_name_set_extern(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { +fileprivate func bjs_Greeter_name_set_extern(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_Greeter_name_set(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { - return bjs_Greeter_name_set_extern(self, newValueBytes, newValueLength) +@inline(never) fileprivate func bjs_Greeter_name_set(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { + return bjs_Greeter_name_set_extern(self, newValueWord0, newValueWord1, newValueWord2) } #if arch(wasm32) @@ -80,19 +80,19 @@ fileprivate func bjs_Greeter_greet_extern(_ self: Int32) -> Int32 { #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_Greeter_changeName") -fileprivate func bjs_Greeter_changeName_extern(_ self: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void +fileprivate func bjs_Greeter_changeName_extern(_ self: Int32, _ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32) -> Void #else -fileprivate func bjs_Greeter_changeName_extern(_ self: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { +fileprivate func bjs_Greeter_changeName_extern(_ self: Int32, _ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_Greeter_changeName(_ self: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { - return bjs_Greeter_changeName_extern(self, nameBytes, nameLength) +@inline(never) fileprivate func bjs_Greeter_changeName(_ self: Int32, _ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32) -> Void { + return bjs_Greeter_changeName_extern(self, nameWord0, nameWord1, nameWord2) } func _$Greeter_init(_ name: String) throws(JSException) -> JSObject { - let ret0 = name.bridgeJSWithLoweredParameter { (nameBytes, nameLength) in - let ret = bjs_Greeter_init(nameBytes, nameLength) + let ret0 = name.bridgeJSWithLoweredParameter { (nameWord0, nameWord1, nameWord2) in + let ret = bjs_Greeter_init(nameWord0, nameWord1, nameWord2) return ret } let ret = ret0 @@ -121,9 +121,9 @@ func _$Greeter_age_get(_ self: JSObject) throws(JSException) -> Double { } func _$Greeter_name_set(_ self: JSObject, _ newValue: String) throws(JSException) -> Void { - newValue.bridgeJSWithLoweredParameter { (newValueBytes, newValueLength) in + newValue.bridgeJSWithLoweredParameter { (newValueWord0, newValueWord1, newValueWord2) in let selfValue = self.bridgeJSLowerParameter() - bjs_Greeter_name_set(selfValue, newValueBytes, newValueLength) + bjs_Greeter_name_set(selfValue, newValueWord0, newValueWord1, newValueWord2) } if let error = _swift_js_take_exception() { throw error @@ -140,9 +140,9 @@ func _$Greeter_greet(_ self: JSObject) throws(JSException) -> String { } func _$Greeter_changeName(_ self: JSObject, _ name: String) throws(JSException) -> Void { - name.bridgeJSWithLoweredParameter { (nameBytes, nameLength) in + name.bridgeJSWithLoweredParameter { (nameWord0, nameWord1, nameWord2) in let selfValue = self.bridgeJSLowerParameter() - bjs_Greeter_changeName(selfValue, nameBytes, nameLength) + bjs_Greeter_changeName(selfValue, nameWord0, nameWord1, nameWord2) } if let error = _swift_js_take_exception() { throw error diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSImportBareModule.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSImportBareModule.swift index 4baf8d0f0..69de3b2ff 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSImportBareModule.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSImportBareModule.swift @@ -40,19 +40,19 @@ func _$localDefaultExport_get() throws(JSException) -> JSObject { #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_nodeBasename") -fileprivate func bjs_nodeBasename_extern(_ pathBytes: Int32, _ pathLength: Int32) -> Int32 +fileprivate func bjs_nodeBasename_extern(_ pathWord0: Int32, _ pathWord1: Int32, _ pathWord2: Int32) -> Int32 #else -fileprivate func bjs_nodeBasename_extern(_ pathBytes: Int32, _ pathLength: Int32) -> Int32 { +fileprivate func bjs_nodeBasename_extern(_ pathWord0: Int32, _ pathWord1: Int32, _ pathWord2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_nodeBasename(_ pathBytes: Int32, _ pathLength: Int32) -> Int32 { - return bjs_nodeBasename_extern(pathBytes, pathLength) +@inline(never) fileprivate func bjs_nodeBasename(_ pathWord0: Int32, _ pathWord1: Int32, _ pathWord2: Int32) -> Int32 { + return bjs_nodeBasename_extern(pathWord0, pathWord1, pathWord2) } func _$nodeBasename(_ path: String) throws(JSException) -> String { - let ret0 = path.bridgeJSWithLoweredParameter { (pathBytes, pathLength) in - let ret = bjs_nodeBasename(pathBytes, pathLength) + let ret0 = path.bridgeJSWithLoweredParameter { (pathWord0, pathWord1, pathWord2) in + let ret = bjs_nodeBasename(pathWord0, pathWord1, pathWord2) return ret } let ret = ret0 @@ -64,19 +64,19 @@ func _$nodeBasename(_ path: String) throws(JSException) -> String { #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_nodeDirname") -fileprivate func bjs_nodeDirname_extern(_ pathBytes: Int32, _ pathLength: Int32) -> Int32 +fileprivate func bjs_nodeDirname_extern(_ pathWord0: Int32, _ pathWord1: Int32, _ pathWord2: Int32) -> Int32 #else -fileprivate func bjs_nodeDirname_extern(_ pathBytes: Int32, _ pathLength: Int32) -> Int32 { +fileprivate func bjs_nodeDirname_extern(_ pathWord0: Int32, _ pathWord1: Int32, _ pathWord2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_nodeDirname(_ pathBytes: Int32, _ pathLength: Int32) -> Int32 { - return bjs_nodeDirname_extern(pathBytes, pathLength) +@inline(never) fileprivate func bjs_nodeDirname(_ pathWord0: Int32, _ pathWord1: Int32, _ pathWord2: Int32) -> Int32 { + return bjs_nodeDirname_extern(pathWord0, pathWord1, pathWord2) } func _$nodeDirname(_ path: String) throws(JSException) -> String { - let ret0 = path.bridgeJSWithLoweredParameter { (pathBytes, pathLength) in - let ret = bjs_nodeDirname(pathBytes, pathLength) + let ret0 = path.bridgeJSWithLoweredParameter { (pathWord0, pathWord1, pathWord2) in + let ret = bjs_nodeDirname(pathWord0, pathWord1, pathWord2) return ret } let ret = ret0 diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSImportBareModuleFallback.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSImportBareModuleFallback.swift index 7780b5eb0..459130153 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSImportBareModuleFallback.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/JSImportBareModuleFallback.swift @@ -40,20 +40,20 @@ func _$kebabCaseFunction() throws(JSException) -> Int { #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_joinPaths") -fileprivate func bjs_joinPaths_extern(_ lhsBytes: Int32, _ lhsLength: Int32, _ rhsBytes: Int32, _ rhsLength: Int32) -> Int32 +fileprivate func bjs_joinPaths_extern(_ lhsWord0: Int32, _ lhsWord1: Int32, _ lhsWord2: Int32, _ rhsWord0: Int32, _ rhsWord1: Int32, _ rhsWord2: Int32) -> Int32 #else -fileprivate func bjs_joinPaths_extern(_ lhsBytes: Int32, _ lhsLength: Int32, _ rhsBytes: Int32, _ rhsLength: Int32) -> Int32 { +fileprivate func bjs_joinPaths_extern(_ lhsWord0: Int32, _ lhsWord1: Int32, _ lhsWord2: Int32, _ rhsWord0: Int32, _ rhsWord1: Int32, _ rhsWord2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_joinPaths(_ lhsBytes: Int32, _ lhsLength: Int32, _ rhsBytes: Int32, _ rhsLength: Int32) -> Int32 { - return bjs_joinPaths_extern(lhsBytes, lhsLength, rhsBytes, rhsLength) +@inline(never) fileprivate func bjs_joinPaths(_ lhsWord0: Int32, _ lhsWord1: Int32, _ lhsWord2: Int32, _ rhsWord0: Int32, _ rhsWord1: Int32, _ rhsWord2: Int32) -> Int32 { + return bjs_joinPaths_extern(lhsWord0, lhsWord1, lhsWord2, rhsWord0, rhsWord1, rhsWord2) } func _$joinPaths(_ lhs: String, _ rhs: String) throws(JSException) -> String { - let ret0 = lhs.bridgeJSWithLoweredParameter { (lhsBytes, lhsLength) in - let ret1 = rhs.bridgeJSWithLoweredParameter { (rhsBytes, rhsLength) in - let ret = bjs_joinPaths(lhsBytes, lhsLength, rhsBytes, rhsLength) + let ret0 = lhs.bridgeJSWithLoweredParameter { (lhsWord0, lhsWord1, lhsWord2) in + let ret1 = rhs.bridgeJSWithLoweredParameter { (rhsWord0, rhsWord1, rhsWord2) in + let ret = bjs_joinPaths(lhsWord0, lhsWord1, lhsWord2, rhsWord0, rhsWord1, rhsWord2) return ret } return ret1 diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Optionals.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Optionals.swift index f45a0bb1e..c35ea24e6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Optionals.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Optionals.swift @@ -484,14 +484,14 @@ fileprivate func _bjs_OptionalPropertyHolder_wrap_extern(_ pointer: UnsafeMutabl #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_init") -fileprivate func bjs_WithOptionalJSClass_init_extern(_ valueOrNullIsSome: Int32, _ valueOrNullBytes: Int32, _ valueOrNullLength: Int32, _ valueOrUndefinedIsSome: Int32, _ valueOrUndefinedBytes: Int32, _ valueOrUndefinedLength: Int32) -> Int32 +fileprivate func bjs_WithOptionalJSClass_init_extern(_ valueOrNullIsSome: Int32, _ valueOrNullWord0: Int32, _ valueOrNullWord1: Int32, _ valueOrNullWord2: Int32, _ valueOrUndefinedIsSome: Int32, _ valueOrUndefinedWord0: Int32, _ valueOrUndefinedWord1: Int32, _ valueOrUndefinedWord2: Int32) -> Int32 #else -fileprivate func bjs_WithOptionalJSClass_init_extern(_ valueOrNullIsSome: Int32, _ valueOrNullBytes: Int32, _ valueOrNullLength: Int32, _ valueOrUndefinedIsSome: Int32, _ valueOrUndefinedBytes: Int32, _ valueOrUndefinedLength: Int32) -> Int32 { +fileprivate func bjs_WithOptionalJSClass_init_extern(_ valueOrNullIsSome: Int32, _ valueOrNullWord0: Int32, _ valueOrNullWord1: Int32, _ valueOrNullWord2: Int32, _ valueOrUndefinedIsSome: Int32, _ valueOrUndefinedWord0: Int32, _ valueOrUndefinedWord1: Int32, _ valueOrUndefinedWord2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_WithOptionalJSClass_init(_ valueOrNullIsSome: Int32, _ valueOrNullBytes: Int32, _ valueOrNullLength: Int32, _ valueOrUndefinedIsSome: Int32, _ valueOrUndefinedBytes: Int32, _ valueOrUndefinedLength: Int32) -> Int32 { - return bjs_WithOptionalJSClass_init_extern(valueOrNullIsSome, valueOrNullBytes, valueOrNullLength, valueOrUndefinedIsSome, valueOrUndefinedBytes, valueOrUndefinedLength) +@inline(never) fileprivate func bjs_WithOptionalJSClass_init(_ valueOrNullIsSome: Int32, _ valueOrNullWord0: Int32, _ valueOrNullWord1: Int32, _ valueOrNullWord2: Int32, _ valueOrUndefinedIsSome: Int32, _ valueOrUndefinedWord0: Int32, _ valueOrUndefinedWord1: Int32, _ valueOrUndefinedWord2: Int32) -> Int32 { + return bjs_WithOptionalJSClass_init_extern(valueOrNullIsSome, valueOrNullWord0, valueOrNullWord1, valueOrNullWord2, valueOrUndefinedIsSome, valueOrUndefinedWord0, valueOrUndefinedWord1, valueOrUndefinedWord2) } #if arch(wasm32) @@ -604,26 +604,26 @@ fileprivate func bjs_WithOptionalJSClass_childOrNull_get_extern(_ self: Int32) - #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_stringOrNull_set") -fileprivate func bjs_WithOptionalJSClass_stringOrNull_set_extern(_ self: Int32, _ newValueIsSome: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void +fileprivate func bjs_WithOptionalJSClass_stringOrNull_set_extern(_ self: Int32, _ newValueIsSome: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void #else -fileprivate func bjs_WithOptionalJSClass_stringOrNull_set_extern(_ self: Int32, _ newValueIsSome: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { +fileprivate func bjs_WithOptionalJSClass_stringOrNull_set_extern(_ self: Int32, _ newValueIsSome: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_WithOptionalJSClass_stringOrNull_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { - return bjs_WithOptionalJSClass_stringOrNull_set_extern(self, newValueIsSome, newValueBytes, newValueLength) +@inline(never) fileprivate func bjs_WithOptionalJSClass_stringOrNull_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { + return bjs_WithOptionalJSClass_stringOrNull_set_extern(self, newValueIsSome, newValueWord0, newValueWord1, newValueWord2) } #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_stringOrUndefined_set") -fileprivate func bjs_WithOptionalJSClass_stringOrUndefined_set_extern(_ self: Int32, _ newValueIsSome: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void +fileprivate func bjs_WithOptionalJSClass_stringOrUndefined_set_extern(_ self: Int32, _ newValueIsSome: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void #else -fileprivate func bjs_WithOptionalJSClass_stringOrUndefined_set_extern(_ self: Int32, _ newValueIsSome: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { +fileprivate func bjs_WithOptionalJSClass_stringOrUndefined_set_extern(_ self: Int32, _ newValueIsSome: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_WithOptionalJSClass_stringOrUndefined_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { - return bjs_WithOptionalJSClass_stringOrUndefined_set_extern(self, newValueIsSome, newValueBytes, newValueLength) +@inline(never) fileprivate func bjs_WithOptionalJSClass_stringOrUndefined_set(_ self: Int32, _ newValueIsSome: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { + return bjs_WithOptionalJSClass_stringOrUndefined_set_extern(self, newValueIsSome, newValueWord0, newValueWord1, newValueWord2) } #if arch(wasm32) @@ -712,26 +712,26 @@ fileprivate func bjs_WithOptionalJSClass_childOrNull_set_extern(_ self: Int32, _ #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_roundTripStringOrNull") -fileprivate func bjs_WithOptionalJSClass_roundTripStringOrNull_extern(_ self: Int32, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void +fileprivate func bjs_WithOptionalJSClass_roundTripStringOrNull_extern(_ self: Int32, _ valueIsSome: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void #else -fileprivate func bjs_WithOptionalJSClass_roundTripStringOrNull_extern(_ self: Int32, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { +fileprivate func bjs_WithOptionalJSClass_roundTripStringOrNull_extern(_ self: Int32, _ valueIsSome: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_WithOptionalJSClass_roundTripStringOrNull(_ self: Int32, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { - return bjs_WithOptionalJSClass_roundTripStringOrNull_extern(self, valueIsSome, valueBytes, valueLength) +@inline(never) fileprivate func bjs_WithOptionalJSClass_roundTripStringOrNull(_ self: Int32, _ valueIsSome: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { + return bjs_WithOptionalJSClass_roundTripStringOrNull_extern(self, valueIsSome, valueWord0, valueWord1, valueWord2) } #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_WithOptionalJSClass_roundTripStringOrUndefined") -fileprivate func bjs_WithOptionalJSClass_roundTripStringOrUndefined_extern(_ self: Int32, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void +fileprivate func bjs_WithOptionalJSClass_roundTripStringOrUndefined_extern(_ self: Int32, _ valueIsSome: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void #else -fileprivate func bjs_WithOptionalJSClass_roundTripStringOrUndefined_extern(_ self: Int32, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { +fileprivate func bjs_WithOptionalJSClass_roundTripStringOrUndefined_extern(_ self: Int32, _ valueIsSome: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_WithOptionalJSClass_roundTripStringOrUndefined(_ self: Int32, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { - return bjs_WithOptionalJSClass_roundTripStringOrUndefined_extern(self, valueIsSome, valueBytes, valueLength) +@inline(never) fileprivate func bjs_WithOptionalJSClass_roundTripStringOrUndefined(_ self: Int32, _ valueIsSome: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { + return bjs_WithOptionalJSClass_roundTripStringOrUndefined_extern(self, valueIsSome, valueWord0, valueWord1, valueWord2) } #if arch(wasm32) @@ -819,9 +819,9 @@ fileprivate func bjs_WithOptionalJSClass_roundTripChildOrNull_extern(_ self: Int } func _$WithOptionalJSClass_init(_ valueOrNull: Optional, _ valueOrUndefined: JSUndefinedOr) throws(JSException) -> JSObject { - let ret0 = valueOrNull.bridgeJSWithLoweredParameter { (valueOrNullIsSome, valueOrNullBytes, valueOrNullLength) in - let ret1 = valueOrUndefined.bridgeJSWithLoweredParameter { (valueOrUndefinedIsSome, valueOrUndefinedBytes, valueOrUndefinedLength) in - let ret = bjs_WithOptionalJSClass_init(valueOrNullIsSome, valueOrNullBytes, valueOrNullLength, valueOrUndefinedIsSome, valueOrUndefinedBytes, valueOrUndefinedLength) + let ret0 = valueOrNull.bridgeJSWithLoweredParameter { (valueOrNullIsSome, valueOrNullWord0, valueOrNullWord1, valueOrNullWord2) in + let ret1 = valueOrUndefined.bridgeJSWithLoweredParameter { (valueOrUndefinedIsSome, valueOrUndefinedWord0, valueOrUndefinedWord1, valueOrUndefinedWord2) in + let ret = bjs_WithOptionalJSClass_init(valueOrNullIsSome, valueOrNullWord0, valueOrNullWord1, valueOrNullWord2, valueOrUndefinedIsSome, valueOrUndefinedWord0, valueOrUndefinedWord1, valueOrUndefinedWord2) return ret } return ret1 @@ -915,9 +915,9 @@ func _$WithOptionalJSClass_childOrNull_get(_ self: JSObject) throws(JSException) } func _$WithOptionalJSClass_stringOrNull_set(_ self: JSObject, _ newValue: Optional) throws(JSException) -> Void { - newValue.bridgeJSWithLoweredParameter { (newValueIsSome, newValueBytes, newValueLength) in + newValue.bridgeJSWithLoweredParameter { (newValueIsSome, newValueWord0, newValueWord1, newValueWord2) in let selfValue = self.bridgeJSLowerParameter() - bjs_WithOptionalJSClass_stringOrNull_set(selfValue, newValueIsSome, newValueBytes, newValueLength) + bjs_WithOptionalJSClass_stringOrNull_set(selfValue, newValueIsSome, newValueWord0, newValueWord1, newValueWord2) } if let error = _swift_js_take_exception() { throw error @@ -925,9 +925,9 @@ func _$WithOptionalJSClass_stringOrNull_set(_ self: JSObject, _ newValue: Option } func _$WithOptionalJSClass_stringOrUndefined_set(_ self: JSObject, _ newValue: JSUndefinedOr) throws(JSException) -> Void { - newValue.bridgeJSWithLoweredParameter { (newValueIsSome, newValueBytes, newValueLength) in + newValue.bridgeJSWithLoweredParameter { (newValueIsSome, newValueWord0, newValueWord1, newValueWord2) in let selfValue = self.bridgeJSLowerParameter() - bjs_WithOptionalJSClass_stringOrUndefined_set(selfValue, newValueIsSome, newValueBytes, newValueLength) + bjs_WithOptionalJSClass_stringOrUndefined_set(selfValue, newValueIsSome, newValueWord0, newValueWord1, newValueWord2) } if let error = _swift_js_take_exception() { throw error @@ -998,9 +998,9 @@ func _$WithOptionalJSClass_childOrNull_set(_ self: JSObject, _ newValue: Optiona } func _$WithOptionalJSClass_roundTripStringOrNull(_ self: JSObject, _ value: Optional) throws(JSException) -> Optional { - value.bridgeJSWithLoweredParameter { (valueIsSome, valueBytes, valueLength) in + value.bridgeJSWithLoweredParameter { (valueIsSome, valueWord0, valueWord1, valueWord2) in let selfValue = self.bridgeJSLowerParameter() - bjs_WithOptionalJSClass_roundTripStringOrNull(selfValue, valueIsSome, valueBytes, valueLength) + bjs_WithOptionalJSClass_roundTripStringOrNull(selfValue, valueIsSome, valueWord0, valueWord1, valueWord2) } if let error = _swift_js_take_exception() { throw error @@ -1009,9 +1009,9 @@ func _$WithOptionalJSClass_roundTripStringOrNull(_ self: JSObject, _ value: Opti } func _$WithOptionalJSClass_roundTripStringOrUndefined(_ self: JSObject, _ value: JSUndefinedOr) throws(JSException) -> JSUndefinedOr { - value.bridgeJSWithLoweredParameter { (valueIsSome, valueBytes, valueLength) in + value.bridgeJSWithLoweredParameter { (valueIsSome, valueWord0, valueWord1, valueWord2) in let selfValue = self.bridgeJSLowerParameter() - bjs_WithOptionalJSClass_roundTripStringOrUndefined(selfValue, valueIsSome, valueBytes, valueLength) + bjs_WithOptionalJSClass_roundTripStringOrUndefined(selfValue, valueIsSome, valueWord0, valueWord1, valueWord2) } if let error = _swift_js_take_exception() { throw error diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift index ec3d2f65a..a91524da5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/Protocol.swift @@ -5,9 +5,9 @@ extension MyViewControllerDelegate where Self: _BridgedSwiftProtocolWrapper { } func onValueChanged(_ value: String) -> Void { - value.bridgeJSWithLoweredParameter { (valueBytes, valueLength) in + value.bridgeJSWithLoweredParameter { (valueWord0, valueWord1, valueWord2) in let jsObjectValue = jsObject.bridgeJSLowerParameter() - bjs_MyViewControllerDelegate_onValueChanged(jsObjectValue, valueBytes, valueLength) + bjs_MyViewControllerDelegate_onValueChanged(jsObjectValue, valueWord0, valueWord1, valueWord2) } } @@ -19,10 +19,10 @@ extension MyViewControllerDelegate where Self: _BridgedSwiftProtocolWrapper { } func onLabelUpdated(_ prefix: String, _ suffix: String) -> Void { - prefix.bridgeJSWithLoweredParameter { (prefixBytes, prefixLength) in - suffix.bridgeJSWithLoweredParameter { (suffixBytes, suffixLength) in + prefix.bridgeJSWithLoweredParameter { (prefixWord0, prefixWord1, prefixWord2) in + suffix.bridgeJSWithLoweredParameter { (suffixWord0, suffixWord1, suffixWord2) in let jsObjectValue = jsObject.bridgeJSLowerParameter() - bjs_MyViewControllerDelegate_onLabelUpdated(jsObjectValue, prefixBytes, prefixLength, suffixBytes, suffixLength) + bjs_MyViewControllerDelegate_onLabelUpdated(jsObjectValue, prefixWord0, prefixWord1, prefixWord2, suffixWord0, suffixWord1, suffixWord2) } } } @@ -103,9 +103,9 @@ extension MyViewControllerDelegate where Self: _BridgedSwiftProtocolWrapper { return Optional.bridgeJSLiftReturnFromSideChannel() } set { - newValue.bridgeJSWithLoweredParameter { (newValueIsSome, newValueBytes, newValueLength) in + newValue.bridgeJSWithLoweredParameter { (newValueIsSome, newValueWord0, newValueWord1, newValueWord2) in let jsObjectValue = jsObject.bridgeJSLowerParameter() - bjs_MyViewControllerDelegate_optionalName_set(jsObjectValue, newValueIsSome, newValueBytes, newValueLength) + bjs_MyViewControllerDelegate_optionalName_set(jsObjectValue, newValueIsSome, newValueWord0, newValueWord1, newValueWord2) } } } @@ -117,9 +117,9 @@ extension MyViewControllerDelegate where Self: _BridgedSwiftProtocolWrapper { return Optional.bridgeJSLiftReturnFromSideChannel() } set { - newValue.bridgeJSWithLoweredParameter { (newValueIsSome, newValueBytes, newValueLength) in + newValue.bridgeJSWithLoweredParameter { (newValueIsSome, newValueWord0, newValueWord1, newValueWord2) in let jsObjectValue = jsObject.bridgeJSLowerParameter() - bjs_MyViewControllerDelegate_optionalRawEnum_set(jsObjectValue, newValueIsSome, newValueBytes, newValueLength) + bjs_MyViewControllerDelegate_optionalRawEnum_set(jsObjectValue, newValueIsSome, newValueWord0, newValueWord1, newValueWord2) } } } @@ -131,9 +131,9 @@ extension MyViewControllerDelegate where Self: _BridgedSwiftProtocolWrapper { return ExampleEnum.bridgeJSLiftReturn(ret) } set { - newValue.bridgeJSWithLoweredParameter { (newValueBytes, newValueLength) in + newValue.bridgeJSWithLoweredParameter { (newValueWord0, newValueWord1, newValueWord2) in let jsObjectValue = jsObject.bridgeJSLowerParameter() - bjs_MyViewControllerDelegate_rawStringEnum_set(jsObjectValue, newValueBytes, newValueLength) + bjs_MyViewControllerDelegate_rawStringEnum_set(jsObjectValue, newValueWord0, newValueWord1, newValueWord2) } } } @@ -239,14 +239,14 @@ fileprivate func bjs_MyViewControllerDelegate_onSomethingHappened_extern(_ jsObj #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_onValueChanged") -fileprivate func bjs_MyViewControllerDelegate_onValueChanged_extern(_ jsObject: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void +fileprivate func bjs_MyViewControllerDelegate_onValueChanged_extern(_ jsObject: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void #else -fileprivate func bjs_MyViewControllerDelegate_onValueChanged_extern(_ jsObject: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { +fileprivate func bjs_MyViewControllerDelegate_onValueChanged_extern(_ jsObject: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_MyViewControllerDelegate_onValueChanged(_ jsObject: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { - return bjs_MyViewControllerDelegate_onValueChanged_extern(jsObject, valueBytes, valueLength) +@inline(never) fileprivate func bjs_MyViewControllerDelegate_onValueChanged(_ jsObject: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { + return bjs_MyViewControllerDelegate_onValueChanged_extern(jsObject, valueWord0, valueWord1, valueWord2) } #if arch(wasm32) @@ -263,14 +263,14 @@ fileprivate func bjs_MyViewControllerDelegate_onCountUpdated_extern(_ jsObject: #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_onLabelUpdated") -fileprivate func bjs_MyViewControllerDelegate_onLabelUpdated_extern(_ jsObject: Int32, _ prefixBytes: Int32, _ prefixLength: Int32, _ suffixBytes: Int32, _ suffixLength: Int32) -> Void +fileprivate func bjs_MyViewControllerDelegate_onLabelUpdated_extern(_ jsObject: Int32, _ prefixWord0: Int32, _ prefixWord1: Int32, _ prefixWord2: Int32, _ suffixWord0: Int32, _ suffixWord1: Int32, _ suffixWord2: Int32) -> Void #else -fileprivate func bjs_MyViewControllerDelegate_onLabelUpdated_extern(_ jsObject: Int32, _ prefixBytes: Int32, _ prefixLength: Int32, _ suffixBytes: Int32, _ suffixLength: Int32) -> Void { +fileprivate func bjs_MyViewControllerDelegate_onLabelUpdated_extern(_ jsObject: Int32, _ prefixWord0: Int32, _ prefixWord1: Int32, _ prefixWord2: Int32, _ suffixWord0: Int32, _ suffixWord1: Int32, _ suffixWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_MyViewControllerDelegate_onLabelUpdated(_ jsObject: Int32, _ prefixBytes: Int32, _ prefixLength: Int32, _ suffixBytes: Int32, _ suffixLength: Int32) -> Void { - return bjs_MyViewControllerDelegate_onLabelUpdated_extern(jsObject, prefixBytes, prefixLength, suffixBytes, suffixLength) +@inline(never) fileprivate func bjs_MyViewControllerDelegate_onLabelUpdated(_ jsObject: Int32, _ prefixWord0: Int32, _ prefixWord1: Int32, _ prefixWord2: Int32, _ suffixWord0: Int32, _ suffixWord1: Int32, _ suffixWord2: Int32) -> Void { + return bjs_MyViewControllerDelegate_onLabelUpdated_extern(jsObject, prefixWord0, prefixWord1, prefixWord2, suffixWord0, suffixWord1, suffixWord2) } #if arch(wasm32) @@ -419,14 +419,14 @@ fileprivate func bjs_MyViewControllerDelegate_optionalName_get_extern(_ jsObject #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_optionalName_set") -fileprivate func bjs_MyViewControllerDelegate_optionalName_set_extern(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void +fileprivate func bjs_MyViewControllerDelegate_optionalName_set_extern(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void #else -fileprivate func bjs_MyViewControllerDelegate_optionalName_set_extern(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { +fileprivate func bjs_MyViewControllerDelegate_optionalName_set_extern(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_MyViewControllerDelegate_optionalName_set(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { - return bjs_MyViewControllerDelegate_optionalName_set_extern(jsObject, newValueIsSome, newValueBytes, newValueLength) +@inline(never) fileprivate func bjs_MyViewControllerDelegate_optionalName_set(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { + return bjs_MyViewControllerDelegate_optionalName_set_extern(jsObject, newValueIsSome, newValueWord0, newValueWord1, newValueWord2) } #if arch(wasm32) @@ -443,14 +443,14 @@ fileprivate func bjs_MyViewControllerDelegate_optionalRawEnum_get_extern(_ jsObj #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_optionalRawEnum_set") -fileprivate func bjs_MyViewControllerDelegate_optionalRawEnum_set_extern(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void +fileprivate func bjs_MyViewControllerDelegate_optionalRawEnum_set_extern(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void #else -fileprivate func bjs_MyViewControllerDelegate_optionalRawEnum_set_extern(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { +fileprivate func bjs_MyViewControllerDelegate_optionalRawEnum_set_extern(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_MyViewControllerDelegate_optionalRawEnum_set(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { - return bjs_MyViewControllerDelegate_optionalRawEnum_set_extern(jsObject, newValueIsSome, newValueBytes, newValueLength) +@inline(never) fileprivate func bjs_MyViewControllerDelegate_optionalRawEnum_set(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { + return bjs_MyViewControllerDelegate_optionalRawEnum_set_extern(jsObject, newValueIsSome, newValueWord0, newValueWord1, newValueWord2) } #if arch(wasm32) @@ -467,14 +467,14 @@ fileprivate func bjs_MyViewControllerDelegate_rawStringEnum_get_extern(_ jsObjec #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_MyViewControllerDelegate_rawStringEnum_set") -fileprivate func bjs_MyViewControllerDelegate_rawStringEnum_set_extern(_ jsObject: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void +fileprivate func bjs_MyViewControllerDelegate_rawStringEnum_set_extern(_ jsObject: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void #else -fileprivate func bjs_MyViewControllerDelegate_rawStringEnum_set_extern(_ jsObject: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { +fileprivate func bjs_MyViewControllerDelegate_rawStringEnum_set_extern(_ jsObject: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_MyViewControllerDelegate_rawStringEnum_set(_ jsObject: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { - return bjs_MyViewControllerDelegate_rawStringEnum_set_extern(jsObject, newValueBytes, newValueLength) +@inline(never) fileprivate func bjs_MyViewControllerDelegate_rawStringEnum_set(_ jsObject: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { + return bjs_MyViewControllerDelegate_rawStringEnum_set_extern(jsObject, newValueWord0, newValueWord1, newValueWord2) } #if arch(wasm32) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StringParameter.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StringParameter.swift index f519c3306..f00cbd49c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StringParameter.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/StringParameter.swift @@ -23,19 +23,19 @@ public func _bjs_roundtripString(_ aBytes: Int32, _ aLength: Int32) -> Void { #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_checkString") -fileprivate func bjs_checkString_extern(_ aBytes: Int32, _ aLength: Int32) -> Void +fileprivate func bjs_checkString_extern(_ aWord0: Int32, _ aWord1: Int32, _ aWord2: Int32) -> Void #else -fileprivate func bjs_checkString_extern(_ aBytes: Int32, _ aLength: Int32) -> Void { +fileprivate func bjs_checkString_extern(_ aWord0: Int32, _ aWord1: Int32, _ aWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_checkString(_ aBytes: Int32, _ aLength: Int32) -> Void { - return bjs_checkString_extern(aBytes, aLength) +@inline(never) fileprivate func bjs_checkString(_ aWord0: Int32, _ aWord1: Int32, _ aWord2: Int32) -> Void { + return bjs_checkString_extern(aWord0, aWord1, aWord2) } func _$checkString(_ a: String) throws(JSException) -> Void { - a.bridgeJSWithLoweredParameter { (aBytes, aLength) in - bjs_checkString(aBytes, aLength) + a.bridgeJSWithLoweredParameter { (aWord0, aWord1, aWord2) in + bjs_checkString(aWord0, aWord1, aWord2) } if let error = _swift_js_take_exception() { throw error @@ -44,20 +44,20 @@ func _$checkString(_ a: String) throws(JSException) -> Void { #if arch(wasm32) @_extern(wasm, module: "TestModule", name: "bjs_checkStringWithLength") -fileprivate func bjs_checkStringWithLength_extern(_ aBytes: Int32, _ aLength: Int32, _ b: Float64) -> Void +fileprivate func bjs_checkStringWithLength_extern(_ aWord0: Int32, _ aWord1: Int32, _ aWord2: Int32, _ b: Float64) -> Void #else -fileprivate func bjs_checkStringWithLength_extern(_ aBytes: Int32, _ aLength: Int32, _ b: Float64) -> Void { +fileprivate func bjs_checkStringWithLength_extern(_ aWord0: Int32, _ aWord1: Int32, _ aWord2: Int32, _ b: Float64) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_checkStringWithLength(_ aBytes: Int32, _ aLength: Int32, _ b: Float64) -> Void { - return bjs_checkStringWithLength_extern(aBytes, aLength, b) +@inline(never) fileprivate func bjs_checkStringWithLength(_ aWord0: Int32, _ aWord1: Int32, _ aWord2: Int32, _ b: Float64) -> Void { + return bjs_checkStringWithLength_extern(aWord0, aWord1, aWord2, b) } func _$checkStringWithLength(_ a: String, _ b: Double) throws(JSException) -> Void { - a.bridgeJSWithLoweredParameter { (aBytes, aLength) in + a.bridgeJSWithLoweredParameter { (aWord0, aWord1, aWord2) in let bValue = b.bridgeJSLowerParameter() - bjs_checkStringWithLength(aBytes, aLength, bValue) + bjs_checkStringWithLength(aWord0, aWord1, aWord2, bValue) } if let error = _swift_js_take_exception() { throw error diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift index af740495c..152b41102 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosure.swift @@ -64,14 +64,14 @@ public func _invoke_swift_closure_TestModule_10TestModule10HttpStatusO_10HttpSta #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO") -fileprivate func invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 +fileprivate func invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 #else -fileprivate func invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { +fileprivate func invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { - return invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO_extern(callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { + return invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO_extern(callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -91,9 +91,9 @@ private enum _BJS_Closure_10TestModule5ThemeO_5ThemeO { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) - let ret0 = param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + let ret0 = param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - let ret = invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO(callbackValue, param0Bytes, param0Length) + let ret = invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO(callbackValue, param0Word0, param0Word1, param0Word2) return ret } let ret = ret0 @@ -387,14 +387,14 @@ public func _invoke_swift_closure_TestModule_10TestModule9DirectionO_9DirectionO #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleKSS_Sb") -fileprivate func invoke_js_callback_TestModule_10TestModuleKSS_Sb_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 +fileprivate func invoke_js_callback_TestModule_10TestModuleKSS_Sb_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 #else -fileprivate func invoke_js_callback_TestModule_10TestModuleKSS_Sb_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { +fileprivate func invoke_js_callback_TestModule_10TestModuleKSS_Sb_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleKSS_Sb(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { - return invoke_js_callback_TestModule_10TestModuleKSS_Sb_extern(callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleKSS_Sb(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { + return invoke_js_callback_TestModule_10TestModuleKSS_Sb_extern(callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -414,9 +414,9 @@ private enum _BJS_Closure_10TestModuleKSS_Sb { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] (param0: String) throws(JSException) -> Bool in #if arch(wasm32) - let ret0 = param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + let ret0 = param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - let ret = invoke_js_callback_TestModule_10TestModuleKSS_Sb(callbackValue, param0Bytes, param0Length) + let ret = invoke_js_callback_TestModule_10TestModuleKSS_Sb(callbackValue, param0Word0, param0Word1, param0Word2) return ret } let ret = ret0 @@ -471,14 +471,14 @@ public func _invoke_swift_closure_TestModule_10TestModuleKSS_Sb(_ boxPtr: Unsafe #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleKSS_Si") -fileprivate func invoke_js_callback_TestModule_10TestModuleKSS_Si_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 +fileprivate func invoke_js_callback_TestModule_10TestModuleKSS_Si_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 #else -fileprivate func invoke_js_callback_TestModule_10TestModuleKSS_Si_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { +fileprivate func invoke_js_callback_TestModule_10TestModuleKSS_Si_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleKSS_Si(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { - return invoke_js_callback_TestModule_10TestModuleKSS_Si_extern(callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleKSS_Si(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { + return invoke_js_callback_TestModule_10TestModuleKSS_Si_extern(callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -498,9 +498,9 @@ private enum _BJS_Closure_10TestModuleKSS_Si { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] (param0: String) throws(JSException) -> Int in #if arch(wasm32) - let ret0 = param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + let ret0 = param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - let ret = invoke_js_callback_TestModule_10TestModuleKSS_Si(callbackValue, param0Bytes, param0Length) + let ret = invoke_js_callback_TestModule_10TestModuleKSS_Si(callbackValue, param0Word0, param0Word1, param0Word2) return ret } let ret = ret0 @@ -555,14 +555,14 @@ public func _invoke_swift_closure_TestModule_10TestModuleKSS_Si(_ boxPtr: Unsafe #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSS_SS") -fileprivate func invoke_js_callback_TestModule_10TestModuleSS_SS_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 +fileprivate func invoke_js_callback_TestModule_10TestModuleSS_SS_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 #else -fileprivate func invoke_js_callback_TestModule_10TestModuleSS_SS_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { +fileprivate func invoke_js_callback_TestModule_10TestModuleSS_SS_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleSS_SS(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { - return invoke_js_callback_TestModule_10TestModuleSS_SS_extern(callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleSS_SS(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { + return invoke_js_callback_TestModule_10TestModuleSS_SS_extern(callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -582,9 +582,9 @@ private enum _BJS_Closure_10TestModuleSS_SS { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) - let ret0 = param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + let ret0 = param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - let ret = invoke_js_callback_TestModule_10TestModuleSS_SS(callbackValue, param0Bytes, param0Length) + let ret = invoke_js_callback_TestModule_10TestModuleSS_SS(callbackValue, param0Word0, param0Word1, param0Word2) return ret } let ret = ret0 @@ -942,14 +942,14 @@ public func _invoke_swift_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10Htt #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO") -fileprivate func invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void +fileprivate func invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void #else -fileprivate func invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { +fileprivate func invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(_ callback: Int32, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { - return invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO_extern(callback, param0IsSome, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(_ callback: Int32, _ param0IsSome: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { + return invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO_extern(callback, param0IsSome, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -969,9 +969,9 @@ private enum _BJS_Closure_10TestModuleSq5ThemeO_Sq5ThemeO { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) - param0.bridgeJSWithLoweredParameter { (param0IsSome, param0Bytes, param0Length) in + param0.bridgeJSWithLoweredParameter { (param0IsSome, param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(callbackValue, param0IsSome, param0Bytes, param0Length) + invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO(callbackValue, param0IsSome, param0Word0, param0Word1, param0Word2) } return Optional.bridgeJSLiftReturnFromSideChannel() #else @@ -1263,14 +1263,14 @@ public func _invoke_swift_closure_TestModule_10TestModuleSq9DirectionO_Sq9Direct #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleSqSS_SqSS") -fileprivate func invoke_js_callback_TestModule_10TestModuleSqSS_SqSS_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSS_SqSS_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void #else -fileprivate func invoke_js_callback_TestModule_10TestModuleSqSS_SqSS_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { +fileprivate func invoke_js_callback_TestModule_10TestModuleSqSS_SqSS_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleSqSS_SqSS(_ callback: Int32, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { - return invoke_js_callback_TestModule_10TestModuleSqSS_SqSS_extern(callback, param0IsSome, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleSqSS_SqSS(_ callback: Int32, _ param0IsSome: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { + return invoke_js_callback_TestModule_10TestModuleSqSS_SqSS_extern(callback, param0IsSome, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -1290,9 +1290,9 @@ private enum _BJS_Closure_10TestModuleSqSS_SqSS { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) - param0.bridgeJSWithLoweredParameter { (param0IsSome, param0Bytes, param0Length) in + param0.bridgeJSWithLoweredParameter { (param0IsSome, param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - invoke_js_callback_TestModule_10TestModuleSqSS_SqSS(callbackValue, param0IsSome, param0Bytes, param0Length) + invoke_js_callback_TestModule_10TestModuleSqSS_SqSS(callbackValue, param0IsSome, param0Word0, param0Word1, param0Word2) } return Optional.bridgeJSLiftReturnFromSideChannel() #else @@ -1584,14 +1584,14 @@ public func _invoke_swift_closure_TestModule_10TestModuleSqSi_SqSi(_ boxPtr: Uns #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleYaKSS_SS") -fileprivate func invoke_js_callback_TestModule_10TestModuleYaKSS_SS_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void +fileprivate func invoke_js_callback_TestModule_10TestModuleYaKSS_SS_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void #else -fileprivate func invoke_js_callback_TestModule_10TestModuleYaKSS_SS_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { +fileprivate func invoke_js_callback_TestModule_10TestModuleYaKSS_SS_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleYaKSS_SS(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { - return invoke_js_callback_TestModule_10TestModuleYaKSS_SS_extern(resolveRef, rejectRef, callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleYaKSS_SS(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { + return invoke_js_callback_TestModule_10TestModuleYaKSS_SS_extern(resolveRef, rejectRef, callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -1616,9 +1616,9 @@ private enum _BJS_Closure_10TestModuleYaKSS_SS { }, makeRejectClosure: { JSTypedClosure<(sending JSValue) -> Void>.sending($0) }) { resolveRef, rejectRef in - param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - invoke_js_callback_TestModule_10TestModuleYaKSS_SS(resolveRef, rejectRef, callbackValue, param0Bytes, param0Length) + invoke_js_callback_TestModule_10TestModuleYaKSS_SS(resolveRef, rejectRef, callbackValue, param0Word0, param0Word1, param0Word2) } } return resolved @@ -1727,14 +1727,14 @@ public func _invoke_swift_closure_TestModule_10TestModuleYaKSb_9APIResultO(_ box #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleYaSS_6AnimalV") -fileprivate func invoke_js_callback_TestModule_10TestModuleYaSS_6AnimalV_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void +fileprivate func invoke_js_callback_TestModule_10TestModuleYaSS_6AnimalV_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void #else -fileprivate func invoke_js_callback_TestModule_10TestModuleYaSS_6AnimalV_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { +fileprivate func invoke_js_callback_TestModule_10TestModuleYaSS_6AnimalV_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleYaSS_6AnimalV(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { - return invoke_js_callback_TestModule_10TestModuleYaSS_6AnimalV_extern(resolveRef, rejectRef, callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleYaSS_6AnimalV(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { + return invoke_js_callback_TestModule_10TestModuleYaSS_6AnimalV_extern(resolveRef, rejectRef, callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -1759,9 +1759,9 @@ private enum _BJS_Closure_10TestModuleYaSS_6AnimalV { }, makeRejectClosure: { JSTypedClosure<(sending JSValue) -> Void>.sending($0) }) { resolveRef, rejectRef in - param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - invoke_js_callback_TestModule_10TestModuleYaSS_6AnimalV(resolveRef, rejectRef, callbackValue, param0Bytes, param0Length) + invoke_js_callback_TestModule_10TestModuleYaSS_6AnimalV(resolveRef, rejectRef, callbackValue, param0Word0, param0Word1, param0Word2) } } return resolved @@ -1799,14 +1799,14 @@ public func _invoke_swift_closure_TestModule_10TestModuleYaSS_6AnimalV(_ boxPtr: #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleYaSS_SS") -fileprivate func invoke_js_callback_TestModule_10TestModuleYaSS_SS_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void +fileprivate func invoke_js_callback_TestModule_10TestModuleYaSS_SS_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void #else -fileprivate func invoke_js_callback_TestModule_10TestModuleYaSS_SS_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { +fileprivate func invoke_js_callback_TestModule_10TestModuleYaSS_SS_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleYaSS_SS(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { - return invoke_js_callback_TestModule_10TestModuleYaSS_SS_extern(resolveRef, rejectRef, callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleYaSS_SS(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { + return invoke_js_callback_TestModule_10TestModuleYaSS_SS_extern(resolveRef, rejectRef, callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -1831,9 +1831,9 @@ private enum _BJS_Closure_10TestModuleYaSS_SS { }, makeRejectClosure: { JSTypedClosure<(sending JSValue) -> Void>.sending($0) }) { resolveRef, rejectRef in - param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - invoke_js_callback_TestModule_10TestModuleYaSS_SS(resolveRef, rejectRef, callbackValue, param0Bytes, param0Length) + invoke_js_callback_TestModule_10TestModuleYaSS_SS(resolveRef, rejectRef, callbackValue, param0Word0, param0Word1, param0Word2) } } return resolved @@ -2057,14 +2057,14 @@ public func _invoke_swift_closure_TestModule_10TestModules9APIResultO_y(_ boxPtr #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModulesSS_y") -fileprivate func invoke_js_callback_TestModule_10TestModulesSS_y_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void +fileprivate func invoke_js_callback_TestModule_10TestModulesSS_y_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void #else -fileprivate func invoke_js_callback_TestModule_10TestModulesSS_y_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { +fileprivate func invoke_js_callback_TestModule_10TestModulesSS_y_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModulesSS_y(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { - return invoke_js_callback_TestModule_10TestModulesSS_y_extern(callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModulesSS_y(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { + return invoke_js_callback_TestModule_10TestModulesSS_y_extern(callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -2084,9 +2084,9 @@ private enum _BJS_Closure_10TestModulesSS_y { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) - param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - invoke_js_callback_TestModule_10TestModulesSS_y(callbackValue, param0Bytes, param0Length) + invoke_js_callback_TestModule_10TestModulesSS_y(callbackValue, param0Word0, param0Word1, param0Word2) } #else fatalError("Only available on WebAssembly") @@ -2741,20 +2741,20 @@ func _$Promise_reject(_ promise: JSObject, _ value: JSValue) throws(JSException) #if arch(wasm32) @_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_SS") -fileprivate func promise_resolve_TestModule_SS_extern(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void +fileprivate func promise_resolve_TestModule_SS_extern(_ promise: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void #else -fileprivate func promise_resolve_TestModule_SS_extern(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { +fileprivate func promise_resolve_TestModule_SS_extern(_ promise: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func promise_resolve_TestModule_SS(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { - return promise_resolve_TestModule_SS_extern(promise, valueBytes, valueLength) +@inline(never) fileprivate func promise_resolve_TestModule_SS(_ promise: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { + return promise_resolve_TestModule_SS_extern(promise, valueWord0, valueWord1, valueWord2) } func _$Promise_resolve_SS(_ promise: JSObject, _ value: String) throws(JSException) -> Void { - value.bridgeJSWithLoweredParameter { (valueBytes, valueLength) in + value.bridgeJSWithLoweredParameter { (valueWord0, valueWord1, valueWord2) in let promiseValue = promise.bridgeJSLowerParameter() - promise_resolve_TestModule_SS(promiseValue, valueBytes, valueLength) + promise_resolve_TestModule_SS(promiseValue, valueWord0, valueWord1, valueWord2) } if let error = _swift_js_take_exception() { throw error } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.swift index 3634ad491..5c22db7f2 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.swift +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSCodegenTests/SwiftClosureImports.swift @@ -1,13 +1,13 @@ #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleKSS_Sb") -fileprivate func invoke_js_callback_TestModule_10TestModuleKSS_Sb_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 +fileprivate func invoke_js_callback_TestModule_10TestModuleKSS_Sb_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 #else -fileprivate func invoke_js_callback_TestModule_10TestModuleKSS_Sb_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { +fileprivate func invoke_js_callback_TestModule_10TestModuleKSS_Sb_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleKSS_Sb(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { - return invoke_js_callback_TestModule_10TestModuleKSS_Sb_extern(callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleKSS_Sb(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { + return invoke_js_callback_TestModule_10TestModuleKSS_Sb_extern(callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -27,9 +27,9 @@ private enum _BJS_Closure_10TestModuleKSS_Sb { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] (param0: String) throws(JSException) -> Bool in #if arch(wasm32) - let ret0 = param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + let ret0 = param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - let ret = invoke_js_callback_TestModule_10TestModuleKSS_Sb(callbackValue, param0Bytes, param0Length) + let ret = invoke_js_callback_TestModule_10TestModuleKSS_Sb(callbackValue, param0Word0, param0Word1, param0Word2) return ret } let ret = ret0 @@ -148,14 +148,14 @@ public func _invoke_swift_closure_TestModule_10TestModuleSi_Si(_ boxPtr: UnsafeM #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModuleYaKSS_SS") -fileprivate func invoke_js_callback_TestModule_10TestModuleYaKSS_SS_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void +fileprivate func invoke_js_callback_TestModule_10TestModuleYaKSS_SS_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void #else -fileprivate func invoke_js_callback_TestModule_10TestModuleYaKSS_SS_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { +fileprivate func invoke_js_callback_TestModule_10TestModuleYaKSS_SS_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleYaKSS_SS(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { - return invoke_js_callback_TestModule_10TestModuleYaKSS_SS_extern(resolveRef, rejectRef, callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModuleYaKSS_SS(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { + return invoke_js_callback_TestModule_10TestModuleYaKSS_SS_extern(resolveRef, rejectRef, callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -180,9 +180,9 @@ private enum _BJS_Closure_10TestModuleYaKSS_SS { }, makeRejectClosure: { JSTypedClosure<(sending JSValue) -> Void>.sending($0) }) { resolveRef, rejectRef in - param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - invoke_js_callback_TestModule_10TestModuleYaKSS_SS(resolveRef, rejectRef, callbackValue, param0Bytes, param0Length) + invoke_js_callback_TestModule_10TestModuleYaKSS_SS(resolveRef, rejectRef, callbackValue, param0Word0, param0Word1, param0Word2) } } return resolved @@ -282,14 +282,14 @@ public func _invoke_swift_closure_TestModule_10TestModules7JSValueV_y(_ boxPtr: #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_TestModule_10TestModulesSS_y") -fileprivate func invoke_js_callback_TestModule_10TestModulesSS_y_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void +fileprivate func invoke_js_callback_TestModule_10TestModulesSS_y_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void #else -fileprivate func invoke_js_callback_TestModule_10TestModulesSS_y_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { +fileprivate func invoke_js_callback_TestModule_10TestModulesSS_y_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModulesSS_y(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { - return invoke_js_callback_TestModule_10TestModulesSS_y_extern(callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_TestModule_10TestModulesSS_y(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { + return invoke_js_callback_TestModule_10TestModulesSS_y_extern(callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -309,9 +309,9 @@ private enum _BJS_Closure_10TestModulesSS_y { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) - param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - invoke_js_callback_TestModule_10TestModulesSS_y(callbackValue, param0Bytes, param0Length) + invoke_js_callback_TestModule_10TestModulesSS_y(callbackValue, param0Word0, param0Word1, param0Word2) } #else fatalError("Only available on WebAssembly") @@ -390,20 +390,20 @@ func _$Promise_reject(_ promise: JSObject, _ value: JSValue) throws(JSException) #if arch(wasm32) @_extern(wasm, module: "bjs", name: "promise_resolve_TestModule_SS") -fileprivate func promise_resolve_TestModule_SS_extern(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void +fileprivate func promise_resolve_TestModule_SS_extern(_ promise: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void #else -fileprivate func promise_resolve_TestModule_SS_extern(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { +fileprivate func promise_resolve_TestModule_SS_extern(_ promise: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func promise_resolve_TestModule_SS(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { - return promise_resolve_TestModule_SS_extern(promise, valueBytes, valueLength) +@inline(never) fileprivate func promise_resolve_TestModule_SS(_ promise: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { + return promise_resolve_TestModule_SS_extern(promise, valueWord0, valueWord1, valueWord2) } func _$Promise_resolve_SS(_ promise: JSObject, _ value: String) throws(JSException) -> Void { - value.bridgeJSWithLoweredParameter { (valueBytes, valueLength) in + value.bridgeJSWithLoweredParameter { (valueWord0, valueWord1, valueWord2) in let promiseValue = promise.bridgeJSLowerParameter() - promise_resolve_TestModule_SS(promiseValue, valueBytes, valueLength) + promise_resolve_TestModule_SS(promiseValue, valueWord0, valueWord1, valueWord2) } if let error = _swift_js_take_exception() { throw error } } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Alias.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Alias.js index b1cfb68aa..d4f2441d3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Alias.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Alias.js @@ -15,6 +15,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -432,8 +434,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -441,8 +443,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -467,8 +469,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -536,11 +538,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -611,19 +613,19 @@ export async function createInstantiator(options, swift) { return swift.memory.retain(obj); }; const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; - TestModule["bjs_acceptTagged"] = function bjs_acceptTagged(taggedBytes, taggedCount) { + TestModule["bjs_acceptTagged"] = function bjs_acceptTagged(taggedWord0, taggedWord1, taggedWord2) { try { - const string = decodeString(taggedBytes, taggedCount); + const string = decodeString(taggedWord0, taggedWord1, taggedWord2); imports.acceptTagged(string); } catch (error) { setException(error); } } - TestModule["bjs_acceptOptionalTagged"] = function bjs_acceptOptionalTagged(taggedIsSome, taggedBytes, taggedCount) { + TestModule["bjs_acceptOptionalTagged"] = function bjs_acceptOptionalTagged(taggedIsSome, taggedWord0, taggedWord1, taggedWord2) { try { let optResult; if (taggedIsSome) { - const string = decodeString(taggedBytes, taggedCount); + const string = decodeString(taggedWord0, taggedWord1, taggedWord2); optResult = string; } else { optResult = null; @@ -633,9 +635,9 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_roundtripTagged"] = function bjs_roundtripTagged(taggedBytes, taggedCount) { + TestModule["bjs_roundtripTagged"] = function bjs_roundtripTagged(taggedWord0, taggedWord1, taggedWord2) { try { - const string = decodeString(taggedBytes, taggedCount); + const string = decodeString(taggedWord0, taggedWord1, taggedWord2); let ret = imports.roundtripTagged(string); tmpRetBytes = textEncoder.encode(ret); return tmpRetBytes.length; @@ -681,7 +683,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AliasInClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AliasInClosure.js index fa9095cd8..ce2baf58c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AliasInClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AliasInClosure.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -42,7 +44,7 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, state.file >>> 0); let length = 0; while (bytes[length] !== 0) { length += 1; } - const fileID = decodeString(state.file, length); + const fileID = decodeUTF8(state.file, length); throw new Error(`Attempted to call a released JSTypedClosure created at ${fileID}:${state.line}`); } return func(...args); @@ -64,8 +66,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -73,8 +75,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -99,8 +101,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -168,11 +170,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -293,7 +295,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js index 6d3992ce5..da9c6e88d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js @@ -22,6 +22,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -495,8 +497,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -504,8 +506,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -530,8 +532,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -606,11 +608,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -743,7 +745,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js index c025cf4f0..40d251279 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js @@ -19,6 +19,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -407,8 +409,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -416,8 +418,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -442,8 +444,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -504,9 +506,9 @@ export async function createInstantiator(options, swift) { setException(error); } } - bjs["promise_resolve_TestModule_SS"] = function(promise, valueBytes, valueCount) { + bjs["promise_resolve_TestModule_SS"] = function(promise, valueWord0, valueWord1, valueWord2) { try { - const string = decodeString(valueBytes, valueCount); + const string = decodeString(valueWord0, valueWord1, valueWord2); swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(string); } catch (error) { setException(error); @@ -555,9 +557,9 @@ export async function createInstantiator(options, swift) { setException(error); } } - bjs["promise_resolve_TestModule_10AsyncThemeO"] = function(promise, valueBytes, valueCount) { + bjs["promise_resolve_TestModule_10AsyncThemeO"] = function(promise, valueWord0, valueWord1, valueWord2) { try { - const string = decodeString(valueBytes, valueCount); + const string = decodeString(valueWord0, valueWord1, valueWord2); swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(string); } catch (error) { setException(error); @@ -570,11 +572,11 @@ export async function createInstantiator(options, swift) { setException(error); } } - bjs["promise_resolve_TestModule_Sq10AsyncThemeO"] = function(promise, valueIsSome, valueBytes, valueCount) { + bjs["promise_resolve_TestModule_Sq10AsyncThemeO"] = function(promise, valueIsSome, valueWord0, valueWord1, valueWord2) { try { let optResult; if (valueIsSome) { - const string = decodeString(valueBytes, valueCount); + const string = decodeString(valueWord0, valueWord1, valueWord2); optResult = string; } else { optResult = null; @@ -660,11 +662,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -727,7 +729,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.js index 49b2ff88b..c6642fccb 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.js @@ -16,6 +16,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -172,8 +174,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -181,8 +183,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -207,8 +209,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -306,11 +308,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -373,7 +375,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncImport.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncImport.js index 96c0d11e8..03ec128fd 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncImport.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncImport.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -131,7 +133,7 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, state.file >>> 0); let length = 0; while (bytes[length] !== 0) { length += 1; } - const fileID = decodeString(state.file, length); + const fileID = decodeUTF8(state.file, length); throw new Error(`Attempted to call a released JSTypedClosure created at ${fileID}:${state.line}`); } return func(...args); @@ -154,8 +156,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -163,8 +165,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -189,8 +191,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -257,11 +259,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -365,10 +367,10 @@ export async function createInstantiator(options, swift) { }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModules8JSObjectC_y); } - bjs["invoke_js_callback_TestModule_10TestModulesSS_y"] = function(callbackId, param0Bytes, param0Count) { + bjs["invoke_js_callback_TestModule_10TestModulesSS_y"] = function(callbackId, param0Word0, param0Word1, param0Word2) { try { const callback = swift.memory.getObject(callbackId); - const string = decodeString(param0Bytes, param0Count); + const string = decodeString(param0Word0, param0Word1, param0Word2); callback(string); } catch (error) { setException(error); @@ -479,10 +481,10 @@ export async function createInstantiator(options, swift) { const reject = swift.memory.getObject(rejectRef); imports.asyncRoundTripInt(v).then(resolve, reject); } - TestModule["bjs_asyncRoundTripString"] = function bjs_asyncRoundTripString(resolveRef, rejectRef, vBytes, vCount) { + TestModule["bjs_asyncRoundTripString"] = function bjs_asyncRoundTripString(resolveRef, rejectRef, vWord0, vWord1, vWord2) { const resolve = swift.memory.getObject(resolveRef); const reject = swift.memory.getObject(rejectRef); - const string = decodeString(vBytes, vCount); + const string = decodeString(vWord0, vWord1, vWord2); imports.asyncRoundTripString(string).then(resolve, reject); } TestModule["bjs_asyncRoundTripBool"] = function bjs_asyncRoundTripBool(resolveRef, rejectRef, v) { @@ -505,7 +507,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncStaticImport.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncStaticImport.js index eea340c35..ae1a3fce0 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncStaticImport.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncStaticImport.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -131,7 +133,7 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, state.file >>> 0); let length = 0; while (bytes[length] !== 0) { length += 1; } - const fileID = decodeString(state.file, length); + const fileID = decodeUTF8(state.file, length); throw new Error(`Attempted to call a released JSTypedClosure created at ${fileID}:${state.line}`); } return func(...args); @@ -154,8 +156,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -163,8 +165,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -189,8 +191,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -257,11 +259,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -401,7 +403,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ClassWithNestedTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ClassWithNestedTypes.js index ecdb0b059..f690854c1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ClassWithNestedTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ClassWithNestedTypes.js @@ -14,6 +14,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -56,8 +58,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -65,8 +67,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -91,8 +93,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -167,11 +169,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -242,7 +244,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js index 9fda637df..f334eb5c7 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js @@ -15,6 +15,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -419,8 +421,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -428,8 +430,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -454,8 +456,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -537,11 +539,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -620,7 +622,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js index 8ccda3c19..3f23333a5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -399,8 +401,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -408,8 +410,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -434,8 +436,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -510,11 +512,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -595,7 +597,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DocComments.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DocComments.js index 6d23d394f..94564ffa4 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DocComments.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DocComments.js @@ -15,6 +15,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -56,8 +58,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -65,8 +67,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -91,8 +93,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -167,11 +169,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -259,7 +261,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAlias.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAlias.js index d8bc06fcf..f34281ef9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAlias.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAlias.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -39,8 +41,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -48,8 +50,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -74,8 +76,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -143,11 +145,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -218,7 +220,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js index 66f85760c..ab12aebd6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js @@ -90,6 +90,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -994,8 +996,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -1003,8 +1005,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -1029,8 +1031,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -1105,11 +1107,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -1180,7 +1182,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.js index 2b36953bb..0c3c8a090 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.js @@ -16,6 +16,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -84,8 +86,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -93,8 +95,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -119,8 +121,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -188,11 +190,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -304,7 +306,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js index 838e3062b..f480062f1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js @@ -33,6 +33,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -63,8 +65,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -72,8 +74,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -98,8 +100,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -167,11 +169,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -234,7 +236,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCaseImport.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCaseImport.js index bde5fc31f..114f145a8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCaseImport.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCaseImport.js @@ -14,6 +14,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -45,8 +47,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -54,8 +56,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -80,8 +82,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -149,11 +151,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -242,7 +244,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js index 0a691374b..622f5aa4c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js @@ -53,6 +53,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -83,8 +85,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -92,8 +94,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -118,8 +120,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -187,11 +189,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -274,7 +276,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js index 03f0a8d9a..bc3952c24 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js @@ -34,6 +34,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -64,8 +66,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -73,8 +75,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -99,8 +101,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -168,11 +170,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -255,7 +257,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js index 09e03e44a..caf2f2dfa 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js @@ -84,6 +84,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -459,8 +461,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -468,8 +470,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -494,8 +496,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -563,11 +565,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -626,9 +628,9 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_closure_unregister"] = function(funcRef) {} const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; - TestModule["bjs_takesFeatureFlag"] = function bjs_takesFeatureFlag(flagBytes, flagCount) { + TestModule["bjs_takesFeatureFlag"] = function bjs_takesFeatureFlag(flagWord0, flagWord1, flagWord2) { try { - const string = decodeString(flagBytes, flagCount); + const string = decodeString(flagWord0, flagWord1, flagWord2); imports.takesFeatureFlag(string); } catch (error) { setException(error); @@ -648,7 +650,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionNestedTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionNestedTypes.js index 85cdb44d4..cabb2aeff 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionNestedTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionNestedTypes.js @@ -25,6 +25,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -110,8 +112,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -119,8 +121,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -145,8 +147,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -228,11 +230,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -303,7 +305,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionOrderIndependence.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionOrderIndependence.js index a9091e925..6c7b9e38f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionOrderIndependence.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionOrderIndependence.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -59,8 +61,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -68,8 +70,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -94,8 +96,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -170,11 +172,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -245,7 +247,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionScopeParity.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionScopeParity.js index 6b8ae44b1..6b51521b3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionScopeParity.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionScopeParity.js @@ -13,6 +13,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -55,8 +57,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -64,8 +66,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -90,8 +92,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -166,11 +168,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -245,7 +247,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/FixedWidthIntegers.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/FixedWidthIntegers.js index 56a31b784..056abf4f6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/FixedWidthIntegers.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/FixedWidthIntegers.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -40,8 +42,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -49,8 +51,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -75,8 +77,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -143,11 +145,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -283,7 +285,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GenericImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GenericImports.js index 529f1772e..811681911 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GenericImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GenericImports.js @@ -25,6 +25,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -506,8 +508,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -515,8 +517,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -541,8 +543,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -653,11 +655,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -734,10 +736,10 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_genericParse"] = function bjs_genericParse(jsonBytes, jsonCount, tTypeId) { + TestModule["bjs_genericParse"] = function bjs_genericParse(jsonWord0, jsonWord1, jsonWord2, tTypeId) { try { const codecT = __bjs_codecForTypeId(tTypeId); - const string = decodeString(jsonBytes, jsonCount); + const string = decodeString(jsonWord0, jsonWord1, jsonWord2); let ret = imports.genericParse(string); codecT.lower(ret); } catch (error) { @@ -829,11 +831,11 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_GenericPairFactory_init"] = function bjs_GenericPairFactory_init(tagBytes, tagCount, tTypeId, uTypeId) { + TestModule["bjs_GenericPairFactory_init"] = function bjs_GenericPairFactory_init(tagWord0, tagWord1, tagWord2, tTypeId, uTypeId) { try { const codecT = __bjs_codecForTypeId(tTypeId); const codecU = __bjs_codecForTypeId(uTypeId); - const string = decodeString(tagBytes, tagCount); + const string = decodeString(tagWord0, tagWord1, tagWord2); const first = codecT.lift(); const second = codecU.lift(); return swift.memory.retain(new imports.GenericPairFactory(string, first, second)); @@ -941,7 +943,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js index adb70913c..ce66a3ffc 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -40,8 +42,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -49,8 +51,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -75,8 +77,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -143,11 +145,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -215,9 +217,9 @@ export async function createInstantiator(options, swift) { return 0 } } - TestModule["bjs_JSConsole_log"] = function bjs_JSConsole_log(self, messageBytes, messageCount) { + TestModule["bjs_JSConsole_log"] = function bjs_JSConsole_log(self, messageWord0, messageWord1, messageWord2) { try { - const string = decodeString(messageBytes, messageCount); + const string = decodeString(messageWord0, messageWord1, messageWord2); swift.memory.getObject(self).log(string); } catch (error) { setException(error); @@ -228,7 +230,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js index 760a6b50c..2791313be 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -39,8 +41,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -48,8 +50,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -74,8 +76,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -142,11 +144,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -214,9 +216,9 @@ export async function createInstantiator(options, swift) { return 0 } } - TestModule["bjs_parseInt"] = function bjs_parseInt(stringBytes, stringCount) { + TestModule["bjs_parseInt"] = function bjs_parseInt(stringWord0, stringWord1, stringWord2) { try { - const string = decodeString(stringBytes, stringCount); + const string = decodeString(stringWord0, stringWord1, stringWord2); let ret = globalThis.parseInt(string); return ret; } catch (error) { @@ -224,17 +226,17 @@ export async function createInstantiator(options, swift) { return 0 } } - TestModule["bjs_JSConsole_log"] = function bjs_JSConsole_log(self, messageBytes, messageCount) { + TestModule["bjs_JSConsole_log"] = function bjs_JSConsole_log(self, messageWord0, messageWord1, messageWord2) { try { - const string = decodeString(messageBytes, messageCount); + const string = decodeString(messageWord0, messageWord1, messageWord2); swift.memory.getObject(self).log(string); } catch (error) { setException(error); } } - TestModule["bjs_WebSocket_init"] = function bjs_WebSocket_init(urlBytes, urlCount) { + TestModule["bjs_WebSocket_init"] = function bjs_WebSocket_init(urlWord0, urlWord1, urlWord2) { try { - const string = decodeString(urlBytes, urlCount); + const string = decodeString(urlWord0, urlWord1, urlWord2); return swift.memory.retain(new globalThis.WebSocket(string)); } catch (error) { setException(error); @@ -253,7 +255,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js index 1e1d14696..282ae4ec9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -39,8 +41,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -48,8 +50,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -74,8 +76,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -142,11 +144,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -225,7 +227,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js index c85aee3af..715a4522d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -39,8 +41,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -48,8 +50,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -74,8 +76,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -142,11 +144,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -225,7 +227,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js index c85aee3af..715a4522d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -39,8 +41,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -48,8 +50,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -74,8 +76,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -142,11 +144,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -225,7 +227,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js index c92ea6ad3..3b918d9cb 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -367,8 +369,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -376,8 +378,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -402,8 +404,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -470,11 +472,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -561,9 +563,9 @@ export async function createInstantiator(options, swift) { return 0 } } - TestModule["bjs_borrowedStringAroundStackParams"] = function bjs_borrowedStringAroundStackParams(sBytes, sCount) { + TestModule["bjs_borrowedStringAroundStackParams"] = function bjs_borrowedStringAroundStackParams(sWord0, sWord1, sWord2) { try { - const string = decodeString(sBytes, sCount); + const string = decodeString(sWord0, sWord1, sWord2); const optValue = __bjs_codec_Optional_Array_Int.lift(); const arrayResult = __bjs_codec_Array_Int.lift(); let ret = imports.borrowedStringAroundStackParams(string, optValue, arrayResult); @@ -578,7 +580,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js index 363f6c595..8e34c8a5a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -403,8 +405,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -412,8 +414,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -438,8 +440,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -514,11 +516,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -590,7 +592,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js index e8fe5ec10..0923c1435 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -40,8 +42,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -49,8 +51,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -75,8 +77,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -143,11 +145,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -296,9 +298,9 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_WeirdNaming_normalProperty_set"] = function bjs_WeirdNaming_normalProperty_set(self, newValueBytes, newValueCount) { + TestModule["bjs_WeirdNaming_normalProperty_set"] = function bjs_WeirdNaming_normalProperty_set(self, newValueWord0, newValueWord1, newValueWord2) { try { - const string = decodeString(newValueBytes, newValueCount); + const string = decodeString(newValueWord0, newValueWord1, newValueWord2); swift.memory.getObject(self).normalProperty = string; } catch (error) { setException(error); @@ -318,9 +320,9 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_WeirdNaming_property_with_spaces_set"] = function bjs_WeirdNaming_property_with_spaces_set(self, newValueBytes, newValueCount) { + TestModule["bjs_WeirdNaming_property_with_spaces_set"] = function bjs_WeirdNaming_property_with_spaces_set(self, newValueWord0, newValueWord1, newValueWord2) { try { - const string = decodeString(newValueBytes, newValueCount); + const string = decodeString(newValueWord0, newValueWord1, newValueWord2); swift.memory.getObject(self)["property with spaces"] = string; } catch (error) { setException(error); @@ -333,25 +335,25 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_WeirdNaming_constructor_set"] = function bjs_WeirdNaming_constructor_set(self, newValueBytes, newValueCount) { + TestModule["bjs_WeirdNaming_constructor_set"] = function bjs_WeirdNaming_constructor_set(self, newValueWord0, newValueWord1, newValueWord2) { try { - const string = decodeString(newValueBytes, newValueCount); + const string = decodeString(newValueWord0, newValueWord1, newValueWord2); swift.memory.getObject(self).constructor = string; } catch (error) { setException(error); } } - TestModule["bjs_WeirdNaming_for_set"] = function bjs_WeirdNaming_for_set(self, newValueBytes, newValueCount) { + TestModule["bjs_WeirdNaming_for_set"] = function bjs_WeirdNaming_for_set(self, newValueWord0, newValueWord1, newValueWord2) { try { - const string = decodeString(newValueBytes, newValueCount); + const string = decodeString(newValueWord0, newValueWord1, newValueWord2); swift.memory.getObject(self).for = string; } catch (error) { setException(error); } } - TestModule["bjs_WeirdNaming_any_set"] = function bjs_WeirdNaming_any_set(self, newValueBytes, newValueCount) { + TestModule["bjs_WeirdNaming_any_set"] = function bjs_WeirdNaming_any_set(self, newValueWord0, newValueWord1, newValueWord2) { try { - const string = decodeString(newValueBytes, newValueCount); + const string = decodeString(newValueWord0, newValueWord1, newValueWord2); swift.memory.getObject(self).Any = string; } catch (error) { setException(error); @@ -391,7 +393,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js index 15b48d4b9..0f4ff9741 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -40,8 +42,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -49,8 +51,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -75,8 +77,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -143,11 +145,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -215,9 +217,9 @@ export async function createInstantiator(options, swift) { return 0 } } - TestModule["bjs_Greeter_init"] = function bjs_Greeter_init(nameBytes, nameCount) { + TestModule["bjs_Greeter_init"] = function bjs_Greeter_init(nameWord0, nameWord1, nameWord2) { try { - const string = decodeString(nameBytes, nameCount); + const string = decodeString(nameWord0, nameWord1, nameWord2); return swift.memory.retain(new imports.Greeter(string)); } catch (error) { setException(error); @@ -242,9 +244,9 @@ export async function createInstantiator(options, swift) { return 0 } } - TestModule["bjs_Greeter_name_set"] = function bjs_Greeter_name_set(self, newValueBytes, newValueCount) { + TestModule["bjs_Greeter_name_set"] = function bjs_Greeter_name_set(self, newValueWord0, newValueWord1, newValueWord2) { try { - const string = decodeString(newValueBytes, newValueCount); + const string = decodeString(newValueWord0, newValueWord1, newValueWord2); swift.memory.getObject(self).name = string; } catch (error) { setException(error); @@ -259,9 +261,9 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_Greeter_changeName"] = function bjs_Greeter_changeName(self, nameBytes, nameCount) { + TestModule["bjs_Greeter_changeName"] = function bjs_Greeter_changeName(self, nameWord0, nameWord1, nameWord2) { try { - const string = decodeString(nameBytes, nameCount); + const string = decodeString(nameWord0, nameWord1, nameWord2); swift.memory.getObject(self).changeName(string); } catch (error) { setException(error); @@ -290,7 +292,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js index 5eaba3c8f..d999f7100 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -40,8 +42,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -49,8 +51,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -75,8 +77,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -143,11 +145,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -273,7 +275,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModule.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModule.js index 6d1b1b6fb..d64deb891 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModule.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModule.js @@ -15,6 +15,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -45,8 +47,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -54,8 +56,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -80,8 +82,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -148,11 +150,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -229,9 +231,9 @@ export async function createInstantiator(options, swift) { return 0 } } - TestModule["bjs_nodeBasename"] = function bjs_nodeBasename(pathBytes, pathCount) { + TestModule["bjs_nodeBasename"] = function bjs_nodeBasename(pathWord0, pathWord1, pathWord2) { try { - const string = decodeString(pathBytes, pathCount); + const string = decodeString(pathWord0, pathWord1, pathWord2); let ret = __bjs_import_3_basename(string); tmpRetBytes = textEncoder.encode(ret); return tmpRetBytes.length; @@ -239,9 +241,9 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_nodeDirname"] = function bjs_nodeDirname(pathBytes, pathCount) { + TestModule["bjs_nodeDirname"] = function bjs_nodeDirname(pathWord0, pathWord1, pathWord2) { try { - const string = decodeString(pathBytes, pathCount); + const string = decodeString(pathWord0, pathWord1, pathWord2); let ret = __bjs_import_3_dirname(string); tmpRetBytes = textEncoder.encode(ret); return tmpRetBytes.length; @@ -298,7 +300,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModuleFallback.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModuleFallback.js index 9428698be..4b407018c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModuleFallback.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModuleFallback.js @@ -12,6 +12,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -42,8 +44,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -51,8 +53,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -77,8 +79,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -145,11 +147,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -226,10 +228,10 @@ export async function createInstantiator(options, swift) { return 0 } } - TestModule["bjs_joinPaths"] = function bjs_joinPaths(lhsBytes, lhsCount, rhsBytes, rhsCount) { + TestModule["bjs_joinPaths"] = function bjs_joinPaths(lhsWord0, lhsWord1, lhsWord2, rhsWord0, rhsWord1, rhsWord2) { try { - const string = decodeString(lhsBytes, lhsCount); - const string1 = decodeString(rhsBytes, rhsCount); + const string = decodeString(lhsWord0, lhsWord1, lhsWord2); + const string1 = decodeString(rhsWord0, rhsWord1, rhsWord2); let ret = __bjs_import_0_join(string, string1); tmpRetBytes = textEncoder.encode(ret); return tmpRetBytes.length; @@ -242,7 +244,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportModule.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportModule.js index aacf5e61a..6938c2713 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportModule.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportModule.js @@ -12,6 +12,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -42,8 +44,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -51,8 +53,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -77,8 +79,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -145,11 +147,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -282,7 +284,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameOverride.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameOverride.js index 68ac11976..ca2eeebb9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameOverride.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameOverride.js @@ -14,6 +14,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -61,8 +63,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -70,8 +72,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -96,8 +98,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -172,11 +174,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -247,7 +249,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameTypes.js index fb061d342..98f9afa5d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameTypes.js @@ -14,6 +14,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -44,8 +46,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -53,8 +55,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -79,8 +81,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -148,11 +150,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -223,7 +225,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSTypedArrayTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSTypedArrayTypes.js index f02f6bcf2..e3322b31e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSTypedArrayTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSTypedArrayTypes.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -39,8 +41,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -48,8 +50,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -74,8 +76,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -142,11 +144,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -209,7 +211,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js index 9fe12ff47..2a14c8c2f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -366,8 +368,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -375,8 +377,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -401,8 +403,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -469,11 +471,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -566,7 +568,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js index 5db38dde5..d3a6e551c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -39,8 +41,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -48,8 +50,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -74,8 +76,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -142,11 +144,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -217,7 +219,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js index 66818952b..70611b70f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -39,8 +41,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -48,8 +50,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -74,8 +76,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -142,11 +144,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -225,7 +227,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js index a732808a6..953b5c479 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -39,8 +41,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -48,8 +50,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -74,8 +76,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -142,11 +144,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -217,7 +219,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NamespacedClassSignature.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NamespacedClassSignature.js index 082d85f65..8e3fc9ba9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NamespacedClassSignature.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NamespacedClassSignature.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -42,7 +44,7 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, state.file >>> 0); let length = 0; while (bytes[length] !== 0) { length += 1; } - const fileID = decodeString(state.file, length); + const fileID = decodeUTF8(state.file, length); throw new Error(`Attempted to call a released JSTypedClosure created at ${fileID}:${state.line}`); } return func(...args); @@ -64,8 +66,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -73,8 +75,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -99,8 +101,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -167,11 +169,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -269,7 +271,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js index ea49220de..8bc37539f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -374,8 +376,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -383,8 +385,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -409,8 +411,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -477,11 +479,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -564,7 +566,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js index 25bd44d05..e0b99db0e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -374,8 +376,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -383,8 +385,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -409,8 +411,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -477,11 +479,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -564,7 +566,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js index f57c4007b..a7fe1afe4 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -64,8 +66,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -73,8 +75,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -99,8 +101,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -182,11 +184,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -261,7 +263,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedTypeNameCollision.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedTypeNameCollision.js index 1f4400ce9..181eb9fce 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedTypeNameCollision.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedTypeNameCollision.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -60,8 +62,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -69,8 +71,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -95,8 +97,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -178,11 +180,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -245,7 +247,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js index b63f360e9..369c453fe 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -390,8 +392,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -399,8 +401,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -425,8 +427,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -493,11 +495,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -568,18 +570,18 @@ export async function createInstantiator(options, swift) { return swift.memory.retain(obj); }; const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; - TestModule["bjs_WithOptionalJSClass_init"] = function bjs_WithOptionalJSClass_init(valueOrNullIsSome, valueOrNullBytes, valueOrNullCount, valueOrUndefinedIsSome, valueOrUndefinedBytes, valueOrUndefinedCount) { + TestModule["bjs_WithOptionalJSClass_init"] = function bjs_WithOptionalJSClass_init(valueOrNullIsSome, valueOrNullWord0, valueOrNullWord1, valueOrNullWord2, valueOrUndefinedIsSome, valueOrUndefinedWord0, valueOrUndefinedWord1, valueOrUndefinedWord2) { try { let optResult; if (valueOrNullIsSome) { - const string = decodeString(valueOrNullBytes, valueOrNullCount); + const string = decodeString(valueOrNullWord0, valueOrNullWord1, valueOrNullWord2); optResult = string; } else { optResult = null; } let optResult1; if (valueOrUndefinedIsSome) { - const string1 = decodeString(valueOrUndefinedBytes, valueOrUndefinedCount); + const string1 = decodeString(valueOrUndefinedWord0, valueOrUndefinedWord1, valueOrUndefinedWord2); optResult1 = string1; } else { optResult1 = undefined; @@ -670,11 +672,11 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_WithOptionalJSClass_stringOrNull_set"] = function bjs_WithOptionalJSClass_stringOrNull_set(self, newValueIsSome, newValueBytes, newValueCount) { + TestModule["bjs_WithOptionalJSClass_stringOrNull_set"] = function bjs_WithOptionalJSClass_stringOrNull_set(self, newValueIsSome, newValueWord0, newValueWord1, newValueWord2) { try { let optResult; if (newValueIsSome) { - const string = decodeString(newValueBytes, newValueCount); + const string = decodeString(newValueWord0, newValueWord1, newValueWord2); optResult = string; } else { optResult = null; @@ -684,11 +686,11 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_WithOptionalJSClass_stringOrUndefined_set"] = function bjs_WithOptionalJSClass_stringOrUndefined_set(self, newValueIsSome, newValueBytes, newValueCount) { + TestModule["bjs_WithOptionalJSClass_stringOrUndefined_set"] = function bjs_WithOptionalJSClass_stringOrUndefined_set(self, newValueIsSome, newValueWord0, newValueWord1, newValueWord2) { try { let optResult; if (newValueIsSome) { - const string = decodeString(newValueBytes, newValueCount); + const string = decodeString(newValueWord0, newValueWord1, newValueWord2); optResult = string; } else { optResult = undefined; @@ -747,11 +749,11 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_WithOptionalJSClass_roundTripStringOrNull"] = function bjs_WithOptionalJSClass_roundTripStringOrNull(self, valueIsSome, valueBytes, valueCount) { + TestModule["bjs_WithOptionalJSClass_roundTripStringOrNull"] = function bjs_WithOptionalJSClass_roundTripStringOrNull(self, valueIsSome, valueWord0, valueWord1, valueWord2) { try { let optResult; if (valueIsSome) { - const string = decodeString(valueBytes, valueCount); + const string = decodeString(valueWord0, valueWord1, valueWord2); optResult = string; } else { optResult = null; @@ -763,11 +765,11 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_WithOptionalJSClass_roundTripStringOrUndefined"] = function bjs_WithOptionalJSClass_roundTripStringOrUndefined(self, valueIsSome, valueBytes, valueCount) { + TestModule["bjs_WithOptionalJSClass_roundTripStringOrUndefined"] = function bjs_WithOptionalJSClass_roundTripStringOrUndefined(self, valueIsSome, valueWord0, valueWord1, valueWord2) { try { let optResult; if (valueIsSome) { - const string = decodeString(valueBytes, valueCount); + const string = decodeString(valueWord0, valueWord1, valueWord2); optResult = string; } else { optResult = undefined; @@ -846,7 +848,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js index d4480a65c..14100292b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -40,8 +42,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -49,8 +51,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -75,8 +77,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -143,11 +145,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -218,7 +220,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js index e9b298fb2..1970e82e3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -40,8 +42,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -49,8 +51,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -75,8 +77,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -143,11 +145,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -229,7 +231,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js index beb9417df..5a157c55b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -39,8 +41,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -48,8 +50,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -74,8 +76,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -142,11 +144,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -217,7 +219,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js index f0c2d3fae..2babe8caa 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js @@ -33,6 +33,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -434,8 +436,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -443,8 +445,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -469,8 +471,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -538,11 +540,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -650,11 +652,11 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_MyViewControllerDelegate_optionalName_set"] = function bjs_MyViewControllerDelegate_optionalName_set(self, valueIsSome, valueBytes, valueCount) { + TestModule["bjs_MyViewControllerDelegate_optionalName_set"] = function bjs_MyViewControllerDelegate_optionalName_set(self, valueIsSome, valueWord0, valueWord1, valueWord2) { try { let optResult; if (valueIsSome) { - const string = decodeString(valueBytes, valueCount); + const string = decodeString(valueWord0, valueWord1, valueWord2); optResult = string; } else { optResult = null; @@ -672,11 +674,11 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_MyViewControllerDelegate_optionalRawEnum_set"] = function bjs_MyViewControllerDelegate_optionalRawEnum_set(self, valueIsSome, valueBytes, valueCount) { + TestModule["bjs_MyViewControllerDelegate_optionalRawEnum_set"] = function bjs_MyViewControllerDelegate_optionalRawEnum_set(self, valueIsSome, valueWord0, valueWord1, valueWord2) { try { let optResult; if (valueIsSome) { - const string = decodeString(valueBytes, valueCount); + const string = decodeString(valueWord0, valueWord1, valueWord2); optResult = string; } else { optResult = null; @@ -695,9 +697,9 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_MyViewControllerDelegate_rawStringEnum_set"] = function bjs_MyViewControllerDelegate_rawStringEnum_set(self, valueBytes, valueCount) { + TestModule["bjs_MyViewControllerDelegate_rawStringEnum_set"] = function bjs_MyViewControllerDelegate_rawStringEnum_set(self, valueWord0, valueWord1, valueWord2) { try { - const string = decodeString(valueBytes, valueCount); + const string = decodeString(valueWord0, valueWord1, valueWord2); swift.memory.getObject(self).rawStringEnum = string; } catch (error) { setException(error); @@ -818,9 +820,9 @@ export async function createInstantiator(options, swift) { setException(error); } } - TestModule["bjs_MyViewControllerDelegate_onValueChanged"] = function bjs_MyViewControllerDelegate_onValueChanged(self, valueBytes, valueCount) { + TestModule["bjs_MyViewControllerDelegate_onValueChanged"] = function bjs_MyViewControllerDelegate_onValueChanged(self, valueWord0, valueWord1, valueWord2) { try { - const string = decodeString(valueBytes, valueCount); + const string = decodeString(valueWord0, valueWord1, valueWord2); swift.memory.getObject(self).onValueChanged(string); } catch (error) { setException(error); @@ -835,10 +837,10 @@ export async function createInstantiator(options, swift) { return 0 } } - TestModule["bjs_MyViewControllerDelegate_onLabelUpdated"] = function bjs_MyViewControllerDelegate_onLabelUpdated(self, prefixBytes, prefixCount, suffixBytes, suffixCount) { + TestModule["bjs_MyViewControllerDelegate_onLabelUpdated"] = function bjs_MyViewControllerDelegate_onLabelUpdated(self, prefixWord0, prefixWord1, prefixWord2, suffixWord0, suffixWord1, suffixWord2) { try { - const string = decodeString(prefixBytes, prefixCount); - const string1 = decodeString(suffixBytes, suffixCount); + const string = decodeString(prefixWord0, prefixWord1, prefixWord2); + const string1 = decodeString(suffixWord0, suffixWord1, suffixWord2); swift.memory.getObject(self).onLabelUpdated(string, string1); } catch (error) { setException(error); @@ -916,7 +918,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js index eed26c581..e08de3586 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -42,7 +44,7 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, state.file >>> 0); let length = 0; while (bytes[length] !== 0) { length += 1; } - const fileID = decodeString(state.file, length); + const fileID = decodeUTF8(state.file, length); throw new Error(`Attempted to call a released JSTypedClosure created at ${fileID}:${state.line}`); } return func(...args); @@ -64,8 +66,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -73,8 +75,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -99,8 +101,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -167,11 +169,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -363,7 +365,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/RelativeQualifiedTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/RelativeQualifiedTypes.js index 2765d709f..47849439b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/RelativeQualifiedTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/RelativeQualifiedTypes.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -82,8 +84,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -91,8 +93,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -117,8 +119,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -221,11 +223,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -300,7 +302,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js index f46f42d10..7ae9d51ad 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js @@ -20,6 +20,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -83,8 +85,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -92,8 +94,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -118,8 +120,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -187,11 +189,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -262,7 +264,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js index 37d3415a4..53b664598 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js @@ -20,6 +20,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -83,8 +85,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -92,8 +94,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -118,8 +120,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -187,11 +189,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -262,7 +264,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js index e2a9093b6..717352169 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js @@ -14,6 +14,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -44,8 +46,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -53,8 +55,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -79,8 +81,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -148,11 +150,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -223,7 +225,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js index f442745e5..8bc834b09 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js @@ -14,6 +14,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -44,8 +46,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -53,8 +55,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -79,8 +81,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -148,11 +150,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -223,7 +225,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js index ebddbefd2..9c7502cbd 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -40,8 +42,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -49,8 +51,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -75,8 +77,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -143,11 +145,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -206,17 +208,17 @@ export async function createInstantiator(options, swift) { } bjs["swift_js_closure_unregister"] = function(funcRef) {} const TestModule = importObject["TestModule"] = importObject["TestModule"] || {}; - TestModule["bjs_checkString"] = function bjs_checkString(aBytes, aCount) { + TestModule["bjs_checkString"] = function bjs_checkString(aWord0, aWord1, aWord2) { try { - const string = decodeString(aBytes, aCount); + const string = decodeString(aWord0, aWord1, aWord2); imports.checkString(string); } catch (error) { setException(error); } } - TestModule["bjs_checkStringWithLength"] = function bjs_checkStringWithLength(aBytes, aCount, b) { + TestModule["bjs_checkStringWithLength"] = function bjs_checkStringWithLength(aWord0, aWord1, aWord2, b) { try { - const string = decodeString(aBytes, aCount); + const string = decodeString(aWord0, aWord1, aWord2); imports.checkStringWithLength(string, b); } catch (error) { setException(error); @@ -227,7 +229,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js index d2dfa204f..01be76bbd 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -40,8 +42,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -49,8 +51,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -75,8 +77,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -143,11 +145,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -220,7 +222,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StructWithNestedTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StructWithNestedTypes.js index 9104e2084..e7529dee8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StructWithNestedTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StructWithNestedTypes.js @@ -24,6 +24,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -98,8 +100,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -107,8 +109,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -133,8 +135,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -230,11 +232,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -297,7 +299,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js index 92ef435fb..1e17ead5f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -40,8 +42,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -49,8 +51,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -75,8 +77,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -143,11 +145,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -245,7 +247,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js index 279a9d3c6..35ca99800 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js @@ -39,6 +39,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -395,7 +397,7 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, state.file >>> 0); let length = 0; while (bytes[length] !== 0) { length += 1; } - const fileID = decodeString(state.file, length); + const fileID = decodeUTF8(state.file, length); throw new Error(`Attempted to call a released JSTypedClosure created at ${fileID}:${state.line}`); } return func(...args); @@ -501,8 +503,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -510,8 +512,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -536,8 +538,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -584,9 +586,9 @@ export async function createInstantiator(options, swift) { promise[__bjs_promiseSettlers] = { resolve, reject }; return swift.memory.retain(promise); } - bjs["promise_resolve_TestModule_SS"] = function(promise, valueBytes, valueCount) { + bjs["promise_resolve_TestModule_SS"] = function(promise, valueWord0, valueWord1, valueWord2) { try { - const string = decodeString(valueBytes, valueCount); + const string = decodeString(valueWord0, valueWord1, valueWord2); swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(string); } catch (error) { setException(error); @@ -644,11 +646,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -733,10 +735,10 @@ export async function createInstantiator(options, swift) { }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule10HttpStatusO_10HttpStatusO); } - bjs["invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO"] = function(callbackId, param0Bytes, param0Count) { + bjs["invoke_js_callback_TestModule_10TestModule5ThemeO_5ThemeO"] = function(callbackId, param0Word0, param0Word1, param0Word2) { try { const callback = swift.memory.getObject(callbackId); - const string = decodeString(param0Bytes, param0Count); + const string = decodeString(param0Word0, param0Word1, param0Word2); let ret = callback(string); tmpRetBytes = textEncoder.encode(ret); return tmpRetBytes.length; @@ -858,10 +860,10 @@ export async function createInstantiator(options, swift) { }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModule9DirectionO_9DirectionO); } - bjs["invoke_js_callback_TestModule_10TestModuleKSS_Sb"] = function(callbackId, param0Bytes, param0Count) { + bjs["invoke_js_callback_TestModule_10TestModuleKSS_Sb"] = function(callbackId, param0Word0, param0Word1, param0Word2) { try { const callback = swift.memory.getObject(callbackId); - const string = decodeString(param0Bytes, param0Count); + const string = decodeString(param0Word0, param0Word1, param0Word2); let ret = callback(string); return ret ? 1 : 0; } catch (error) { @@ -884,10 +886,10 @@ export async function createInstantiator(options, swift) { }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleKSS_Sb); } - bjs["invoke_js_callback_TestModule_10TestModuleKSS_Si"] = function(callbackId, param0Bytes, param0Count) { + bjs["invoke_js_callback_TestModule_10TestModuleKSS_Si"] = function(callbackId, param0Word0, param0Word1, param0Word2) { try { const callback = swift.memory.getObject(callbackId); - const string = decodeString(param0Bytes, param0Count); + const string = decodeString(param0Word0, param0Word1, param0Word2); let ret = callback(string); return ret; } catch (error) { @@ -910,10 +912,10 @@ export async function createInstantiator(options, swift) { }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleKSS_Si); } - bjs["invoke_js_callback_TestModule_10TestModuleSS_SS"] = function(callbackId, param0Bytes, param0Count) { + bjs["invoke_js_callback_TestModule_10TestModuleSS_SS"] = function(callbackId, param0Word0, param0Word1, param0Word2) { try { const callback = swift.memory.getObject(callbackId); - const string = decodeString(param0Bytes, param0Count); + const string = decodeString(param0Word0, param0Word1, param0Word2); let ret = callback(string); tmpRetBytes = textEncoder.encode(ret); return tmpRetBytes.length; @@ -1056,12 +1058,12 @@ export async function createInstantiator(options, swift) { }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq10HttpStatusO_Sq10HttpStatusO); } - bjs["invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO"] = function(callbackId, param0IsSome, param0Bytes, param0Count) { + bjs["invoke_js_callback_TestModule_10TestModuleSq5ThemeO_Sq5ThemeO"] = function(callbackId, param0IsSome, param0Word0, param0Word1, param0Word2) { try { const callback = swift.memory.getObject(callbackId); let optResult; if (param0IsSome) { - const string = decodeString(param0Bytes, param0Count); + const string = decodeString(param0Word0, param0Word1, param0Word2); optResult = string; } else { optResult = null; @@ -1228,12 +1230,12 @@ export async function createInstantiator(options, swift) { }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSq9DirectionO_Sq9DirectionO); } - bjs["invoke_js_callback_TestModule_10TestModuleSqSS_SqSS"] = function(callbackId, param0IsSome, param0Bytes, param0Count) { + bjs["invoke_js_callback_TestModule_10TestModuleSqSS_SqSS"] = function(callbackId, param0IsSome, param0Word0, param0Word1, param0Word2) { try { const callback = swift.memory.getObject(callbackId); let optResult; if (param0IsSome) { - const string = decodeString(param0Bytes, param0Count); + const string = decodeString(param0Word0, param0Word1, param0Word2); optResult = string; } else { optResult = null; @@ -1375,11 +1377,11 @@ export async function createInstantiator(options, swift) { }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSqSi_SqSi); } - bjs["invoke_js_callback_TestModule_10TestModuleYaKSS_SS"] = function(resolveRef, rejectRef, callbackId, param0Bytes, param0Count) { + bjs["invoke_js_callback_TestModule_10TestModuleYaKSS_SS"] = function(resolveRef, rejectRef, callbackId, param0Word0, param0Word1, param0Word2) { const resolve = swift.memory.getObject(resolveRef); const reject = swift.memory.getObject(rejectRef); const callback = swift.memory.getObject(callbackId); - const string = decodeString(param0Bytes, param0Count); + const string = decodeString(param0Word0, param0Word1, param0Word2); callback(string).then(resolve, reject); } bjs["make_swift_closure_TestModule_10TestModuleYaKSS_SS"] = function(boxPtr, file, line) { @@ -1420,11 +1422,11 @@ export async function createInstantiator(options, swift) { }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleYaKSb_9APIResultO); } - bjs["invoke_js_callback_TestModule_10TestModuleYaSS_6AnimalV"] = function(resolveRef, rejectRef, callbackId, param0Bytes, param0Count) { + bjs["invoke_js_callback_TestModule_10TestModuleYaSS_6AnimalV"] = function(resolveRef, rejectRef, callbackId, param0Word0, param0Word1, param0Word2) { const resolve = swift.memory.getObject(resolveRef); const reject = swift.memory.getObject(rejectRef); const callback = swift.memory.getObject(callbackId); - const string = decodeString(param0Bytes, param0Count); + const string = decodeString(param0Word0, param0Word1, param0Word2); callback(string).then(resolve, reject); } bjs["make_swift_closure_TestModule_10TestModuleYaSS_6AnimalV"] = function(boxPtr, file, line) { @@ -1438,11 +1440,11 @@ export async function createInstantiator(options, swift) { }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleYaSS_6AnimalV); } - bjs["invoke_js_callback_TestModule_10TestModuleYaSS_SS"] = function(resolveRef, rejectRef, callbackId, param0Bytes, param0Count) { + bjs["invoke_js_callback_TestModule_10TestModuleYaSS_SS"] = function(resolveRef, rejectRef, callbackId, param0Word0, param0Word1, param0Word2) { const resolve = swift.memory.getObject(resolveRef); const reject = swift.memory.getObject(rejectRef); const callback = swift.memory.getObject(callbackId); - const string = decodeString(param0Bytes, param0Count); + const string = decodeString(param0Word0, param0Word1, param0Word2); callback(string).then(resolve, reject); } bjs["make_swift_closure_TestModule_10TestModuleYaSS_SS"] = function(boxPtr, file, line) { @@ -1522,10 +1524,10 @@ export async function createInstantiator(options, swift) { }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModules9APIResultO_y); } - bjs["invoke_js_callback_TestModule_10TestModulesSS_y"] = function(callbackId, param0Bytes, param0Count) { + bjs["invoke_js_callback_TestModule_10TestModulesSS_y"] = function(callbackId, param0Word0, param0Word1, param0Word2) { try { const callback = swift.memory.getObject(callbackId); - const string = decodeString(param0Bytes, param0Count); + const string = decodeString(param0Word0, param0Word1, param0Word2); callback(string); } catch (error) { setException(error); @@ -1562,7 +1564,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js index 96c78dd22..c1b3bec76 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -131,7 +133,7 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, state.file >>> 0); let length = 0; while (bytes[length] !== 0) { length += 1; } - const fileID = decodeString(state.file, length); + const fileID = decodeUTF8(state.file, length); throw new Error(`Attempted to call a released JSTypedClosure created at ${fileID}:${state.line}`); } return func(...args); @@ -154,8 +156,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -163,8 +165,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -189,8 +191,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -229,9 +231,9 @@ export async function createInstantiator(options, swift) { promise[__bjs_promiseSettlers] = { resolve, reject }; return swift.memory.retain(promise); } - bjs["promise_resolve_TestModule_SS"] = function(promise, valueBytes, valueCount) { + bjs["promise_resolve_TestModule_SS"] = function(promise, valueWord0, valueWord1, valueWord2) { try { - const string = decodeString(valueBytes, valueCount); + const string = decodeString(valueWord0, valueWord1, valueWord2); swift.memory.getObject(promise)[__bjs_promiseSettlers].resolve(string); } catch (error) { setException(error); @@ -273,11 +275,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -339,10 +341,10 @@ export async function createInstantiator(options, swift) { const func = swift.memory.getObject(funcRef); func.__unregister(); } - bjs["invoke_js_callback_TestModule_10TestModuleKSS_Sb"] = function(callbackId, param0Bytes, param0Count) { + bjs["invoke_js_callback_TestModule_10TestModuleKSS_Sb"] = function(callbackId, param0Word0, param0Word1, param0Word2) { try { const callback = swift.memory.getObject(callbackId); - const string = decodeString(param0Bytes, param0Count); + const string = decodeString(param0Word0, param0Word1, param0Word2); let ret = callback(string); return ret ? 1 : 0; } catch (error) { @@ -388,11 +390,11 @@ export async function createInstantiator(options, swift) { }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModuleSi_Si); } - bjs["invoke_js_callback_TestModule_10TestModuleYaKSS_SS"] = function(resolveRef, rejectRef, callbackId, param0Bytes, param0Count) { + bjs["invoke_js_callback_TestModule_10TestModuleYaKSS_SS"] = function(resolveRef, rejectRef, callbackId, param0Word0, param0Word1, param0Word2) { const resolve = swift.memory.getObject(resolveRef); const reject = swift.memory.getObject(rejectRef); const callback = swift.memory.getObject(callbackId); - const string = decodeString(param0Bytes, param0Count); + const string = decodeString(param0Word0, param0Word1, param0Word2); callback(string).then(resolve, reject); } bjs["make_swift_closure_TestModule_10TestModuleYaKSS_SS"] = function(boxPtr, file, line) { @@ -434,10 +436,10 @@ export async function createInstantiator(options, swift) { }; return makeClosure(boxPtr, file, line, lower_closure_TestModule_10TestModules7JSValueV_y); } - bjs["invoke_js_callback_TestModule_10TestModulesSS_y"] = function(callbackId, param0Bytes, param0Count) { + bjs["invoke_js_callback_TestModule_10TestModulesSS_y"] = function(callbackId, param0Word0, param0Word1, param0Word2) { try { const callback = swift.memory.getObject(callbackId); - const string = decodeString(param0Bytes, param0Count); + const string = decodeString(param0Word0, param0Word1, param0Word2); callback(string); } catch (error) { setException(error); @@ -484,7 +486,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js index 0bfd7c2e2..52ebbfc22 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js @@ -14,6 +14,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -544,8 +546,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -553,8 +555,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -579,8 +581,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -704,11 +706,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -779,7 +781,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js index 134d7c28e..f793de7fc 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -385,8 +387,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -394,8 +396,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -420,8 +422,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -496,11 +498,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -582,7 +584,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.js index 500a005a3..6f5e2ac06 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -42,7 +44,7 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, state.file >>> 0); let length = 0; while (bytes[length] !== 0) { length += 1; } - const fileID = decodeString(state.file, length); + const fileID = decodeUTF8(state.file, length); throw new Error(`Attempted to call a released JSTypedClosure created at ${fileID}:${state.line}`); } return func(...args); @@ -64,8 +66,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -73,8 +75,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -99,8 +101,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -167,11 +169,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -327,7 +329,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js index 58ff6a85a..4a5cec34c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -39,8 +41,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -48,8 +50,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -74,8 +76,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -142,11 +144,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -209,7 +211,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js index 416e5c281..56bc6b1ac 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -56,8 +58,8 @@ export async function createInstantiator(options, swift) { addImports: (importObject, importsContext) => { bjs = {}; importObject["bjs"] = bjs; - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -65,8 +67,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -91,8 +93,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -167,11 +169,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -234,7 +236,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js index 81b09eaf4..63d6a1a6a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js @@ -9,6 +9,8 @@ export async function createInstantiator(options, swift) { let memory; let setException; let decodeString; + let decodeUTF8; + const immortalStrings = new Map(); const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); let tmpRetString; @@ -40,8 +42,8 @@ export async function createInstantiator(options, swift) { bjs = {}; importObject["bjs"] = bjs; const imports = options.getImports(importsContext); - bjs["swift_js_return_string"] = function(ptr, len) { - tmpRetString = decodeString(ptr, len); + bjs["swift_js_return_string"] = function(word0, word1, word2) { + tmpRetString = decodeString(word0, word1, word2); } bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); @@ -49,8 +51,8 @@ export async function createInstantiator(options, swift) { const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } - bjs["swift_js_make_js_string"] = function(ptr, len) { - return swift.memory.retain(decodeString(ptr, len)); + bjs["swift_js_make_js_string"] = function(word0, word1, word2) { + return swift.memory.retain(decodeString(word0, word1, word2)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); @@ -75,8 +77,8 @@ export async function createInstantiator(options, swift) { bjs["swift_js_push_f64"] = function(v) { f64Stack.push(v); } - bjs["swift_js_push_string"] = function(ptr, len) { - const value = decodeString(ptr, len); + bjs["swift_js_push_string"] = function(word0, word1, word2) { + const value = decodeString(word0, word1, word2); strStack.push(value); } bjs["swift_js_pop_i32"] = function() { @@ -143,11 +145,11 @@ export async function createInstantiator(options, swift) { tmpRetOptionalDouble = value; } } - bjs["swift_js_return_optional_string"] = function(isSome, ptr, len) { + bjs["swift_js_return_optional_string"] = function(isSome, word0, word1, word2) { if (isSome === 0) { tmpRetString = null; } else { - tmpRetString = decodeString(ptr, len); + tmpRetString = decodeString(word0, word1, word2); } } bjs["swift_js_return_optional_object"] = function(isSome, objectId) { @@ -218,7 +220,68 @@ export async function createInstantiator(options, swift) { instance = i; memory = instance.exports.memory; - decodeString = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } + decodeString = (() => { + const byteAt = (word0, word1, word2, i) => { + if (i < 4) return (word0 >>> (i * 8)) & 0xff; + if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; + if (i === 8) return word2 & 0xff; + return (word2 >>> 16) & 0xff; + }; + const decodeSmallUTF8 = (word0, word1, word2, count) => { + let result = ""; + let i = 0; + while (i < count) { + const b0 = byteAt(word0, word1, word2, i++); + let codePoint; + if (b0 < 0x80) { + codePoint = b0; + } else if (b0 < 0xe0) { + codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); + } else if (b0 < 0xf0) { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + } else { + const b1 = byteAt(word0, word1, word2, i++); + const b2 = byteAt(word0, word1, word2, i++); + const b3 = byteAt(word0, word1, word2, i++); + codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + } + result += String.fromCodePoint(codePoint); + } + return result; + }; + const decodeSmall = (word0, word1, word2) => { + const count = (word2 >>> 8) & 0x0f; + if ((word2 & 0x4000 /* ASCII */) === 0) return decodeSmallUTF8(word0, word1, word2, count); + const char = String.fromCharCode; + switch (count) { + case 0: return ""; + case 1: return char(word0 & 0xff); + case 2: return char(word0 & 0xff, (word0 >>> 8) & 0xff); + case 3: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff); + case 4: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24); + case 5: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff); + case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); + case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); + case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); + default: return decodeSmallUTF8(word0, word1, word2, count); + } + }; + return (word0, word1, word2) => { + if (word2 & 0x2000 /* small */) return decodeSmall(word0, word1, word2); + const ptr = (word1 + 20 /* nativeBias */) >>> 0; + const len = word0 >>> 0; + if ((word2 & 0x8000 /* immortal */) === 0 || len >= 0x200000 /* 2^21 Number key */) return decodeUTF8(ptr, len); + const key = ptr + len * 0x100000000; + const cached = immortalStrings.get(key); + if (cached !== undefined) return cached; + const value = decodeUTF8(ptr, len); + immortalStrings.set(key, value); + return value; + }; + })(); setException = (error) => { instance.exports._swift_js_exception.value = swift.memory.retain(error) diff --git a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift index 6946d6a59..dd5e1e970 100644 --- a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift +++ b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift @@ -452,7 +452,7 @@ extension _BridgedSwiftAlias where JSRepresentation: _BridgedSwiftAssociatedValu extension _BridgedSwiftAlias where JSRepresentation == String { // MARK: ImportTS - @_spi(BridgeJS) public consuming func bridgeJSWithLoweredParameter(_ body: (Int32, Int32) -> T) -> T { + @_spi(BridgeJS) public consuming func bridgeJSWithLoweredParameter(_ body: (Int32, Int32, Int32) -> T) -> T { bridgeToJS().bridgeJSWithLoweredParameter(body) } @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ bytesCount: Int32) -> Self { @@ -476,7 +476,7 @@ extension _BridgedSwiftAlias where JSRepresentation == String { extension _BridgedAsOptional where Wrapped: _BridgedSwiftAlias, Wrapped.JSRepresentation == String { @_spi(BridgeJS) public consuming func bridgeJSWithLoweredParameter( - _ body: (Int32, Int32, Int32) -> T + _ body: (Int32, Int32, Int32, Int32) -> T ) -> T { asOptional.map { $0.bridgeToJS() }.bridgeJSWithLoweredParameter(body) } @@ -798,12 +798,29 @@ extension Double: _BridgedSwiftTypeLoweredIntoSingleWasmCoreType, _BridgedSwiftS extension String: _BridgedSwiftStackType { public typealias StackLiftResult = String + /// Lends the three wasm32 `String` words to `body` for the duration of a synchronous JS call. + /// + /// The 12-byte layout is a Swift stdlib implementation detail. JS interprets small-string + /// flags in `word2` and, for large strings, UTF-8 at `word1 + 20` (`nativeBias` on 32-bit). + @inline(__always) + fileprivate consuming func withBridgeJSRawWords(_ body: (Int32, Int32, Int32) -> Result) -> Result { + #if arch(wasm32) + return withUnsafeBytes(of: self) { bytes in + precondition(bytes.count == 12, "BridgeJS expects the 12-byte wasm32 String layout") + let word0 = bytes.load(fromByteOffset: 0, as: Int32.self) + let word1 = bytes.load(fromByteOffset: 4, as: Int32.self) + let word2 = bytes.load(fromByteOffset: 8, as: Int32.self) + return body(word0, word1, word2) + } + #else + _onlyAvailableOnWasm() + #endif + } + // MARK: ImportTS - @_spi(BridgeJS) public consuming func bridgeJSWithLoweredParameter(_ body: (Int32, Int32) -> T) -> T { - return self.withUTF8 { b in - body(Int32(bitPattern: UInt32(UInt(bitPattern: b.baseAddress))), Int32(b.count)) - } + @_spi(BridgeJS) public consuming func bridgeJSWithLoweredParameter(_ body: (Int32, Int32, Int32) -> T) -> T { + withBridgeJSRawWords(body) } @_spi(BridgeJS) public static func bridgeJSLiftReturn(_ bytesCount: Int32) -> String { @@ -835,14 +852,14 @@ extension String: _BridgedSwiftStackType { } @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { - return self.withUTF8 { ptr in - _swift_js_return_string(ptr.baseAddress, Int32(ptr.count)) + withBridgeJSRawWords { word0, word1, word2 in + _swift_js_return_string(word0, word1, word2) } } @_spi(BridgeJS) public consuming func bridgeJSStackPush() { - self.withUTF8 { ptr in - _swift_js_push_string(ptr.baseAddress, Int32(ptr.count)) + withBridgeJSRawWords { word0, word1, word2 in + _swift_js_push_string(word0, word1, word2) } } } @@ -1290,7 +1307,7 @@ extension _BridgedSwiftStruct { extension _BridgedSwiftEnumNoPayload where Self: RawRepresentable, RawValue == String { // MARK: ImportTS - @_spi(BridgeJS) public consuming func bridgeJSWithLoweredParameter(_ body: (Int32, Int32) -> T) -> T { + @_spi(BridgeJS) public consuming func bridgeJSWithLoweredParameter(_ body: (Int32, Int32, Int32) -> T) -> T { rawValue.bridgeJSWithLoweredParameter(body) } @@ -1348,15 +1365,15 @@ private func _swift_js_init_memory_extern(_ sourceId: Int32, _ ptr: UnsafeMutabl #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_push_string") -private func _swift_js_push_string_extern(_ ptr: UnsafePointer?, _ len: Int32) +private func _swift_js_push_string_extern(_ word0: Int32, _ word1: Int32, _ word2: Int32) #else -private func _swift_js_push_string_extern(_ ptr: UnsafePointer?, _ len: Int32) { +private func _swift_js_push_string_extern(_ word0: Int32, _ word1: Int32, _ word2: Int32) { _onlyAvailableOnWasm() } #endif -@_spi(BridgeJS) @inline(never) public func _swift_js_push_string(_ ptr: UnsafePointer?, _ len: Int32) { - _swift_js_push_string_extern(ptr, len) +@_spi(BridgeJS) @inline(never) public func _swift_js_push_string(_ word0: Int32, _ word1: Int32, _ word2: Int32) { + _swift_js_push_string_extern(word0, word1, word2) } #if arch(wasm32) @@ -1542,15 +1559,15 @@ extension UInt: _BridgedNumericArray { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_make_js_string") -private func _swift_js_make_js_string_extern(_ ptr: UnsafePointer?, _ len: Int32) -> Int32 +private func _swift_js_make_js_string_extern(_ word0: Int32, _ word1: Int32, _ word2: Int32) -> Int32 #else -/// Creates a JavaScript string from UTF-8 data in WebAssembly memory -private func _swift_js_make_js_string_extern(_ ptr: UnsafePointer?, _ len: Int32) -> Int32 { +/// Creates a JavaScript string from the wasm32 Swift `String` layout words +private func _swift_js_make_js_string_extern(_ word0: Int32, _ word1: Int32, _ word2: Int32) -> Int32 { _onlyAvailableOnWasm() } #endif -@inline(never) func _swift_js_make_js_string(_ ptr: UnsafePointer?, _ len: Int32) -> Int32 { - _swift_js_make_js_string_extern(ptr, len) +@inline(never) func _swift_js_make_js_string(_ word0: Int32, _ word1: Int32, _ word2: Int32) -> Int32 { + _swift_js_make_js_string_extern(word0, word1, word2) } #if arch(wasm32) @@ -1568,15 +1585,15 @@ private func _swift_js_init_memory_with_result_extern(_ ptr: UnsafePointer?, _ len: Int32) +private func _swift_js_return_string_extern(_ word0: Int32, _ word1: Int32, _ word2: Int32) #else /// Write a string to reserved string storage to be returned to JavaScript -private func _swift_js_return_string_extern(_ ptr: UnsafePointer?, _ len: Int32) { +private func _swift_js_return_string_extern(_ word0: Int32, _ word1: Int32, _ word2: Int32) { _onlyAvailableOnWasm() } #endif -@inline(never) func _swift_js_return_string(_ ptr: UnsafePointer?, _ len: Int32) { - _swift_js_return_string_extern(ptr, len) +@inline(never) func _swift_js_return_string(_ word0: Int32, _ word1: Int32, _ word2: Int32) { + _swift_js_return_string_extern(word0, word1, word2) } #if arch(wasm32) @@ -1657,15 +1674,15 @@ private func _swift_js_get_optional_string_extern() -> Int32 { #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_return_optional_string") -private func _swift_js_return_optional_string_extern(_ isSome: Int32, _ ptr: UnsafePointer?, _ len: Int32) +private func _swift_js_return_optional_string_extern(_ isSome: Int32, _ word0: Int32, _ word1: Int32, _ word2: Int32) #else /// Write an optional string to reserved string storage to be returned to JavaScript -private func _swift_js_return_optional_string_extern(_ isSome: Int32, _ ptr: UnsafePointer?, _ len: Int32) { +private func _swift_js_return_optional_string_extern(_ isSome: Int32, _ word0: Int32, _ word1: Int32, _ word2: Int32) { _onlyAvailableOnWasm() } #endif -@inline(never) func _swift_js_return_optional_string(_ isSome: Int32, _ ptr: UnsafePointer?, _ len: Int32) { - _swift_js_return_optional_string_extern(isSome, ptr, len) +@inline(never) func _swift_js_return_optional_string(_ isSome: Int32, _ word0: Int32, _ word1: Int32, _ word2: Int32) { + _swift_js_return_optional_string_extern(isSome, word0, word1, word2) } #if arch(wasm32) @@ -2156,14 +2173,14 @@ extension _BridgedAsOptional where Wrapped == Bool { extension _BridgedAsOptional where Wrapped == String { @_spi(BridgeJS) @_transparent public consuming func bridgeJSWithLoweredParameter( - _ body: (Int32, Int32, Int32) -> T + _ body: (Int32, Int32, Int32, Int32) -> T ) -> T { switch asOptional { case .none: - return body(0, 0, 0) + return body(0, 0, 0, 0) case .some(let value): - return value.bridgeJSWithLoweredParameter { bytes, count in - return body(1, bytes, count) + return value.bridgeJSWithLoweredParameter { word0, word1, word2 in + return body(1, word0, word1, word2) } } } @@ -2194,10 +2211,10 @@ extension _BridgedAsOptional where Wrapped == String { @_spi(BridgeJS) public consuming func bridgeJSLowerReturn() -> Void { switch asOptional { case .none: - _swift_js_return_optional_string(0, nil, 0) - case .some(var value): - value.withUTF8 { ptr in - _swift_js_return_optional_string(1, ptr.baseAddress, Int32(ptr.count)) + _swift_js_return_optional_string(0, 0, 0, 0) + case .some(let value): + value.withBridgeJSRawWords { word0, word1, word2 in + _swift_js_return_optional_string(1, word0, word1, word2) } } } @@ -2358,14 +2375,14 @@ extension _BridgedAsOptional where Wrapped: _BridgedSwiftCaseEnum { extension _BridgedAsOptional where Wrapped: _BridgedSwiftEnumNoPayload, Wrapped: RawRepresentable, Wrapped.RawValue == String { @_spi(BridgeJS) @_transparent public consuming func bridgeJSWithLoweredParameter( - _ body: (Int32, Int32, Int32) -> T + _ body: (Int32, Int32, Int32, Int32) -> T ) -> T { switch asOptional { case .none: - return body(0, 0, 0) + return body(0, 0, 0, 0) case .some(let wrapped): - return wrapped.bridgeJSWithLoweredParameter { bytes, count in - return body(1, bytes, count) + return wrapped.bridgeJSWithLoweredParameter { word0, word1, word2 in + return body(1, word0, word1, word2) } } } diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index acb3e23f1..7118f688f 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -202,14 +202,14 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests13D #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS") -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 #else -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { - return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS_extern(callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS_extern(callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -229,9 +229,9 @@ private enum _BJS_Closure_20BridgeJSRuntimeTests5ThemeO_SS { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) - let ret0 = param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + let ret0 = param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS(callbackValue, param0Bytes, param0Length) + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_SS(callbackValue, param0Word0, param0Word1, param0Word2) return ret } let ret = ret0 @@ -269,14 +269,14 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5Th #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb") -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 #else -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { - return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb_extern(callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb_extern(callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -296,9 +296,9 @@ private enum _BJS_Closure_20BridgeJSRuntimeTests5ThemeO_Sb { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) - let ret0 = param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + let ret0 = param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb(callbackValue, param0Bytes, param0Length) + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTests5ThemeO_Sb(callbackValue, param0Word0, param0Word1, param0Word2) return ret } let ret = ret0 @@ -846,14 +846,14 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsAl7 #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Sb") -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Sb_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Sb_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 #else -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Sb_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Sb_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Sb(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { - return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Sb_extern(callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Sb(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Sb_extern(callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -873,9 +873,9 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsKSS_Sb { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] (param0: String) throws(JSException) -> Bool in #if arch(wasm32) - let ret0 = param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + let ret0 = param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Sb(callbackValue, param0Bytes, param0Length) + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Sb(callbackValue, param0Word0, param0Word1, param0Word2) return ret } let ret = ret0 @@ -930,14 +930,14 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Si") -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Si_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Si_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 #else -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Si_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Si_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Si(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { - return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Si_extern(callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Si(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Si_extern(callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -957,9 +957,9 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsKSS_Si { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] (param0: String) throws(JSException) -> Int in #if arch(wasm32) - let ret0 = param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + let ret0 = param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Si(callbackValue, param0Bytes, param0Length) + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS_Si(callbackValue, param0Word0, param0Word1, param0Word2) return ret } let ret = ret0 @@ -1014,14 +1014,14 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsKSS #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC") -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> UnsafeMutableRawPointer +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> UnsafeMutableRawPointer #else -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> UnsafeMutableRawPointer { +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> UnsafeMutableRawPointer { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> UnsafeMutableRawPointer { - return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC_extern(callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> UnsafeMutableRawPointer { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC_extern(callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -1041,9 +1041,9 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsSS_7GreeterC { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) - let ret0 = param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + let ret0 = param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC(callbackValue, param0Bytes, param0Length) + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_7GreeterC(callbackValue, param0Word0, param0Word1, param0Word2) return ret } let ret = ret0 @@ -1081,14 +1081,14 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_ #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS") -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 #else -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { - return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS_extern(callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS_extern(callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -1108,9 +1108,9 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsSS_SS { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) - let ret0 = param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + let ret0 = param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS(callbackValue, param0Bytes, param0Length) + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSS_SS(callbackValue, param0Word0, param0Word1, param0Word2) return ret } let ret = ret0 @@ -1726,14 +1726,14 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSd_ #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS") -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS_extern(_ callback: Int32, _ param0: Int32, _ param1Bytes: Int32, _ param1Length: Int32, _ param2: Float64) -> Int32 +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS_extern(_ callback: Int32, _ param0: Int32, _ param1Word0: Int32, _ param1Word1: Int32, _ param1Word2: Int32, _ param2: Float64) -> Int32 #else -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS_extern(_ callback: Int32, _ param0: Int32, _ param1Bytes: Int32, _ param1Length: Int32, _ param2: Float64) -> Int32 { +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS_extern(_ callback: Int32, _ param0: Int32, _ param1Word0: Int32, _ param1Word1: Int32, _ param1Word2: Int32, _ param2: Float64) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS(_ callback: Int32, _ param0: Int32, _ param1Bytes: Int32, _ param1Length: Int32, _ param2: Float64) -> Int32 { - return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS_extern(callback, param0, param1Bytes, param1Length, param2) +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS(_ callback: Int32, _ param0: Int32, _ param1Word0: Int32, _ param1Word1: Int32, _ param1Word2: Int32, _ param2: Float64) -> Int32 { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS_extern(callback, param0, param1Word0, param1Word1, param1Word2, param2) } #if arch(wasm32) @@ -1753,11 +1753,11 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsSiSSSd_SS { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] (param0, param1, param2) in #if arch(wasm32) - let ret0 = param1.bridgeJSWithLoweredParameter { (param1Bytes, param1Length) in + let ret0 = param1.bridgeJSWithLoweredParameter { (param1Word0, param1Word1, param1Word2) in let param2Value = param2.bridgeJSLowerParameter() let param0Value = param0.bridgeJSLowerParameter() let callbackValue = callback.bridgeJSLowerParameter() - let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS(callbackValue, param0Value, param1Bytes, param1Length, param2Value) + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSiSSSd_SS(callbackValue, param0Value, param1Word0, param1Word1, param1Word2, param2Value) return ret } let ret = ret0 @@ -2126,14 +2126,14 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq1 #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS") -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 #else -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { - return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS_extern(callback, param0IsSome, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS_extern(callback, param0IsSome, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -2153,9 +2153,9 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsSq5ThemeO_SS { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) - let ret0 = param0.bridgeJSWithLoweredParameter { (param0IsSome, param0Bytes, param0Length) in + let ret0 = param0.bridgeJSWithLoweredParameter { (param0IsSome, param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS(callbackValue, param0IsSome, param0Bytes, param0Length) + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq5ThemeO_SS(callbackValue, param0IsSome, param0Word0, param0Word1, param0Word2) return ret } let ret = ret0 @@ -2449,14 +2449,14 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSq9 #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS") -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 #else -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Int32 { - return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS_extern(callback, param0IsSome, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS(_ callback: Int32, _ param0IsSome: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Int32 { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS_extern(callback, param0IsSome, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -2476,9 +2476,9 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsSqSS_SS { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) - let ret0 = param0.bridgeJSWithLoweredParameter { (param0IsSome, param0Bytes, param0Length) in + let ret0 = param0.bridgeJSWithLoweredParameter { (param0IsSome, param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS(callbackValue, param0IsSome, param0Bytes, param0Length) + let ret = invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqSS_SS(callbackValue, param0IsSome, param0Word0, param0Word1, param0Word2) return ret } let ret = ret0 @@ -2580,14 +2580,14 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsSqS #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_SS") -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_SS_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_SS_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void #else -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_SS_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_SS_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_SS(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { - return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_SS_extern(resolveRef, rejectRef, callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_SS(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_SS_extern(resolveRef, rejectRef, callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -2612,9 +2612,9 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsYaKSS_SS { }, makeRejectClosure: { JSTypedClosure<(sending JSValue) -> Void>.sending($0) }) { resolveRef, rejectRef in - param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_SS(resolveRef, rejectRef, callbackValue, param0Bytes, param0Length) + invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_SS(resolveRef, rejectRef, callbackValue, param0Word0, param0Word1, param0Word2) } } return resolved @@ -2652,14 +2652,14 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaK #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_y") -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_y_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_y_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void #else -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_y_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_y_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_y(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { - return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_y_extern(resolveRef, rejectRef, callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_y(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_y_extern(resolveRef, rejectRef, callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -2684,9 +2684,9 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsYaKSS_y { }, makeRejectClosure: { JSTypedClosure<(sending JSValue) -> Void>.sending($0) }) { resolveRef, rejectRef in - param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_y(resolveRef, rejectRef, callbackValue, param0Bytes, param0Length) + invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaKSS_y(resolveRef, rejectRef, callbackValue, param0Word0, param0Word1, param0Word2) } } #else @@ -2794,14 +2794,14 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaK #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaSS_SS") -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaSS_SS_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaSS_SS_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void #else -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaSS_SS_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaSS_SS_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaSS_SS(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { - return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaSS_SS_extern(resolveRef, rejectRef, callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaSS_SS(_ resolveRef: Int32, _ rejectRef: Int32, _ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaSS_SS_extern(resolveRef, rejectRef, callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -2826,9 +2826,9 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestsYaSS_SS { }, makeRejectClosure: { JSTypedClosure<(sending JSValue) -> Void>.sending($0) }) { resolveRef, rejectRef in - param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaSS_SS(resolveRef, rejectRef, callbackValue, param0Bytes, param0Length) + invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaSS_SS(resolveRef, rejectRef, callbackValue, param0Word0, param0Word1, param0Word2) } } return resolved @@ -3008,14 +3008,14 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestsYaS #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss11FeatureFlagO_y") -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss11FeatureFlagO_y_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss11FeatureFlagO_y_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void #else -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss11FeatureFlagO_y_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss11FeatureFlagO_y_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss11FeatureFlagO_y(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { - return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss11FeatureFlagO_y_extern(callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss11FeatureFlagO_y(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss11FeatureFlagO_y_extern(callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -3035,9 +3035,9 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestss11FeatureFlagO_y { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) - param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss11FeatureFlagO_y(callbackValue, param0Bytes, param0Length) + invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss11FeatureFlagO_y(callbackValue, param0Word0, param0Word1, param0Word2) } #else fatalError("Only available on WebAssembly") @@ -3381,14 +3381,14 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestss9D #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSS_y") -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSS_y_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSS_y_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void #else -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSS_y_extern(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSS_y_extern(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSS_y(_ callback: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { - return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSS_y_extern(callback, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSS_y(_ callback: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSS_y_extern(callback, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -3408,9 +3408,9 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestssSS_y { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) - param0.bridgeJSWithLoweredParameter { (param0Bytes, param0Length) in + param0.bridgeJSWithLoweredParameter { (param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSS_y(callbackValue, param0Bytes, param0Length) + invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSS_y(callbackValue, param0Word0, param0Word1, param0Word2) } #else fatalError("Only available on WebAssembly") @@ -3878,14 +3878,14 @@ public func _invoke_swift_closure_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSq #if arch(wasm32) @_extern(wasm, module: "bjs", name: "invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSqSS_y") -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSqSS_y_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSqSS_y_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void #else -fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSqSS_y_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { +fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSqSS_y_extern(_ callback: Int32, _ param0IsSome: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSqSS_y(_ callback: Int32, _ param0IsSome: Int32, _ param0Bytes: Int32, _ param0Length: Int32) -> Void { - return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSqSS_y_extern(callback, param0IsSome, param0Bytes, param0Length) +@inline(never) fileprivate func invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSqSS_y(_ callback: Int32, _ param0IsSome: Int32, _ param0Word0: Int32, _ param0Word1: Int32, _ param0Word2: Int32) -> Void { + return invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSqSS_y_extern(callback, param0IsSome, param0Word0, param0Word1, param0Word2) } #if arch(wasm32) @@ -3905,9 +3905,9 @@ private enum _BJS_Closure_20BridgeJSRuntimeTestssSqSS_y { let callback = JSObject.bridgeJSLiftParameter(callbackId) return { [callback] param0 in #if arch(wasm32) - param0.bridgeJSWithLoweredParameter { (param0IsSome, param0Bytes, param0Length) in + param0.bridgeJSWithLoweredParameter { (param0IsSome, param0Word0, param0Word1, param0Word2) in let callbackValue = callback.bridgeJSLowerParameter() - invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSqSS_y(callbackValue, param0IsSome, param0Bytes, param0Length) + invoke_js_callback_BridgeJSRuntimeTests_20BridgeJSRuntimeTestssSqSS_y(callbackValue, param0IsSome, param0Word0, param0Word1, param0Word2) } #else fatalError("Only available on WebAssembly") @@ -4308,10 +4308,10 @@ extension DataProcessor where Self: _BridgedSwiftProtocolWrapper { } func setLabelElements(_ labelPrefix: String, _ labelSuffix: String) -> Void { - labelPrefix.bridgeJSWithLoweredParameter { (labelPrefixBytes, labelPrefixLength) in - labelSuffix.bridgeJSWithLoweredParameter { (labelSuffixBytes, labelSuffixLength) in + labelPrefix.bridgeJSWithLoweredParameter { (labelPrefixWord0, labelPrefixWord1, labelPrefixWord2) in + labelSuffix.bridgeJSWithLoweredParameter { (labelSuffixWord0, labelSuffixWord1, labelSuffixWord2) in let jsObjectValue = jsObject.bridgeJSLowerParameter() - bjs_DataProcessor_setLabelElements(jsObjectValue, labelPrefixBytes, labelPrefixLength, labelSuffixBytes, labelSuffixLength) + bjs_DataProcessor_setLabelElements(jsObjectValue, labelPrefixWord0, labelPrefixWord1, labelPrefixWord2, labelSuffixWord0, labelSuffixWord1, labelSuffixWord2) } } } @@ -4394,9 +4394,9 @@ extension DataProcessor where Self: _BridgedSwiftProtocolWrapper { return Optional.bridgeJSLiftReturnFromSideChannel() } set { - newValue.bridgeJSWithLoweredParameter { (newValueIsSome, newValueBytes, newValueLength) in + newValue.bridgeJSWithLoweredParameter { (newValueIsSome, newValueWord0, newValueWord1, newValueWord2) in let jsObjectValue = jsObject.bridgeJSLowerParameter() - bjs_DataProcessor_optionalTag_set(jsObjectValue, newValueIsSome, newValueBytes, newValueLength) + bjs_DataProcessor_optionalTag_set(jsObjectValue, newValueIsSome, newValueWord0, newValueWord1, newValueWord2) } } } @@ -4434,9 +4434,9 @@ extension DataProcessor where Self: _BridgedSwiftProtocolWrapper { return Optional.bridgeJSLiftReturnFromSideChannel() } set { - newValue.bridgeJSWithLoweredParameter { (newValueIsSome, newValueBytes, newValueLength) in + newValue.bridgeJSWithLoweredParameter { (newValueIsSome, newValueWord0, newValueWord1, newValueWord2) in let jsObjectValue = jsObject.bridgeJSLowerParameter() - bjs_DataProcessor_optionalTheme_set(jsObjectValue, newValueIsSome, newValueBytes, newValueLength) + bjs_DataProcessor_optionalTheme_set(jsObjectValue, newValueIsSome, newValueWord0, newValueWord1, newValueWord2) } } } @@ -4528,14 +4528,14 @@ fileprivate func bjs_DataProcessor_getValue_extern(_ jsObject: Int32) -> Int32 { #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_setLabelElements") -fileprivate func bjs_DataProcessor_setLabelElements_extern(_ jsObject: Int32, _ labelPrefixBytes: Int32, _ labelPrefixLength: Int32, _ labelSuffixBytes: Int32, _ labelSuffixLength: Int32) -> Void +fileprivate func bjs_DataProcessor_setLabelElements_extern(_ jsObject: Int32, _ labelPrefixWord0: Int32, _ labelPrefixWord1: Int32, _ labelPrefixWord2: Int32, _ labelSuffixWord0: Int32, _ labelSuffixWord1: Int32, _ labelSuffixWord2: Int32) -> Void #else -fileprivate func bjs_DataProcessor_setLabelElements_extern(_ jsObject: Int32, _ labelPrefixBytes: Int32, _ labelPrefixLength: Int32, _ labelSuffixBytes: Int32, _ labelSuffixLength: Int32) -> Void { +fileprivate func bjs_DataProcessor_setLabelElements_extern(_ jsObject: Int32, _ labelPrefixWord0: Int32, _ labelPrefixWord1: Int32, _ labelPrefixWord2: Int32, _ labelSuffixWord0: Int32, _ labelSuffixWord1: Int32, _ labelSuffixWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_DataProcessor_setLabelElements(_ jsObject: Int32, _ labelPrefixBytes: Int32, _ labelPrefixLength: Int32, _ labelSuffixBytes: Int32, _ labelSuffixLength: Int32) -> Void { - return bjs_DataProcessor_setLabelElements_extern(jsObject, labelPrefixBytes, labelPrefixLength, labelSuffixBytes, labelSuffixLength) +@inline(never) fileprivate func bjs_DataProcessor_setLabelElements(_ jsObject: Int32, _ labelPrefixWord0: Int32, _ labelPrefixWord1: Int32, _ labelPrefixWord2: Int32, _ labelSuffixWord0: Int32, _ labelSuffixWord1: Int32, _ labelSuffixWord2: Int32) -> Void { + return bjs_DataProcessor_setLabelElements_extern(jsObject, labelPrefixWord0, labelPrefixWord1, labelPrefixWord2, labelSuffixWord0, labelSuffixWord1, labelSuffixWord2) } #if arch(wasm32) @@ -4684,14 +4684,14 @@ fileprivate func bjs_DataProcessor_optionalTag_get_extern(_ jsObject: Int32) -> #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_optionalTag_set") -fileprivate func bjs_DataProcessor_optionalTag_set_extern(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void +fileprivate func bjs_DataProcessor_optionalTag_set_extern(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void #else -fileprivate func bjs_DataProcessor_optionalTag_set_extern(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { +fileprivate func bjs_DataProcessor_optionalTag_set_extern(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_DataProcessor_optionalTag_set(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { - return bjs_DataProcessor_optionalTag_set_extern(jsObject, newValueIsSome, newValueBytes, newValueLength) +@inline(never) fileprivate func bjs_DataProcessor_optionalTag_set(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { + return bjs_DataProcessor_optionalTag_set_extern(jsObject, newValueIsSome, newValueWord0, newValueWord1, newValueWord2) } #if arch(wasm32) @@ -4756,14 +4756,14 @@ fileprivate func bjs_DataProcessor_optionalTheme_get_extern(_ jsObject: Int32) - #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_DataProcessor_optionalTheme_set") -fileprivate func bjs_DataProcessor_optionalTheme_set_extern(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void +fileprivate func bjs_DataProcessor_optionalTheme_set_extern(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void #else -fileprivate func bjs_DataProcessor_optionalTheme_set_extern(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { +fileprivate func bjs_DataProcessor_optionalTheme_set_extern(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_DataProcessor_optionalTheme_set(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { - return bjs_DataProcessor_optionalTheme_set_extern(jsObject, newValueIsSome, newValueBytes, newValueLength) +@inline(never) fileprivate func bjs_DataProcessor_optionalTheme_set(_ jsObject: Int32, _ newValueIsSome: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { + return bjs_DataProcessor_optionalTheme_set_extern(jsObject, newValueIsSome, newValueWord0, newValueWord1, newValueWord2) } #if arch(wasm32) @@ -7672,6 +7672,138 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { } } +@_expose(wasm, "bjs_StringABIExports_static_smallEmpty") +@_cdecl("bjs_StringABIExports_static_smallEmpty") +public func _bjs_StringABIExports_static_smallEmpty() -> Void { + #if arch(wasm32) + let ret = StringABIExports.smallEmpty() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StringABIExports_static_smallASCII") +@_cdecl("bjs_StringABIExports_static_smallASCII") +public func _bjs_StringABIExports_static_smallASCII() -> Void { + #if arch(wasm32) + let ret = StringABIExports.smallASCII() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StringABIExports_static_smallEight") +@_cdecl("bjs_StringABIExports_static_smallEight") +public func _bjs_StringABIExports_static_smallEight() -> Void { + #if arch(wasm32) + let ret = StringABIExports.smallEight() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StringABIExports_static_smallNine") +@_cdecl("bjs_StringABIExports_static_smallNine") +public func _bjs_StringABIExports_static_smallNine() -> Void { + #if arch(wasm32) + let ret = StringABIExports.smallNine() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StringABIExports_static_smallTen") +@_cdecl("bjs_StringABIExports_static_smallTen") +public func _bjs_StringABIExports_static_smallTen() -> Void { + #if arch(wasm32) + let ret = StringABIExports.smallTen() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StringABIExports_static_smallUTF8") +@_cdecl("bjs_StringABIExports_static_smallUTF8") +public func _bjs_StringABIExports_static_smallUTF8() -> Void { + #if arch(wasm32) + let ret = StringABIExports.smallUTF8() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StringABIExports_static_largeImmortal") +@_cdecl("bjs_StringABIExports_static_largeImmortal") +public func _bjs_StringABIExports_static_largeImmortal() -> Void { + #if arch(wasm32) + let ret = StringABIExports.largeImmortal() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StringABIExports_static_largeImmortalAgain") +@_cdecl("bjs_StringABIExports_static_largeImmortalAgain") +public func _bjs_StringABIExports_static_largeImmortalAgain() -> Void { + #if arch(wasm32) + let ret = StringABIExports.largeImmortalAgain() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StringABIExports_static_largeDynamic") +@_cdecl("bjs_StringABIExports_static_largeDynamic") +public func _bjs_StringABIExports_static_largeDynamic() -> Void { + #if arch(wasm32) + let ret = StringABIExports.largeDynamic() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StringABIExports_static_immortalSubstring") +@_cdecl("bjs_StringABIExports_static_immortalSubstring") +public func _bjs_StringABIExports_static_immortalSubstring() -> Void { + #if arch(wasm32) + let ret = StringABIExports.immortalSubstring() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StringABIExports_static_optionalNone") +@_cdecl("bjs_StringABIExports_static_optionalNone") +public func _bjs_StringABIExports_static_optionalNone() -> Void { + #if arch(wasm32) + let ret = StringABIExports.optionalNone() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StringABIExports_static_optionalSome") +@_cdecl("bjs_StringABIExports_static_optionalSome") +public func _bjs_StringABIExports_static_optionalSome() -> Void { + #if arch(wasm32) + let ret = StringABIExports.optionalSome() + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + extension JSCoordinate: _BridgedSwiftStruct { @_spi(BridgeJS) @_transparent public static func bridgeJSStackPop() -> JSCoordinate { let longitude = Double.bridgeJSStackPop() @@ -16234,20 +16366,20 @@ func _$Promise_reject(_ promise: JSObject, _ value: JSValue) throws(JSException) #if arch(wasm32) @_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_SS") -fileprivate func promise_resolve_BridgeJSRuntimeTests_SS_extern(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void +fileprivate func promise_resolve_BridgeJSRuntimeTests_SS_extern(_ promise: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void #else -fileprivate func promise_resolve_BridgeJSRuntimeTests_SS_extern(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { +fileprivate func promise_resolve_BridgeJSRuntimeTests_SS_extern(_ promise: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_SS(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { - return promise_resolve_BridgeJSRuntimeTests_SS_extern(promise, valueBytes, valueLength) +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_SS(_ promise: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_SS_extern(promise, valueWord0, valueWord1, valueWord2) } func _$Promise_resolve_SS(_ promise: JSObject, _ value: String) throws(JSException) -> Void { - value.bridgeJSWithLoweredParameter { (valueBytes, valueLength) in + value.bridgeJSWithLoweredParameter { (valueWord0, valueWord1, valueWord2) in let promiseValue = promise.bridgeJSLowerParameter() - promise_resolve_BridgeJSRuntimeTests_SS(promiseValue, valueBytes, valueLength) + promise_resolve_BridgeJSRuntimeTests_SS(promiseValue, valueWord0, valueWord1, valueWord2) } if let error = _swift_js_take_exception() { throw error } } @@ -16402,20 +16534,20 @@ func _$Promise_resolve_8JSObjectC(_ promise: JSObject, _ value: JSObject) throws #if arch(wasm32) @_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_5ThemeO") -fileprivate func promise_resolve_BridgeJSRuntimeTests_5ThemeO_extern(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void +fileprivate func promise_resolve_BridgeJSRuntimeTests_5ThemeO_extern(_ promise: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void #else -fileprivate func promise_resolve_BridgeJSRuntimeTests_5ThemeO_extern(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { +fileprivate func promise_resolve_BridgeJSRuntimeTests_5ThemeO_extern(_ promise: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_5ThemeO(_ promise: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { - return promise_resolve_BridgeJSRuntimeTests_5ThemeO_extern(promise, valueBytes, valueLength) +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_5ThemeO(_ promise: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_5ThemeO_extern(promise, valueWord0, valueWord1, valueWord2) } func _$Promise_resolve_5ThemeO(_ promise: JSObject, _ value: Theme) throws(JSException) -> Void { - value.bridgeJSWithLoweredParameter { (valueBytes, valueLength) in + value.bridgeJSWithLoweredParameter { (valueWord0, valueWord1, valueWord2) in let promiseValue = promise.bridgeJSLowerParameter() - promise_resolve_BridgeJSRuntimeTests_5ThemeO(promiseValue, valueBytes, valueLength) + promise_resolve_BridgeJSRuntimeTests_5ThemeO(promiseValue, valueWord0, valueWord1, valueWord2) } if let error = _swift_js_take_exception() { throw error } } @@ -16445,20 +16577,20 @@ func _$Promise_resolve_9DirectionO(_ promise: JSObject, _ value: Direction) thro #if arch(wasm32) @_extern(wasm, module: "bjs", name: "promise_resolve_BridgeJSRuntimeTests_Sq5ThemeO") -fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq5ThemeO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq5ThemeO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void #else -fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq5ThemeO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { +fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq5ThemeO_extern(_ promise: Int32, _ valueIsSome: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq5ThemeO(_ promise: Int32, _ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { - return promise_resolve_BridgeJSRuntimeTests_Sq5ThemeO_extern(promise, valueIsSome, valueBytes, valueLength) +@inline(never) fileprivate func promise_resolve_BridgeJSRuntimeTests_Sq5ThemeO(_ promise: Int32, _ valueIsSome: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { + return promise_resolve_BridgeJSRuntimeTests_Sq5ThemeO_extern(promise, valueIsSome, valueWord0, valueWord1, valueWord2) } func _$Promise_resolve_Sq5ThemeO(_ promise: JSObject, _ value: Optional) throws(JSException) -> Void { - value.bridgeJSWithLoweredParameter { (valueIsSome, valueBytes, valueLength) in + value.bridgeJSWithLoweredParameter { (valueIsSome, valueWord0, valueWord1, valueWord2) in let promiseValue = promise.bridgeJSLowerParameter() - promise_resolve_BridgeJSRuntimeTests_Sq5ThemeO(promiseValue, valueIsSome, valueBytes, valueLength) + promise_resolve_BridgeJSRuntimeTests_Sq5ThemeO(promiseValue, valueIsSome, valueWord0, valueWord1, valueWord2) } if let error = _swift_js_take_exception() { throw error } } @@ -16802,14 +16934,14 @@ extension Boxed: _BridgedSwiftAlias, _BridgedSwiftStackType {} #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Surface_init") -fileprivate func bjs_Surface_init_extern(_ labelBytes: Int32, _ labelLength: Int32) -> Int32 +fileprivate func bjs_Surface_init_extern(_ labelWord0: Int32, _ labelWord1: Int32, _ labelWord2: Int32) -> Int32 #else -fileprivate func bjs_Surface_init_extern(_ labelBytes: Int32, _ labelLength: Int32) -> Int32 { +fileprivate func bjs_Surface_init_extern(_ labelWord0: Int32, _ labelWord1: Int32, _ labelWord2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_Surface_init(_ labelBytes: Int32, _ labelLength: Int32) -> Int32 { - return bjs_Surface_init_extern(labelBytes, labelLength) +@inline(never) fileprivate func bjs_Surface_init(_ labelWord0: Int32, _ labelWord1: Int32, _ labelWord2: Int32) -> Int32 { + return bjs_Surface_init_extern(labelWord0, labelWord1, labelWord2) } #if arch(wasm32) @@ -16825,8 +16957,8 @@ fileprivate func bjs_Surface_label_get_extern(_ self: Int32) -> Int32 { } func _$Surface_init(_ label: String) throws(JSException) -> JSObject { - let ret0 = label.bridgeJSWithLoweredParameter { (labelBytes, labelLength) in - let ret = bjs_Surface_init(labelBytes, labelLength) + let ret0 = label.bridgeJSWithLoweredParameter { (labelWord0, labelWord1, labelWord2) in + let ret = bjs_Surface_init(labelWord0, labelWord1, labelWord2) return ret } let ret = ret0 @@ -16847,38 +16979,38 @@ func _$Surface_label_get(_ self: JSObject) throws(JSException) -> String { #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_AliasImports_jsRoundTripTagged_static") -fileprivate func bjs_AliasImports_jsRoundTripTagged_static_extern(_ valueBytes: Int32, _ valueLength: Int32) -> Int32 +fileprivate func bjs_AliasImports_jsRoundTripTagged_static_extern(_ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Int32 #else -fileprivate func bjs_AliasImports_jsRoundTripTagged_static_extern(_ valueBytes: Int32, _ valueLength: Int32) -> Int32 { +fileprivate func bjs_AliasImports_jsRoundTripTagged_static_extern(_ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_AliasImports_jsRoundTripTagged_static(_ valueBytes: Int32, _ valueLength: Int32) -> Int32 { - return bjs_AliasImports_jsRoundTripTagged_static_extern(valueBytes, valueLength) +@inline(never) fileprivate func bjs_AliasImports_jsRoundTripTagged_static(_ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Int32 { + return bjs_AliasImports_jsRoundTripTagged_static_extern(valueWord0, valueWord1, valueWord2) } #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_AliasImports_jsRoundTripOptionalTagged_static") -fileprivate func bjs_AliasImports_jsRoundTripOptionalTagged_static_extern(_ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void +fileprivate func bjs_AliasImports_jsRoundTripOptionalTagged_static_extern(_ valueIsSome: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void #else -fileprivate func bjs_AliasImports_jsRoundTripOptionalTagged_static_extern(_ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { +fileprivate func bjs_AliasImports_jsRoundTripOptionalTagged_static_extern(_ valueIsSome: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_AliasImports_jsRoundTripOptionalTagged_static(_ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { - return bjs_AliasImports_jsRoundTripOptionalTagged_static_extern(valueIsSome, valueBytes, valueLength) +@inline(never) fileprivate func bjs_AliasImports_jsRoundTripOptionalTagged_static(_ valueIsSome: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { + return bjs_AliasImports_jsRoundTripOptionalTagged_static_extern(valueIsSome, valueWord0, valueWord1, valueWord2) } #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_AliasImports_jsProduceOptionalCanvas_static") -fileprivate func bjs_AliasImports_jsProduceOptionalCanvas_static_extern(_ labelIsSome: Int32, _ labelBytes: Int32, _ labelLength: Int32) -> Void +fileprivate func bjs_AliasImports_jsProduceOptionalCanvas_static_extern(_ labelIsSome: Int32, _ labelWord0: Int32, _ labelWord1: Int32, _ labelWord2: Int32) -> Void #else -fileprivate func bjs_AliasImports_jsProduceOptionalCanvas_static_extern(_ labelIsSome: Int32, _ labelBytes: Int32, _ labelLength: Int32) -> Void { +fileprivate func bjs_AliasImports_jsProduceOptionalCanvas_static_extern(_ labelIsSome: Int32, _ labelWord0: Int32, _ labelWord1: Int32, _ labelWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_AliasImports_jsProduceOptionalCanvas_static(_ labelIsSome: Int32, _ labelBytes: Int32, _ labelLength: Int32) -> Void { - return bjs_AliasImports_jsProduceOptionalCanvas_static_extern(labelIsSome, labelBytes, labelLength) +@inline(never) fileprivate func bjs_AliasImports_jsProduceOptionalCanvas_static(_ labelIsSome: Int32, _ labelWord0: Int32, _ labelWord1: Int32, _ labelWord2: Int32) -> Void { + return bjs_AliasImports_jsProduceOptionalCanvas_static_extern(labelIsSome, labelWord0, labelWord1, labelWord2) } #if arch(wasm32) @@ -16942,8 +17074,8 @@ fileprivate func bjs_AliasImports_jsRoundTripOptionalUserId_static_extern(_ valu } func _$AliasImports_jsRoundTripTagged(_ value: Tagged) throws(JSException) -> Tagged { - let ret0 = value.bridgeJSWithLoweredParameter { (valueBytes, valueLength) in - let ret = bjs_AliasImports_jsRoundTripTagged_static(valueBytes, valueLength) + let ret0 = value.bridgeJSWithLoweredParameter { (valueWord0, valueWord1, valueWord2) in + let ret = bjs_AliasImports_jsRoundTripTagged_static(valueWord0, valueWord1, valueWord2) return ret } let ret = ret0 @@ -16954,8 +17086,8 @@ func _$AliasImports_jsRoundTripTagged(_ value: Tagged) throws(JSException) -> Ta } func _$AliasImports_jsRoundTripOptionalTagged(_ value: Optional) throws(JSException) -> Optional { - value.bridgeJSWithLoweredParameter { (valueIsSome, valueBytes, valueLength) in - bjs_AliasImports_jsRoundTripOptionalTagged_static(valueIsSome, valueBytes, valueLength) + value.bridgeJSWithLoweredParameter { (valueIsSome, valueWord0, valueWord1, valueWord2) in + bjs_AliasImports_jsRoundTripOptionalTagged_static(valueIsSome, valueWord0, valueWord1, valueWord2) } if let error = _swift_js_take_exception() { throw error @@ -16964,8 +17096,8 @@ func _$AliasImports_jsRoundTripOptionalTagged(_ value: Optional) throws( } func _$AliasImports_jsProduceOptionalCanvas(_ label: Optional) throws(JSException) -> Optional { - label.bridgeJSWithLoweredParameter { (labelIsSome, labelBytes, labelLength) in - bjs_AliasImports_jsProduceOptionalCanvas_static(labelIsSome, labelBytes, labelLength) + label.bridgeJSWithLoweredParameter { (labelIsSome, labelWord0, labelWord1, labelWord2) in + bjs_AliasImports_jsProduceOptionalCanvas_static(labelIsSome, labelWord0, labelWord1, labelWord2) } if let error = _swift_js_take_exception() { throw error @@ -17020,14 +17152,14 @@ func _$AliasImports_jsRoundTripOptionalUserId(_ value: Optional) throws( #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ArrayElementObject_init") -fileprivate func bjs_ArrayElementObject_init_extern(_ idBytes: Int32, _ idLength: Int32) -> Int32 +fileprivate func bjs_ArrayElementObject_init_extern(_ idWord0: Int32, _ idWord1: Int32, _ idWord2: Int32) -> Int32 #else -fileprivate func bjs_ArrayElementObject_init_extern(_ idBytes: Int32, _ idLength: Int32) -> Int32 { +fileprivate func bjs_ArrayElementObject_init_extern(_ idWord0: Int32, _ idWord1: Int32, _ idWord2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_ArrayElementObject_init(_ idBytes: Int32, _ idLength: Int32) -> Int32 { - return bjs_ArrayElementObject_init_extern(idBytes, idLength) +@inline(never) fileprivate func bjs_ArrayElementObject_init(_ idWord0: Int32, _ idWord1: Int32, _ idWord2: Int32) -> Int32 { + return bjs_ArrayElementObject_init_extern(idWord0, idWord1, idWord2) } #if arch(wasm32) @@ -17043,8 +17175,8 @@ fileprivate func bjs_ArrayElementObject_id_get_extern(_ self: Int32) -> Int32 { } func _$ArrayElementObject_init(_ id: String) throws(JSException) -> JSObject { - let ret0 = id.bridgeJSWithLoweredParameter { (idBytes, idLength) in - let ret = bjs_ArrayElementObject_init(idBytes, idLength) + let ret0 = id.bridgeJSWithLoweredParameter { (idWord0, idWord1, idWord2) in + let ret = bjs_ArrayElementObject_init(idWord0, idWord1, idWord2) return ret } let ret = ret0 @@ -17455,26 +17587,26 @@ fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripBool_static_extern(_ res #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_AsyncImportImports_jsAsyncRoundTripString_static") -fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripString_static_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ vBytes: Int32, _ vLength: Int32) -> Void +fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripString_static_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ vWord0: Int32, _ vWord1: Int32, _ vWord2: Int32) -> Void #else -fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripString_static_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ vBytes: Int32, _ vLength: Int32) -> Void { +fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripString_static_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ vWord0: Int32, _ vWord1: Int32, _ vWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripString_static(_ resolveRef: Int32, _ rejectRef: Int32, _ vBytes: Int32, _ vLength: Int32) -> Void { - return bjs_AsyncImportImports_jsAsyncRoundTripString_static_extern(resolveRef, rejectRef, vBytes, vLength) +@inline(never) fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripString_static(_ resolveRef: Int32, _ rejectRef: Int32, _ vWord0: Int32, _ vWord1: Int32, _ vWord2: Int32) -> Void { + return bjs_AsyncImportImports_jsAsyncRoundTripString_static_extern(resolveRef, rejectRef, vWord0, vWord1, vWord2) } #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_AsyncImportImports_jsAsyncRoundTripOptionalString_static") -fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripOptionalString_static_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ vIsSome: Int32, _ vBytes: Int32, _ vLength: Int32) -> Void +fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripOptionalString_static_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ vIsSome: Int32, _ vWord0: Int32, _ vWord1: Int32, _ vWord2: Int32) -> Void #else -fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripOptionalString_static_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ vIsSome: Int32, _ vBytes: Int32, _ vLength: Int32) -> Void { +fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripOptionalString_static_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ vIsSome: Int32, _ vWord0: Int32, _ vWord1: Int32, _ vWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripOptionalString_static(_ resolveRef: Int32, _ rejectRef: Int32, _ vIsSome: Int32, _ vBytes: Int32, _ vLength: Int32) -> Void { - return bjs_AsyncImportImports_jsAsyncRoundTripOptionalString_static_extern(resolveRef, rejectRef, vIsSome, vBytes, vLength) +@inline(never) fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripOptionalString_static(_ resolveRef: Int32, _ rejectRef: Int32, _ vIsSome: Int32, _ vWord0: Int32, _ vWord1: Int32, _ vWord2: Int32) -> Void { + return bjs_AsyncImportImports_jsAsyncRoundTripOptionalString_static_extern(resolveRef, rejectRef, vIsSome, vWord0, vWord1, vWord2) } #if arch(wasm32) @@ -17527,14 +17659,14 @@ fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripStringArray_static_exter #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_AsyncImportImports_jsAsyncRoundTripFeatureFlag_static") -fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripFeatureFlag_static_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ vBytes: Int32, _ vLength: Int32) -> Void +fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripFeatureFlag_static_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ vWord0: Int32, _ vWord1: Int32, _ vWord2: Int32) -> Void #else -fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripFeatureFlag_static_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ vBytes: Int32, _ vLength: Int32) -> Void { +fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripFeatureFlag_static_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ vWord0: Int32, _ vWord1: Int32, _ vWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripFeatureFlag_static(_ resolveRef: Int32, _ rejectRef: Int32, _ vBytes: Int32, _ vLength: Int32) -> Void { - return bjs_AsyncImportImports_jsAsyncRoundTripFeatureFlag_static_extern(resolveRef, rejectRef, vBytes, vLength) +@inline(never) fileprivate func bjs_AsyncImportImports_jsAsyncRoundTripFeatureFlag_static(_ resolveRef: Int32, _ rejectRef: Int32, _ vWord0: Int32, _ vWord1: Int32, _ vWord2: Int32) -> Void { + return bjs_AsyncImportImports_jsAsyncRoundTripFeatureFlag_static_extern(resolveRef, rejectRef, vWord0, vWord1, vWord2) } #if arch(wasm32) @@ -17601,8 +17733,8 @@ func _$AsyncImportImports_jsAsyncRoundTripString(_ v: String) async throws(JSExc }, makeRejectClosure: { JSTypedClosure<(sending JSValue) -> Void>.sending($0) }) { resolveRef, rejectRef in - v.bridgeJSWithLoweredParameter { (vBytes, vLength) in - bjs_AsyncImportImports_jsAsyncRoundTripString_static(resolveRef, rejectRef, vBytes, vLength) + v.bridgeJSWithLoweredParameter { (vWord0, vWord1, vWord2) in + bjs_AsyncImportImports_jsAsyncRoundTripString_static(resolveRef, rejectRef, vWord0, vWord1, vWord2) } } return resolved @@ -17614,8 +17746,8 @@ func _$AsyncImportImports_jsAsyncRoundTripOptionalString(_ v: Optional) }, makeRejectClosure: { JSTypedClosure<(sending JSValue) -> Void>.sending($0) }) { resolveRef, rejectRef in - v.bridgeJSWithLoweredParameter { (vIsSome, vBytes, vLength) in - bjs_AsyncImportImports_jsAsyncRoundTripOptionalString_static(resolveRef, rejectRef, vIsSome, vBytes, vLength) + v.bridgeJSWithLoweredParameter { (vIsSome, vWord0, vWord1, vWord2) in + bjs_AsyncImportImports_jsAsyncRoundTripOptionalString_static(resolveRef, rejectRef, vIsSome, vWord0, vWord1, vWord2) } } return resolved @@ -17675,8 +17807,8 @@ func _$AsyncImportImports_jsAsyncRoundTripFeatureFlag(_ v: FeatureFlag) async th }, makeRejectClosure: { JSTypedClosure<(sending JSValue) -> Void>.sending($0) }) { resolveRef, rejectRef in - v.bridgeJSWithLoweredParameter { (vBytes, vLength) in - bjs_AsyncImportImports_jsAsyncRoundTripFeatureFlag_static(resolveRef, rejectRef, vBytes, vLength) + v.bridgeJSWithLoweredParameter { (vWord0, vWord1, vWord2) in + bjs_AsyncImportImports_jsAsyncRoundTripFeatureFlag_static(resolveRef, rejectRef, vWord0, vWord1, vWord2) } } return resolved @@ -17778,14 +17910,14 @@ fileprivate func bjs_ClosureSupportImports_jsApplyDouble_static_extern(_ value: #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsApplyString_static") -fileprivate func bjs_ClosureSupportImports_jsApplyString_static_extern(_ valueBytes: Int32, _ valueLength: Int32, _ transform: Int32) -> Int32 +fileprivate func bjs_ClosureSupportImports_jsApplyString_static_extern(_ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32, _ transform: Int32) -> Int32 #else -fileprivate func bjs_ClosureSupportImports_jsApplyString_static_extern(_ valueBytes: Int32, _ valueLength: Int32, _ transform: Int32) -> Int32 { +fileprivate func bjs_ClosureSupportImports_jsApplyString_static_extern(_ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32, _ transform: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_ClosureSupportImports_jsApplyString_static(_ valueBytes: Int32, _ valueLength: Int32, _ transform: Int32) -> Int32 { - return bjs_ClosureSupportImports_jsApplyString_static_extern(valueBytes, valueLength, transform) +@inline(never) fileprivate func bjs_ClosureSupportImports_jsApplyString_static(_ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32, _ transform: Int32) -> Int32 { + return bjs_ClosureSupportImports_jsApplyString_static_extern(valueWord0, valueWord1, valueWord2, transform) } #if arch(wasm32) @@ -17886,14 +18018,14 @@ fileprivate func bjs_ClosureSupportImports_jsMakeDoubleToDouble_static_extern(_ #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_ClosureSupportImports_jsMakeStringToString_static") -fileprivate func bjs_ClosureSupportImports_jsMakeStringToString_static_extern(_ prefixBytes: Int32, _ prefixLength: Int32) -> Int32 +fileprivate func bjs_ClosureSupportImports_jsMakeStringToString_static_extern(_ prefixWord0: Int32, _ prefixWord1: Int32, _ prefixWord2: Int32) -> Int32 #else -fileprivate func bjs_ClosureSupportImports_jsMakeStringToString_static_extern(_ prefixBytes: Int32, _ prefixLength: Int32) -> Int32 { +fileprivate func bjs_ClosureSupportImports_jsMakeStringToString_static_extern(_ prefixWord0: Int32, _ prefixWord1: Int32, _ prefixWord2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_ClosureSupportImports_jsMakeStringToString_static(_ prefixBytes: Int32, _ prefixLength: Int32) -> Int32 { - return bjs_ClosureSupportImports_jsMakeStringToString_static_extern(prefixBytes, prefixLength) +@inline(never) fileprivate func bjs_ClosureSupportImports_jsMakeStringToString_static(_ prefixWord0: Int32, _ prefixWord1: Int32, _ prefixWord2: Int32) -> Int32 { + return bjs_ClosureSupportImports_jsMakeStringToString_static_extern(prefixWord0, prefixWord1, prefixWord2) } #if arch(wasm32) @@ -18042,9 +18174,9 @@ func _$ClosureSupportImports_jsApplyDouble(_ value: Double, _ transform: JSTyped } func _$ClosureSupportImports_jsApplyString(_ value: String, _ transform: JSTypedClosure<(String) -> String>) throws(JSException) -> String { - let ret0 = value.bridgeJSWithLoweredParameter { (valueBytes, valueLength) in + let ret0 = value.bridgeJSWithLoweredParameter { (valueWord0, valueWord1, valueWord2) in let transformFuncRef = transform.bridgeJSLowerParameter() - let ret = bjs_ClosureSupportImports_jsApplyString_static(valueBytes, valueLength, transformFuncRef) + let ret = bjs_ClosureSupportImports_jsApplyString_static(valueWord0, valueWord1, valueWord2, transformFuncRef) return ret } let ret = ret0 @@ -18133,8 +18265,8 @@ func _$ClosureSupportImports_jsMakeDoubleToDouble(_ base: Double) throws(JSExcep } func _$ClosureSupportImports_jsMakeStringToString(_ prefix: String) throws(JSException) -> (String) -> String { - let ret0 = prefix.bridgeJSWithLoweredParameter { (prefixBytes, prefixLength) in - let ret = bjs_ClosureSupportImports_jsMakeStringToString_static(prefixBytes, prefixLength) + let ret0 = prefix.bridgeJSWithLoweredParameter { (prefixWord0, prefixWord1, prefixWord2) in + let ret = bjs_ClosureSupportImports_jsMakeStringToString_static(prefixWord0, prefixWord1, prefixWord2) return ret } let ret = ret0 @@ -18386,14 +18518,14 @@ func _$DictionarySupportImports_jsRoundTripDictionaryDoubleArray(_ values: [Stri #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Foo_init") -fileprivate func bjs_Foo_init_extern(_ valueBytes: Int32, _ valueLength: Int32) -> Int32 +fileprivate func bjs_Foo_init_extern(_ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Int32 #else -fileprivate func bjs_Foo_init_extern(_ valueBytes: Int32, _ valueLength: Int32) -> Int32 { +fileprivate func bjs_Foo_init_extern(_ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_Foo_init(_ valueBytes: Int32, _ valueLength: Int32) -> Int32 { - return bjs_Foo_init_extern(valueBytes, valueLength) +@inline(never) fileprivate func bjs_Foo_init(_ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Int32 { + return bjs_Foo_init_extern(valueWord0, valueWord1, valueWord2) } #if arch(wasm32) @@ -18409,8 +18541,8 @@ fileprivate func bjs_Foo_value_get_extern(_ self: Int32) -> Int32 { } func _$Foo_init(_ value: String) throws(JSException) -> JSObject { - let ret0 = value.bridgeJSWithLoweredParameter { (valueBytes, valueLength) in - let ret = bjs_Foo_init(valueBytes, valueLength) + let ret0 = value.bridgeJSWithLoweredParameter { (valueWord0, valueWord1, valueWord2) in + let ret = bjs_Foo_init(valueWord0, valueWord1, valueWord2) return ret } let ret = ret0 @@ -18512,19 +18644,19 @@ func _$jsRoundTripBool(_ v: Bool) throws(JSException) -> Bool { #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripString") -fileprivate func bjs_jsRoundTripString_extern(_ vBytes: Int32, _ vLength: Int32) -> Int32 +fileprivate func bjs_jsRoundTripString_extern(_ vWord0: Int32, _ vWord1: Int32, _ vWord2: Int32) -> Int32 #else -fileprivate func bjs_jsRoundTripString_extern(_ vBytes: Int32, _ vLength: Int32) -> Int32 { +fileprivate func bjs_jsRoundTripString_extern(_ vWord0: Int32, _ vWord1: Int32, _ vWord2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_jsRoundTripString(_ vBytes: Int32, _ vLength: Int32) -> Int32 { - return bjs_jsRoundTripString_extern(vBytes, vLength) +@inline(never) fileprivate func bjs_jsRoundTripString(_ vWord0: Int32, _ vWord1: Int32, _ vWord2: Int32) -> Int32 { + return bjs_jsRoundTripString_extern(vWord0, vWord1, vWord2) } func _$jsRoundTripString(_ v: String) throws(JSException) -> String { - let ret0 = v.bridgeJSWithLoweredParameter { (vBytes, vLength) in - let ret = bjs_jsRoundTripString(vBytes, vLength) + let ret0 = v.bridgeJSWithLoweredParameter { (vWord0, vWord1, vWord2) in + let ret = bjs_jsRoundTripString(vWord0, vWord1, vWord2) return ret } let ret = ret0 @@ -18640,19 +18772,19 @@ func _$jsThrowOrString(_ shouldThrow: Bool) throws(JSException) -> String { #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsRoundTripFeatureFlag") -fileprivate func bjs_jsRoundTripFeatureFlag_extern(_ flagBytes: Int32, _ flagLength: Int32) -> Int32 +fileprivate func bjs_jsRoundTripFeatureFlag_extern(_ flagWord0: Int32, _ flagWord1: Int32, _ flagWord2: Int32) -> Int32 #else -fileprivate func bjs_jsRoundTripFeatureFlag_extern(_ flagBytes: Int32, _ flagLength: Int32) -> Int32 { +fileprivate func bjs_jsRoundTripFeatureFlag_extern(_ flagWord0: Int32, _ flagWord1: Int32, _ flagWord2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_jsRoundTripFeatureFlag(_ flagBytes: Int32, _ flagLength: Int32) -> Int32 { - return bjs_jsRoundTripFeatureFlag_extern(flagBytes, flagLength) +@inline(never) fileprivate func bjs_jsRoundTripFeatureFlag(_ flagWord0: Int32, _ flagWord1: Int32, _ flagWord2: Int32) -> Int32 { + return bjs_jsRoundTripFeatureFlag_extern(flagWord0, flagWord1, flagWord2) } func _$jsRoundTripFeatureFlag(_ flag: FeatureFlag) throws(JSException) -> FeatureFlag { - let ret0 = flag.bridgeJSWithLoweredParameter { (flagBytes, flagLength) in - let ret = bjs_jsRoundTripFeatureFlag(flagBytes, flagLength) + let ret0 = flag.bridgeJSWithLoweredParameter { (flagWord0, flagWord1, flagWord2) in + let ret = bjs_jsRoundTripFeatureFlag(flagWord0, flagWord1, flagWord2) return ret } let ret = ret0 @@ -18686,14 +18818,14 @@ func _$runAsyncWorks() async throws(JSException) -> Void { #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_fetchWeatherData") -fileprivate func bjs_fetchWeatherData_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ cityBytes: Int32, _ cityLength: Int32) -> Void +fileprivate func bjs_fetchWeatherData_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ cityWord0: Int32, _ cityWord1: Int32, _ cityWord2: Int32) -> Void #else -fileprivate func bjs_fetchWeatherData_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ cityBytes: Int32, _ cityLength: Int32) -> Void { +fileprivate func bjs_fetchWeatherData_extern(_ resolveRef: Int32, _ rejectRef: Int32, _ cityWord0: Int32, _ cityWord1: Int32, _ cityWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_fetchWeatherData(_ resolveRef: Int32, _ rejectRef: Int32, _ cityBytes: Int32, _ cityLength: Int32) -> Void { - return bjs_fetchWeatherData_extern(resolveRef, rejectRef, cityBytes, cityLength) +@inline(never) fileprivate func bjs_fetchWeatherData(_ resolveRef: Int32, _ rejectRef: Int32, _ cityWord0: Int32, _ cityWord1: Int32, _ cityWord2: Int32) -> Void { + return bjs_fetchWeatherData_extern(resolveRef, rejectRef, cityWord0, cityWord1, cityWord2) } func _$fetchWeatherData(_ city: String) async throws(JSException) -> WeatherData { @@ -18702,8 +18834,8 @@ func _$fetchWeatherData(_ city: String) async throws(JSException) -> WeatherData }, makeRejectClosure: { JSTypedClosure<(sending JSValue) -> Void>.sending($0) }) { resolveRef, rejectRef in - city.bridgeJSWithLoweredParameter { (cityBytes, cityLength) in - bjs_fetchWeatherData(resolveRef, rejectRef, cityBytes, cityLength) + city.bridgeJSWithLoweredParameter { (cityWord0, cityWord1, cityWord2) in + bjs_fetchWeatherData(resolveRef, rejectRef, cityWord0, cityWord1, cityWord2) } } return resolved @@ -18731,19 +18863,19 @@ func _$_jsWeirdFunction() throws(JSException) -> Double { #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_parseInt") -fileprivate func bjs_parseInt_extern(_ stringBytes: Int32, _ stringLength: Int32) -> Float64 +fileprivate func bjs_parseInt_extern(_ stringWord0: Int32, _ stringWord1: Int32, _ stringWord2: Int32) -> Float64 #else -fileprivate func bjs_parseInt_extern(_ stringBytes: Int32, _ stringLength: Int32) -> Float64 { +fileprivate func bjs_parseInt_extern(_ stringWord0: Int32, _ stringWord1: Int32, _ stringWord2: Int32) -> Float64 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_parseInt(_ stringBytes: Int32, _ stringLength: Int32) -> Float64 { - return bjs_parseInt_extern(stringBytes, stringLength) +@inline(never) fileprivate func bjs_parseInt(_ stringWord0: Int32, _ stringWord1: Int32, _ stringWord2: Int32) -> Float64 { + return bjs_parseInt_extern(stringWord0, stringWord1, stringWord2) } func _$parseInt(_ string: String) throws(JSException) -> Double { - let ret0 = string.bridgeJSWithLoweredParameter { (stringBytes, stringLength) in - let ret = bjs_parseInt(stringBytes, stringLength) + let ret0 = string.bridgeJSWithLoweredParameter { (stringWord0, stringWord1, stringWord2) in + let ret = bjs_parseInt(stringWord0, stringWord1, stringWord2) return ret } let ret = ret0 @@ -18755,14 +18887,14 @@ func _$parseInt(_ string: String) throws(JSException) -> Double { #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JsGreeter_init") -fileprivate func bjs_JsGreeter_init_extern(_ nameBytes: Int32, _ nameLength: Int32, _ prefixBytes: Int32, _ prefixLength: Int32) -> Int32 +fileprivate func bjs_JsGreeter_init_extern(_ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32, _ prefixWord0: Int32, _ prefixWord1: Int32, _ prefixWord2: Int32) -> Int32 #else -fileprivate func bjs_JsGreeter_init_extern(_ nameBytes: Int32, _ nameLength: Int32, _ prefixBytes: Int32, _ prefixLength: Int32) -> Int32 { +fileprivate func bjs_JsGreeter_init_extern(_ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32, _ prefixWord0: Int32, _ prefixWord1: Int32, _ prefixWord2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_JsGreeter_init(_ nameBytes: Int32, _ nameLength: Int32, _ prefixBytes: Int32, _ prefixLength: Int32) -> Int32 { - return bjs_JsGreeter_init_extern(nameBytes, nameLength, prefixBytes, prefixLength) +@inline(never) fileprivate func bjs_JsGreeter_init(_ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32, _ prefixWord0: Int32, _ prefixWord1: Int32, _ prefixWord2: Int32) -> Int32 { + return bjs_JsGreeter_init_extern(nameWord0, nameWord1, nameWord2, prefixWord0, prefixWord1, prefixWord2) } #if arch(wasm32) @@ -18791,14 +18923,14 @@ fileprivate func bjs_JsGreeter_prefix_get_extern(_ self: Int32) -> Int32 { #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JsGreeter_name_set") -fileprivate func bjs_JsGreeter_name_set_extern(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void +fileprivate func bjs_JsGreeter_name_set_extern(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void #else -fileprivate func bjs_JsGreeter_name_set_extern(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { +fileprivate func bjs_JsGreeter_name_set_extern(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_JsGreeter_name_set(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { - return bjs_JsGreeter_name_set_extern(self, newValueBytes, newValueLength) +@inline(never) fileprivate func bjs_JsGreeter_name_set(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { + return bjs_JsGreeter_name_set_extern(self, newValueWord0, newValueWord1, newValueWord2) } #if arch(wasm32) @@ -18815,20 +18947,20 @@ fileprivate func bjs_JsGreeter_greet_extern(_ self: Int32) -> Int32 { #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_JsGreeter_changeName") -fileprivate func bjs_JsGreeter_changeName_extern(_ self: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void +fileprivate func bjs_JsGreeter_changeName_extern(_ self: Int32, _ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32) -> Void #else -fileprivate func bjs_JsGreeter_changeName_extern(_ self: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { +fileprivate func bjs_JsGreeter_changeName_extern(_ self: Int32, _ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_JsGreeter_changeName(_ self: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { - return bjs_JsGreeter_changeName_extern(self, nameBytes, nameLength) +@inline(never) fileprivate func bjs_JsGreeter_changeName(_ self: Int32, _ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32) -> Void { + return bjs_JsGreeter_changeName_extern(self, nameWord0, nameWord1, nameWord2) } func _$JsGreeter_init(_ name: String, _ prefix: String) throws(JSException) -> JSObject { - let ret0 = name.bridgeJSWithLoweredParameter { (nameBytes, nameLength) in - let ret1 = prefix.bridgeJSWithLoweredParameter { (prefixBytes, prefixLength) in - let ret = bjs_JsGreeter_init(nameBytes, nameLength, prefixBytes, prefixLength) + let ret0 = name.bridgeJSWithLoweredParameter { (nameWord0, nameWord1, nameWord2) in + let ret1 = prefix.bridgeJSWithLoweredParameter { (prefixWord0, prefixWord1, prefixWord2) in + let ret = bjs_JsGreeter_init(nameWord0, nameWord1, nameWord2, prefixWord0, prefixWord1, prefixWord2) return ret } return ret1 @@ -18859,9 +18991,9 @@ func _$JsGreeter_prefix_get(_ self: JSObject) throws(JSException) -> String { } func _$JsGreeter_name_set(_ self: JSObject, _ newValue: String) throws(JSException) -> Void { - newValue.bridgeJSWithLoweredParameter { (newValueBytes, newValueLength) in + newValue.bridgeJSWithLoweredParameter { (newValueWord0, newValueWord1, newValueWord2) in let selfValue = self.bridgeJSLowerParameter() - bjs_JsGreeter_name_set(selfValue, newValueBytes, newValueLength) + bjs_JsGreeter_name_set(selfValue, newValueWord0, newValueWord1, newValueWord2) } if let error = _swift_js_take_exception() { throw error @@ -18878,9 +19010,9 @@ func _$JsGreeter_greet(_ self: JSObject) throws(JSException) -> String { } func _$JsGreeter_changeName(_ self: JSObject, _ name: String) throws(JSException) -> Void { - name.bridgeJSWithLoweredParameter { (nameBytes, nameLength) in + name.bridgeJSWithLoweredParameter { (nameWord0, nameWord1, nameWord2) in let selfValue = self.bridgeJSLowerParameter() - bjs_JsGreeter_changeName(selfValue, nameBytes, nameLength) + bjs_JsGreeter_changeName(selfValue, nameWord0, nameWord1, nameWord2) } if let error = _swift_js_take_exception() { throw error @@ -18937,14 +19069,14 @@ fileprivate func bjs_WeatherData_temperature_set_extern(_ self: Int32, _ newValu #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_WeatherData_description_set") -fileprivate func bjs_WeatherData_description_set_extern(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void +fileprivate func bjs_WeatherData_description_set_extern(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void #else -fileprivate func bjs_WeatherData_description_set_extern(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { +fileprivate func bjs_WeatherData_description_set_extern(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_WeatherData_description_set(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { - return bjs_WeatherData_description_set_extern(self, newValueBytes, newValueLength) +@inline(never) fileprivate func bjs_WeatherData_description_set(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { + return bjs_WeatherData_description_set_extern(self, newValueWord0, newValueWord1, newValueWord2) } #if arch(wasm32) @@ -18996,9 +19128,9 @@ func _$WeatherData_temperature_set(_ self: JSObject, _ newValue: Double) throws( } func _$WeatherData_description_set(_ self: JSObject, _ newValue: String) throws(JSException) -> Void { - newValue.bridgeJSWithLoweredParameter { (newValueBytes, newValueLength) in + newValue.bridgeJSWithLoweredParameter { (newValueWord0, newValueWord1, newValueWord2) in let selfValue = self.bridgeJSLowerParameter() - bjs_WeatherData_description_set(selfValue, newValueBytes, newValueLength) + bjs_WeatherData_description_set(selfValue, newValueWord0, newValueWord1, newValueWord2) } if let error = _swift_js_take_exception() { throw error @@ -19180,14 +19312,14 @@ func _$StaticBox_value(_ self: JSObject) throws(JSException) -> Double { #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Animal_init") -fileprivate func bjs_Animal_init_extern(_ nameBytes: Int32, _ nameLength: Int32, _ age: Float64, _ isCat: Int32) -> Int32 +fileprivate func bjs_Animal_init_extern(_ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32, _ age: Float64, _ isCat: Int32) -> Int32 #else -fileprivate func bjs_Animal_init_extern(_ nameBytes: Int32, _ nameLength: Int32, _ age: Float64, _ isCat: Int32) -> Int32 { +fileprivate func bjs_Animal_init_extern(_ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32, _ age: Float64, _ isCat: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_Animal_init(_ nameBytes: Int32, _ nameLength: Int32, _ age: Float64, _ isCat: Int32) -> Int32 { - return bjs_Animal_init_extern(nameBytes, nameLength, age, isCat) +@inline(never) fileprivate func bjs_Animal_init(_ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32, _ age: Float64, _ isCat: Int32) -> Int32 { + return bjs_Animal_init_extern(nameWord0, nameWord1, nameWord2, age, isCat) } #if arch(wasm32) @@ -19228,14 +19360,14 @@ fileprivate func bjs_Animal_isCat_get_extern(_ self: Int32) -> Int32 { #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_Animal_name_set") -fileprivate func bjs_Animal_name_set_extern(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void +fileprivate func bjs_Animal_name_set_extern(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void #else -fileprivate func bjs_Animal_name_set_extern(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { +fileprivate func bjs_Animal_name_set_extern(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_Animal_name_set(_ self: Int32, _ newValueBytes: Int32, _ newValueLength: Int32) -> Void { - return bjs_Animal_name_set_extern(self, newValueBytes, newValueLength) +@inline(never) fileprivate func bjs_Animal_name_set(_ self: Int32, _ newValueWord0: Int32, _ newValueWord1: Int32, _ newValueWord2: Int32) -> Void { + return bjs_Animal_name_set_extern(self, newValueWord0, newValueWord1, newValueWord2) } #if arch(wasm32) @@ -19287,10 +19419,10 @@ fileprivate func bjs_Animal_getIsCat_extern(_ self: Int32) -> Int32 { } func _$Animal_init(_ name: String, _ age: Double, _ isCat: Bool) throws(JSException) -> JSObject { - let ret0 = name.bridgeJSWithLoweredParameter { (nameBytes, nameLength) in + let ret0 = name.bridgeJSWithLoweredParameter { (nameWord0, nameWord1, nameWord2) in let isCatValue = isCat.bridgeJSLowerParameter() let ageValue = age.bridgeJSLowerParameter() - let ret = bjs_Animal_init(nameBytes, nameLength, ageValue, isCatValue) + let ret = bjs_Animal_init(nameWord0, nameWord1, nameWord2, ageValue, isCatValue) return ret } let ret = ret0 @@ -19328,9 +19460,9 @@ func _$Animal_isCat_get(_ self: JSObject) throws(JSException) -> Bool { } func _$Animal_name_set(_ self: JSObject, _ newValue: String) throws(JSException) -> Void { - newValue.bridgeJSWithLoweredParameter { (newValueBytes, newValueLength) in + newValue.bridgeJSWithLoweredParameter { (newValueWord0, newValueWord1, newValueWord2) in let selfValue = self.bridgeJSLowerParameter() - bjs_Animal_name_set(selfValue, newValueBytes, newValueLength) + bjs_Animal_name_set(selfValue, newValueWord0, newValueWord1, newValueWord2) } if let error = _swift_js_take_exception() { throw error @@ -19504,21 +19636,21 @@ func _$jsJoinEnumThenArray(_ a: ImportedPayloadSignal, _ b: [Int]) throws(JSExce #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsJoinStringThenStackParams") -fileprivate func bjs_jsJoinStringThenStackParams_extern(_ sBytes: Int32, _ sLength: Int32) -> Int32 +fileprivate func bjs_jsJoinStringThenStackParams_extern(_ sWord0: Int32, _ sWord1: Int32, _ sWord2: Int32) -> Int32 #else -fileprivate func bjs_jsJoinStringThenStackParams_extern(_ sBytes: Int32, _ sLength: Int32) -> Int32 { +fileprivate func bjs_jsJoinStringThenStackParams_extern(_ sWord0: Int32, _ sWord1: Int32, _ sWord2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_jsJoinStringThenStackParams(_ sBytes: Int32, _ sLength: Int32) -> Int32 { - return bjs_jsJoinStringThenStackParams_extern(sBytes, sLength) +@inline(never) fileprivate func bjs_jsJoinStringThenStackParams(_ sWord0: Int32, _ sWord1: Int32, _ sWord2: Int32) -> Int32 { + return bjs_jsJoinStringThenStackParams_extern(sWord0, sWord1, sWord2) } func _$jsJoinStringThenStackParams(_ s: String, _ a: Optional<[Int]>, _ b: [Int]) throws(JSException) -> String { - let ret0 = s.bridgeJSWithLoweredParameter { (sBytes, sLength) in + let ret0 = s.bridgeJSWithLoweredParameter { (sWord0, sWord1, sWord2) in let _ = b.bridgeJSLowerParameter() let _ = a.bridgeJSLowerParameter() - let ret = bjs_jsJoinStringThenStackParams(sBytes, sLength) + let ret = bjs_jsJoinStringThenStackParams(sWord0, sWord1, sWord2) return ret } let ret = ret0 @@ -19572,19 +19704,19 @@ func _$jsGenericRoundTripClass(_ value: T) thr #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_jsGenericParsePoint") -fileprivate func bjs_jsGenericParsePoint_extern(_ jsonBytes: Int32, _ jsonLength: Int32, _ _generic0TypeId: Int32) -> Void +fileprivate func bjs_jsGenericParsePoint_extern(_ jsonWord0: Int32, _ jsonWord1: Int32, _ jsonWord2: Int32, _ _generic0TypeId: Int32) -> Void #else -fileprivate func bjs_jsGenericParsePoint_extern(_ jsonBytes: Int32, _ jsonLength: Int32, _ _generic0TypeId: Int32) -> Void { +fileprivate func bjs_jsGenericParsePoint_extern(_ jsonWord0: Int32, _ jsonWord1: Int32, _ jsonWord2: Int32, _ _generic0TypeId: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_jsGenericParsePoint(_ jsonBytes: Int32, _ jsonLength: Int32, _ _generic0TypeId: Int32) -> Void { - return bjs_jsGenericParsePoint_extern(jsonBytes, jsonLength, _generic0TypeId) +@inline(never) fileprivate func bjs_jsGenericParsePoint(_ jsonWord0: Int32, _ jsonWord1: Int32, _ jsonWord2: Int32, _ _generic0TypeId: Int32) -> Void { + return bjs_jsGenericParsePoint_extern(jsonWord0, jsonWord1, jsonWord2, _generic0TypeId) } func _$jsGenericParsePoint(_ json: String) throws(JSException) -> T { - json.bridgeJSWithLoweredParameter { (jsonBytes, jsonLength) in - bjs_jsGenericParsePoint(jsonBytes, jsonLength, T.bridgeJSTypeID) + json.bridgeJSWithLoweredParameter { (jsonWord0, jsonWord1, jsonWord2) in + bjs_jsGenericParsePoint(jsonWord0, jsonWord1, jsonWord2, T.bridgeJSTypeID) } if let error = _swift_js_take_exception() { throw error @@ -20398,19 +20530,19 @@ func _$defaultExport_get() throws(JSException) -> JSObject { #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_nodeBasename") -fileprivate func bjs_nodeBasename_extern(_ pathBytes: Int32, _ pathLength: Int32) -> Int32 +fileprivate func bjs_nodeBasename_extern(_ pathWord0: Int32, _ pathWord1: Int32, _ pathWord2: Int32) -> Int32 #else -fileprivate func bjs_nodeBasename_extern(_ pathBytes: Int32, _ pathLength: Int32) -> Int32 { +fileprivate func bjs_nodeBasename_extern(_ pathWord0: Int32, _ pathWord1: Int32, _ pathWord2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_nodeBasename(_ pathBytes: Int32, _ pathLength: Int32) -> Int32 { - return bjs_nodeBasename_extern(pathBytes, pathLength) +@inline(never) fileprivate func bjs_nodeBasename(_ pathWord0: Int32, _ pathWord1: Int32, _ pathWord2: Int32) -> Int32 { + return bjs_nodeBasename_extern(pathWord0, pathWord1, pathWord2) } func _$nodeBasename(_ path: String) throws(JSException) -> String { - let ret0 = path.bridgeJSWithLoweredParameter { (pathBytes, pathLength) in - let ret = bjs_nodeBasename(pathBytes, pathLength) + let ret0 = path.bridgeJSWithLoweredParameter { (pathWord0, pathWord1, pathWord2) in + let ret = bjs_nodeBasename(pathWord0, pathWord1, pathWord2) return ret } let ret = ret0 @@ -20422,20 +20554,20 @@ func _$nodeBasename(_ path: String) throws(JSException) -> String { #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_nodeJoin") -fileprivate func bjs_nodeJoin_extern(_ lhsBytes: Int32, _ lhsLength: Int32, _ rhsBytes: Int32, _ rhsLength: Int32) -> Int32 +fileprivate func bjs_nodeJoin_extern(_ lhsWord0: Int32, _ lhsWord1: Int32, _ lhsWord2: Int32, _ rhsWord0: Int32, _ rhsWord1: Int32, _ rhsWord2: Int32) -> Int32 #else -fileprivate func bjs_nodeJoin_extern(_ lhsBytes: Int32, _ lhsLength: Int32, _ rhsBytes: Int32, _ rhsLength: Int32) -> Int32 { +fileprivate func bjs_nodeJoin_extern(_ lhsWord0: Int32, _ lhsWord1: Int32, _ lhsWord2: Int32, _ rhsWord0: Int32, _ rhsWord1: Int32, _ rhsWord2: Int32) -> Int32 { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_nodeJoin(_ lhsBytes: Int32, _ lhsLength: Int32, _ rhsBytes: Int32, _ rhsLength: Int32) -> Int32 { - return bjs_nodeJoin_extern(lhsBytes, lhsLength, rhsBytes, rhsLength) +@inline(never) fileprivate func bjs_nodeJoin(_ lhsWord0: Int32, _ lhsWord1: Int32, _ lhsWord2: Int32, _ rhsWord0: Int32, _ rhsWord1: Int32, _ rhsWord2: Int32) -> Int32 { + return bjs_nodeJoin_extern(lhsWord0, lhsWord1, lhsWord2, rhsWord0, rhsWord1, rhsWord2) } func _$nodeJoin(_ lhs: String, _ rhs: String) throws(JSException) -> String { - let ret0 = lhs.bridgeJSWithLoweredParameter { (lhsBytes, lhsLength) in - let ret1 = rhs.bridgeJSWithLoweredParameter { (rhsBytes, rhsLength) in - let ret = bjs_nodeJoin(lhsBytes, lhsLength, rhsBytes, rhsLength) + let ret0 = lhs.bridgeJSWithLoweredParameter { (lhsWord0, lhsWord1, lhsWord2) in + let ret1 = rhs.bridgeJSWithLoweredParameter { (rhsWord0, rhsWord1, rhsWord2) in + let ret = bjs_nodeJoin(lhsWord0, lhsWord1, lhsWord2, rhsWord0, rhsWord1, rhsWord2) return ret } return ret1 @@ -20979,26 +21111,26 @@ fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalNumberUndefined_s #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_OptionalSupportImports_jsRoundTripOptionalStringNull_static") -fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringNull_static_extern(_ nameIsSome: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void +fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringNull_static_extern(_ nameIsSome: Int32, _ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32) -> Void #else -fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringNull_static_extern(_ nameIsSome: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { +fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringNull_static_extern(_ nameIsSome: Int32, _ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringNull_static(_ nameIsSome: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { - return bjs_OptionalSupportImports_jsRoundTripOptionalStringNull_static_extern(nameIsSome, nameBytes, nameLength) +@inline(never) fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringNull_static(_ nameIsSome: Int32, _ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32) -> Void { + return bjs_OptionalSupportImports_jsRoundTripOptionalStringNull_static_extern(nameIsSome, nameWord0, nameWord1, nameWord2) } #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_OptionalSupportImports_jsRoundTripOptionalStringUndefined_static") -fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringUndefined_static_extern(_ nameIsSome: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void +fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringUndefined_static_extern(_ nameIsSome: Int32, _ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32) -> Void #else -fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringUndefined_static_extern(_ nameIsSome: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { +fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringUndefined_static_extern(_ nameIsSome: Int32, _ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32) -> Void { fatalError("Only available on WebAssembly") } #endif -@inline(never) fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringUndefined_static(_ nameIsSome: Int32, _ nameBytes: Int32, _ nameLength: Int32) -> Void { - return bjs_OptionalSupportImports_jsRoundTripOptionalStringUndefined_static_extern(nameIsSome, nameBytes, nameLength) +@inline(never) fileprivate func bjs_OptionalSupportImports_jsRoundTripOptionalStringUndefined_static(_ nameIsSome: Int32, _ nameWord0: Int32, _ nameWord1: Int32, _ nameWord2: Int32) -> Void { + return bjs_OptionalSupportImports_jsRoundTripOptionalStringUndefined_static_extern(nameIsSome, nameWord0, nameWord1, nameWord2) } #if arch(wasm32) @@ -21092,8 +21224,8 @@ func _$OptionalSupportImports_jsRoundTripOptionalNumberUndefined(_ value: JSUnde } func _$OptionalSupportImports_jsRoundTripOptionalStringNull(_ name: Optional) throws(JSException) -> Optional { - name.bridgeJSWithLoweredParameter { (nameIsSome, nameBytes, nameLength) in - bjs_OptionalSupportImports_jsRoundTripOptionalStringNull_static(nameIsSome, nameBytes, nameLength) + name.bridgeJSWithLoweredParameter { (nameIsSome, nameWord0, nameWord1, nameWord2) in + bjs_OptionalSupportImports_jsRoundTripOptionalStringNull_static(nameIsSome, nameWord0, nameWord1, nameWord2) } if let error = _swift_js_take_exception() { throw error @@ -21102,8 +21234,8 @@ func _$OptionalSupportImports_jsRoundTripOptionalStringNull(_ name: Optional) throws(JSException) -> JSUndefinedOr { - name.bridgeJSWithLoweredParameter { (nameIsSome, nameBytes, nameLength) in - bjs_OptionalSupportImports_jsRoundTripOptionalStringUndefined_static(nameIsSome, nameBytes, nameLength) + name.bridgeJSWithLoweredParameter { (nameIsSome, nameWord0, nameWord1, nameWord2) in + bjs_OptionalSupportImports_jsRoundTripOptionalStringUndefined_static(nameIsSome, nameWord0, nameWord1, nameWord2) } if let error = _swift_js_take_exception() { throw error @@ -21163,6 +21295,71 @@ func _$OptionalSupportImports_runJsOptionalSupportTests() throws(JSException) -> } } +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_StringABIImports_jsEcho_static") +fileprivate func bjs_StringABIImports_jsEcho_static_extern(_ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Int32 +#else +fileprivate func bjs_StringABIImports_jsEcho_static_extern(_ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Int32 { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_StringABIImports_jsEcho_static(_ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Int32 { + return bjs_StringABIImports_jsEcho_static_extern(valueWord0, valueWord1, valueWord2) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_StringABIImports_jsEchoOptional_static") +fileprivate func bjs_StringABIImports_jsEchoOptional_static_extern(_ valueIsSome: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void +#else +fileprivate func bjs_StringABIImports_jsEchoOptional_static_extern(_ valueIsSome: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_StringABIImports_jsEchoOptional_static(_ valueIsSome: Int32, _ valueWord0: Int32, _ valueWord1: Int32, _ valueWord2: Int32) -> Void { + return bjs_StringABIImports_jsEchoOptional_static_extern(valueIsSome, valueWord0, valueWord1, valueWord2) +} + +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_StringABIImports_runJsStringABITests_static") +fileprivate func bjs_StringABIImports_runJsStringABITests_static_extern() -> Void +#else +fileprivate func bjs_StringABIImports_runJsStringABITests_static_extern() -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_StringABIImports_runJsStringABITests_static() -> Void { + return bjs_StringABIImports_runJsStringABITests_static_extern() +} + +func _$StringABIImports_jsEcho(_ value: String) throws(JSException) -> String { + let ret0 = value.bridgeJSWithLoweredParameter { (valueWord0, valueWord1, valueWord2) in + let ret = bjs_StringABIImports_jsEcho_static(valueWord0, valueWord1, valueWord2) + return ret + } + let ret = ret0 + if let error = _swift_js_take_exception() { + throw error + } + return String.bridgeJSLiftReturn(ret) +} + +func _$StringABIImports_jsEchoOptional(_ value: Optional) throws(JSException) -> Optional { + value.bridgeJSWithLoweredParameter { (valueIsSome, valueWord0, valueWord1, valueWord2) in + bjs_StringABIImports_jsEchoOptional_static(valueIsSome, valueWord0, valueWord1, valueWord2) + } + if let error = _swift_js_take_exception() { + throw error + } + return Optional.bridgeJSLiftReturnFromSideChannel() +} + +func _$StringABIImports_runJsStringABITests() throws(JSException) -> Void { + bjs_StringABIImports_runJsStringABITests_static() + if let error = _swift_js_take_exception() { + throw error + } +} + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_gc") fileprivate func bjs_gc_extern() -> Void diff --git a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json index 4749c6eb3..c031c8fb7 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json +++ b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json @@ -13085,6 +13085,330 @@ ], "swiftCallName" : "APIOptionalResult", "tsFullPath" : "APIOptionalResult" + }, + { + "cases" : [ + + ], + "emitStyle" : "const", + "name" : "StringABIExports", + "staticMethods" : [ + { + "abiName" : "bjs_StringABIExports_static_smallEmpty", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "smallEmpty", + "namespace" : [ + "StringABIExports" + ], + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "StringABIExports" + } + } + }, + { + "abiName" : "bjs_StringABIExports_static_smallASCII", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "smallASCII", + "namespace" : [ + "StringABIExports" + ], + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "StringABIExports" + } + } + }, + { + "abiName" : "bjs_StringABIExports_static_smallEight", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "smallEight", + "namespace" : [ + "StringABIExports" + ], + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "StringABIExports" + } + } + }, + { + "abiName" : "bjs_StringABIExports_static_smallNine", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "smallNine", + "namespace" : [ + "StringABIExports" + ], + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "StringABIExports" + } + } + }, + { + "abiName" : "bjs_StringABIExports_static_smallTen", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "smallTen", + "namespace" : [ + "StringABIExports" + ], + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "StringABIExports" + } + } + }, + { + "abiName" : "bjs_StringABIExports_static_smallUTF8", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "smallUTF8", + "namespace" : [ + "StringABIExports" + ], + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "StringABIExports" + } + } + }, + { + "abiName" : "bjs_StringABIExports_static_largeImmortal", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "largeImmortal", + "namespace" : [ + "StringABIExports" + ], + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "StringABIExports" + } + } + }, + { + "abiName" : "bjs_StringABIExports_static_largeImmortalAgain", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "largeImmortalAgain", + "namespace" : [ + "StringABIExports" + ], + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "StringABIExports" + } + } + }, + { + "abiName" : "bjs_StringABIExports_static_largeDynamic", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "largeDynamic", + "namespace" : [ + "StringABIExports" + ], + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "StringABIExports" + } + } + }, + { + "abiName" : "bjs_StringABIExports_static_immortalSubstring", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "immortalSubstring", + "namespace" : [ + "StringABIExports" + ], + "parameters" : [ + + ], + "returnType" : { + "string" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "StringABIExports" + } + } + }, + { + "abiName" : "bjs_StringABIExports_static_optionalNone", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "optionalNone", + "namespace" : [ + "StringABIExports" + ], + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "StringABIExports" + } + } + }, + { + "abiName" : "bjs_StringABIExports_static_optionalSome", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "optionalSome", + "namespace" : [ + "StringABIExports" + ], + "parameters" : [ + + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "StringABIExports" + } + } + } + ], + "staticProperties" : [ + + ], + "swiftCallName" : "StringABIExports", + "tsFullPath" : "StringABIExports" } ], "exposeToGlobal" : false, @@ -27823,6 +28147,103 @@ } ] }, + { + "functions" : [ + + ], + "types" : [ + { + "accessLevel" : "internal", + "getters" : [ + + ], + "methods" : [ + + ], + "name" : "StringABIImports", + "setters" : [ + + ], + "staticMethods" : [ + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "jsEcho", + "parameters" : [ + { + "name" : "value", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "jsEchoOptional", + "parameters" : [ + { + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "runJsStringABITests", + "parameters" : [ + + ], + "returnType" : { + "void" : { + + } + } + } + ] + } + ] + }, { "functions" : [ { diff --git a/Tests/BridgeJSRuntimeTests/JavaScript/StringABITests.mjs b/Tests/BridgeJSRuntimeTests/JavaScript/StringABITests.mjs new file mode 100644 index 000000000..49b09ee0a --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/JavaScript/StringABITests.mjs @@ -0,0 +1,40 @@ +// @ts-check + +import assert from 'node:assert'; + +/** + * @returns {import('../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Imports["StringABIImports"]} + */ +export function getImports(importsContext) { + return { + jsEcho: (value) => value, + jsEchoOptional: (value) => value ?? null, + runJsStringABITests: () => { + const exports = importsContext.getExports(); + if (!exports) { throw new Error("No exports!?"); } + runJsStringABITests(exports); + }, + }; +} + +/** + * Swift→JS string layout coverage: small, immortal, dynamic, substring, optional. + * @param {import('../../../.build/plugins/PackageToJS/outputs/PackageTests/bridge-js.d.ts').Exports} rootExports + */ +export function runJsStringABITests(rootExports) { + const exports = rootExports.StringABIExports; + const immortal = "this is a long immortal literal string"; + + assert.equal(exports.smallEmpty(), ""); + assert.equal(exports.smallASCII(), "div"); + assert.equal(exports.smallEight(), "abcdefgh"); + assert.equal(exports.smallNine(), "abcdefghi"); + assert.equal(exports.smallTen(), "abcdefghij"); + assert.equal(exports.smallUTF8(), "é"); + assert.equal(exports.largeImmortal(), immortal); + assert.equal(exports.largeImmortalAgain(), immortal); + assert.equal(exports.largeDynamic(), immortal); + assert.equal(exports.immortalSubstring(), immortal.slice(10)); + assert.equal(exports.optionalNone(), null); + assert.equal(exports.optionalSome(), immortal); +} diff --git a/Tests/BridgeJSRuntimeTests/StringABITests.swift b/Tests/BridgeJSRuntimeTests/StringABITests.swift new file mode 100644 index 000000000..c96d74218 --- /dev/null +++ b/Tests/BridgeJSRuntimeTests/StringABITests.swift @@ -0,0 +1,62 @@ +import XCTest +import JavaScriptKit +import JavaScriptEventLoop + +private let largeImmortalLiteral = "this is a long immortal literal string" + +@inline(never) +private func runtimeCopy(_ string: String) -> String { + String(decoding: Array(string.utf8), as: UTF8.self) +} + +@JSClass struct StringABIImports { + @JSFunction static func jsEcho(_ value: String) throws(JSException) -> String + @JSFunction static func jsEchoOptional(_ value: String?) throws(JSException) -> String? + @JSFunction static func runJsStringABITests() throws(JSException) +} + +@JS enum StringABIExports { + @JS static func smallEmpty() -> String { "" } + @JS static func smallASCII() -> String { "div" } + @JS static func smallEight() -> String { "abcdefgh" } + @JS static func smallNine() -> String { "abcdefghi" } + @JS static func smallTen() -> String { "abcdefghij" } + @JS static func smallUTF8() -> String { "é" } + @JS static func largeImmortal() -> String { largeImmortalLiteral } + @JS static func largeImmortalAgain() -> String { largeImmortalLiteral } + @JS static func largeDynamic() -> String { runtimeCopy(largeImmortalLiteral) } + @JS static func immortalSubstring() -> String { String(largeImmortalLiteral.dropFirst(10)) } + @JS static func optionalNone() -> String? { nil } + @JS static func optionalSome() -> String? { largeImmortalLiteral } +} + +final class StringABITests: XCTestCase { + func testRunJsStringABITests() throws { + try StringABIImports.runJsStringABITests() + } + + func testImportEchoesSmallStrings() throws { + try XCTAssertEqual(StringABIImports.jsEcho(""), "") + try XCTAssertEqual(StringABIImports.jsEcho("div"), "div") + try XCTAssertEqual(StringABIImports.jsEcho("abcdefgh"), "abcdefgh") + try XCTAssertEqual(StringABIImports.jsEcho("abcdefghi"), "abcdefghi") + try XCTAssertEqual(StringABIImports.jsEcho("abcdefghij"), "abcdefghij") + try XCTAssertEqual(StringABIImports.jsEcho("é"), "é") + } + + func testImportEchoesLargeImmortalAndDynamicStrings() throws { + try XCTAssertEqual(StringABIImports.jsEcho(largeImmortalLiteral), largeImmortalLiteral) + try XCTAssertEqual(StringABIImports.jsEcho(largeImmortalLiteral), largeImmortalLiteral) + try XCTAssertEqual(StringABIImports.jsEcho(runtimeCopy(largeImmortalLiteral)), largeImmortalLiteral) + try XCTAssertEqual( + StringABIImports.jsEcho(String(largeImmortalLiteral.dropFirst(10))), + String(largeImmortalLiteral.dropFirst(10)) + ) + } + + func testImportEchoesOptionalStrings() throws { + try XCTAssertNil(StringABIImports.jsEchoOptional(nil)) + try XCTAssertEqual(StringABIImports.jsEchoOptional("div"), "div") + try XCTAssertEqual(StringABIImports.jsEchoOptional(largeImmortalLiteral), largeImmortalLiteral) + } +} diff --git a/Tests/prelude.mjs b/Tests/prelude.mjs index 5287df791..8a109bcb5 100644 --- a/Tests/prelude.mjs +++ b/Tests/prelude.mjs @@ -11,6 +11,7 @@ import { getImports as getClosureThrowsImports } from './BridgeJSRuntimeTests/Ja import { getImports as getClosureAsyncImports } from './BridgeJSRuntimeTests/JavaScript/ClosureAsyncTests.mjs'; import { getImports as getSwiftClassSupportImports } from './BridgeJSRuntimeTests/JavaScript/SwiftClassSupportTests.mjs'; import { getImports as getOptionalSupportImports } from './BridgeJSRuntimeTests/JavaScript/OptionalSupportTests.mjs'; +import { getImports as getStringABIImports } from './BridgeJSRuntimeTests/JavaScript/StringABITests.mjs'; import { getImports as getArraySupportImports, ArrayElementObject } from './BridgeJSRuntimeTests/JavaScript/ArraySupportTests.mjs'; import { getImports as getDictionarySupportImports } from './BridgeJSRuntimeTests/JavaScript/DictionarySupportTests.mjs'; import { getImports as getDefaultArgumentImports } from './BridgeJSRuntimeTests/JavaScript/DefaultArgumentTests.mjs'; @@ -212,6 +213,7 @@ export async function setupOptions(options, context) { ClosureAsyncImports: getClosureAsyncImports(importsContext), SwiftClassSupportImports: getSwiftClassSupportImports(importsContext), OptionalSupportImports: getOptionalSupportImports(importsContext), + StringABIImports: getStringABIImports(importsContext), ArraySupportImports: getArraySupportImports(importsContext), DictionarySupportImports: getDictionarySupportImports(importsContext), DefaultArgumentImports: getDefaultArgumentImports(importsContext), @@ -289,6 +291,12 @@ function BridgeJSRuntimeTests_runJsWorks(instance, exports) { assert.equal(exports.roundTripBool(v), v); } for (const v of [ + "", + "div", + "abcdefgh", + "abcdefghi", + "abcdefghij", + "é", "Hello, world!", "😄", "こんにちは", From 3dac1e03fdb05d3a7b6a8ac0280a1a61e5adc144 Mon Sep 17 00:00:00 2001 From: Simon Leeb <52261246+sliemeobn@users.noreply.github.com> Date: Sun, 4 Oct 2026 23:08:08 +0200 Subject: [PATCH 2/3] faster small UTF deocding --- .../Sources/BridgeJSLink/BridgeJSLink.swift | 185 +++++++++++++++--- .../Inputs/StringDecoderTests.mjs | 90 +++++++++ .../StringDecoderTests.swift | 44 +++++ .../__Snapshots__/BridgeJSLinkTests/Alias.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/AliasInClosure.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/ArrayTypes.js | 185 +++++++++++++++--- .../__Snapshots__/BridgeJSLinkTests/Async.js | 185 +++++++++++++++--- .../AsyncAssociatedValueEnum.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/AsyncImport.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/AsyncStaticImport.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/ClassWithNestedTypes.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/DefaultParameters.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/DictionaryTypes.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/DocComments.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/EnumAlias.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/EnumAssociatedValue.js | 185 +++++++++++++++--- .../EnumAssociatedValueImport.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/EnumCase.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/EnumCaseImport.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/EnumNamespace.Global.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/EnumNamespace.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/EnumRawType.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/ExtensionNestedTypes.js | 185 +++++++++++++++--- .../ExtensionOrderIndependence.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/ExtensionScopeParity.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/FixedWidthIntegers.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/GenericImports.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/GlobalGetter.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/GlobalThisImports.js | 185 +++++++++++++++--- .../IdentityModeClass.ConfigPointer.js | 185 +++++++++++++++--- .../IdentityModeClass.PerClass.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/IdentityModeClass.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/ImportArray.js | 185 +++++++++++++++--- .../ImportedTypeInExportedInterface.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/InvalidPropertyNames.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/JSClass.js | 185 +++++++++++++++--- .../JSClassStaticFunctions.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/JSImportBareModule.js | 185 +++++++++++++++--- .../JSImportBareModuleFallback.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/JSImportModule.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/JSNameOverride.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/JSNameTypes.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/JSTypedArrayTypes.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/JSValue.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/MixedGlobal.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/MixedModules.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/MixedPrivate.js | 185 +++++++++++++++--- .../NamespacedClassSignature.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/Namespaces.Global.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/Namespaces.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/NestedType.js | 185 +++++++++++++++--- .../NestedTypeNameCollision.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/Optionals.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/PrimitiveParameters.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/PrimitiveReturn.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/PropertyTypes.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/Protocol.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/ProtocolInClosure.js | 185 +++++++++++++++--- .../RelativeQualifiedTypes.js | 185 +++++++++++++++--- .../StaticFunctions.Global.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/StaticFunctions.js | 185 +++++++++++++++--- .../StaticProperties.Global.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/StaticProperties.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/StringParameter.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/StringReturn.js | 185 +++++++++++++++--- .../StructWithNestedTypes.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/SwiftClass.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/SwiftClosure.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/SwiftClosureImports.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/SwiftStruct.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/SwiftStructImports.js | 185 +++++++++++++++--- .../SwiftTypedClosureAccess.js | 185 +++++++++++++++--- .../__Snapshots__/BridgeJSLinkTests/Throws.js | 185 +++++++++++++++--- .../BridgeJSLinkTests/UnsafePointer.js | 185 +++++++++++++++--- .../VoidParameterVoidReturn.js | 185 +++++++++++++++--- .../Generated/BridgeJS.swift | 57 ++++++ .../Generated/JavaScript/BridgeJS.json | 149 ++++++++++++++ .../JavaScript/StringABITests.mjs | 13 ++ .../BridgeJSRuntimeTests/StringABITests.swift | 19 ++ 79 files changed, 12125 insertions(+), 1752 deletions(-) create mode 100644 Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StringDecoderTests.mjs create mode 100644 Plugins/BridgeJS/Tests/BridgeJSToolTests/StringDecoderTests.swift diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index d12749e0e..cb96e3d33 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -326,35 +326,171 @@ public struct BridgeJSLink { printer.write( multilineString: """ \(JSGlueVariableScope.reservedDecodeString) = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); } - result += String.fromCodePoint(codePoint); + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } + } else { + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } + } + } + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); } - return result; }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; @@ -1370,6 +1506,7 @@ public struct BridgeJSLink { printer.write("setInstance: (i) => {") printer.indent { printer.write(lines: [ + "if (\(JSGlueVariableScope.reservedMemory) !== i.exports.memory) \(JSGlueVariableScope.reservedImmortalStrings).clear();", "\(JSGlueVariableScope.reservedInstance) = i;", "\(JSGlueVariableScope.reservedMemory) = \(JSGlueVariableScope.reservedInstance).exports.memory;", ]) diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StringDecoderTests.mjs b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StringDecoderTests.mjs new file mode 100644 index 000000000..c83a0d8db --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/Inputs/StringDecoderTests.mjs @@ -0,0 +1,90 @@ +import assert from 'node:assert/strict'; +import { readFile } from 'node:fs/promises'; + +// Execute generated glue rather than a duplicate of the decoder implementation. +const source = await readFile(process.argv[2] ?? new URL('../__Snapshots__/BridgeJSLinkTests/StringReturn.js', import.meta.url), 'utf8'); +const shared = process.argv[3] === 'shared'; +const { createInstantiator } = await import(`data:text/javascript;base64,${Buffer.from(source).toString('base64')}`); +const encoder = new TextEncoder(); +const decoder = new TextDecoder(); +const swift = { memory: { heap: [], retain: (value) => value } }; +const bridge = await createInstantiator({ getImports: () => ({}) }, swift); +const imports = {}; +bridge.addImports(imports, {}); +let words; +function instance(memory) { + return { exports: { memory, bjs_checkString: () => imports.bjs.swift_js_return_string(...words) } }; +} +let memory = new WebAssembly.Memory({ initial: 40, maximum: 41, shared }); +let wasm = instance(memory); +bridge.setInstance(wasm); +let exports = bridge.createExports(wasm); +function small(value) { + const bytes = encoder.encode(value); + assert.ok(bytes.length <= 10); + const storage = new Uint8Array(12); + storage.set(bytes.subarray(0, 8)); + storage[8] = bytes[8] ?? 0; + storage[10] = bytes[9] ?? 0; + storage[9] = (bytes.every((b) => b < 128) ? 0xe0 : 0xa0) | bytes.length; + const view = new DataView(storage.buffer); + return [0, 4, 8].map((offset) => view.getInt32(offset, true)); +} +function large(value, immortal = false, ptr = 64) { + const bytes = encoder.encode(value); + new Uint8Array(memory.buffer, ptr, bytes.length).set(bytes); + return [bytes.length, ptr - 20, immortal ? 0x8000 : 0]; +} +const values = ['', 'div', 'abcdefgh', 'abcdefghi', 'abcdefghij', 'abcdefé', 'abcdefgé', + 'abcdefghé', 'abcdefghié', 'abc€', 'abcdefg€', 'abc😄', 'abcdef😄', 'abcdefg😄', + 'a\0b', '\ufeff', '\ufeffx', 'x\ufeff', '\ufeff\ufeffx', '\ufeffabcdefghijk', + 'abc\ufeffdefghijk', '\ufeff\ufeffabcdefghijk']; +for (const value of values) { + const expected = decoder.decode(encoder.encode(value)); + if (encoder.encode(value).length <= 10) { + words = small(value); + assert.equal(exports.checkString(), expected); + } + words = large(value); + assert.equal(exports.checkString(), expected); +} +// Alternate full and short inputs: bytes outside count must never leak into the result. +for (const value of ['abcdefghé', 'é', 'abcdef😄', '\ufeff', 'abcdefghij', '', 'x\0', '€', '\ufeff\ufeff']) { + words = small(value); + assert.equal(exports.checkString(), decoder.decode(encoder.encode(value))); +} +// Every ASCII byte, including NUL, at every small-string length. +for (let byte = 0; byte < 128; byte++) { + for (let count = 0; count <= 10; count++) { + const value = String.fromCharCode(byte).repeat(count); + words = small(value); + assert.equal(exports.checkString(), value); + } +} +words = large('first literal', true); +assert.equal(exports.checkString(), 'first literal'); +// A new instance using the same memory must preserve valid cache entries. +wasm = instance(memory); +bridge.setInstance(wasm); +exports = bridge.createExports(wasm); +assert.equal(exports.checkString(), 'first literal'); +// A different memory may reuse the same pointer/length for different contents. +memory = new WebAssembly.Memory({ initial: 40, maximum: 41, shared }); +wasm = instance(memory); +bridge.setInstance(wasm); +exports = bridge.createExports(wasm); +words = large('other literal', true); +assert.equal(exports.checkString(), 'other literal'); +// Same pointer with a different length must have a distinct key. +words = large('other', true); +assert.equal(exports.checkString(), 'other'); +// Values at the numeric-key cutoff bypass the cache. +const huge = 'x'.repeat(2 ** 21); +words = large(huge, true); +assert.equal(exports.checkString(), huge); +new Uint8Array(memory.buffer)[64] = 121; +assert.equal(exports.checkString(), 'y' + huge.slice(1)); +memory.grow(1); +words = large('after memory growth'); +assert.equal(exports.checkString(), 'after memory growth'); +console.log('String decoder regressions passed'); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/StringDecoderTests.swift b/Plugins/BridgeJS/Tests/BridgeJSToolTests/StringDecoderTests.swift new file mode 100644 index 000000000..96449b4de --- /dev/null +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/StringDecoderTests.swift @@ -0,0 +1,44 @@ +import Foundation +import SwiftParser +import Testing +@testable import BridgeJSCore +@testable import BridgeJSLink +@testable import TS2Swift + +@Suite struct StringDecoderTests { + @Test(arguments: [false, true]) + func generatedStringDecoder(sharedMemory: Bool) throws { + let directory = URL(fileURLWithPath: #filePath).deletingLastPathComponent() + let fixture = directory.appendingPathComponent("Inputs/MacroSwift/StringReturn.swift") + let collector = SwiftToSkeleton( + progress: .silent, + moduleName: "TestModule", + exposeToGlobal: false, + externalModuleIndex: .empty + ) + collector.addSourceFile( + Parser.parse(source: try String(contentsOf: fixture, encoding: .utf8)), + inputFilePath: fixture.path + ) + var linker = BridgeJSLink() + try linker.addSkeletonFile(data: JSONEncoder().encode(collector.finalize())) + let output = try linker.link(sharedMemory: sharedMemory) + guard let node = which("node") else { + Issue.record("Node.js is required for string decoder regression tests") + return + } + try withTemporaryDirectory { temporaryDirectory, _ in + let glue = temporaryDirectory.appendingPathComponent("bridge.js") + try output.outputJs.write(to: glue, atomically: true, encoding: .utf8) + let process = Process() + process.executableURL = node + process.arguments = [ + directory.appendingPathComponent("Inputs/StringDecoderTests.mjs").path, + glue.path, sharedMemory ? "shared" : "unshared", + ] + try process.run() + process.waitUntilExit() + #expect(process.terminationStatus == 0) + } + } +} diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Alias.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Alias.js index d4f2441d3..20dc542a1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Alias.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Alias.js @@ -680,40 +680,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AliasInClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AliasInClosure.js index ce2baf58c..ed149ff5f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AliasInClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AliasInClosure.js @@ -292,40 +292,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js index da9c6e88d..e16e3cc7c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js @@ -742,40 +742,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js index 40d251279..178e5d996 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js @@ -726,40 +726,177 @@ export async function createInstantiator(options, swift) { bjs["swift_js_closure_unregister"] = function(funcRef) {} }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.js index c6642fccb..ebd330084 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.js @@ -372,40 +372,177 @@ export async function createInstantiator(options, swift) { bjs["swift_js_closure_unregister"] = function(funcRef) {} }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncImport.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncImport.js index 03ec128fd..dadb79152 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncImport.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncImport.js @@ -504,40 +504,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncStaticImport.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncStaticImport.js index ae1a3fce0..4bc797fe3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncStaticImport.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncStaticImport.js @@ -400,40 +400,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ClassWithNestedTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ClassWithNestedTypes.js index f690854c1..959f91e49 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ClassWithNestedTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ClassWithNestedTypes.js @@ -241,40 +241,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js index f334eb5c7..660430ffb 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js @@ -619,40 +619,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js index 3f23333a5..1e7265ebf 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js @@ -594,40 +594,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DocComments.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DocComments.js index 94564ffa4..cabc84b5f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DocComments.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DocComments.js @@ -258,40 +258,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAlias.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAlias.js index f34281ef9..7b2a181be 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAlias.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAlias.js @@ -217,40 +217,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js index ab12aebd6..883369326 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js @@ -1179,40 +1179,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.js index 0c3c8a090..de96c2d60 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.js @@ -303,40 +303,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js index f480062f1..b357bc35c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js @@ -233,40 +233,177 @@ export async function createInstantiator(options, swift) { bjs["swift_js_closure_unregister"] = function(funcRef) {} }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCaseImport.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCaseImport.js index 114f145a8..6cc6e39a2 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCaseImport.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCaseImport.js @@ -241,40 +241,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js index 622f5aa4c..bc5e3deb9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js @@ -273,40 +273,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js index bc3952c24..692244d58 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js @@ -254,40 +254,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js index caf2f2dfa..303a9cdd4 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js @@ -647,40 +647,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionNestedTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionNestedTypes.js index cabb2aeff..3095ed089 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionNestedTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionNestedTypes.js @@ -302,40 +302,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionOrderIndependence.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionOrderIndependence.js index 6c7b9e38f..e8a049f17 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionOrderIndependence.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionOrderIndependence.js @@ -244,40 +244,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionScopeParity.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionScopeParity.js index 6b51521b3..7e6b1c7a0 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionScopeParity.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionScopeParity.js @@ -244,40 +244,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/FixedWidthIntegers.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/FixedWidthIntegers.js index 056abf4f6..716137841 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/FixedWidthIntegers.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/FixedWidthIntegers.js @@ -282,40 +282,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GenericImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GenericImports.js index 811681911..5163037d0 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GenericImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GenericImports.js @@ -940,40 +940,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js index ce66a3ffc..ed5f54415 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js @@ -227,40 +227,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js index 2791313be..5cd128d06 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js @@ -252,40 +252,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js index 282ae4ec9..fda322eb2 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js @@ -224,40 +224,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js index 715a4522d..6987a311d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js @@ -224,40 +224,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js index 715a4522d..6987a311d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js @@ -224,40 +224,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js index 3b918d9cb..754eb5092 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js @@ -577,40 +577,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js index 8e34c8a5a..5af5b2a92 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js @@ -589,40 +589,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js index 0923c1435..98602fbc5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js @@ -390,40 +390,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js index 0f4ff9741..106c88ecc 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js @@ -289,40 +289,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js index d999f7100..cb7bac8a3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js @@ -272,40 +272,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModule.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModule.js index d64deb891..7dbfcaf54 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModule.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModule.js @@ -297,40 +297,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModuleFallback.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModuleFallback.js index 4b407018c..23787ee21 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModuleFallback.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModuleFallback.js @@ -241,40 +241,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportModule.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportModule.js index 6938c2713..fdf47fe02 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportModule.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportModule.js @@ -281,40 +281,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameOverride.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameOverride.js index ca2eeebb9..160ac2200 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameOverride.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameOverride.js @@ -246,40 +246,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameTypes.js index 98f9afa5d..db43bbb31 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameTypes.js @@ -222,40 +222,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSTypedArrayTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSTypedArrayTypes.js index e3322b31e..97a201100 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSTypedArrayTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSTypedArrayTypes.js @@ -208,40 +208,177 @@ export async function createInstantiator(options, swift) { bjs["swift_js_closure_unregister"] = function(funcRef) {} }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js index 2a14c8c2f..74914d2e1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js @@ -565,40 +565,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js index d3a6e551c..0706a2e1e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js @@ -216,40 +216,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js index 70611b70f..77aa4384b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js @@ -224,40 +224,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js index 953b5c479..fd3ad6249 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js @@ -216,40 +216,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NamespacedClassSignature.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NamespacedClassSignature.js index 8e3fc9ba9..a77ae484d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NamespacedClassSignature.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NamespacedClassSignature.js @@ -268,40 +268,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js index 8bc37539f..fa8ae3d23 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js @@ -563,40 +563,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js index e0b99db0e..f372bb013 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js @@ -563,40 +563,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js index a7fe1afe4..430d6535f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js @@ -260,40 +260,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedTypeNameCollision.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedTypeNameCollision.js index 181eb9fce..b538dd72d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedTypeNameCollision.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedTypeNameCollision.js @@ -244,40 +244,177 @@ export async function createInstantiator(options, swift) { bjs["swift_js_closure_unregister"] = function(funcRef) {} }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js index 369c453fe..77f3eff82 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js @@ -845,40 +845,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js index 14100292b..67cb2a38d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js @@ -217,40 +217,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js index 1970e82e3..dc680d750 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js @@ -228,40 +228,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js index 5a157c55b..9028b8001 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js @@ -216,40 +216,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js index 2babe8caa..129f14aca 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js @@ -915,40 +915,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js index e08de3586..a711ae42f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js @@ -362,40 +362,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/RelativeQualifiedTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/RelativeQualifiedTypes.js index 47849439b..8d4d756f3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/RelativeQualifiedTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/RelativeQualifiedTypes.js @@ -299,40 +299,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js index 7ae9d51ad..0d9f6652f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js @@ -261,40 +261,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js index 53b664598..ecf07e995 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js @@ -261,40 +261,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js index 717352169..a860a945d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js @@ -222,40 +222,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js index 8bc834b09..fb3564317 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js @@ -222,40 +222,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js index 9c7502cbd..ff6eea294 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js @@ -226,40 +226,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js index 01be76bbd..80fc0ad79 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js @@ -219,40 +219,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StructWithNestedTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StructWithNestedTypes.js index e7529dee8..9c7bc2b41 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StructWithNestedTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StructWithNestedTypes.js @@ -296,40 +296,177 @@ export async function createInstantiator(options, swift) { bjs["swift_js_closure_unregister"] = function(funcRef) {} }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js index 1e17ead5f..8c9efae8d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js @@ -244,40 +244,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js index 35ca99800..4f6525070 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js @@ -1561,40 +1561,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js index c1b3bec76..5b3cf529b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js @@ -483,40 +483,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js index 52ebbfc22..42a55d247 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js @@ -778,40 +778,177 @@ export async function createInstantiator(options, swift) { }; }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js index f793de7fc..ab8e969e8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js @@ -581,40 +581,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.js index 6f5e2ac06..dbadc1f65 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.js @@ -326,40 +326,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js index 4a5cec34c..a67b77270 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js @@ -208,40 +208,177 @@ export async function createInstantiator(options, swift) { bjs["swift_js_closure_unregister"] = function(funcRef) {} }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js index 56bc6b1ac..2e4204e07 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js @@ -233,40 +233,177 @@ export async function createInstantiator(options, swift) { bjs["swift_js_closure_unregister"] = function(funcRef) {} }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js index 63d6a1a6a..799cc30bd 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js @@ -217,40 +217,177 @@ export async function createInstantiator(options, swift) { } }, setInstance: (i) => { + if (memory !== i.exports.memory) immortalStrings.clear(); instance = i; memory = instance.exports.memory; decodeUTF8 = (ptr, len) => { const bytes = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); return textDecoder.decode(bytes); } decodeString = (() => { - const byteAt = (word0, word1, word2, i) => { - if (i < 4) return (word0 >>> (i * 8)) & 0xff; - if (i < 8) return (word1 >>> ((i - 4) * 8)) & 0xff; - if (i === 8) return word2 & 0xff; - return (word2 >>> 16) & 0xff; - }; + const byteAt = (word0, word1, word2, byteIndex) => + byteIndex < 4 + ? (word0 >>> (byteIndex * 8)) & 255 + : byteIndex < 8 + ? (word1 >>> ((byteIndex - 4) * 8)) & 255 + : byteIndex === 8 + ? word2 & 255 + : (word2 >>> 16) & 255; + // Valid small Swift strings need at most ten UTF-16 code units. const decodeSmallUTF8 = (word0, word1, word2, count) => { - let result = ""; - let i = 0; - while (i < count) { - const b0 = byteAt(word0, word1, word2, i++); + let byteIndex = 0, + unitCount = 0, + u0 = 0, + u1 = 0, + u2 = 0, + u3 = 0, + u4 = 0, + u5 = 0, + u6 = 0, + u7 = 0, + u8 = 0, + u9 = 0; + while (byteIndex < count) { + const start = byteIndex; + const b0 = byteAt(word0, word1, word2, byteIndex++); let codePoint; - if (b0 < 0x80) { - codePoint = b0; - } else if (b0 < 0xe0) { - codePoint = ((b0 & 0x1f) << 6) | (byteAt(word0, word1, word2, i++) & 0x3f); - } else if (b0 < 0xf0) { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x0f) << 12) | ((b1 & 0x3f) << 6) | (b2 & 0x3f); + if (b0 < 128) codePoint = b0; + else if (b0 < 224) codePoint = ((b0 & 31) << 6) | (byteAt(word0, word1, word2, byteIndex++) & 63); + else if (b0 < 240) { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 15) << 12) | ((b1 & 63) << 6) | (b2 & 63); + } else { + const b1 = byteAt(word0, word1, word2, byteIndex++), + b2 = byteAt(word0, word1, word2, byteIndex++), + b3 = byteAt(word0, word1, word2, byteIndex++); + codePoint = ((b0 & 7) << 18) | ((b1 & 63) << 12) | ((b2 & 63) << 6) | (b3 & 63); + } + // Match TextDecoder: consume exactly one leading UTF-8 BOM. + if (start === 0 && codePoint === 0xfeff) continue; + if (codePoint <= 0xffff) { + switch (unitCount++) { + case 0: + u0 = codePoint; + break; + case 1: + u1 = codePoint; + break; + case 2: + u2 = codePoint; + break; + case 3: + u3 = codePoint; + break; + case 4: + u4 = codePoint; + break; + case 5: + u5 = codePoint; + break; + case 6: + u6 = codePoint; + break; + case 7: + u7 = codePoint; + break; + case 8: + u8 = codePoint; + break; + case 9: + u9 = codePoint; + break; + } } else { - const b1 = byteAt(word0, word1, word2, i++); - const b2 = byteAt(word0, word1, word2, i++); - const b3 = byteAt(word0, word1, word2, i++); - codePoint = ((b0 & 0x07) << 18) | ((b1 & 0x3f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f); + codePoint -= 0x10000; + switch (unitCount++) { + case 0: + u0 = 0xd800 + (codePoint >>> 10); + break; + case 1: + u1 = 0xd800 + (codePoint >>> 10); + break; + case 2: + u2 = 0xd800 + (codePoint >>> 10); + break; + case 3: + u3 = 0xd800 + (codePoint >>> 10); + break; + case 4: + u4 = 0xd800 + (codePoint >>> 10); + break; + case 5: + u5 = 0xd800 + (codePoint >>> 10); + break; + case 6: + u6 = 0xd800 + (codePoint >>> 10); + break; + case 7: + u7 = 0xd800 + (codePoint >>> 10); + break; + case 8: + u8 = 0xd800 + (codePoint >>> 10); + break; + case 9: + u9 = 0xd800 + (codePoint >>> 10); + break; + } + switch (unitCount++) { + case 0: + u0 = 0xdc00 + (codePoint & 1023); + break; + case 1: + u1 = 0xdc00 + (codePoint & 1023); + break; + case 2: + u2 = 0xdc00 + (codePoint & 1023); + break; + case 3: + u3 = 0xdc00 + (codePoint & 1023); + break; + case 4: + u4 = 0xdc00 + (codePoint & 1023); + break; + case 5: + u5 = 0xdc00 + (codePoint & 1023); + break; + case 6: + u6 = 0xdc00 + (codePoint & 1023); + break; + case 7: + u7 = 0xdc00 + (codePoint & 1023); + break; + case 8: + u8 = 0xdc00 + (codePoint & 1023); + break; + case 9: + u9 = 0xdc00 + (codePoint & 1023); + break; + } } - result += String.fromCodePoint(codePoint); } - return result; + switch (unitCount) { + case 0: + return ""; + case 1: + return String.fromCharCode(u0); + case 2: + return String.fromCharCode(u0, u1); + case 3: + return String.fromCharCode(u0, u1, u2); + case 4: + return String.fromCharCode(u0, u1, u2, u3); + case 5: + return String.fromCharCode(u0, u1, u2, u3, u4); + case 6: + return String.fromCharCode(u0, u1, u2, u3, u4, u5); + case 7: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6); + case 8: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7); + case 9: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8); + case 10: + return String.fromCharCode(u0, u1, u2, u3, u4, u5, u6, u7, u8, u9); + } }; const decodeSmall = (word0, word1, word2) => { const count = (word2 >>> 8) & 0x0f; diff --git a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift index 7118f688f..52799fa7c 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift +++ b/Tests/BridgeJSRuntimeTests/Generated/BridgeJS.swift @@ -7672,6 +7672,42 @@ extension APIOptionalResult: _BridgedSwiftAssociatedValueEnum { } } +@_expose(wasm, "bjs_StringABIExports_static_echo") +@_cdecl("bjs_StringABIExports_static_echo") +public func _bjs_StringABIExports_static_echo(_ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + let value = String.bridgeJSLiftParameter(valueBytes, valueLength) + let ret = StringABIExports.echo(_: value) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StringABIExports_static_echoOptional") +@_cdecl("bjs_StringABIExports_static_echoOptional") +public func _bjs_StringABIExports_static_echoOptional(_ valueIsSome: Int32, _ valueBytes: Int32, _ valueLength: Int32) -> Void { + #if arch(wasm32) + let value = Optional.bridgeJSLiftParameter(valueIsSome, valueBytes, valueLength) + let ret = StringABIExports.echoOptional(_: value) + return ret.bridgeJSLowerReturn() + #else + fatalError("Only available on WebAssembly") + #endif +} + +@_expose(wasm, "bjs_StringABIExports_static_echoArray") +@_cdecl("bjs_StringABIExports_static_echoArray") +public func _bjs_StringABIExports_static_echoArray() -> Void { + #if arch(wasm32) + let value = [String].bridgeJSStackPop() + let ret = StringABIExports.echoArray(_: value) + ret.bridgeJSStackPush() + #else + fatalError("Only available on WebAssembly") + #endif +} + @_expose(wasm, "bjs_StringABIExports_static_smallEmpty") @_cdecl("bjs_StringABIExports_static_smallEmpty") public func _bjs_StringABIExports_static_smallEmpty() -> Void { @@ -21319,6 +21355,18 @@ fileprivate func bjs_StringABIImports_jsEchoOptional_static_extern(_ valueIsSome return bjs_StringABIImports_jsEchoOptional_static_extern(valueIsSome, valueWord0, valueWord1, valueWord2) } +#if arch(wasm32) +@_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_StringABIImports_jsEchoArray_static") +fileprivate func bjs_StringABIImports_jsEchoArray_static_extern() -> Void +#else +fileprivate func bjs_StringABIImports_jsEchoArray_static_extern() -> Void { + fatalError("Only available on WebAssembly") +} +#endif +@inline(never) fileprivate func bjs_StringABIImports_jsEchoArray_static() -> Void { + return bjs_StringABIImports_jsEchoArray_static_extern() +} + #if arch(wasm32) @_extern(wasm, module: "BridgeJSRuntimeTests", name: "bjs_StringABIImports_runJsStringABITests_static") fileprivate func bjs_StringABIImports_runJsStringABITests_static_extern() -> Void @@ -21353,6 +21401,15 @@ func _$StringABIImports_jsEchoOptional(_ value: Optional) throws(JSExcep return Optional.bridgeJSLiftReturnFromSideChannel() } +func _$StringABIImports_jsEchoArray(_ value: [String]) throws(JSException) -> [String] { + let _ = value.bridgeJSLowerParameter() + bjs_StringABIImports_jsEchoArray_static() + if let error = _swift_js_take_exception() { + throw error + } + return [String].bridgeJSLiftReturn() +} + func _$StringABIImports_runJsStringABITests() throws(JSException) -> Void { bjs_StringABIImports_runJsStringABITests_static() if let error = _swift_js_take_exception() { diff --git a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json index c031c8fb7..d649d4e76 100644 --- a/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json +++ b/Tests/BridgeJSRuntimeTests/Generated/JavaScript/BridgeJS.json @@ -13093,6 +13093,123 @@ "emitStyle" : "const", "name" : "StringABIExports", "staticMethods" : [ + { + "abiName" : "bjs_StringABIExports_static_echo", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "echo", + "namespace" : [ + "StringABIExports" + ], + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "string" : { + + } + } + } + ], + "returnType" : { + "string" : { + + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "StringABIExports" + } + } + }, + { + "abiName" : "bjs_StringABIExports_static_echoOptional", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "echoOptional", + "namespace" : [ + "StringABIExports" + ], + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + } + } + ], + "returnType" : { + "nullable" : { + "_0" : { + "string" : { + + } + }, + "_1" : "null" + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "StringABIExports" + } + } + }, + { + "abiName" : "bjs_StringABIExports_static_echoArray", + "effects" : { + "isAsync" : false, + "isStatic" : true, + "isThrows" : false + }, + "name" : "echoArray", + "namespace" : [ + "StringABIExports" + ], + "parameters" : [ + { + "label" : "_", + "name" : "value", + "type" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + }, + "staticContext" : { + "namespaceEnum" : { + "_0" : "StringABIExports" + } + } + }, { "abiName" : "bjs_StringABIExports_static_smallEmpty", "effects" : { @@ -28223,6 +28340,38 @@ } } }, + { + "accessLevel" : "internal", + "effects" : { + "isAsync" : false, + "isStatic" : false, + "isThrows" : true + }, + "name" : "jsEchoArray", + "parameters" : [ + { + "name" : "value", + "type" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + } + ], + "returnType" : { + "array" : { + "_0" : { + "string" : { + + } + } + } + } + }, { "accessLevel" : "internal", "effects" : { diff --git a/Tests/BridgeJSRuntimeTests/JavaScript/StringABITests.mjs b/Tests/BridgeJSRuntimeTests/JavaScript/StringABITests.mjs index 49b09ee0a..8468e1faf 100644 --- a/Tests/BridgeJSRuntimeTests/JavaScript/StringABITests.mjs +++ b/Tests/BridgeJSRuntimeTests/JavaScript/StringABITests.mjs @@ -8,6 +8,7 @@ import assert from 'node:assert'; export function getImports(importsContext) { return { jsEcho: (value) => value, + jsEchoArray: (value) => value, jsEchoOptional: (value) => value ?? null, runJsStringABITests: () => { const exports = importsContext.getExports(); @@ -37,4 +38,16 @@ export function runJsStringABITests(rootExports) { assert.equal(exports.immortalSubstring(), immortal.slice(10)); assert.equal(exports.optionalNone(), null); assert.equal(exports.optionalSome(), immortal); + const expected = samples.map((s) => s.startsWith("\ufeff") ? s.slice(1) : s); + for (let i = 0; i < samples.length; i++) { + assert.equal(exports.echo(samples[i]), expected[i]); + assert.equal(exports.echoOptional(samples[i]), expected[i]); + } + assert.deepEqual(exports.echoArray(samples), expected); } + +const samples = [ + "abcdefé", "abcdefgé", "abcdefghé", "abcdefghié", "abc€", "abcdefg€", + "abc😄", "abcdef😄", "abcdefg😄", "a\0b", "\ufeffx", "x\ufeff", + "\ufeff\ufeffx", "\ufeffabcdefghijk", "abc\ufeffdefghijk", "\ufeff\ufeffabcdefghijk", +]; diff --git a/Tests/BridgeJSRuntimeTests/StringABITests.swift b/Tests/BridgeJSRuntimeTests/StringABITests.swift index c96d74218..c3f424011 100644 --- a/Tests/BridgeJSRuntimeTests/StringABITests.swift +++ b/Tests/BridgeJSRuntimeTests/StringABITests.swift @@ -12,10 +12,14 @@ private func runtimeCopy(_ string: String) -> String { @JSClass struct StringABIImports { @JSFunction static func jsEcho(_ value: String) throws(JSException) -> String @JSFunction static func jsEchoOptional(_ value: String?) throws(JSException) -> String? + @JSFunction static func jsEchoArray(_ value: [String]) throws(JSException) -> [String] @JSFunction static func runJsStringABITests() throws(JSException) } @JS enum StringABIExports { + @JS static func echo(_ value: String) -> String { value } + @JS static func echoOptional(_ value: String?) -> String? { value } + @JS static func echoArray(_ value: [String]) -> [String] { value } @JS static func smallEmpty() -> String { "" } @JS static func smallASCII() -> String { "div" } @JS static func smallEight() -> String { "abcdefgh" } @@ -35,6 +39,21 @@ final class StringABITests: XCTestCase { try StringABIImports.runJsStringABITests() } + func testUnicodeAndBOMParametersAndStacks() throws { + let samples = [ + "abcdefé", "abcdefgé", "abcdefghé", "abcdefghié", + "abc€", "abcdefg€", "abc😄", "abcdef😄", "abcdefg😄", "a\0b", + "\u{FEFF}x", "x\u{FEFF}", "\u{FEFF}\u{FEFF}x", + "\u{FEFF}abcdefghijk", "abc\u{FEFF}defghijk", "\u{FEFF}\u{FEFF}abcdefghijk", + ] + let expected = samples.map { $0.first == "\u{FEFF}" ? String($0.dropFirst()) : $0 } + for (input, output) in zip(samples, expected) { + try XCTAssertEqual(StringABIImports.jsEcho(input), output) + try XCTAssertEqual(StringABIImports.jsEchoOptional(input), output) + } + try XCTAssertEqual(StringABIImports.jsEchoArray(samples), expected) + } + func testImportEchoesSmallStrings() throws { try XCTAssertEqual(StringABIImports.jsEcho(""), "") try XCTAssertEqual(StringABIImports.jsEcho("div"), "div") From 297694a7fcc06d9040153d543ce319995461dbe7 Mon Sep 17 00:00:00 2001 From: Simon Leeb <52261246+sliemeobn@users.noreply.github.com> Date: Sun, 4 Oct 2026 23:38:11 +0200 Subject: [PATCH 3/3] hardcodeASCII 9 and 10, simplified inline UTF8 decoding --- .../Sources/BridgeJSLink/BridgeJSLink.swift | 132 +++++++----------- .../__Snapshots__/BridgeJSLinkTests/Alias.js | 128 +++++++---------- .../BridgeJSLinkTests/AliasInClosure.js | 128 +++++++---------- .../BridgeJSLinkTests/ArrayTypes.js | 128 +++++++---------- .../__Snapshots__/BridgeJSLinkTests/Async.js | 128 +++++++---------- .../AsyncAssociatedValueEnum.js | 128 +++++++---------- .../BridgeJSLinkTests/AsyncImport.js | 128 +++++++---------- .../BridgeJSLinkTests/AsyncStaticImport.js | 128 +++++++---------- .../BridgeJSLinkTests/ClassWithNestedTypes.js | 128 +++++++---------- .../BridgeJSLinkTests/DefaultParameters.js | 128 +++++++---------- .../BridgeJSLinkTests/DictionaryTypes.js | 128 +++++++---------- .../BridgeJSLinkTests/DocComments.js | 128 +++++++---------- .../BridgeJSLinkTests/EnumAlias.js | 128 +++++++---------- .../BridgeJSLinkTests/EnumAssociatedValue.js | 128 +++++++---------- .../EnumAssociatedValueImport.js | 128 +++++++---------- .../BridgeJSLinkTests/EnumCase.js | 128 +++++++---------- .../BridgeJSLinkTests/EnumCaseImport.js | 128 +++++++---------- .../BridgeJSLinkTests/EnumNamespace.Global.js | 128 +++++++---------- .../BridgeJSLinkTests/EnumNamespace.js | 128 +++++++---------- .../BridgeJSLinkTests/EnumRawType.js | 128 +++++++---------- .../BridgeJSLinkTests/ExtensionNestedTypes.js | 128 +++++++---------- .../ExtensionOrderIndependence.js | 128 +++++++---------- .../BridgeJSLinkTests/ExtensionScopeParity.js | 128 +++++++---------- .../BridgeJSLinkTests/FixedWidthIntegers.js | 128 +++++++---------- .../BridgeJSLinkTests/GenericImports.js | 128 +++++++---------- .../BridgeJSLinkTests/GlobalGetter.js | 128 +++++++---------- .../BridgeJSLinkTests/GlobalThisImports.js | 128 +++++++---------- .../IdentityModeClass.ConfigPointer.js | 128 +++++++---------- .../IdentityModeClass.PerClass.js | 128 +++++++---------- .../BridgeJSLinkTests/IdentityModeClass.js | 128 +++++++---------- .../BridgeJSLinkTests/ImportArray.js | 128 +++++++---------- .../ImportedTypeInExportedInterface.js | 128 +++++++---------- .../BridgeJSLinkTests/InvalidPropertyNames.js | 128 +++++++---------- .../BridgeJSLinkTests/JSClass.js | 128 +++++++---------- .../JSClassStaticFunctions.js | 128 +++++++---------- .../BridgeJSLinkTests/JSImportBareModule.js | 128 +++++++---------- .../JSImportBareModuleFallback.js | 128 +++++++---------- .../BridgeJSLinkTests/JSImportModule.js | 128 +++++++---------- .../BridgeJSLinkTests/JSNameOverride.js | 128 +++++++---------- .../BridgeJSLinkTests/JSNameTypes.js | 128 +++++++---------- .../BridgeJSLinkTests/JSTypedArrayTypes.js | 128 +++++++---------- .../BridgeJSLinkTests/JSValue.js | 128 +++++++---------- .../BridgeJSLinkTests/MixedGlobal.js | 128 +++++++---------- .../BridgeJSLinkTests/MixedModules.js | 128 +++++++---------- .../BridgeJSLinkTests/MixedPrivate.js | 128 +++++++---------- .../NamespacedClassSignature.js | 128 +++++++---------- .../BridgeJSLinkTests/Namespaces.Global.js | 128 +++++++---------- .../BridgeJSLinkTests/Namespaces.js | 128 +++++++---------- .../BridgeJSLinkTests/NestedType.js | 128 +++++++---------- .../NestedTypeNameCollision.js | 128 +++++++---------- .../BridgeJSLinkTests/Optionals.js | 128 +++++++---------- .../BridgeJSLinkTests/PrimitiveParameters.js | 128 +++++++---------- .../BridgeJSLinkTests/PrimitiveReturn.js | 128 +++++++---------- .../BridgeJSLinkTests/PropertyTypes.js | 128 +++++++---------- .../BridgeJSLinkTests/Protocol.js | 128 +++++++---------- .../BridgeJSLinkTests/ProtocolInClosure.js | 128 +++++++---------- .../RelativeQualifiedTypes.js | 128 +++++++---------- .../StaticFunctions.Global.js | 128 +++++++---------- .../BridgeJSLinkTests/StaticFunctions.js | 128 +++++++---------- .../StaticProperties.Global.js | 128 +++++++---------- .../BridgeJSLinkTests/StaticProperties.js | 128 +++++++---------- .../BridgeJSLinkTests/StringParameter.js | 128 +++++++---------- .../BridgeJSLinkTests/StringReturn.js | 128 +++++++---------- .../StructWithNestedTypes.js | 128 +++++++---------- .../BridgeJSLinkTests/SwiftClass.js | 128 +++++++---------- .../BridgeJSLinkTests/SwiftClosure.js | 128 +++++++---------- .../BridgeJSLinkTests/SwiftClosureImports.js | 128 +++++++---------- .../BridgeJSLinkTests/SwiftStruct.js | 128 +++++++---------- .../BridgeJSLinkTests/SwiftStructImports.js | 128 +++++++---------- .../SwiftTypedClosureAccess.js | 128 +++++++---------- .../__Snapshots__/BridgeJSLinkTests/Throws.js | 128 +++++++---------- .../BridgeJSLinkTests/UnsafePointer.js | 128 +++++++---------- .../VoidParameterVoidReturn.js | 128 +++++++---------- 73 files changed, 3652 insertions(+), 5696 deletions(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index cb96e3d33..fa664ca6b 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -318,8 +318,8 @@ public struct BridgeJSLink { /// The wasm32 12-byte Swift `String` layout is a standard-library /// implementation detail, not a stable ABI. Small strings (`word2 & 0x2000`) /// store up to 10 UTF-8 bytes inline. Large strings store the UTF-8 count in - /// `word0` and a storage pointer in `word1` already biased by `nativeBias` - /// (20), so UTF-8 starts at `word1 + 20`. Immortal large strings + /// `word0` and a variant/object pointer in `word1`; UTF-8 starts at + /// `word1 + nativeBias` (20 on 32-bit). Immortal large strings /// (`word2 & 0x8000`) are cached by a 53-bit `ptr + len * 2**32` key when /// `len < 2**21`; longer immortals skip the cache. private func emitDecodeString(_ printer: CodeFragmentPrinter) { @@ -366,103 +366,74 @@ public struct BridgeJSLink { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -506,7 +477,8 @@ public struct BridgeJSLink { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Alias.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Alias.js index 20dc542a1..04c230153 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Alias.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Alias.js @@ -726,103 +726,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -866,7 +837,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AliasInClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AliasInClosure.js index ed149ff5f..55b7e1126 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AliasInClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AliasInClosure.js @@ -338,103 +338,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -478,7 +449,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js index e16e3cc7c..1dcebf70f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js @@ -788,103 +788,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -928,7 +899,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js index 178e5d996..12bc60107 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js @@ -772,103 +772,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -912,7 +883,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.js index ebd330084..ec946060c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncAssociatedValueEnum.js @@ -418,103 +418,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -558,7 +529,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncImport.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncImport.js index dadb79152..e4555d1ce 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncImport.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncImport.js @@ -550,103 +550,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -690,7 +661,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncStaticImport.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncStaticImport.js index 4bc797fe3..ccce528a6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncStaticImport.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncStaticImport.js @@ -446,103 +446,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -586,7 +557,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ClassWithNestedTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ClassWithNestedTypes.js index 959f91e49..e302251de 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ClassWithNestedTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ClassWithNestedTypes.js @@ -287,103 +287,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -427,7 +398,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js index 660430ffb..ad278c725 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js @@ -665,103 +665,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -805,7 +776,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js index 1e7265ebf..5c76843c8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js @@ -640,103 +640,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -780,7 +751,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DocComments.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DocComments.js index cabc84b5f..97a37a148 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DocComments.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DocComments.js @@ -304,103 +304,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -444,7 +415,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAlias.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAlias.js index 7b2a181be..55dc286af 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAlias.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAlias.js @@ -263,103 +263,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -403,7 +374,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js index 883369326..a13fa75cd 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js @@ -1225,103 +1225,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -1365,7 +1336,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.js index de96c2d60..aee8b8a04 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValueImport.js @@ -349,103 +349,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -489,7 +460,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js index b357bc35c..29f861a26 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js @@ -279,103 +279,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -419,7 +390,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCaseImport.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCaseImport.js index 6cc6e39a2..b8fbe139a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCaseImport.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCaseImport.js @@ -287,103 +287,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -427,7 +398,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js index bc5e3deb9..77c82c250 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js @@ -319,103 +319,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -459,7 +430,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js index 692244d58..4c80ed652 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js @@ -300,103 +300,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -440,7 +411,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js index 303a9cdd4..301dd8793 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js @@ -693,103 +693,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -833,7 +804,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionNestedTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionNestedTypes.js index 3095ed089..44ee3d149 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionNestedTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionNestedTypes.js @@ -348,103 +348,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -488,7 +459,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionOrderIndependence.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionOrderIndependence.js index e8a049f17..5c68fab90 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionOrderIndependence.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionOrderIndependence.js @@ -290,103 +290,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -430,7 +401,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionScopeParity.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionScopeParity.js index 7e6b1c7a0..18f3cf3aa 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionScopeParity.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ExtensionScopeParity.js @@ -290,103 +290,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -430,7 +401,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/FixedWidthIntegers.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/FixedWidthIntegers.js index 716137841..51b98268d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/FixedWidthIntegers.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/FixedWidthIntegers.js @@ -328,103 +328,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -468,7 +439,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GenericImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GenericImports.js index 5163037d0..0c3ec9536 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GenericImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GenericImports.js @@ -986,103 +986,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -1126,7 +1097,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js index ed5f54415..6e005fed1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js @@ -273,103 +273,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -413,7 +384,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js index 5cd128d06..4cc797a77 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js @@ -298,103 +298,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -438,7 +409,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js index fda322eb2..8bd456b5f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js @@ -270,103 +270,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -410,7 +381,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js index 6987a311d..576761318 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js @@ -270,103 +270,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -410,7 +381,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js index 6987a311d..576761318 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js @@ -270,103 +270,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -410,7 +381,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js index 754eb5092..6c83791a5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js @@ -623,103 +623,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -763,7 +734,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js index 5af5b2a92..497377caf 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js @@ -635,103 +635,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -775,7 +746,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js index 98602fbc5..0156496e2 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js @@ -436,103 +436,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -576,7 +547,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js index 106c88ecc..b885c3ca8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js @@ -335,103 +335,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -475,7 +446,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js index cb7bac8a3..2bd7418a9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js @@ -318,103 +318,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -458,7 +429,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModule.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModule.js index 7dbfcaf54..b6f5d0a12 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModule.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModule.js @@ -343,103 +343,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -483,7 +454,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModuleFallback.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModuleFallback.js index 23787ee21..3b09b2ba0 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModuleFallback.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportBareModuleFallback.js @@ -287,103 +287,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -427,7 +398,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportModule.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportModule.js index fdf47fe02..edc9f3281 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportModule.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSImportModule.js @@ -327,103 +327,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -467,7 +438,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameOverride.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameOverride.js index 160ac2200..fe118a424 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameOverride.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameOverride.js @@ -292,103 +292,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -432,7 +403,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameTypes.js index db43bbb31..520da96b8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSNameTypes.js @@ -268,103 +268,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -408,7 +379,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSTypedArrayTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSTypedArrayTypes.js index 97a201100..d8c39e4ad 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSTypedArrayTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSTypedArrayTypes.js @@ -254,103 +254,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -394,7 +365,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js index 74914d2e1..26a3d4574 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js @@ -611,103 +611,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -751,7 +722,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js index 0706a2e1e..d078d252f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js @@ -262,103 +262,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -402,7 +373,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js index 77aa4384b..85d6df975 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js @@ -270,103 +270,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -410,7 +381,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js index fd3ad6249..9c020acb1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js @@ -262,103 +262,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -402,7 +373,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NamespacedClassSignature.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NamespacedClassSignature.js index a77ae484d..6614fae0e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NamespacedClassSignature.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NamespacedClassSignature.js @@ -314,103 +314,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -454,7 +425,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js index fa8ae3d23..d390ed3e0 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js @@ -609,103 +609,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -749,7 +720,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js index f372bb013..79fe1ae72 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js @@ -609,103 +609,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -749,7 +720,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js index 430d6535f..cf5379258 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js @@ -306,103 +306,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -446,7 +417,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedTypeNameCollision.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedTypeNameCollision.js index b538dd72d..f2a47150e 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedTypeNameCollision.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedTypeNameCollision.js @@ -290,103 +290,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -430,7 +401,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js index 77f3eff82..46f1d40d7 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js @@ -891,103 +891,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -1031,7 +1002,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js index 67cb2a38d..2e1aaffa3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js @@ -263,103 +263,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -403,7 +374,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js index dc680d750..d0a97f7a3 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js @@ -274,103 +274,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -414,7 +385,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js index 9028b8001..f8abe0d0a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js @@ -262,103 +262,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -402,7 +373,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js index 129f14aca..f6b5c4b38 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js @@ -961,103 +961,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -1101,7 +1072,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js index a711ae42f..b2ceaf5be 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js @@ -408,103 +408,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -548,7 +519,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/RelativeQualifiedTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/RelativeQualifiedTypes.js index 8d4d756f3..37f9aee78 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/RelativeQualifiedTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/RelativeQualifiedTypes.js @@ -345,103 +345,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -485,7 +456,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js index 0d9f6652f..e23e7a885 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js @@ -307,103 +307,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -447,7 +418,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js index ecf07e995..869d297b7 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js @@ -307,103 +307,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -447,7 +418,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js index a860a945d..895864e0a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js @@ -268,103 +268,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -408,7 +379,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js index fb3564317..7ec51867d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js @@ -268,103 +268,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -408,7 +379,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js index ff6eea294..4339f3395 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js @@ -272,103 +272,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -412,7 +383,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js index 80fc0ad79..f8ccb25a9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js @@ -265,103 +265,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -405,7 +376,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StructWithNestedTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StructWithNestedTypes.js index 9c7bc2b41..70146e4bd 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StructWithNestedTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StructWithNestedTypes.js @@ -342,103 +342,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -482,7 +453,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js index 8c9efae8d..45b693895 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js @@ -290,103 +290,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -430,7 +401,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js index 4f6525070..a129f7b8b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js @@ -1607,103 +1607,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -1747,7 +1718,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js index 5b3cf529b..8768e4ee1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js @@ -529,103 +529,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -669,7 +640,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js index 42a55d247..d04bc0fbb 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js @@ -824,103 +824,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -964,7 +935,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js index ab8e969e8..9ef137a8b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js @@ -627,103 +627,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -767,7 +738,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.js index dbadc1f65..1c8fcc597 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.js @@ -372,103 +372,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -512,7 +483,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js index a67b77270..98a4ea18d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js @@ -254,103 +254,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -394,7 +365,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js index 2e4204e07..50d4ba990 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js @@ -279,103 +279,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -419,7 +390,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js index 799cc30bd..a5753441c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js @@ -263,103 +263,74 @@ export async function createInstantiator(options, swift) { } // Match TextDecoder: consume exactly one leading UTF-8 BOM. if (start === 0 && codePoint === 0xfeff) continue; - if (codePoint <= 0xffff) { - switch (unitCount++) { - case 0: - u0 = codePoint; - break; - case 1: - u1 = codePoint; - break; - case 2: - u2 = codePoint; - break; - case 3: - u3 = codePoint; - break; - case 4: - u4 = codePoint; - break; - case 5: - u5 = codePoint; - break; - case 6: - u6 = codePoint; - break; - case 7: - u7 = codePoint; - break; - case 8: - u8 = codePoint; - break; - case 9: - u9 = codePoint; - break; - } - } else { - codePoint -= 0x10000; - switch (unitCount++) { - case 0: - u0 = 0xd800 + (codePoint >>> 10); - break; - case 1: - u1 = 0xd800 + (codePoint >>> 10); - break; - case 2: - u2 = 0xd800 + (codePoint >>> 10); - break; - case 3: - u3 = 0xd800 + (codePoint >>> 10); - break; - case 4: - u4 = 0xd800 + (codePoint >>> 10); - break; - case 5: - u5 = 0xd800 + (codePoint >>> 10); - break; - case 6: - u6 = 0xd800 + (codePoint >>> 10); - break; - case 7: - u7 = 0xd800 + (codePoint >>> 10); - break; - case 8: - u8 = 0xd800 + (codePoint >>> 10); - break; - case 9: - u9 = 0xd800 + (codePoint >>> 10); - break; - } + const supplementary = codePoint > 0xffff; + const codeUnit = supplementary + ? 0xd800 + ((codePoint - 0x10000) >>> 10) + : codePoint; + switch (unitCount++) { + case 0: + u0 = codeUnit; + break; + case 1: + u1 = codeUnit; + break; + case 2: + u2 = codeUnit; + break; + case 3: + u3 = codeUnit; + break; + case 4: + u4 = codeUnit; + break; + case 5: + u5 = codeUnit; + break; + case 6: + u6 = codeUnit; + break; + case 7: + u7 = codeUnit; + break; + case 8: + u8 = codeUnit; + break; + case 9: + u9 = codeUnit; + break; + } + if (supplementary) { + const lowSurrogate = 0xdc00 + ((codePoint - 0x10000) & 1023); switch (unitCount++) { case 0: - u0 = 0xdc00 + (codePoint & 1023); + u0 = lowSurrogate; break; case 1: - u1 = 0xdc00 + (codePoint & 1023); + u1 = lowSurrogate; break; case 2: - u2 = 0xdc00 + (codePoint & 1023); + u2 = lowSurrogate; break; case 3: - u3 = 0xdc00 + (codePoint & 1023); + u3 = lowSurrogate; break; case 4: - u4 = 0xdc00 + (codePoint & 1023); + u4 = lowSurrogate; break; case 5: - u5 = 0xdc00 + (codePoint & 1023); + u5 = lowSurrogate; break; case 6: - u6 = 0xdc00 + (codePoint & 1023); + u6 = lowSurrogate; break; case 7: - u7 = 0xdc00 + (codePoint & 1023); + u7 = lowSurrogate; break; case 8: - u8 = 0xdc00 + (codePoint & 1023); + u8 = lowSurrogate; break; case 9: - u9 = 0xdc00 + (codePoint & 1023); + u9 = lowSurrogate; break; } } @@ -403,7 +374,8 @@ export async function createInstantiator(options, swift) { case 6: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff); case 7: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff); case 8: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24); - default: return decodeSmallUTF8(word0, word1, word2, count); + case 9: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff); + case 10: return char(word0 & 0xff, (word0 >>> 8) & 0xff, (word0 >>> 16) & 0xff, word0 >>> 24, word1 & 0xff, (word1 >>> 8) & 0xff, (word1 >>> 16) & 0xff, word1 >>> 24, word2 & 0xff, (word2 >>> 16) & 0xff); } }; return (word0, word1, word2) => {