From 9b87015efd01caeee4f48ed4073fdfa0b82f0526 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Thu, 3 Jul 2025 19:09:13 +0900 Subject: [PATCH 1/2] make regenerate_swiftpm_resources --- Plugins/PackageToJS/Templates/runtime.mjs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Plugins/PackageToJS/Templates/runtime.mjs b/Plugins/PackageToJS/Templates/runtime.mjs index fe16a65e..df50e1c4 100644 --- a/Plugins/PackageToJS/Templates/runtime.mjs +++ b/Plugins/PackageToJS/Templates/runtime.mjs @@ -796,8 +796,9 @@ class SwiftRuntime { throw new Error("threadChannel is not set in options given to SwiftRuntime. Please set it to request transferring objects."); } const broker = getMessageBroker(this.options.threadChannel); - const sendingObjects = decodeObjectRefs(sending_objects, sending_objects_count, this.getDataView()); - const transferringObjects = decodeObjectRefs(transferring_objects, transferring_objects_count, this.getDataView()); + const dataView = this.getDataView(); + const sendingObjects = decodeObjectRefs(sending_objects, sending_objects_count, dataView); + const transferringObjects = decodeObjectRefs(transferring_objects, transferring_objects_count, dataView); broker.request({ type: "request", data: { From 1993735fe726198b85991848e8a07a184effc007 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Thu, 3 Jul 2025 19:14:21 +0900 Subject: [PATCH 2/2] Check if the memory is backed by a SAB by checking the constructor name --- Plugins/PackageToJS/Templates/runtime.mjs | 7 ++++++- Runtime/src/index.ts | 8 +++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Plugins/PackageToJS/Templates/runtime.mjs b/Plugins/PackageToJS/Templates/runtime.mjs index df50e1c4..66a2e0ad 100644 --- a/Plugins/PackageToJS/Templates/runtime.mjs +++ b/Plugins/PackageToJS/Templates/runtime.mjs @@ -308,7 +308,12 @@ class SwiftRuntime { // Cache the DataView as it's not a cheap operation let cachedDataView = new DataView(wasmMemory.buffer); let cachedUint8Array = new Uint8Array(wasmMemory.buffer); - if (typeof SharedArrayBuffer !== "undefined" && wasmMemory.buffer instanceof SharedArrayBuffer) { + // Check the constructor name of the buffer to determine if it's backed by a SharedArrayBuffer. + // We can't reference SharedArrayBuffer directly here because: + // 1. It may not be available in the global scope if the context is not cross-origin isolated. + // 2. The underlying buffer may be still backed by SAB even if the context is not cross-origin + // isolated (e.g. localhost on Chrome on Android). + if (Object.getPrototypeOf(wasmMemory.buffer).constructor.name === "SharedArrayBuffer") { // When the wasm memory is backed by a SharedArrayBuffer, growing the memory // doesn't invalidate the data view by setting the byte length to 0. Instead, // the data view points to an old buffer after growing the memory. So we have diff --git a/Runtime/src/index.ts b/Runtime/src/index.ts index 77cc2451..199db33d 100644 --- a/Runtime/src/index.ts +++ b/Runtime/src/index.ts @@ -64,7 +64,13 @@ export class SwiftRuntime { // Cache the DataView as it's not a cheap operation let cachedDataView = new DataView(wasmMemory.buffer); let cachedUint8Array = new Uint8Array(wasmMemory.buffer); - if (typeof SharedArrayBuffer !== "undefined" && wasmMemory.buffer instanceof SharedArrayBuffer) { + + // Check the constructor name of the buffer to determine if it's backed by a SharedArrayBuffer. + // We can't reference SharedArrayBuffer directly here because: + // 1. It may not be available in the global scope if the context is not cross-origin isolated. + // 2. The underlying buffer may be still backed by SAB even if the context is not cross-origin + // isolated (e.g. localhost on Chrome on Android). + if (Object.getPrototypeOf(wasmMemory.buffer).constructor.name === "SharedArrayBuffer") { // When the wasm memory is backed by a SharedArrayBuffer, growing the memory // doesn't invalidate the data view by setting the byte length to 0. Instead, // the data view points to an old buffer after growing the memory. So we have