From 037a77cecf10dffb6390c6a8fbf08869afa4df5e Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Mon, 1 Sep 2025 18:13:18 +0200 Subject: [PATCH 1/5] Test SharedArrayBuffer created in different realm --- test/buffer-source.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/buffer-source.js b/test/buffer-source.js index 1dd6b48..35ab889 100644 --- a/test/buffer-source.js +++ b/test/buffer-source.js @@ -111,6 +111,13 @@ if (typeof SharedArrayBuffer === "function") { label: "SharedArrayBuffer same realm", creator: () => new SharedArrayBuffer(0) }); + bufferSourceCreators.push({ + typeName: "SharedArrayBuffer", + isShared: true, + isDetached: false, + label: "SharedArrayBuffer different realm", + creator: () => vm.runInContext(`new SharedArrayBuffer(0)`, differentRealm) + }); } for (const constructor of bufferSourceConstructors) { From ec19d05adb643dac1b06d4a694873e9bed4297ba Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Mon, 1 Sep 2025 18:22:46 +0200 Subject: [PATCH 2/5] Add conversion for `SharedArrayBuffer` --- lib/index.js | 11 +++++++++++ test/buffer-source.js | 21 +++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/lib/index.js b/lib/index.js index 0229347..1abc37f 100644 --- a/lib/index.js +++ b/lib/index.js @@ -350,6 +350,17 @@ exports.ArrayBuffer = (value, options = {}) => { return value; }; +exports.SharedArrayBuffer = (value, options = {}) => { + if (!isSharedArrayBuffer(value)) { + throw makeException(TypeError, "is not a SharedArrayBuffer", options); + } + if (isArrayBufferDetached(value)) { + throw makeException(TypeError, "is a detached SharedArrayBuffer", options); + } + + return value; +}; + const dvByteLengthGetter = Object.getOwnPropertyDescriptor(DataView.prototype, "byteLength").get; exports.DataView = (value, options = {}) => { diff --git a/test/buffer-source.js b/test/buffer-source.js index 35ab889..b8fdd71 100644 --- a/test/buffer-source.js +++ b/test/buffer-source.js @@ -220,6 +220,27 @@ for (const type of bufferSourceConstructors) { }); } +if (typeof SharedArrayBuffer === "function") { + const typeName = "SharedArrayBuffer"; + const sut = conversions[typeName]; + + describe(`WebIDL SharedArrayBuffer type`, () => { + for (const innerType of bufferSourceCreators) { + const testFunction = + innerType.typeName === typeName && + innerType.isShared && + !innerType.isDetached && + !innerType.isForged ? + testOk : + testNotOk; + + testFunction(innerType.label, sut, innerType.creator); + } + + commonNotOk(sut); + }); +} + describe("WebIDL ArrayBufferView type", () => { const sut = conversions.ArrayBufferView; From 8a3e8cb2e5618786ee4ff1581d0afacd20db1f22 Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Mon, 1 Sep 2025 18:39:01 +0200 Subject: [PATCH 3/5] Fix `conversions.ArrayBuffer` with `allowShared` not accepting a `SharedArrayBuffer` --- lib/index.js | 9 ++++++--- test/buffer-source.js | 6 +++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/index.js b/lib/index.js index 1abc37f..eaf6995 100644 --- a/lib/index.js +++ b/lib/index.js @@ -338,10 +338,13 @@ function isArrayBufferDetached(value) { exports.ArrayBuffer = (value, options = {}) => { if (!isNonSharedArrayBuffer(value)) { - if (options.allowShared && !isSharedArrayBuffer(value)) { - throw makeException(TypeError, "is not an ArrayBuffer or SharedArrayBuffer", options); + if (options.allowShared) { + if (!isSharedArrayBuffer(value)) { + throw makeException(TypeError, "is not an ArrayBuffer or SharedArrayBuffer", options); + } + } else { + throw makeException(TypeError, "is not an ArrayBuffer", options); } - throw makeException(TypeError, "is not an ArrayBuffer", options); } if (isArrayBufferDetached(value)) { throw makeException(TypeError, "is a detached ArrayBuffer", options); diff --git a/test/buffer-source.js b/test/buffer-source.js index b8fdd71..09d469e 100644 --- a/test/buffer-source.js +++ b/test/buffer-source.js @@ -211,7 +211,11 @@ for (const type of bufferSourceConstructors) { const allowSharedSUT = (v, opts) => conversions[typeName](v, { ...opts, allowShared: true }); for (const { label, creator, typeName: innerTypeName, isDetached, isForged } of bufferSourceCreators) { - const testFunction = innerTypeName === typeName && !isDetached && !isForged ? testOk : testNotOk; + const testFunction = ( + innerTypeName === typeName || (innerTypeName === "SharedArrayBuffer" && typeName === "ArrayBuffer") + ) && !isDetached && !isForged ? + testOk : + testNotOk; testFunction(label, allowSharedSUT, creator); } From a069bd037babe9f5b52ee58499484846bf58bc1a Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Mon, 1 Sep 2025 19:11:21 +0200 Subject: [PATCH 4/5] Simplify conversions --- lib/index.js | 44 +++++++++++--------------------------------- 1 file changed, 11 insertions(+), 33 deletions(-) diff --git a/lib/index.js b/lib/index.js index eaf6995..27cd32b 100644 --- a/lib/index.js +++ b/lib/index.js @@ -372,15 +372,7 @@ exports.DataView = (value, options = {}) => { } catch (e) { throw makeException(TypeError, "is not a DataView", options); } - - if (!options.allowShared && isSharedArrayBuffer(value.buffer)) { - throw makeException(TypeError, "is backed by a SharedArrayBuffer, which is not allowed", options); - } - if (isArrayBufferDetached(value.buffer)) { - throw makeException(TypeError, "is backed by a detached ArrayBuffer", options); - } - - return value; + return exports.ArrayBufferView(value, options); }; // Returns the unforgeable `TypedArray` constructor name or `undefined`, @@ -408,14 +400,7 @@ const typedArrayNameGetter = Object.getOwnPropertyDescriptor( if (!ArrayBuffer.isView(value) || typedArrayNameGetter.call(value) !== name) { throw makeException(TypeError, `is not ${article} ${name} object`, options); } - if (!options.allowShared && isSharedArrayBuffer(value.buffer)) { - throw makeException(TypeError, "is a view on a SharedArrayBuffer, which is not allowed", options); - } - if (isArrayBufferDetached(value.buffer)) { - throw makeException(TypeError, "is a view on a detached ArrayBuffer", options); - } - - return value; + return exports.ArrayBufferView(value, options); }; }); @@ -438,27 +423,20 @@ exports.ArrayBufferView = (value, options = {}) => { exports.BufferSource = (value, options = {}) => { if (ArrayBuffer.isView(value)) { - if (!options.allowShared && isSharedArrayBuffer(value.buffer)) { - throw makeException(TypeError, "is a view on a SharedArrayBuffer, which is not allowed", options); - } - - if (isArrayBufferDetached(value.buffer)) { - throw makeException(TypeError, "is a view on a detached ArrayBuffer", options); - } - return value; + return exports.ArrayBufferView(value, options); } - if (!options.allowShared && !isNonSharedArrayBuffer(value)) { - throw makeException(TypeError, "is not an ArrayBuffer or a view on one", options); + if (isNonSharedArrayBuffer(value)) { + return exports.ArrayBuffer(value, options); + } else if (options.allowShared && isSharedArrayBuffer(value)) { + return exports.SharedArrayBuffer(value, options); } - if (options.allowShared && !isSharedArrayBuffer(value) && !isNonSharedArrayBuffer(value)) { + + if (options.allowShared) { throw makeException(TypeError, "is not an ArrayBuffer, SharedArrayBuffer, or a view on one", options); + } else { + throw makeException(TypeError, "is not an ArrayBuffer or a view on one", options); } - if (isArrayBufferDetached(value)) { - throw makeException(TypeError, "is a detached ArrayBuffer", options); - } - - return value; }; exports.DOMTimeStamp = exports["unsigned long long"]; From 1f93c9e21b2df9026a196139fb47ff006a3ca34d Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Thu, 4 Sep 2025 22:03:49 +0200 Subject: [PATCH 5/5] Remove `allowShared` option from `conversions.ArrayBuffer` --- lib/index.js | 8 +------- test/buffer-source.js | 6 +----- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/lib/index.js b/lib/index.js index 27cd32b..5884336 100644 --- a/lib/index.js +++ b/lib/index.js @@ -338,13 +338,7 @@ function isArrayBufferDetached(value) { exports.ArrayBuffer = (value, options = {}) => { if (!isNonSharedArrayBuffer(value)) { - if (options.allowShared) { - if (!isSharedArrayBuffer(value)) { - throw makeException(TypeError, "is not an ArrayBuffer or SharedArrayBuffer", options); - } - } else { - throw makeException(TypeError, "is not an ArrayBuffer", options); - } + throw makeException(TypeError, "is not an ArrayBuffer", options); } if (isArrayBufferDetached(value)) { throw makeException(TypeError, "is a detached ArrayBuffer", options); diff --git a/test/buffer-source.js b/test/buffer-source.js index 09d469e..b8fdd71 100644 --- a/test/buffer-source.js +++ b/test/buffer-source.js @@ -211,11 +211,7 @@ for (const type of bufferSourceConstructors) { const allowSharedSUT = (v, opts) => conversions[typeName](v, { ...opts, allowShared: true }); for (const { label, creator, typeName: innerTypeName, isDetached, isForged } of bufferSourceCreators) { - const testFunction = ( - innerTypeName === typeName || (innerTypeName === "SharedArrayBuffer" && typeName === "ArrayBuffer") - ) && !isDetached && !isForged ? - testOk : - testNotOk; + const testFunction = innerTypeName === typeName && !isDetached && !isForged ? testOk : testNotOk; testFunction(label, allowSharedSUT, creator); }