From 5f0bab088134ecebb010258b44b1846aa5a847a9 Mon Sep 17 00:00:00 2001 From: Krzysztof Rodak Date: Wed, 20 May 2026 11:17:26 +0200 Subject: [PATCH] BridgeJS: Optimize string encoding for JS-to-Swift crossings Two techniques applied to all JS-to-Swift string paths: 1. LRU encoding cache for parameter and return paths - avoids re-encoding repeated strings via a Map with 256-entry LRU eviction. 2. Direct string retain + encodeInto() for stack ABI paths (arrays, structs, enums, dictionaries) - skips the intermediate Uint8Array allocation entirely by retaining the JS string and encoding directly into the WASM linear memory buffer. _swift_js_init_memory now returns the actual byte count written, which the stack ABI path needs since it passes a worst-case buffer size (string.length * 3) rather than the exact UTF-8 byte count. Benchmarks (100k iterations, Node.js): StringRoundtrip/takeString: -21% ArrayRoundtrip/takeStringArray: -35% ArrayRoundtrip/roundtripStringArray: -29% --- .../Sources/BridgeJSLink/BridgeJSLink.swift | 11 +++ .../Sources/BridgeJSLink/JSGlueGen.swift | 18 +++-- .../BridgeJSLinkTests/ArrayTypes.js | 44 +++++------ .../__Snapshots__/BridgeJSLinkTests/Async.js | 9 ++- .../BridgeJSLinkTests/AsyncImport.js | 9 ++- .../BridgeJSLinkTests/AsyncStaticImport.js | 7 ++ .../BridgeJSLinkTests/DefaultParameters.js | 39 ++++++---- .../BridgeJSLinkTests/DictionaryTypes.js | 52 ++++++------- .../BridgeJSLinkTests/EnumAssociatedValue.js | 77 +++++++++---------- .../BridgeJSLinkTests/EnumCase.js | 7 ++ .../BridgeJSLinkTests/EnumNamespace.Global.js | 7 ++ .../BridgeJSLinkTests/EnumNamespace.js | 7 ++ .../BridgeJSLinkTests/EnumRawType.js | 23 ++++-- .../BridgeJSLinkTests/FixedWidthIntegers.js | 7 ++ .../BridgeJSLinkTests/GlobalGetter.js | 7 ++ .../BridgeJSLinkTests/GlobalThisImports.js | 7 ++ .../IdentityModeClass.ConfigPointer.js | 11 ++- .../IdentityModeClass.PerClass.js | 11 ++- .../BridgeJSLinkTests/IdentityModeClass.js | 11 ++- .../BridgeJSLinkTests/ImportArray.js | 7 ++ .../ImportedTypeInExportedInterface.js | 7 ++ .../BridgeJSLinkTests/InvalidPropertyNames.js | 17 ++-- .../BridgeJSLinkTests/JSClass.js | 11 ++- .../JSClassStaticFunctions.js | 7 ++ .../BridgeJSLinkTests/JSValue.js | 7 ++ .../BridgeJSLinkTests/MixedGlobal.js | 7 ++ .../BridgeJSLinkTests/MixedModules.js | 7 ++ .../BridgeJSLinkTests/MixedPrivate.js | 7 ++ .../BridgeJSLinkTests/Namespaces.Global.js | 9 ++- .../BridgeJSLinkTests/Namespaces.js | 9 ++- .../BridgeJSLinkTests/NestedType.js | 7 ++ .../BridgeJSLinkTests/Optionals.js | 31 +++++--- .../BridgeJSLinkTests/PrimitiveParameters.js | 7 ++ .../BridgeJSLinkTests/PrimitiveReturn.js | 7 ++ .../BridgeJSLinkTests/PropertyTypes.js | 17 ++-- .../BridgeJSLinkTests/Protocol.js | 34 ++++---- .../BridgeJSLinkTests/ProtocolInClosure.js | 19 +++-- .../StaticFunctions.Global.js | 14 +++- .../BridgeJSLinkTests/StaticFunctions.js | 14 +++- .../StaticProperties.Global.js | 19 +++-- .../BridgeJSLinkTests/StaticProperties.js | 19 +++-- .../BridgeJSLinkTests/StringParameter.js | 11 ++- .../BridgeJSLinkTests/StringReturn.js | 9 ++- .../BridgeJSLinkTests/SwiftClass.js | 13 +++- .../BridgeJSLinkTests/SwiftClosure.js | 33 ++++---- .../BridgeJSLinkTests/SwiftClosureImports.js | 7 ++ .../BridgeJSLinkTests/SwiftStruct.js | 40 +++++----- .../BridgeJSLinkTests/SwiftStructImports.js | 7 ++ .../SwiftTypedClosureAccess.js | 7 ++ .../__Snapshots__/BridgeJSLinkTests/Throws.js | 7 ++ .../BridgeJSLinkTests/UnsafePointer.js | 7 ++ .../VoidParameterVoidReturn.js | 7 ++ .../JavaScriptKit/BridgeJSIntrinsics.swift | 27 ++++--- 53 files changed, 573 insertions(+), 249 deletions(-) diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift index ceaaae8f1..a9fa731f3 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift @@ -331,6 +331,9 @@ public struct BridgeJSLink { "let \(JSGlueVariableScope.reservedDecodeString);", "const \(JSGlueVariableScope.reservedTextDecoder) = new TextDecoder(\"utf-8\");", "const \(JSGlueVariableScope.reservedTextEncoder) = new TextEncoder(\"utf-8\");", + "const \(JSGlueVariableScope.reservedStrEncCache) = new Map();", + "const \(JSGlueVariableScope.reservedStrEncCacheMax) = 256;", + "function \(JSGlueVariableScope.reservedCachedEncode)(s) { let b = \(JSGlueVariableScope.reservedStrEncCache).get(s); if (b) { \(JSGlueVariableScope.reservedStrEncCache).delete(s); \(JSGlueVariableScope.reservedStrEncCache).set(s, b); return b; } b = \(JSGlueVariableScope.reservedTextEncoder).encode(s); if (\(JSGlueVariableScope.reservedStrEncCache).size >= \(JSGlueVariableScope.reservedStrEncCacheMax)) { \(JSGlueVariableScope.reservedStrEncCache).delete(\(JSGlueVariableScope.reservedStrEncCache).keys().next().value); } \(JSGlueVariableScope.reservedStrEncCache).set(s, b); return b; };", "let \(JSGlueVariableScope.reservedStorageToReturnString);", "let \(JSGlueVariableScope.reservedStorageToReturnBytes);", "let \(JSGlueVariableScope.reservedStorageToReturnException);", @@ -393,7 +396,15 @@ public struct BridgeJSLink { printer.write( "const bytes = new Uint8Array(\(JSGlueVariableScope.reservedMemory).buffer, bytesPtr);" ) + printer.write("if (typeof source === 'string') {") + printer.indent { + printer.write( + "return \(JSGlueVariableScope.reservedTextEncoder).encodeInto(source, bytes).written;" + ) + } + printer.write("}") printer.write("bytes.set(source);") + printer.write("return source.length;") } printer.write("}") printer.write("bjs[\"swift_js_make_js_string\"] = function(ptr, len) {") diff --git a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift index 1ad397f71..2ff491763 100644 --- a/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift +++ b/Plugins/BridgeJS/Sources/BridgeJSLink/JSGlueGen.swift @@ -24,6 +24,9 @@ final class JSGlueVariableScope { static let reservedStorageToReturnOptionalHeapObject = "tmpRetOptionalHeapObject" static let reservedTextEncoder = "textEncoder" static let reservedTextDecoder = "textDecoder" + static let reservedCachedEncode = "_cachedEncode" + static let reservedStrEncCache = "_strEncCache" + static let reservedStrEncCacheMax = "_strEncCacheMax" static let reservedStringStack = "strStack" static let reservedI32Stack = "i32Stack" static let reservedI64Stack = "i64Stack" @@ -53,6 +56,9 @@ final class JSGlueVariableScope { reservedStorageToReturnOptionalHeapObject, reservedTextEncoder, reservedTextDecoder, + reservedCachedEncode, + reservedStrEncCache, + reservedStrEncCacheMax, reservedStringStack, reservedI32Stack, reservedI64Stack, @@ -263,7 +269,7 @@ struct IntrinsicJSFragment: Sendable { let argument = arguments[0] let bytesLabel = scope.variable("\(argument)Bytes") let bytesIdLabel = scope.variable("\(argument)Id") - printer.write("const \(bytesLabel) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(argument));") + printer.write("const \(bytesLabel) = \(JSGlueVariableScope.reservedCachedEncode)(\(argument));") printer.write("const \(bytesIdLabel) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesLabel));") return [bytesIdLabel, "\(bytesLabel).length"] } @@ -296,7 +302,7 @@ struct IntrinsicJSFragment: Sendable { printCode: { arguments, context in let printer = context.printer printer.write( - "\(JSGlueVariableScope.reservedStorageToReturnBytes) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(arguments[0]));" + "\(JSGlueVariableScope.reservedStorageToReturnBytes) = \(JSGlueVariableScope.reservedCachedEncode)(\(arguments[0]));" ) return ["\(JSGlueVariableScope.reservedStorageToReturnBytes).length"] } @@ -2116,15 +2122,11 @@ struct IntrinsicJSFragment: Sendable { printCode: { arguments, context in let (scope, printer) = (context.scope, context.printer) let value = arguments[0] - let bytesVar = scope.variable("bytes") let idVar = scope.variable("id") printer.write( - "const \(bytesVar) = \(JSGlueVariableScope.reservedTextEncoder).encode(\(value));" - ) - printer.write( - "const \(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(bytesVar));" + "const \(idVar) = \(JSGlueVariableScope.reservedSwift).memory.retain(\(value));" ) - scope.emitPushI32Parameter("\(bytesVar).length", printer: printer) + scope.emitPushI32Parameter("\(value).length * 3", printer: printer) scope.emitPushI32Parameter(idVar, printer: printer) return [] } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js index 8359220c9..9c65aac7d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ArrayTypes.js @@ -24,6 +24,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -70,7 +73,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -301,9 +308,8 @@ export async function createInstantiator(options, swift) { arrayResult.reverse(); let ret = imports.importProcessStrings(arrayResult); for (const elem of ret) { - const bytes = textEncoder.encode(elem); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(elem); + i32Stack.push(elem.length * 3); i32Stack.push(id); } i32Stack.push(ret.length); @@ -411,9 +417,8 @@ export async function createInstantiator(options, swift) { } i32Stack.push(nums.length); for (const elem1 of strs) { - const bytes = textEncoder.encode(elem1); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(elem1); + i32Stack.push(elem1.length * 3); i32Stack.push(id); } i32Stack.push(strs.length); @@ -466,9 +471,8 @@ export async function createInstantiator(options, swift) { }, processStringArray: function bjs_processStringArray(values) { for (const elem of values) { - const bytes = textEncoder.encode(elem); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(elem); + i32Stack.push(elem.length * 3); i32Stack.push(id); } i32Stack.push(values.length); @@ -570,7 +574,7 @@ export async function createInstantiator(options, swift) { structHelpers.Point.lower(elem); } i32Stack.push(points.length); - const matchingBytes = textEncoder.encode(matching); + const matchingBytes = _cachedEncode(matching); const matchingId = swift.memory.retain(matchingBytes); instance.exports.bjs_findFirstPoint(matchingId, matchingBytes.length); const structValue = structHelpers.Point.lift(); @@ -651,9 +655,8 @@ export async function createInstantiator(options, swift) { for (const elem of values) { const isSome = elem != null ? 1 : 0; if (isSome) { - const bytes = textEncoder.encode(elem); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(elem); + i32Stack.push(elem.length * 3); i32Stack.push(id); } i32Stack.push(isSome); @@ -807,9 +810,8 @@ export async function createInstantiator(options, swift) { processNestedStringArray: function bjs_processNestedStringArray(values) { for (const elem of values) { for (const elem1 of elem) { - const bytes = textEncoder.encode(elem1); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(elem1); + i32Stack.push(elem1.length * 3); i32Stack.push(id); } i32Stack.push(elem.length); @@ -976,9 +978,8 @@ export async function createInstantiator(options, swift) { } i32Stack.push(nums.length); for (const elem1 of strs) { - const bytes = textEncoder.encode(elem1); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(elem1); + i32Stack.push(elem1.length * 3); i32Stack.push(id); } i32Stack.push(strs.length); @@ -997,9 +998,8 @@ export async function createInstantiator(options, swift) { const isSome1 = b != null; if (isSome1) { for (const elem1 of b) { - const bytes = textEncoder.encode(elem1); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(elem1); + i32Stack.push(elem1.length * 3); i32Stack.push(id); } i32Stack.push(b.length); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js index bf368738e..7336910a8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Async.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -45,7 +48,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -216,7 +223,7 @@ export async function createInstantiator(options, swift) { return ret1; }, asyncRoundTripString: function bjs_asyncRoundTripString(v) { - const vBytes = textEncoder.encode(v); + const vBytes = _cachedEncode(v); const vId = swift.memory.retain(vBytes); const ret = instance.exports.bjs_asyncRoundTripString(vId, vBytes.length); const ret1 = swift.memory.getObject(ret); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncImport.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncImport.js index 89ab29827..e7657deb8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncImport.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncImport.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -160,7 +163,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -360,7 +367,7 @@ export async function createInstantiator(options, swift) { } bjs["make_swift_closure_TestModule_10TestModulesSS_y"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModulesSS_y = function(param0) { - const param0Bytes = textEncoder.encode(param0); + const param0Bytes = _cachedEncode(param0); const param0Id = swift.memory.retain(param0Bytes); instance.exports.invoke_swift_closure_TestModule_10TestModulesSS_y(boxPtr, param0Id, param0Bytes.length); if (tmpRetException) { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncStaticImport.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncStaticImport.js index 7fd6a0d6b..ef04da1ba 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncStaticImport.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/AsyncStaticImport.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -159,7 +162,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js index cafd250b0..8c8e5a442 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DefaultParameters.js @@ -17,6 +17,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -38,9 +41,8 @@ export async function createInstantiator(options, swift) { let bjs = null; const __bjs_createConfigHelpers = () => ({ lower: (value) => { - const bytes = textEncoder.encode(value.name); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.name); + i32Stack.push(value.name.length * 3); i32Stack.push(id); i32Stack.push((value.value | 0)); i32Stack.push(value.enabled ? 1 : 0); @@ -87,7 +89,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -331,7 +337,7 @@ export async function createInstantiator(options, swift) { } constructor(name) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); const ret = instance.exports.bjs_DefaultGreeter_init(nameId, nameBytes.length); return DefaultGreeter.__construct(ret); @@ -343,7 +349,7 @@ export async function createInstantiator(options, swift) { return ret; } set name(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_DefaultGreeter_name_set(this.pointer, valueId, valueBytes.length); } @@ -364,12 +370,12 @@ export async function createInstantiator(options, swift) { } constructor(name = "Default", count = 42, enabled = true, status = StatusValues.Active, tag = null) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); const isSome = tag != null; let result, result1; if (isSome) { - const tagBytes = textEncoder.encode(tag); + const tagBytes = _cachedEncode(tag); const tagId = swift.memory.retain(tagBytes); result = tagId; result1 = tagBytes.length; @@ -387,7 +393,7 @@ export async function createInstantiator(options, swift) { return ret; } set name(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_ConstructorDefaults_name_set(this.pointer, valueId, valueBytes.length); } @@ -422,7 +428,7 @@ export async function createInstantiator(options, swift) { const isSome = value != null; let result, result1; if (isSome) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); result = valueId; result1 = valueBytes.length; @@ -444,7 +450,7 @@ export async function createInstantiator(options, swift) { EmptyGreeter, ConstructorDefaults, testStringDefault: function bjs_testStringDefault(message = "Hello World") { - const messageBytes = textEncoder.encode(message); + const messageBytes = _cachedEncode(message); const messageId = swift.memory.retain(messageBytes); instance.exports.bjs_testStringDefault(messageId, messageBytes.length); const ret = tmpRetString; @@ -471,7 +477,7 @@ export async function createInstantiator(options, swift) { const isSome = name != null; let result, result1; if (isSome) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); result = nameId; result1 = nameBytes.length; @@ -488,7 +494,7 @@ export async function createInstantiator(options, swift) { const isSome = greeting != null; let result, result1; if (isSome) { - const greetingBytes = textEncoder.encode(greeting); + const greetingBytes = _cachedEncode(greeting); const greetingId = swift.memory.retain(greetingBytes); result = greetingId; result1 = greetingBytes.length; @@ -502,7 +508,7 @@ export async function createInstantiator(options, swift) { return optResult; }, testMultipleDefaults: function bjs_testMultipleDefaults(title = "Default Title", count = 10, enabled = false) { - const titleBytes = textEncoder.encode(title); + const titleBytes = _cachedEncode(title); const titleId = swift.memory.retain(titleBytes); instance.exports.bjs_testMultipleDefaults(titleId, titleBytes.length, count, enabled); const ret = tmpRetString; @@ -560,9 +566,8 @@ export async function createInstantiator(options, swift) { }, testStringArrayDefault: function bjs_testStringArrayDefault(names = ["a", "b", "c"]) { for (const elem of names) { - const bytes = textEncoder.encode(elem); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(elem); + i32Stack.push(elem.length * 3); i32Stack.push(id); } i32Stack.push(names.length); @@ -622,7 +627,7 @@ export async function createInstantiator(options, swift) { return arrayResult; }, testMixedWithArrayDefault: function bjs_testMixedWithArrayDefault(name = "test", values = [10, 20, 30], enabled = true) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); for (const elem of values) { i32Stack.push((elem | 0)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js index 920017972..193a3de9a 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/DictionaryTypes.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -32,16 +35,14 @@ export async function createInstantiator(options, swift) { let bjs = null; const __bjs_createCountersHelpers = () => ({ lower: (value) => { - const bytes = textEncoder.encode(value.name); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.name); + i32Stack.push(value.name.length * 3); i32Stack.push(id); const entries = Object.entries(value.counts); for (const entry of entries) { const [key, value] = entry; - const bytes1 = textEncoder.encode(key); - const id1 = swift.memory.retain(bytes1); - i32Stack.push(bytes1.length); + const id1 = swift.memory.retain(key); + i32Stack.push(key.length * 3); i32Stack.push(id1); const isSome = value != null ? 1 : 0; if (isSome) { @@ -86,7 +87,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -258,9 +263,8 @@ export async function createInstantiator(options, swift) { const entries = Object.entries(ret); for (const entry of entries) { const [key, value] = entry; - const bytes = textEncoder.encode(key); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(key); + i32Stack.push(key.length * 3); i32Stack.push(id); f64Stack.push(value); } @@ -349,9 +353,8 @@ export async function createInstantiator(options, swift) { const entries = Object.entries(values); for (const entry of entries) { const [key, value] = entry; - const bytes = textEncoder.encode(key); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(key); + i32Stack.push(key.length * 3); i32Stack.push(id); i32Stack.push((value | 0)); } @@ -372,13 +375,11 @@ export async function createInstantiator(options, swift) { const entries = Object.entries(values); for (const entry of entries) { const [key, value] = entry; - const bytes = textEncoder.encode(key); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(key); + i32Stack.push(key.length * 3); i32Stack.push(id); - const bytes1 = textEncoder.encode(value); - const id1 = swift.memory.retain(bytes1); - i32Stack.push(bytes1.length); + const id1 = swift.memory.retain(value); + i32Stack.push(value.length * 3); i32Stack.push(id1); } i32Stack.push(entries.length); @@ -405,9 +406,8 @@ export async function createInstantiator(options, swift) { const entries = Object.entries(values); for (const entry of entries) { const [key, value] = entry; - const bytes = textEncoder.encode(key); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(key); + i32Stack.push(key.length * 3); i32Stack.push(id); for (const elem of value) { i32Stack.push((elem | 0)); @@ -435,9 +435,8 @@ export async function createInstantiator(options, swift) { const entries = Object.entries(boxes); for (const entry of entries) { const [key, value] = entry; - const bytes = textEncoder.encode(key); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(key); + i32Stack.push(key.length * 3); i32Stack.push(id); ptrStack.push(value.pointer); } @@ -457,9 +456,8 @@ export async function createInstantiator(options, swift) { const entries = Object.entries(boxes); for (const entry of entries) { const [key, value] = entry; - const bytes = textEncoder.encode(key); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(key); + i32Stack.push(key.length * 3); i32Stack.push(id); const isSome = value != null ? 1 : 0; if (isSome) { diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js index 3d2230c6c..1dc904c7d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumAssociatedValue.js @@ -92,6 +92,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -127,9 +130,8 @@ export async function createInstantiator(options, swift) { const enumTag = value.tag; switch (enumTag) { case APIResultValues.Tag.Success: { - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.param0); + i32Stack.push(value.param0.length * 3); i32Stack.push(id); return APIResultValues.Tag.Success; } @@ -188,24 +190,21 @@ export async function createInstantiator(options, swift) { const enumTag = value.tag; switch (enumTag) { case ComplexResultValues.Tag.Success: { - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.param0); + i32Stack.push(value.param0.length * 3); i32Stack.push(id); return ComplexResultValues.Tag.Success; } case ComplexResultValues.Tag.Error: { i32Stack.push((value.param1 | 0)); - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.param0); + i32Stack.push(value.param0.length * 3); i32Stack.push(id); return ComplexResultValues.Tag.Error; } case ComplexResultValues.Tag.Status: { - const bytes = textEncoder.encode(value.param2); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.param2); + i32Stack.push(value.param2.length * 3); i32Stack.push(id); i32Stack.push((value.param1 | 0)); i32Stack.push(value.param0 ? 1 : 0); @@ -218,17 +217,14 @@ export async function createInstantiator(options, swift) { return ComplexResultValues.Tag.Coordinates; } case ComplexResultValues.Tag.Comprehensive: { - const bytes = textEncoder.encode(value.param8); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.param8); + i32Stack.push(value.param8.length * 3); i32Stack.push(id); - const bytes1 = textEncoder.encode(value.param7); - const id1 = swift.memory.retain(bytes1); - i32Stack.push(bytes1.length); + const id1 = swift.memory.retain(value.param7); + i32Stack.push(value.param7.length * 3); i32Stack.push(id1); - const bytes2 = textEncoder.encode(value.param6); - const id2 = swift.memory.retain(bytes2); - i32Stack.push(bytes2.length); + const id2 = swift.memory.retain(value.param6); + i32Stack.push(value.param6.length * 3); i32Stack.push(id2); f64Stack.push(value.param5); f64Stack.push(value.param4); @@ -290,24 +286,21 @@ export async function createInstantiator(options, swift) { const enumTag = value.tag; switch (enumTag) { case ResultValues.Tag.Success: { - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.param0); + i32Stack.push(value.param0.length * 3); i32Stack.push(id); return ResultValues.Tag.Success; } case ResultValues.Tag.Failure: { i32Stack.push((value.param1 | 0)); - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.param0); + i32Stack.push(value.param0.length * 3); i32Stack.push(id); return ResultValues.Tag.Failure; } case ResultValues.Tag.Status: { - const bytes = textEncoder.encode(value.param2); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.param2); + i32Stack.push(value.param2.length * 3); i32Stack.push(id); i32Stack.push((value.param1 | 0)); i32Stack.push(value.param0 ? 1 : 0); @@ -343,17 +336,15 @@ export async function createInstantiator(options, swift) { const enumTag = value.tag; switch (enumTag) { case NetworkingResultValues.Tag.Success: { - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.param0); + i32Stack.push(value.param0.length * 3); i32Stack.push(id); return NetworkingResultValues.Tag.Success; } case NetworkingResultValues.Tag.Failure: { i32Stack.push((value.param1 | 0)); - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.param0); + i32Stack.push(value.param0.length * 3); i32Stack.push(id); return NetworkingResultValues.Tag.Failure; } @@ -383,9 +374,8 @@ export async function createInstantiator(options, swift) { case APIOptionalResultValues.Tag.Success: { const isSome = value.param0 != null ? 1 : 0; if (isSome) { - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.param0); + i32Stack.push(value.param0.length * 3); i32Stack.push(id); } i32Stack.push(isSome); @@ -407,9 +397,8 @@ export async function createInstantiator(options, swift) { case APIOptionalResultValues.Tag.Status: { const isSome = value.param2 != null ? 1 : 0; if (isSome) { - const bytes = textEncoder.encode(value.param2); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.param2); + i32Stack.push(value.param2.length * 3); i32Stack.push(id); } i32Stack.push(isSome); @@ -778,7 +767,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js index fe94c046f..73bcd0e48 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumCase.js @@ -35,6 +35,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -69,7 +72,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js index 10fe31f64..6e5b4b68d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.Global.js @@ -55,6 +55,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -89,7 +92,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js index a6aeee4b0..3d844f3a1 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumNamespace.js @@ -36,6 +36,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -70,7 +73,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js index 7e5334811..055ed88b5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/EnumRawType.js @@ -86,6 +86,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -121,7 +124,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -276,7 +283,7 @@ export async function createInstantiator(options, swift) { TestModule["bjs_returnsFeatureFlag"] = function bjs_returnsFeatureFlag() { try { let ret = imports.returnsFeatureFlag(); - tmpRetBytes = textEncoder.encode(ret); + tmpRetBytes = _cachedEncode(ret); return tmpRetBytes.length; } catch (error) { setException(error); @@ -298,7 +305,7 @@ export async function createInstantiator(options, swift) { const js = swift.memory.heap; const exports = { setTheme: function bjs_setTheme(theme) { - const themeBytes = textEncoder.encode(theme); + const themeBytes = _cachedEncode(theme); const themeId = swift.memory.retain(themeBytes); instance.exports.bjs_setTheme(themeId, themeBytes.length); }, @@ -312,7 +319,7 @@ export async function createInstantiator(options, swift) { const isSome = input != null; let result, result1; if (isSome) { - const inputBytes = textEncoder.encode(input); + const inputBytes = _cachedEncode(input); const inputId = swift.memory.retain(inputBytes); result = inputId; result1 = inputBytes.length; @@ -326,7 +333,7 @@ export async function createInstantiator(options, swift) { return optResult; }, setTSTheme: function bjs_setTSTheme(theme) { - const themeBytes = textEncoder.encode(theme); + const themeBytes = _cachedEncode(theme); const themeId = swift.memory.retain(themeBytes); instance.exports.bjs_setTSTheme(themeId, themeBytes.length); }, @@ -340,7 +347,7 @@ export async function createInstantiator(options, swift) { const isSome = input != null; let result, result1; if (isSome) { - const inputBytes = textEncoder.encode(input); + const inputBytes = _cachedEncode(input); const inputId = swift.memory.retain(inputBytes); result = inputId; result1 = inputBytes.length; @@ -354,7 +361,7 @@ export async function createInstantiator(options, swift) { return optResult; }, setFeatureFlag: function bjs_setFeatureFlag(flag) { - const flagBytes = textEncoder.encode(flag); + const flagBytes = _cachedEncode(flag); const flagId = swift.memory.retain(flagBytes); instance.exports.bjs_setFeatureFlag(flagId, flagBytes.length); }, @@ -368,7 +375,7 @@ export async function createInstantiator(options, swift) { const isSome = input != null; let result, result1; if (isSome) { - const inputBytes = textEncoder.encode(input); + const inputBytes = _cachedEncode(input); const inputId = swift.memory.retain(inputBytes); result = inputId; result1 = inputBytes.length; @@ -520,7 +527,7 @@ export async function createInstantiator(options, swift) { return optResult; }, processTheme: function bjs_processTheme(theme) { - const themeBytes = textEncoder.encode(theme); + const themeBytes = _cachedEncode(theme); const themeId = swift.memory.retain(themeBytes); const ret = instance.exports.bjs_processTheme(themeId, themeBytes.length); return ret; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/FixedWidthIntegers.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/FixedWidthIntegers.js index 53ddd7301..3adca04f6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/FixedWidthIntegers.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/FixedWidthIntegers.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -46,7 +49,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js index 346b74eac..bcbb3e5f9 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalGetter.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -46,7 +49,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js index f74095374..3e477fe21 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/GlobalThisImports.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -45,7 +48,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js index c2490c0ea..ed4351f6d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.ConfigPointer.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -45,7 +48,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -277,7 +284,7 @@ export async function createInstantiator(options, swift) { } constructor(name) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); const ret = instance.exports.bjs_CachedModel_init(nameId, nameBytes.length); return CachedModel.__construct(ret); @@ -289,7 +296,7 @@ export async function createInstantiator(options, swift) { return ret; } set name(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_CachedModel_name_set(this.pointer, valueId, valueBytes.length); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js index d970c5d77..8a849debf 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.PerClass.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -45,7 +48,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -277,7 +284,7 @@ export async function createInstantiator(options, swift) { } constructor(name) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); const ret = instance.exports.bjs_CachedModel_init(nameId, nameBytes.length); return CachedModel.__construct(ret); @@ -289,7 +296,7 @@ export async function createInstantiator(options, swift) { return ret; } set name(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_CachedModel_name_set(this.pointer, valueId, valueBytes.length); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js index d970c5d77..8a849debf 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/IdentityModeClass.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -45,7 +48,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -277,7 +284,7 @@ export async function createInstantiator(options, swift) { } constructor(name) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); const ret = instance.exports.bjs_CachedModel_init(nameId, nameBytes.length); return CachedModel.__construct(ret); @@ -289,7 +296,7 @@ export async function createInstantiator(options, swift) { return ret; } set name(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_CachedModel_name_set(this.pointer, valueId, valueBytes.length); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js index 06cf6550e..f8e372949 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportArray.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -46,7 +49,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js index c469fcb58..107167ca6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ImportedTypeInExportedInterface.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -84,7 +87,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js index 952197c2a..a9cc4764d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/InvalidPropertyNames.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -46,7 +49,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -211,7 +218,7 @@ export async function createInstantiator(options, swift) { TestModule["bjs_WeirdNaming_normalProperty_get"] = function bjs_WeirdNaming_normalProperty_get(self) { try { let ret = swift.memory.getObject(self).normalProperty; - tmpRetBytes = textEncoder.encode(ret); + tmpRetBytes = _cachedEncode(ret); return tmpRetBytes.length; } catch (error) { setException(error); @@ -238,7 +245,7 @@ export async function createInstantiator(options, swift) { TestModule["bjs_WeirdNaming_property_with_spaces_get"] = function bjs_WeirdNaming_property_with_spaces_get(self) { try { let ret = swift.memory.getObject(self)["property with spaces"]; - tmpRetBytes = textEncoder.encode(ret); + tmpRetBytes = _cachedEncode(ret); return tmpRetBytes.length; } catch (error) { setException(error); @@ -256,7 +263,7 @@ export async function createInstantiator(options, swift) { TestModule["bjs_WeirdNaming_constructor_get"] = function bjs_WeirdNaming_constructor_get(self) { try { let ret = swift.memory.getObject(self).constructor; - tmpRetBytes = textEncoder.encode(ret); + tmpRetBytes = _cachedEncode(ret); return tmpRetBytes.length; } catch (error) { setException(error); @@ -265,7 +272,7 @@ export async function createInstantiator(options, swift) { TestModule["bjs_WeirdNaming_for_get"] = function bjs_WeirdNaming_for_get(self) { try { let ret = swift.memory.getObject(self).for; - tmpRetBytes = textEncoder.encode(ret); + tmpRetBytes = _cachedEncode(ret); return tmpRetBytes.length; } catch (error) { setException(error); @@ -274,7 +281,7 @@ export async function createInstantiator(options, swift) { TestModule["bjs_WeirdNaming_Any_get"] = function bjs_WeirdNaming_Any_get(self) { try { let ret = swift.memory.getObject(self).Any; - tmpRetBytes = textEncoder.encode(ret); + tmpRetBytes = _cachedEncode(ret); return tmpRetBytes.length; } catch (error) { setException(error); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js index 88a5adb38..f77fb1f3b 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClass.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -46,7 +49,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -211,7 +218,7 @@ export async function createInstantiator(options, swift) { TestModule["bjs_Greeter_name_get"] = function bjs_Greeter_name_get(self) { try { let ret = swift.memory.getObject(self).name; - tmpRetBytes = textEncoder.encode(ret); + tmpRetBytes = _cachedEncode(ret); return tmpRetBytes.length; } catch (error) { setException(error); @@ -237,7 +244,7 @@ export async function createInstantiator(options, swift) { TestModule["bjs_Greeter_greet"] = function bjs_Greeter_greet(self) { try { let ret = swift.memory.getObject(self).greet(); - tmpRetBytes = textEncoder.encode(ret); + tmpRetBytes = _cachedEncode(ret); return tmpRetBytes.length; } catch (error) { setException(error); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js index 10fafb7a0..2896efa97 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSClassStaticFunctions.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -46,7 +49,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js index 0258b63b6..6a62b98ae 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/JSValue.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -135,7 +138,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js index 195eef468..55f8a9523 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedGlobal.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -45,7 +48,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js index ca54493f6..2b08e1192 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedModules.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -45,7 +48,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js index 3551caab2..a3174d904 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/MixedPrivate.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -45,7 +48,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js index a63df44be..dfd235d1c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.Global.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -45,7 +48,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -279,7 +286,7 @@ export async function createInstantiator(options, swift) { } constructor(name) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); const ret = instance.exports.bjs___Swift_Foundation_Greeter_init(nameId, nameBytes.length); return Greeter.__construct(ret); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js index 32a325bda..17ebcef03 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Namespaces.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -45,7 +48,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -279,7 +286,7 @@ export async function createInstantiator(options, swift) { } constructor(name) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); const ret = instance.exports.bjs___Swift_Foundation_Greeter_init(nameId, nameBytes.length); return Greeter.__construct(ret); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js index cf24e7e2d..2c1841539 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/NestedType.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -56,7 +59,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js index 1d585ce0b..b9278d5a8 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Optionals.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -46,7 +49,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -577,7 +584,7 @@ export async function createInstantiator(options, swift) { const isSome = name != null; let result, result1; if (isSome) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); result = nameId; result1 = nameBytes.length; @@ -598,7 +605,7 @@ export async function createInstantiator(options, swift) { const isSome = name != null; let result, result1; if (isSome) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); result = nameId; result1 = nameBytes.length; @@ -618,7 +625,7 @@ export async function createInstantiator(options, swift) { const isSome = value != null; let result, result1; if (isSome) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); result = valueId; result1 = valueBytes.length; @@ -648,7 +655,7 @@ export async function createInstantiator(options, swift) { const isSome = value != null; let result, result1; if (isSome) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); result = valueId; result1 = valueBytes.length; @@ -721,7 +728,7 @@ export async function createInstantiator(options, swift) { const isSome = name != null; let result, result1; if (isSome) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); result = nameId; result1 = nameBytes.length; @@ -808,7 +815,7 @@ export async function createInstantiator(options, swift) { const isSome = name != null; let result, result1; if (isSome) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); result = nameId; result1 = nameBytes.length; @@ -825,7 +832,7 @@ export async function createInstantiator(options, swift) { const isSome = name != null; let result, result1; if (isSome) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); result = nameId; result1 = nameBytes.length; @@ -842,7 +849,7 @@ export async function createInstantiator(options, swift) { const isSome = name != null; let result, result1; if (isSome) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); result = nameId; result1 = nameBytes.length; @@ -859,7 +866,7 @@ export async function createInstantiator(options, swift) { const isSome = name != null; let result, result1; if (isSome) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); result = nameId; result1 = nameBytes.length; @@ -890,7 +897,7 @@ export async function createInstantiator(options, swift) { const isSome = name != null; let result, result1; if (isSome) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); result = nameId; result1 = nameBytes.length; @@ -907,7 +914,7 @@ export async function createInstantiator(options, swift) { const isSome = firstName != null; let result, result1; if (isSome) { - const firstNameBytes = textEncoder.encode(firstName); + const firstNameBytes = _cachedEncode(firstName); const firstNameId = swift.memory.retain(firstNameBytes); result = firstNameId; result1 = firstNameBytes.length; @@ -918,7 +925,7 @@ export async function createInstantiator(options, swift) { const isSome1 = lastName != null; let result2, result3; if (isSome1) { - const lastNameBytes = textEncoder.encode(lastName); + const lastNameBytes = _cachedEncode(lastName); const lastNameId = swift.memory.retain(lastNameBytes); result2 = lastNameId; result3 = lastNameBytes.length; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js index 490f2b4e2..3f8343395 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveParameters.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -46,7 +49,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js index bec07b959..672683577 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PrimitiveReturn.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -46,7 +49,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js index 7f840708e..c946a7c1c 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/PropertyTypes.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -45,7 +48,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -267,7 +274,7 @@ export async function createInstantiator(options, swift) { } constructor(intValue, floatValue, doubleValue, boolValue, stringValue, jsObject) { - const stringValueBytes = textEncoder.encode(stringValue); + const stringValueBytes = _cachedEncode(stringValue); const stringValueId = swift.memory.retain(stringValueBytes); const ret = instance.exports.bjs_PropertyHolder_init(intValue, floatValue, doubleValue, boolValue, stringValueId, stringValueBytes.length, swift.memory.retain(jsObject)); return PropertyHolder.__construct(ret); @@ -313,7 +320,7 @@ export async function createInstantiator(options, swift) { return ret; } set stringValue(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_PropertyHolder_stringValue_set(this.pointer, valueId, valueBytes.length); } @@ -362,7 +369,7 @@ export async function createInstantiator(options, swift) { return ret; } set lazyValue(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_PropertyHolder_lazyValue_set(this.pointer, valueId, valueBytes.length); } @@ -377,7 +384,7 @@ export async function createInstantiator(options, swift) { return ret; } set computedReadWrite(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_PropertyHolder_computedReadWrite_set(this.pointer, valueId, valueBytes.length); } @@ -392,7 +399,7 @@ export async function createInstantiator(options, swift) { const exports = { PropertyHolder, createPropertyHolder: function bjs_createPropertyHolder(intValue, floatValue, doubleValue, boolValue, stringValue, jsObject) { - const stringValueBytes = textEncoder.encode(stringValue); + const stringValueBytes = _cachedEncode(stringValue); const stringValueId = swift.memory.retain(stringValueBytes); const ret = instance.exports.bjs_createPropertyHolder(intValue, floatValue, doubleValue, boolValue, stringValueId, stringValueBytes.length, swift.memory.retain(jsObject)); return PropertyHolder.__construct(ret); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js index 9fb9b172b..fe8c64d3d 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Protocol.js @@ -35,6 +35,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -59,9 +62,8 @@ export async function createInstantiator(options, swift) { const enumTag = value.tag; switch (enumTag) { case ResultValues.Tag.Success: { - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.param0); + i32Stack.push(value.param0.length * 3); i32Stack.push(id); return ResultValues.Tag.Success; } @@ -102,7 +104,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -281,7 +287,7 @@ export async function createInstantiator(options, swift) { TestModule["bjs_MyViewControllerDelegate_delegateName_get"] = function bjs_MyViewControllerDelegate_delegateName_get(self) { try { let ret = swift.memory.getObject(self).delegateName; - tmpRetBytes = textEncoder.encode(ret); + tmpRetBytes = _cachedEncode(ret); return tmpRetBytes.length; } catch (error) { setException(error); @@ -334,7 +340,7 @@ export async function createInstantiator(options, swift) { TestModule["bjs_MyViewControllerDelegate_rawStringEnum_get"] = function bjs_MyViewControllerDelegate_rawStringEnum_get(self) { try { let ret = swift.memory.getObject(self).rawStringEnum; - tmpRetBytes = textEncoder.encode(ret); + tmpRetBytes = _cachedEncode(ret); return tmpRetBytes.length; } catch (error) { setException(error); @@ -533,7 +539,7 @@ export async function createInstantiator(options, swift) { TestModule["bjs_MyViewControllerDelegate_createEnum"] = function bjs_MyViewControllerDelegate_createEnum(self) { try { let ret = swift.memory.getObject(self).createEnum(); - tmpRetBytes = textEncoder.encode(ret); + tmpRetBytes = _cachedEncode(ret); return tmpRetBytes.length; } catch (error) { setException(error); @@ -654,7 +660,7 @@ export async function createInstantiator(options, swift) { instance.exports.bjs_MyViewController_triggerEvent(this.pointer); } updateValue(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_MyViewController_updateValue(this.pointer, valueId, valueBytes.length); } @@ -663,9 +669,9 @@ export async function createInstantiator(options, swift) { return ret !== 0; } updateLabel(prefix, suffix) { - const prefixBytes = textEncoder.encode(prefix); + const prefixBytes = _cachedEncode(prefix); const prefixId = swift.memory.retain(prefixBytes); - const suffixBytes = textEncoder.encode(suffix); + const suffixBytes = _cachedEncode(suffix); const suffixId = swift.memory.retain(suffixBytes); instance.exports.bjs_MyViewController_updateLabel(this.pointer, prefixId, prefixBytes.length, suffixId, suffixBytes.length); } @@ -757,9 +763,8 @@ export async function createInstantiator(options, swift) { const entries = Object.entries(value); for (const entry of entries) { const [key, value1] = entry; - const bytes = textEncoder.encode(key); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(key); + i32Stack.push(key.length * 3); i32Stack.push(id); const objId = swift.memory.retain(value1); i32Stack.push(objId); @@ -797,9 +802,8 @@ export async function createInstantiator(options, swift) { const entries = Object.entries(delegates); for (const entry of entries) { const [key, value] = entry; - const bytes = textEncoder.encode(key); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(key); + i32Stack.push(key.length * 3); i32Stack.push(id); const objId = swift.memory.retain(value); i32Stack.push(objId); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js index aefdb5679..22be24aff 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/ProtocolInClosure.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -70,7 +73,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -246,7 +253,7 @@ export async function createInstantiator(options, swift) { try { const callback = swift.memory.getObject(callbackId); let ret = callback(swift.memory.getObject(param0)); - tmpRetBytes = textEncoder.encode(ret); + tmpRetBytes = _cachedEncode(ret); return tmpRetBytes.length; } catch (error) { setException(error); @@ -271,7 +278,7 @@ export async function createInstantiator(options, swift) { try { const callback = swift.memory.getObject(callbackId); let ret = callback(param0IsSome ? swift.memory.getObject(param0ObjectId) : null); - tmpRetBytes = textEncoder.encode(ret); + tmpRetBytes = _cachedEncode(ret); return tmpRetBytes.length; } catch (error) { setException(error); @@ -336,7 +343,7 @@ export async function createInstantiator(options, swift) { TestModule["bjs_Renderable_render"] = function bjs_Renderable_render(self) { try { let ret = swift.memory.getObject(self).render(); - tmpRetBytes = textEncoder.encode(ret); + tmpRetBytes = _cachedEncode(ret); return tmpRetBytes.length; } catch (error) { setException(error); @@ -413,7 +420,7 @@ export async function createInstantiator(options, swift) { } constructor(name) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); const ret = instance.exports.bjs_Widget_init(nameId, nameBytes.length); return Widget.__construct(ret); @@ -425,7 +432,7 @@ export async function createInstantiator(options, swift) { return ret; } set name(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_Widget_name_set(this.pointer, valueId, valueBytes.length); } @@ -440,7 +447,7 @@ export async function createInstantiator(options, swift) { return ret; }, makeRenderableFactory: function bjs_makeRenderableFactory(defaultName) { - const defaultNameBytes = textEncoder.encode(defaultName); + const defaultNameBytes = _cachedEncode(defaultName); const defaultNameId = swift.memory.retain(defaultNameBytes); const ret = instance.exports.bjs_makeRenderableFactory(defaultNameId, defaultNameBytes.length); return swift.memory.getObject(ret); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js index ef685b8a4..0de0f16d7 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.Global.js @@ -22,6 +22,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -46,9 +49,8 @@ export async function createInstantiator(options, swift) { const enumTag = value.tag; switch (enumTag) { case APIResultValues.Tag.Success: { - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.param0); + i32Stack.push(value.param0.length * 3); i32Stack.push(id); return APIResultValues.Tag.Success; } @@ -89,7 +91,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -375,7 +381,7 @@ export async function createInstantiator(options, swift) { Utils: { String: { uppercase: function bjs_Utils_String_static_uppercase(text) { - const textBytes = textEncoder.encode(text); + const textBytes = _cachedEncode(text); const textId = swift.memory.retain(textBytes); instance.exports.bjs_Utils_String_static_uppercase(textId, textBytes.length); const ret = tmpRetString; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js index 1fd066076..5b96750d5 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticFunctions.js @@ -22,6 +22,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -46,9 +49,8 @@ export async function createInstantiator(options, swift) { const enumTag = value.tag; switch (enumTag) { case APIResultValues.Tag.Success: { - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.param0); + i32Stack.push(value.param0.length * 3); i32Stack.push(id); return APIResultValues.Tag.Success; } @@ -89,7 +91,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -369,7 +375,7 @@ export async function createInstantiator(options, swift) { Utils: { String: { uppercase: function bjs_Utils_String_static_uppercase(text) { - const textBytes = textEncoder.encode(text); + const textBytes = _cachedEncode(text); const textId = swift.memory.retain(textBytes); instance.exports.bjs_Utils_String_static_uppercase(textId, textBytes.length); const ret = tmpRetString; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js index 5800fcb56..75ea3fb53 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.Global.js @@ -16,6 +16,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -50,7 +53,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -304,7 +311,7 @@ export async function createInstantiator(options, swift) { return ret; } static set classVariable(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_PropertyClass_static_classVariable_set(valueId, valueBytes.length); } @@ -315,7 +322,7 @@ export async function createInstantiator(options, swift) { return ret; } static set computedProperty(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_PropertyClass_static_computedProperty_set(valueId, valueBytes.length); } @@ -333,7 +340,7 @@ export async function createInstantiator(options, swift) { const isSome = value != null; let result, result1; if (isSome) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); result = valueId; result1 = valueBytes.length; @@ -361,7 +368,7 @@ export async function createInstantiator(options, swift) { return ret; }, set enumProperty(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_PropertyEnum_static_enumProperty_set(valueId, valueBytes.length); }, @@ -376,7 +383,7 @@ export async function createInstantiator(options, swift) { return ret; }, set computedEnum(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_PropertyEnum_static_computedEnum_set(valueId, valueBytes.length); } @@ -389,7 +396,7 @@ export async function createInstantiator(options, swift) { return ret; }, set namespaceProperty(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_PropertyNamespace_static_namespaceProperty_set(valueId, valueBytes.length); }, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js index b81255810..5c789d8c0 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StaticProperties.js @@ -16,6 +16,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -50,7 +53,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -304,7 +311,7 @@ export async function createInstantiator(options, swift) { return ret; } static set classVariable(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_PropertyClass_static_classVariable_set(valueId, valueBytes.length); } @@ -315,7 +322,7 @@ export async function createInstantiator(options, swift) { return ret; } static set computedProperty(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_PropertyClass_static_computedProperty_set(valueId, valueBytes.length); } @@ -333,7 +340,7 @@ export async function createInstantiator(options, swift) { const isSome = value != null; let result, result1; if (isSome) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); result = valueId; result1 = valueBytes.length; @@ -355,7 +362,7 @@ export async function createInstantiator(options, swift) { return ret; }, set enumProperty(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_PropertyEnum_static_enumProperty_set(valueId, valueBytes.length); }, @@ -370,7 +377,7 @@ export async function createInstantiator(options, swift) { return ret; }, set computedEnum(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_PropertyEnum_static_computedEnum_set(valueId, valueBytes.length); } @@ -383,7 +390,7 @@ export async function createInstantiator(options, swift) { return ret; }, set namespaceProperty(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_PropertyNamespace_static_namespaceProperty_set(valueId, valueBytes.length); }, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js index 033f08cd2..eab22df46 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringParameter.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -46,7 +49,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -222,12 +229,12 @@ export async function createInstantiator(options, swift) { const js = swift.memory.heap; const exports = { checkString: function bjs_checkString(a) { - const aBytes = textEncoder.encode(a); + const aBytes = _cachedEncode(a); const aId = swift.memory.retain(aBytes); instance.exports.bjs_checkString(aId, aBytes.length); }, roundtripString: function bjs_roundtripString(a) { - const aBytes = textEncoder.encode(a); + const aBytes = _cachedEncode(a); const aId = swift.memory.retain(aBytes); instance.exports.bjs_roundtripString(aId, aBytes.length); const ret = tmpRetString; diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js index 8187b9e92..7340491c2 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/StringReturn.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -46,7 +49,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -193,7 +200,7 @@ export async function createInstantiator(options, swift) { TestModule["bjs_checkString"] = function bjs_checkString() { try { let ret = imports.checkString(); - tmpRetBytes = textEncoder.encode(ret); + tmpRetBytes = _cachedEncode(ret); return tmpRetBytes.length; } catch (error) { setException(error); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js index 9ee57d692..f99d3e3fb 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClass.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -46,7 +49,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -295,7 +302,7 @@ export async function createInstantiator(options, swift) { } constructor(name) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); const ret = instance.exports.bjs_Greeter_init(nameId, nameBytes.length); return Greeter.__construct(ret); @@ -307,7 +314,7 @@ export async function createInstantiator(options, swift) { return ret; } changeName(name) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); instance.exports.bjs_Greeter_changeName(this.pointer, nameId, nameBytes.length); } @@ -330,7 +337,7 @@ export async function createInstantiator(options, swift) { return ret; } set name(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_Greeter_name_set(this.pointer, valueId, valueBytes.length); } diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js index 0b4ca3dcc..ce6584a3f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosure.js @@ -41,6 +41,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -87,9 +90,8 @@ export async function createInstantiator(options, swift) { const __bjs_createAnimalHelpers = () => ({ lower: (value) => { - const bytes = textEncoder.encode(value.type); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.type); + i32Stack.push(value.type.length * 3); i32Stack.push(id); }, lift: () => { @@ -102,9 +104,8 @@ export async function createInstantiator(options, swift) { const enumTag = value.tag; switch (enumTag) { case APIResultValues.Tag.Success: { - const bytes = textEncoder.encode(value.param0); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.param0); + i32Stack.push(value.param0.length * 3); i32Stack.push(id); return APIResultValues.Tag.Success; } @@ -173,7 +174,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -355,7 +360,7 @@ export async function createInstantiator(options, swift) { const callback = swift.memory.getObject(callbackId); const string = decodeString(param0Bytes, param0Count); let ret = callback(string); - tmpRetBytes = textEncoder.encode(ret); + tmpRetBytes = _cachedEncode(ret); return tmpRetBytes.length; } catch (error) { setException(error); @@ -363,7 +368,7 @@ export async function createInstantiator(options, swift) { } bjs["make_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModule5ThemeO_5ThemeO = function(param0) { - const param0Bytes = textEncoder.encode(param0); + const param0Bytes = _cachedEncode(param0); const param0Id = swift.memory.retain(param0Bytes); instance.exports.invoke_swift_closure_TestModule_10TestModule5ThemeO_5ThemeO(boxPtr, param0Id, param0Bytes.length); const ret = tmpRetString; @@ -480,7 +485,7 @@ export async function createInstantiator(options, swift) { const callback = swift.memory.getObject(callbackId); const string = decodeString(param0Bytes, param0Count); let ret = callback(string); - tmpRetBytes = textEncoder.encode(ret); + tmpRetBytes = _cachedEncode(ret); return tmpRetBytes.length; } catch (error) { setException(error); @@ -488,7 +493,7 @@ export async function createInstantiator(options, swift) { } bjs["make_swift_closure_TestModule_10TestModuleSS_SS"] = function(boxPtr, file, line) { const lower_closure_TestModule_10TestModuleSS_SS = function(param0) { - const param0Bytes = textEncoder.encode(param0); + const param0Bytes = _cachedEncode(param0); const param0Id = swift.memory.retain(param0Bytes); instance.exports.invoke_swift_closure_TestModule_10TestModuleSS_SS(boxPtr, param0Id, param0Bytes.length); const ret = tmpRetString; @@ -643,7 +648,7 @@ export async function createInstantiator(options, swift) { const isSome = param0 != null; let result, result1; if (isSome) { - const param0Bytes = textEncoder.encode(param0); + const param0Bytes = _cachedEncode(param0); const param0Id = swift.memory.retain(param0Bytes); result = param0Id; result1 = param0Bytes.length; @@ -830,7 +835,7 @@ export async function createInstantiator(options, swift) { const isSome = param0 != null; let result, result1; if (isSome) { - const param0Bytes = textEncoder.encode(param0); + const param0Bytes = _cachedEncode(param0); const param0Id = swift.memory.retain(param0Bytes); result = param0Id; result1 = param0Bytes.length; @@ -1038,7 +1043,7 @@ export async function createInstantiator(options, swift) { } constructor(name) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); const ret = instance.exports.bjs_Person_init(nameId, nameBytes.length); return Person.__construct(ret); @@ -1185,7 +1190,7 @@ export async function createInstantiator(options, swift) { APIResult: APIResultValues, Animal: { init: function(type) { - const typeBytes = textEncoder.encode(type); + const typeBytes = _cachedEncode(type); const typeId = swift.memory.retain(typeBytes); instance.exports.bjs_Animal_init(typeId, typeBytes.length); const structValue = structHelpers.Animal.lift(); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js index d9df868ec..050db7a52 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftClosureImports.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -71,7 +74,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js index abfb24d48..9014cd650 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStruct.js @@ -16,6 +16,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -39,9 +42,8 @@ export async function createInstantiator(options, swift) { lower: (value) => { f64Stack.push(value.x); f64Stack.push(value.y); - const bytes = textEncoder.encode(value.label); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.label); + i32Stack.push(value.label.length * 3); i32Stack.push(id); const isSome = value.optCount != null ? 1 : 0; if (isSome) { @@ -79,13 +81,11 @@ export async function createInstantiator(options, swift) { }); const __bjs_createAddressHelpers = () => ({ lower: (value) => { - const bytes = textEncoder.encode(value.street); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.street); + i32Stack.push(value.street.length * 3); i32Stack.push(id); - const bytes1 = textEncoder.encode(value.city); - const id1 = swift.memory.retain(bytes1); - i32Stack.push(bytes1.length); + const id1 = swift.memory.retain(value.city); + i32Stack.push(value.city.length * 3); i32Stack.push(id1); const isSome = value.zipCode != null ? 1 : 0; if (isSome) { @@ -109,17 +109,15 @@ export async function createInstantiator(options, swift) { }); const __bjs_createPersonHelpers = () => ({ lower: (value) => { - const bytes = textEncoder.encode(value.name); - const id = swift.memory.retain(bytes); - i32Stack.push(bytes.length); + const id = swift.memory.retain(value.name); + i32Stack.push(value.name.length * 3); i32Stack.push(id); i32Stack.push((value.age | 0)); structHelpers.Address.lower(value.address); const isSome = value.email != null ? 1 : 0; if (isSome) { - const bytes1 = textEncoder.encode(value.email); - const id1 = swift.memory.retain(bytes1); - i32Stack.push(bytes1.length); + const id1 = swift.memory.retain(value.email); + i32Stack.push(value.email.length * 3); i32Stack.push(id1); } i32Stack.push(isSome); @@ -258,7 +256,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); @@ -536,7 +538,7 @@ export async function createInstantiator(options, swift) { } constructor(name) { - const nameBytes = textEncoder.encode(name); + const nameBytes = _cachedEncode(name); const nameId = swift.memory.retain(nameBytes); const ret = instance.exports.bjs_Greeter_init(nameId, nameBytes.length); return Greeter.__construct(ret); @@ -554,7 +556,7 @@ export async function createInstantiator(options, swift) { return ret; } set name(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_Greeter_name_set(this.pointer, valueId, valueBytes.length); } @@ -600,7 +602,7 @@ export async function createInstantiator(options, swift) { Precision: PrecisionValues, DataPoint: { init: function(x, y, label, optCount, optFlag) { - const labelBytes = textEncoder.encode(label); + const labelBytes = _cachedEncode(label); const labelId = swift.memory.retain(labelBytes); const isSome = optCount != null; const isSome1 = optFlag != null; @@ -630,7 +632,7 @@ export async function createInstantiator(options, swift) { return ret; }, set defaultConfig(value) { - const valueBytes = textEncoder.encode(value); + const valueBytes = _cachedEncode(value); const valueId = swift.memory.retain(valueBytes); instance.exports.bjs_ConfigStruct_static_defaultConfig_set(valueId, valueBytes.length); }, diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js index d4f1160f3..d5013e4ec 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftStructImports.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -57,7 +60,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.js index 4e0fd8341..735342bc6 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/SwiftTypedClosureAccess.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -70,7 +73,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js index b2c381a03..9bdfbd14f 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/Throws.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -45,7 +48,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js index ef81ef69e..ae2dbe176 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/UnsafePointer.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -62,7 +65,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js index 97948b286..af95e7373 100644 --- a/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js +++ b/Plugins/BridgeJS/Tests/BridgeJSToolTests/__Snapshots__/BridgeJSLinkTests/VoidParameterVoidReturn.js @@ -11,6 +11,9 @@ export async function createInstantiator(options, swift) { let decodeString; const textDecoder = new TextDecoder("utf-8"); const textEncoder = new TextEncoder("utf-8"); + const _strEncCache = new Map(); + const _strEncCacheMax = 256; + function _cachedEncode(s) { let b = _strEncCache.get(s); if (b) { _strEncCache.delete(s); _strEncCache.set(s, b); return b; } b = textEncoder.encode(s); if (_strEncCache.size >= _strEncCacheMax) { _strEncCache.delete(_strEncCache.keys().next().value); } _strEncCache.set(s, b); return b; }; let tmpRetString; let tmpRetBytes; let tmpRetException; @@ -46,7 +49,11 @@ export async function createInstantiator(options, swift) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); const bytes = new Uint8Array(memory.buffer, bytesPtr); + if (typeof source === 'string') { + return textEncoder.encodeInto(source, bytes).written; + } bytes.set(source); + return source.length; } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); diff --git a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift index 86a1aaf3f..6c150455e 100644 --- a/Sources/JavaScriptKit/BridgeJSIntrinsics.swift +++ b/Sources/JavaScriptKit/BridgeJSIntrinsics.swift @@ -472,8 +472,8 @@ extension String: _BridgedSwiftStackType { guard #available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) else { _onlyAvailableOnWasm() } #endif return String(unsafeUninitializedCapacity: Int(count)) { b in - _swift_js_init_memory(bytes, b.baseAddress.unsafelyUnwrapped) - return Int(count) + let written = _swift_js_init_memory(bytes, b.baseAddress.unsafelyUnwrapped) + return Int(written) } } @@ -899,22 +899,27 @@ where Self: RawRepresentable, RawValue: _BridgedSwiftTypeLoweredIntoSingleWasmCo #if arch(wasm32) @_extern(wasm, module: "bjs", name: "swift_js_init_memory") -private func _swift_js_init_memory_extern(_ sourceId: Int32, _ ptr: UnsafeMutablePointer) +private func _swift_js_init_memory_extern(_ sourceId: Int32, _ ptr: UnsafeMutablePointer) -> Int32 #else -private func _swift_js_init_memory_extern(_ sourceId: Int32, _ ptr: UnsafeMutablePointer) { +private func _swift_js_init_memory_extern(_ sourceId: Int32, _ ptr: UnsafeMutablePointer) -> Int32 { _onlyAvailableOnWasm() } #endif -/// Initializes WebAssembly memory with a Uint8Array referenced by `sourceId` at `ptr`. -/// Note that the ownership of the source Uint8Array id is taken by the callee, so callers -/// must not release the source Uint8Array id by themselves. +/// Initializes WebAssembly memory with a source referenced by `sourceId` at `ptr`. +/// The source may be a Uint8Array or a string. If a string, the JS side uses `encodeInto()` +/// and returns the actual byte count written. +/// Note that the ownership of the source id is taken by the callee, so callers +/// must not release it by themselves. /// -/// - Parameter sourceId: The object ID of the source Uint8Array. +/// - Parameter sourceId: The object ID of the source (Uint8Array or string). /// - Parameter ptr: The pointer to the WebAssembly memory to initialize. -@_spi(BridgeJS) @inline(never) public func _swift_js_init_memory(_ sourceId: Int32, _ ptr: UnsafeMutablePointer) -{ - _swift_js_init_memory_extern(sourceId, ptr) +/// - Returns: The number of bytes actually written. +@_spi(BridgeJS) @inline(never) public func _swift_js_init_memory( + _ sourceId: Int32, + _ ptr: UnsafeMutablePointer +) -> Int32 { + return _swift_js_init_memory_extern(sourceId, ptr) } #if arch(wasm32)