diff --git a/BrowserRuntime/dist/index.mjs b/BrowserRuntime/dist/index.mjs index 568954c..97d2956 100644 --- a/BrowserRuntime/dist/index.mjs +++ b/BrowserRuntime/dist/index.mjs @@ -41,10 +41,12 @@ const decode = (kind, payload1, payload2, objectSpace) => { } }; const decodeArray = (ptr, length, memory, objectSpace) => { - if (length === 0) return []; + const basePtr = ptr >>> 0; + const count = length >>> 0; + if (count === 0) return []; let result = []; - for (let index = 0; index < length; index++) { - const base = ptr + 16 * index; + for (let index = 0; index < count; index++) { + const base = basePtr + 16 * index; const kind = memory.getUint32(base, true); const payload1 = memory.getUint32(base + 4, true); const payload2 = memory.getFloat64(base + 8, true); @@ -54,22 +56,24 @@ const decodeArray = (ptr, length, memory, objectSpace) => { }; const write = (value, kind_ptr, payload1_ptr, payload2_ptr, is_exception, memory, objectSpace) => { const kind = writeAndReturnKindBits(value, payload1_ptr, payload2_ptr, is_exception, memory, objectSpace); - memory.setUint32(kind_ptr, kind, true); + memory.setUint32(kind_ptr >>> 0, kind, true); }; const writeAndReturnKindBits = (value, payload1_ptr, payload2_ptr, is_exception, memory, objectSpace) => { const exceptionBit = (is_exception ? 1 : 0) << 31; + const payload1Offset = payload1_ptr >>> 0; + const payload2Offset = payload2_ptr >>> 0; if (value === null) return exceptionBit | 4; const writeRef = (kind) => { - memory.setUint32(payload1_ptr, objectSpace.retain(value), true); + memory.setUint32(payload1Offset, objectSpace.retain(value), true); return exceptionBit | kind; }; const type = typeof value; switch (type) { case "boolean": - memory.setUint32(payload1_ptr, value ? 1 : 0, true); + memory.setUint32(payload1Offset, value ? 1 : 0, true); return exceptionBit | 0; case "number": - memory.setFloat64(payload2_ptr, value, true); + memory.setFloat64(payload2Offset, value, true); return exceptionBit | 2; case "string": return writeRef(1); case "undefined": return exceptionBit | 5; @@ -82,8 +86,10 @@ const writeAndReturnKindBits = (value, payload1_ptr, payload2_ptr, is_exception, throw new Error("Unreachable"); }; function decodeObjectRefs(ptr, length, memory) { - const result = new Array(length); - for (let i = 0; i < length; i++) result[i] = memory.getUint32(ptr + 4 * i, true); + const basePtr = ptr >>> 0; + const count = length >>> 0; + const result = new Array(count); + for (let i = 0; i < count; i++) result[i] = memory.getUint32(basePtr + 4 * i, true); return result; } var ITCInterface = class { @@ -453,21 +459,25 @@ var SwiftRuntime = class { const memory = this.memory; const bytes = this.textEncoder.encode(memory.getObject(ref)); const bytes_ptr = memory.retain(bytes); - this.getDataView().setUint32(bytes_ptr_result, bytes_ptr, true); + this.getDataView().setUint32(bytes_ptr_result >>> 0, bytes_ptr, true); return bytes.length; }, swjs_decode_string: this.options.sharedMemory == true ? (bytes_ptr, length) => { - const bytes = this.getUint8Array().slice(bytes_ptr, bytes_ptr + length); + const bytesOffset = bytes_ptr >>> 0; + const byteLength = length >>> 0; + const bytes = this.getUint8Array().slice(bytesOffset, bytesOffset + byteLength); const string = this.textDecoder.decode(bytes); return this.memory.retain(string); } : (bytes_ptr, length) => { - const bytes = this.getUint8Array().subarray(bytes_ptr, bytes_ptr + length); + const bytesOffset = bytes_ptr >>> 0; + const byteLength = length >>> 0; + const bytes = this.getUint8Array().subarray(bytesOffset, bytesOffset + byteLength); const string = this.textDecoder.decode(bytes); return this.memory.retain(string); }, swjs_load_string: (ref, buffer) => { const bytes = this.memory.getObject(ref); - this.getUint8Array().set(bytes, buffer); + this.getUint8Array().set(bytes, buffer >>> 0); }, swjs_call_function: (ref, argv, argc, payload1_ptr, payload2_ptr) => { const memory = this.memory; @@ -547,7 +557,7 @@ var SwiftRuntime = class { swjs_create_typed_array: (constructor_ref, elementsPtr, length) => { const ArrayType = this.memory.getObject(constructor_ref); if (length == 0) return this.memory.retain(new ArrayType()); - const array = new ArrayType(this.wasmMemory.buffer, elementsPtr, length); + const array = new ArrayType(this.wasmMemory.buffer, elementsPtr >>> 0, length >>> 0); return this.memory.retain(array.slice()); }, swjs_create_object: () => { @@ -556,7 +566,7 @@ var SwiftRuntime = class { swjs_load_typed_array: (ref, buffer) => { const typedArray = this.memory.getObject(ref); const bytes = new Uint8Array(typedArray.buffer); - this.getUint8Array().set(bytes, buffer); + this.getUint8Array().set(bytes, buffer >>> 0); }, swjs_release: (ref) => { this.memory.release(ref); @@ -780,7 +790,7 @@ async function createInstantiator(options, swift) { }; const real = (...args) => { if (state.unregistered) { - const bytes = new Uint8Array(memory.buffer, state.file); + const bytes = new Uint8Array(memory.buffer, state.file >>> 0); let length = 0; while (bytes[length] !== 0) length += 1; const fileID = decodeString(state.file, length); @@ -836,13 +846,13 @@ async function createInstantiator(options, swift) { bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); - new Uint8Array(memory.buffer, bytesPtr).set(source); + new Uint8Array(memory.buffer, bytesPtr >>> 0).set(source); }; bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); }; bjs["swift_js_init_memory_with_result"] = function(ptr, len) { - new Uint8Array(memory.buffer, ptr, len).set(tmpRetBytes); + new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0).set(tmpRetBytes); tmpRetBytes = void 0; }; bjs["swift_js_throw"] = function(id) { @@ -918,6 +928,19 @@ async function createInstantiator(options, swift) { const value = structHelpers.JSAnimationTiming.lift(); return swift.memory.retain(value); }; + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { + resolve = res; + reject = rej; + }); + promise[__bjs_promiseSettlers] = { + resolve, + reject + }; + return swift.memory.retain(promise); + }; bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) {} }; diff --git a/BrowserRuntime/src/generated/bridge-js.js b/BrowserRuntime/src/generated/bridge-js.js index d22a535..eeee33d 100644 --- a/BrowserRuntime/src/generated/bridge-js.js +++ b/BrowserRuntime/src/generated/bridge-js.js @@ -53,7 +53,7 @@ export async function createInstantiator(options, swift) { const state = { pointer, file, line, unregistered: false }; const real = (...args) => { if (state.unregistered) { - const bytes = new Uint8Array(memory.buffer, state.file); + const bytes = new Uint8Array(memory.buffer, state.file >>> 0); let length = 0; while (bytes[length] !== 0) { length += 1; } const fileID = decodeString(state.file, length); @@ -112,14 +112,14 @@ export async function createInstantiator(options, swift) { bjs["swift_js_init_memory"] = function(sourceId, bytesPtr) { const source = swift.memory.getObject(sourceId); swift.memory.release(sourceId); - const bytes = new Uint8Array(memory.buffer, bytesPtr); + const bytes = new Uint8Array(memory.buffer, bytesPtr >>> 0); bytes.set(source); } bjs["swift_js_make_js_string"] = function(ptr, len) { return swift.memory.retain(decodeString(ptr, len)); } bjs["swift_js_init_memory_with_result"] = function(ptr, len) { - const target = new Uint8Array(memory.buffer, ptr, len); + const target = new Uint8Array(memory.buffer, ptr >>> 0, len >>> 0); target.set(tmpRetBytes); tmpRetBytes = undefined; } @@ -187,6 +187,13 @@ export async function createInstantiator(options, swift) { const value = structHelpers.JSAnimationTiming.lift(); return swift.memory.retain(value); } + const __bjs_promiseSettlers = Symbol("JavaScriptKit.promiseSettlers"); + bjs["swift_js_make_promise"] = function() { + let resolve, reject; + const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); + promise[__bjs_promiseSettlers] = { resolve, reject }; + return swift.memory.retain(promise); + } bjs["swift_js_return_optional_bool"] = function(isSome, value) { if (isSome === 0) { tmpRetOptionalBool = null; diff --git a/BrowserRuntime/src/vendored/javascriptkit/index.mjs b/BrowserRuntime/src/vendored/javascriptkit/index.mjs index daf4f3a..b0be54b 100644 --- a/BrowserRuntime/src/vendored/javascriptkit/index.mjs +++ b/BrowserRuntime/src/vendored/javascriptkit/index.mjs @@ -49,13 +49,15 @@ const decode = (kind, payload1, payload2, objectSpace) => { // Note: // `decodeValues` assumes that the size of RawJSValue is 16. const decodeArray = (ptr, length, memory, objectSpace) => { + const basePtr = ptr >>> 0; + const count = length >>> 0; // fast path for empty array - if (length === 0) { + if (count === 0) { return []; } let result = []; - for (let index = 0; index < length; index++) { - const base = ptr + 16 * index; + for (let index = 0; index < count; index++) { + const base = basePtr + 16 * index; const kind = memory.getUint32(base, true); const payload1 = memory.getUint32(base + 4, true); const payload2 = memory.getFloat64(base + 8, true); @@ -69,25 +71,27 @@ const decodeArray = (ptr, length, memory, objectSpace) => { // This function should be used only when kind flag is stored in memory. const write = (value, kind_ptr, payload1_ptr, payload2_ptr, is_exception, memory, objectSpace) => { const kind = writeAndReturnKindBits(value, payload1_ptr, payload2_ptr, is_exception, memory, objectSpace); - memory.setUint32(kind_ptr, kind, true); + memory.setUint32(kind_ptr >>> 0, kind, true); }; const writeAndReturnKindBits = (value, payload1_ptr, payload2_ptr, is_exception, memory, objectSpace) => { const exceptionBit = (is_exception ? 1 : 0) << 31; + const payload1Offset = payload1_ptr >>> 0; + const payload2Offset = payload2_ptr >>> 0; if (value === null) { return exceptionBit | 4 /* Kind.Null */; } const writeRef = (kind) => { - memory.setUint32(payload1_ptr, objectSpace.retain(value), true); + memory.setUint32(payload1Offset, objectSpace.retain(value), true); return exceptionBit | kind; }; const type = typeof value; switch (type) { case "boolean": { - memory.setUint32(payload1_ptr, value ? 1 : 0, true); + memory.setUint32(payload1Offset, value ? 1 : 0, true); return exceptionBit | 0 /* Kind.Boolean */; } case "number": { - memory.setFloat64(payload2_ptr, value, true); + memory.setFloat64(payload2Offset, value, true); return exceptionBit | 2 /* Kind.Number */; } case "string": { @@ -114,9 +118,11 @@ const writeAndReturnKindBits = (value, payload1_ptr, payload2_ptr, is_exception, throw new Error("Unreachable"); }; function decodeObjectRefs(ptr, length, memory) { - const result = new Array(length); - for (let i = 0; i < length; i++) { - result[i] = memory.getUint32(ptr + 4 * i, true); + const basePtr = ptr >>> 0; + const count = length >>> 0; + const result = new Array(count); + for (let i = 0; i < count; i++) { + result[i] = memory.getUint32(basePtr + 4 * i, true); } return result; } @@ -617,25 +623,29 @@ class SwiftRuntime { const memory = this.memory; const bytes = this.textEncoder.encode(memory.getObject(ref)); const bytes_ptr = memory.retain(bytes); - this.getDataView().setUint32(bytes_ptr_result, bytes_ptr, true); + this.getDataView().setUint32(bytes_ptr_result >>> 0, bytes_ptr, true); return bytes.length; }, swjs_decode_string: // NOTE: TextDecoder can't decode typed arrays backed by SharedArrayBuffer this.options.sharedMemory == true ? (bytes_ptr, length) => { - const bytes = this.getUint8Array().slice(bytes_ptr, bytes_ptr + length); + const bytesOffset = bytes_ptr >>> 0; + const byteLength = length >>> 0; + const bytes = this.getUint8Array().slice(bytesOffset, bytesOffset + byteLength); const string = this.textDecoder.decode(bytes); return this.memory.retain(string); } : (bytes_ptr, length) => { - const bytes = this.getUint8Array().subarray(bytes_ptr, bytes_ptr + length); + const bytesOffset = bytes_ptr >>> 0; + const byteLength = length >>> 0; + const bytes = this.getUint8Array().subarray(bytesOffset, bytesOffset + byteLength); const string = this.textDecoder.decode(bytes); return this.memory.retain(string); }, swjs_load_string: (ref, buffer) => { const bytes = this.memory.getObject(ref); - this.getUint8Array().set(bytes, buffer); + this.getUint8Array().set(bytes, buffer >>> 0); }, swjs_call_function: (ref, argv, argc, payload1_ptr, payload2_ptr) => { const memory = this.memory; @@ -739,7 +749,7 @@ class SwiftRuntime { // See https://github.com/swiftwasm/swift/issues/5599 return this.memory.retain(new ArrayType()); } - const array = new ArrayType(this.wasmMemory.buffer, elementsPtr, length); + const array = new ArrayType(this.wasmMemory.buffer, elementsPtr >>> 0, length >>> 0); // Call `.slice()` to copy the memory return this.memory.retain(array.slice()); }, @@ -750,7 +760,7 @@ class SwiftRuntime { const memory = this.memory; const typedArray = memory.getObject(ref); const bytes = new Uint8Array(typedArray.buffer); - this.getUint8Array().set(bytes, buffer); + this.getUint8Array().set(bytes, buffer >>> 0); }, swjs_release: (ref) => { this.memory.release(ref); diff --git a/Package.swift b/Package.swift index 4386ea9..1ba404f 100644 --- a/Package.swift +++ b/Package.swift @@ -12,7 +12,7 @@ let package = Package( .trait(name: "TraceLogs", description: "Enables trace logs for the ElementaryUI internals") ], dependencies: [ - .package(url: "https://github.com/swiftwasm/JavaScriptKit", .upToNextMinor(from: "0.53.0")), + .package(url: "https://github.com/swiftwasm/JavaScriptKit", .upToNextMinor(from: "0.55.0")), .package(url: "https://github.com/elementary-swift/elementary", from: "0.7.0"), .package(url: "https://github.com/apple/swift-collections", from: "1.6.0", traits: ["UnstableContainersPreview"]), .package(url: "https://github.com/swiftlang/swift-syntax", "600.0.0"..<"604.0.0"), diff --git a/Scripts/_generate-bridgejs.sh b/Scripts/_generate-bridgejs.sh index cf2c881..05e3ba0 100755 --- a/Scripts/_generate-bridgejs.sh +++ b/Scripts/_generate-bridgejs.sh @@ -10,16 +10,4 @@ cd "$ROOT_DIR" echo "Generating BridgeJS artifacts for BrowserInterop..." swift package --build-system swiftbuild --allow-writing-to-package-directory bridge-js --target BrowserInterop -if [[ -f "$GENERATED_SWIFT_FILE" ]]; then - if ! grep -qF '// swift-format-ignore-file' "$GENERATED_SWIFT_FILE"; then - tmp_file="$(mktemp)" - { - echo "// swift-format-ignore-file" - echo - cat "$GENERATED_SWIFT_FILE" - } > "$tmp_file" - mv "$tmp_file" "$GENERATED_SWIFT_FILE" - fi -fi - echo "BridgeJS generation complete."