diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /js/src/tests/test262/built-ins/Atomics | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/tests/test262/built-ins/Atomics')
424 files changed, 19605 insertions, 0 deletions
diff --git a/js/src/tests/test262/built-ins/Atomics/Symbol.toStringTag.js b/js/src/tests/test262/built-ins/Atomics/Symbol.toStringTag.js new file mode 100644 index 0000000000..0e0721c000 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/Symbol.toStringTag.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics-@@tostringtag +description: > + `Symbol.toStringTag` property descriptor on Atomics +info: | + The initial value of the @@toStringTag property is the String value + "Atomics". + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Atomics, Symbol, Symbol.toStringTag] +---*/ + +assert.sameValue( + Atomics[Symbol.toStringTag], + 'Atomics', + 'The value of Atomics[Symbol.toStringTag] is "Atomics"' +); + +verifyNotEnumerable(Atomics, Symbol.toStringTag); +verifyNotWritable(Atomics, Symbol.toStringTag); +verifyConfigurable(Atomics, Symbol.toStringTag); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/add/bad-range.js b/js/src/tests/test262/built-ins/Atomics/add/bad-range.js new file mode 100644 index 0000000000..9e783fc690 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/add/bad-range.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.add +description: > + Test range checking of Atomics.add on arrays that allow atomic operations +includes: [testAtomics.js, testTypedArray.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +const buffer = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2); +const views = intArrayConstructors.slice(); + +testWithTypedArrayConstructors(function(TA) { + let view = new TA(buffer); + testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.add(view, IdxGen(view), 10); + }, '`Atomics.add(view, IdxGen(view), 10)` throws RangeError'); + }); +}, views); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/add/bigint/bad-range.js b/js/src/tests/test262/built-ins/Atomics/add/bigint/bad-range.js new file mode 100644 index 0000000000..4e0504be81 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/add/bigint/bad-range.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.add +description: > + Test range checking of Atomics.add on arrays that allow atomic operations +includes: [testAtomics.js, testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ +var buffer = new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 2); + +testWithBigIntTypedArrayConstructors(function(TA) { + let view = new TA(buffer); + + testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.add(view, IdxGen(view), 10n); + }, '`Atomics.add(view, IdxGen(view), 10n)` throws RangeError'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/add/bigint/browser.js b/js/src/tests/test262/built-ins/Atomics/add/bigint/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/add/bigint/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/add/bigint/good-views.js b/js/src/tests/test262/built-ins/Atomics/add/bigint/good-views.js new file mode 100644 index 0000000000..6e98751f5c --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/add/bigint/good-views.js @@ -0,0 +1,56 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.add +description: Test Atomics.add on arrays that allow atomic operations. +includes: [testAtomics.js, testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ +const sab = new SharedArrayBuffer(1024); +const ab = new ArrayBuffer(16); + +testWithBigIntTypedArrayConstructors(function(TA) { + const view = new TA(sab, 32, 20); + const control = new TA(ab, 0, 2); + view[8] = 0n; + assert.sameValue(Atomics.add(view, 8, 10n), 0n, 'Atomics.add(view, 8, 10n) returns 0'); + assert.sameValue(view[8], 10n, 'The value of view[8] is 10n'); + assert.sameValue(Atomics.add(view, 8, -5n), 10n, 'Atomics.add(view, 8, -5n) returns 10n'); + assert.sameValue(view[8], 5n, 'The value of view[8] is 5n'); + view[3] = -5n; + control[0] = -5n; + + assert.sameValue( + Atomics.add(view, 3, 0n), + control[0], + 'Atomics.add(view, 3, 0n) returns the value of `control[0]` (-5n)' + ); + + control[0] = 12345n; + view[3] = 12345n; + + assert.sameValue( + Atomics.add(view, 3, 0n), + control[0], + 'Atomics.add(view, 3, 0n) returns the value of `control[0]` (12345n)' + ); + + control[0] = 123456789n; + view[3] = 123456789n; + + assert.sameValue( + Atomics.add(view, 3, 0n), + control[0], + 'Atomics.add(view, 3, 0n) returns the value of `control[0]` (123456789n)' + ); + + testWithAtomicsInBoundsIndices(function(IdxGen) { + let Idx = IdxGen(view); + view.fill(0n); + Atomics.store(view, Idx, 37n); + assert.sameValue(Atomics.add(view, Idx, 0n), 37n, 'Atomics.add(view, Idx, 0) returns 37n'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/add/bigint/non-shared-bufferdata.js b/js/src/tests/test262/built-ins/Atomics/add/bigint/non-shared-bufferdata.js new file mode 100644 index 0000000000..92387eec28 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/add/bigint/non-shared-bufferdata.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.add +description: > + Atomics.add will operate on TA when TA.buffer is not a SharedArrayBuffer +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ +testWithBigIntTypedArrayConstructors(TA => { + const buffer = new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4); + const view = new TA(buffer); + assert.sameValue(Atomics.add(view, 0, 1n), 0n, 'Atomics.add(view, 0, 1n) returns 0n'); + assert.sameValue(Atomics.load(view, 0), 1n, 'Atomics.load(view, 0) returns 1n'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/add/bigint/shell.js b/js/src/tests/test262/built-ins/Atomics/add/bigint/shell.js new file mode 100644 index 0000000000..90ee9c114d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/add/bigint/shell.js @@ -0,0 +1,42 @@ +// GENERATED, DO NOT EDIT +// file: testBigIntTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of BigInt TypedArray objects. +defines: + - TypedArray + - testWithBigIntTypedArrayConstructors +---*/ + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithBigIntTypedArrayConstructors(f, selected) { + /** + * Array containing every BigInt typed array constructor. + */ + var constructors = selected || [ + BigInt64Array, + BigUint64Array + ]; + + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} diff --git a/js/src/tests/test262/built-ins/Atomics/add/browser.js b/js/src/tests/test262/built-ins/Atomics/add/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/add/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/add/descriptor.js b/js/src/tests/test262/built-ins/Atomics/add/descriptor.js new file mode 100644 index 0000000000..9eda979c91 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/add/descriptor.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-atomics.add +description: Testing descriptor property of Atomics.add +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics, 'add', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/add/expected-return-value.js b/js/src/tests/test262/built-ins/Atomics/add/expected-return-value.js new file mode 100644 index 0000000000..2a6e701349 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/add/expected-return-value.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.add +description: > + Atomics.add returns the value that existed at the + index prior to the operation. +info: | + Atomics.add( typedArray, index, value ) + + 1. Return ? AtomicReadModifyWrite(typedArray, index, value, add). + + AtomicReadModifyWrite( typedArray, index, value, op ) + + ... + 9. Return GetModifySetValueInBuffer(buffer, indexedPosition, + elementType, v, op). + + + GetModifySetValueInBuffer( arrayBuffer, + byteIndex, type, value, op [ , isLittleEndian ] ) + + ... + 16. Return RawBytesToNumber(type, rawBytesRead, isLittleEndian). + +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); +const newValue = 0b00000001000000001000000010000001; + +assert.sameValue(Atomics.add(i32a, 0, newValue), 0, 'Atomics.add(i32a, 0, newValue) returns 0'); +assert.sameValue(i32a[0], newValue, 'The value of i32a[0] equals the value of `newValue` (0b00000001000000001000000010000001)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/add/good-views.js b/js/src/tests/test262/built-ins/Atomics/add/good-views.js new file mode 100644 index 0000000000..2b68c773b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/add/good-views.js @@ -0,0 +1,57 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.add +description: Test Atomics.add on arrays that allow atomic operations. +includes: [testAtomics.js, testTypedArray.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +const sab = new SharedArrayBuffer(1024); +const ab = new ArrayBuffer(16); +const views = intArrayConstructors.slice(); + +testWithTypedArrayConstructors(function(TA) { + // Make it interesting - use non-zero byteOffsets and non-zero indexes. + + const view = new TA(sab, 32, 20); + const control = new TA(ab, 0, 2); + + // Add positive number + view[8] = 0; + assert.sameValue(Atomics.add(view, 8, 10), 0, 'Atomics.add(view, 8, 10) returns 0'); + assert.sameValue(view[8], 10, 'The value of view[8] is 10'); + + // Add negative number + assert.sameValue(Atomics.add(view, 8, -5), 10, 'Atomics.add(view, 8, -5) returns 10'); + assert.sameValue(view[8], 5, 'The value of view[8] is 5'); + + view[3] = -5; + control[0] = -5; + assert.sameValue(Atomics.add(view, 3, 0), control[0], + 'Atomics.add(view, 3, 0) returns the value of `control[0]` (-5)'); + + control[0] = 12345; + view[3] = 12345; + assert.sameValue(Atomics.add(view, 3, 0), control[0], + 'Atomics.add(view, 3, 0) returns the value of `control[0]` (12345)'); + + control[0] = 123456789; + view[3] = 123456789; + assert.sameValue(Atomics.add(view, 3, 0), control[0], + 'Atomics.add(view, 3, 0) returns the value of `control[0]` (123456789)'); + + // In-bounds boundary cases for indexing + testWithAtomicsInBoundsIndices(function(IdxGen) { + let Idx = IdxGen(view); + view.fill(0); + // Atomics.store() computes an index from Idx in the same way as other + // Atomics operations, not quite like view[Idx]. + Atomics.store(view, Idx, 37); + assert.sameValue(Atomics.add(view, Idx, 0), 37, 'Atomics.add(view, Idx, 0) returns 37'); + }); +}, views); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/add/length.js b/js/src/tests/test262/built-ins/Atomics/add/length.js new file mode 100644 index 0000000000..dbeba75cbf --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/add/length.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.add +description: > + Atomics.add.length is 3. +info: | + Atomics.add ( ia, index, val ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this + value is equal to the largest number of named arguments shown in the + subclause headings for the function description, including optional + parameters. However, rest parameters shown using the form “...name” + are not included in the default argument count. + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.add, 'length', { + value: 3, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/add/name.js b/js/src/tests/test262/built-ins/Atomics/add/name.js new file mode 100644 index 0000000000..4896e062f3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/add/name.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.add +description: > + Atomics.add.name is "add". +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.add, 'name', { + value: 'add', + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/add/non-shared-bufferdata.js b/js/src/tests/test262/built-ins/Atomics/add/non-shared-bufferdata.js new file mode 100644 index 0000000000..2ca4c447f8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/add/non-shared-bufferdata.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.add +description: > + Atomics.add will operate on TA when TA.buffer is not a SharedArrayBuffer +includes: [testTypedArray.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ +testWithAtomicsFriendlyTypedArrayConstructors(TA => { + const view = new TA( + new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4) + ); + + assert.sameValue(Atomics.add(view, 0, 1), 0, 'Atomics.add(view, 0, 1) returns 0'); + assert.sameValue(Atomics.load(view, 0), 1, 'Atomics.load(view, 0) returns 1'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/add/non-shared-int-views-throws.js b/js/src/tests/test262/built-ins/Atomics/add/non-shared-int-views-throws.js new file mode 100644 index 0000000000..6c7c88cec1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/add/non-shared-int-views-throws.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.add +description: > + Atomics.add throws when operating on non-sharable integer TypedArrays +includes: [testTypedArray.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ +testWithNonAtomicsFriendlyTypedArrayConstructors(TA => { + const buffer = new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4); + const view = new TA(buffer); + + assert.throws(TypeError, function() { + Atomics.add(view, 0, 1); + }, `Atomics.add(new ${TA.name}(buffer), 0, 1) throws TypeError`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/add/non-views.js b/js/src/tests/test262/built-ins/Atomics/add/non-views.js new file mode 100644 index 0000000000..8675ac1c1e --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/add/non-views.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.add +description: > + Test Atomics.add on view values other than TypedArrays +includes: [testAtomics.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +testWithAtomicsNonViewValues(function(view) { + assert.throws(TypeError, function() { + Atomics.add(view, 0, 0); + }, '`Atomics.add(view, 0, 0)` throws TypeError'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/add/not-a-constructor.js b/js/src/tests/test262/built-ins/Atomics/add/not-a-constructor.js new file mode 100644 index 0000000000..ce6371e345 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/add/not-a-constructor.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Atomics.add does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, Atomics, arrow-function, TypedArray, SharedArrayBuffer] +---*/ + +assert.sameValue(isConstructor(Atomics.add), false, 'isConstructor(Atomics.add) must return false'); + +assert.throws(TypeError, () => { + new Atomics.add(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT))); +}, '`new Atomics.add(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT)))` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/add/shell.js b/js/src/tests/test262/built-ins/Atomics/add/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/add/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Atomics/add/validate-arraytype-before-index-coercion.js b/js/src/tests/test262/built-ins/Atomics/add/validate-arraytype-before-index-coercion.js new file mode 100644 index 0000000000..811e46fd70 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/add/validate-arraytype-before-index-coercion.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.add +description: > + TypedArray type is validated before `index` argument is coerced. +info: | + 24.4.2 Atomics.add ( typedArray, index, value ) + 1. Return ? AtomicReadModifyWrite(typedArray, index, value, add). + + 24.4.1.11 AtomicReadModifyWrite ( typedArray, index, value, op ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var index = { + valueOf() { + throw new Test262Error("index coerced"); + } +}; + +var badArrayTypes = [ + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.add(typedArray, index, 0); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/add/validate-arraytype-before-value-coercion.js b/js/src/tests/test262/built-ins/Atomics/add/validate-arraytype-before-value-coercion.js new file mode 100644 index 0000000000..ba714e757b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/add/validate-arraytype-before-value-coercion.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.add +description: > + TypedArray type is validated before `value` argument is coerced. +info: | + 24.4.2 Atomics.add ( typedArray, index, value ) + 1. Return ? AtomicReadModifyWrite(typedArray, index, value, add). + + 24.4.1.11 AtomicReadModifyWrite ( typedArray, index, value, op ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var value = { + valueOf() { + throw new Test262Error("value coerced"); + } +}; + +var badArrayTypes = [ + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.add(typedArray, 0, value); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/and/bad-range.js b/js/src/tests/test262/built-ins/Atomics/and/bad-range.js new file mode 100644 index 0000000000..056db7b036 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/and/bad-range.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.and +description: > + Test range checking of Atomics.and on arrays that allow atomic operations +includes: [testAtomics.js, testTypedArray.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +const buffer = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2); +const views = intArrayConstructors.slice(); + +testWithTypedArrayConstructors(function(TA) { + const view = new TA(buffer); + testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.and(view, IdxGen(view), 10); + }, '`Atomics.and(view, IdxGen(view), 10)` throws RangeError'); + }); +}, views); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/and/bigint/bad-range.js b/js/src/tests/test262/built-ins/Atomics/and/bigint/bad-range.js new file mode 100644 index 0000000000..3876238ead --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/and/bigint/bad-range.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.and +description: > + Test range checking of Atomics.and on arrays that allow atomic operations +includes: [testAtomics.js, testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ +const buffer = new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 2); + +testWithBigIntTypedArrayConstructors(function(TA) { + const view = new TA(buffer); + + testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.and(view, IdxGen(view), 10n); + }, '`Atomics.and(view, IdxGen(view), 10n)` throws RangeError'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/and/bigint/browser.js b/js/src/tests/test262/built-ins/Atomics/and/bigint/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/and/bigint/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/and/bigint/good-views.js b/js/src/tests/test262/built-ins/Atomics/and/bigint/good-views.js new file mode 100644 index 0000000000..2f94f23de3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/and/bigint/good-views.js @@ -0,0 +1,86 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.and +description: Test Atomics.and on arrays that allow atomic operations +includes: [testAtomics.js, testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ +const sab = new SharedArrayBuffer(1024); +const ab = new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 2); + +testWithBigIntTypedArrayConstructors(function(TA) { + const view = new TA(sab, 32, 20); + const control = new TA(ab, 0, 2); + view[8] = 0x33333333n; + control[0] = 0x33333333n; + + assert.sameValue( + Atomics.and(view, 8, 0x55555555n), + control[0], + 'Atomics.and(view, 8, 0x55555555n) returns the value of `control[0]` (0x33333333n)' + ); + + control[0] = 0x11111111n; + + assert.sameValue( + view[8], + control[0], + 'The value of view[8] equals the value of `control[0]` (0x11111111n)' + ); + + assert.sameValue( + Atomics.and(view, 8, 0xF0F0F0F0n), + control[0], + 'Atomics.and(view, 8, 0xF0F0F0F0n) returns the value of `control[0]` (0x11111111n)' + ); + + control[0] = 0x10101010n; + + assert.sameValue( + view[8], + control[0], + 'The value of view[8] equals the value of `control[0]` (0x10101010n)' + ); + + view[3] = -5n; + control[0] = -5n; + + assert.sameValue( + Atomics.and(view, 3, 0n), + control[0], + 'Atomics.and(view, 3, 0n) returns the value of `control[0]` (-5n)' + ); + + assert.sameValue(view[3], 0n, 'The value of view[3] is 0n'); + control[0] = 12345n; + view[3] = 12345n; + + assert.sameValue( + Atomics.and(view, 3, 0n), + control[0], + 'Atomics.and(view, 3, 0n) returns the value of `control[0]` (12345n)' + ); + + assert.sameValue(view[3], 0n, 'The value of view[3] is 0n'); + control[0] = 123456789n; + view[3] = 123456789n; + + assert.sameValue( + Atomics.and(view, 3, 0n), + control[0], + 'Atomics.and(view, 3, 0n) returns the value of `control[0]` (123456789n)' + ); + + assert.sameValue(view[3], 0n, 'The value of view[3] is 0n'); + + testWithAtomicsInBoundsIndices(function(IdxGen) { + let Idx = IdxGen(view); + view.fill(0n); + Atomics.store(view, Idx, 37n); + assert.sameValue(Atomics.and(view, Idx, 0n), 37n, 'Atomics.and(view, Idx, 0n) returns 37n'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/and/bigint/non-shared-bufferdata.js b/js/src/tests/test262/built-ins/Atomics/and/bigint/non-shared-bufferdata.js new file mode 100644 index 0000000000..92f02253d2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/and/bigint/non-shared-bufferdata.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.and +description: > + Atomics.and will operate on TA when TA.buffer is not a SharedArrayBuffer +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ +testWithBigIntTypedArrayConstructors(TA => { + const buffer = new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4); + const view = new TA(buffer); + assert.sameValue(Atomics.and(view, 0, 1n), 0n, 'Atomics.and(view, 0, 1n) returns 0n'); + assert.sameValue(Atomics.load(view, 0), 0n, 'Atomics.load(view, 0) returns 0n'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/and/bigint/shell.js b/js/src/tests/test262/built-ins/Atomics/and/bigint/shell.js new file mode 100644 index 0000000000..90ee9c114d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/and/bigint/shell.js @@ -0,0 +1,42 @@ +// GENERATED, DO NOT EDIT +// file: testBigIntTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of BigInt TypedArray objects. +defines: + - TypedArray + - testWithBigIntTypedArrayConstructors +---*/ + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithBigIntTypedArrayConstructors(f, selected) { + /** + * Array containing every BigInt typed array constructor. + */ + var constructors = selected || [ + BigInt64Array, + BigUint64Array + ]; + + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} diff --git a/js/src/tests/test262/built-ins/Atomics/and/browser.js b/js/src/tests/test262/built-ins/Atomics/and/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/and/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/and/descriptor.js b/js/src/tests/test262/built-ins/Atomics/and/descriptor.js new file mode 100644 index 0000000000..14a0240a83 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/and/descriptor.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-atomics.and +description: Testing descriptor property of Atomics.and +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics, 'and', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/and/expected-return-value.js b/js/src/tests/test262/built-ins/Atomics/and/expected-return-value.js new file mode 100644 index 0000000000..737b262f3d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/and/expected-return-value.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.and +description: > + Atomics.and returns the value that existed at the + index prior to the operation. +info: | + Atomics.and( typedArray, index, value ) + + 1. Return ? AtomicReadModifyWrite(typedArray, index, value, and). + + AtomicReadModifyWrite( typedArray, index, value, op ) + + ... + 9. Return GetModifySetValueInBuffer(buffer, indexedPosition, + elementType, v, op). + + + GetModifySetValueInBuffer( arrayBuffer, + byteIndex, type, value, op [ , isLittleEndian ] ) + + ... + 16. Return RawBytesToNumber(type, rawBytesRead, isLittleEndian). + +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); +const a = 0b00000001000000001000000010000001; +const b = 0b00000001111111111000000011111111; +const c = 0b00000001000000001000000010000001; + +i32a[0] = a; + +assert.sameValue( + Atomics.and(i32a, 0, b), + a, + 'Atomics.and(i32a, 0, b) returns the value of `a` (0b00000001000000001000000010000001)' +); + +assert.sameValue(i32a[0], c, 'The value of i32a[0] equals the value of `c` (0b00000001000000001000000010000001)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/and/good-views.js b/js/src/tests/test262/built-ins/Atomics/and/good-views.js new file mode 100644 index 0000000000..f242b8d271 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/and/good-views.js @@ -0,0 +1,72 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.and +description: Test Atomics.and on arrays that allow atomic operations +includes: [testAtomics.js, testTypedArray.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +const sab = new SharedArrayBuffer(1024); +const ab = new ArrayBuffer(16); +const views = intArrayConstructors.slice(); + +testWithTypedArrayConstructors(function(TA) { + // Make it interesting - use non-zero byteOffsets and non-zero indexes. + + const view = new TA(sab, 32, 20); + const control = new TA(ab, 0, 2); + + view[8] = 0x33333333; + control[0] = 0x33333333; + assert.sameValue(Atomics.and(view, 8, 0x55555555), control[0], + 'Atomics.and(view, 8, 0x55555555) returns the value of `control[0]` (0x33333333)'); + + control[0] = 0x11111111; + assert.sameValue( + view[8], + control[0], + 'The value of view[8] equals the value of `control[0]` (0x11111111)' + ); + assert.sameValue(Atomics.and(view, 8, 0xF0F0F0F0), control[0], + 'Atomics.and(view, 8, 0xF0F0F0F0) returns the value of `control[0]` (0x11111111)'); + + control[0] = 0x10101010; + assert.sameValue( + view[8], + control[0], + 'The value of view[8] equals the value of `control[0]` (0x10101010)' + ); + + view[3] = -5; + control[0] = -5; + assert.sameValue(Atomics.and(view, 3, 0), control[0], + 'Atomics.and(view, 3, 0) returns the value of `control[0]` (-5)'); + assert.sameValue(view[3], 0, 'The value of view[3] is 0'); + + control[0] = 12345; + view[3] = 12345; + assert.sameValue(Atomics.and(view, 3, 0), control[0], + 'Atomics.and(view, 3, 0) returns the value of `control[0]` (12345)'); + assert.sameValue(view[3], 0, 'The value of view[3] is 0'); + + control[0] = 123456789; + view[3] = 123456789; + assert.sameValue(Atomics.and(view, 3, 0), control[0], + 'Atomics.and(view, 3, 0) returns the value of `control[0]` (123456789)'); + assert.sameValue(view[3], 0, 'The value of view[3] is 0'); + + // In-bounds boundary cases for indexing + testWithAtomicsInBoundsIndices(function(IdxGen) { + let Idx = IdxGen(view); + view.fill(0); + // Atomics.store() computes an index from Idx in the same way as other + // Atomics operations, not quite like view[Idx]. + Atomics.store(view, Idx, 37); + assert.sameValue(Atomics.and(view, Idx, 0), 37, 'Atomics.and(view, Idx, 0) returns 37'); + }); +}, views); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/and/length.js b/js/src/tests/test262/built-ins/Atomics/and/length.js new file mode 100644 index 0000000000..ef93eed764 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/and/length.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.and +description: > + Atomics.and.length is 3. +info: | + Atomics.and ( ia, index, val ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this + value is equal to the largest number of named arguments shown in the + subclause headings for the function description, including optional + parameters. However, rest parameters shown using the form “...name” + are not included in the default argument count. + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.and, 'length', { + value: 3, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/and/name.js b/js/src/tests/test262/built-ins/Atomics/and/name.js new file mode 100644 index 0000000000..db8dc05d8c --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/and/name.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.and +description: > + Atomics.and.name is "and". +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.and, 'name', { + value: 'and', + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/and/non-shared-bufferdata.js b/js/src/tests/test262/built-ins/Atomics/and/non-shared-bufferdata.js new file mode 100644 index 0000000000..be959d353d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/and/non-shared-bufferdata.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.and +description: > + Atomics.and will operate on TA when TA.buffer is not a SharedArrayBuffer +includes: [testTypedArray.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ +testWithAtomicsFriendlyTypedArrayConstructors(TA => { + const view = new TA( + new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4) + ); + + assert.sameValue(Atomics.and(view, 0, 1), 0, 'Atomics.and(view, 0, 1) returns 0'); + assert.sameValue(Atomics.load(view, 0), 0, 'Atomics.load(view, 0) returns 0'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/and/non-shared-int-views-throws.js b/js/src/tests/test262/built-ins/Atomics/and/non-shared-int-views-throws.js new file mode 100644 index 0000000000..90987ae1ce --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/and/non-shared-int-views-throws.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.and +description: > + Atomics.and throws when operating on non-sharable integer TypedArrays +includes: [testTypedArray.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ +testWithNonAtomicsFriendlyTypedArrayConstructors(TA => { + const buffer = new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4); + const view = new TA(buffer); + + assert.throws(TypeError, function() { + Atomics.and(view, 0, 1); + }, `Atomics.and(new ${TA.name}(buffer), 0, 1) throws TypeError`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/and/non-views.js b/js/src/tests/test262/built-ins/Atomics/and/non-views.js new file mode 100644 index 0000000000..9ffc1e5b9e --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/and/non-views.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.and +description: > + Test Atomics.and on view values other than TypedArrays +includes: [testAtomics.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +testWithAtomicsNonViewValues(function(view) { + assert.throws(TypeError, function() { + Atomics.and(view, 0, 0); + }, '`Atomics.and(view, 0, 0)` throws TypeError'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/and/not-a-constructor.js b/js/src/tests/test262/built-ins/Atomics/and/not-a-constructor.js new file mode 100644 index 0000000000..5a2df7e008 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/and/not-a-constructor.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Atomics.and does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, Atomics, arrow-function, TypedArray, SharedArrayBuffer] +---*/ + +assert.sameValue(isConstructor(Atomics.and), false, 'isConstructor(Atomics.and) must return false'); + +assert.throws(TypeError, () => { + new Atomics.and(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT))); +}, '`new Atomics.and(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT)))` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/and/shell.js b/js/src/tests/test262/built-ins/Atomics/and/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/and/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Atomics/and/validate-arraytype-before-index-coercion.js b/js/src/tests/test262/built-ins/Atomics/and/validate-arraytype-before-index-coercion.js new file mode 100644 index 0000000000..1cf082f8f6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/and/validate-arraytype-before-index-coercion.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.add +description: > + TypedArray type is validated before `index` argument is coerced. +info: | + 24.4.3 Atomics.and ( typedArray, index, value ) + 1. Return ? AtomicReadModifyWrite(typedArray, index, value, and). + + 24.4.1.11 AtomicReadModifyWrite ( typedArray, index, value, op ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var index = { + valueOf() { + throw new Test262Error("index coerced"); + } +}; + +var badArrayTypes = [ + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.and(typedArray, index, 0); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/and/validate-arraytype-before-value-coercion.js b/js/src/tests/test262/built-ins/Atomics/and/validate-arraytype-before-value-coercion.js new file mode 100644 index 0000000000..c84bea0800 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/and/validate-arraytype-before-value-coercion.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.add +description: > + TypedArray type is validated before `value` argument is coerced. +info: | + 24.4.3 Atomics.and ( typedArray, index, value ) + 1. Return ? AtomicReadModifyWrite(typedArray, index, value, and). + + 24.4.1.11 AtomicReadModifyWrite ( typedArray, index, value, op ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var value = { + valueOf() { + throw new Test262Error("value coerced"); + } +}; + +var badArrayTypes = [ + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.and(typedArray, 0, value); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/browser.js b/js/src/tests/test262/built-ins/Atomics/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/compareExchange/bad-range.js b/js/src/tests/test262/built-ins/Atomics/compareExchange/bad-range.js new file mode 100644 index 0000000000..570a7a864d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/compareExchange/bad-range.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.compareexchange +description: > + Test range checking of Atomics.compareExchange on arrays that allow atomic operations +includes: [testAtomics.js, testTypedArray.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +const buffer = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2); +const views = intArrayConstructors.slice(); + +testWithTypedArrayConstructors(function(TA) { + const view = new TA(buffer); + testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.compareExchange(view, IdxGen(view), 10, 0); + }, '`Atomics.compareExchange(view, IdxGen(view), 10, 0)` throws RangeError'); + }); +}, views); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/compareExchange/bigint/bad-range.js b/js/src/tests/test262/built-ins/Atomics/compareExchange/bigint/bad-range.js new file mode 100644 index 0000000000..63b286bb72 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/compareExchange/bigint/bad-range.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.compareexchange +description: > + Test range checking of Atomics.compareExchange on arrays that allow atomic operations +includes: [testAtomics.js, testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ +const buffer = new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 2); + +testWithBigIntTypedArrayConstructors(function(TA) { + const view = new TA(buffer); + + testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.compareExchange(view, IdxGen(view), 10, 0n); + }, '`Atomics.compareExchange(view, IdxGen(view), 10, 0n)` throws RangeError'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/compareExchange/bigint/browser.js b/js/src/tests/test262/built-ins/Atomics/compareExchange/bigint/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/compareExchange/bigint/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/compareExchange/bigint/good-views.js b/js/src/tests/test262/built-ins/Atomics/compareExchange/bigint/good-views.js new file mode 100644 index 0000000000..1ecc88ce13 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/compareExchange/bigint/good-views.js @@ -0,0 +1,94 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.compareexchange +description: Test Atomics.compareExchange on arrays that allow atomic operations. +includes: [testAtomics.js, testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ +const sab = new SharedArrayBuffer(1024); +const ab = new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 2); + +testWithBigIntTypedArrayConstructors(function(TA) { + const view = new TA(sab, 32, 20); + const control = new TA(ab, 0, 2); + view[8] = 0n; + + assert.sameValue( + Atomics.compareExchange(view, 8, 0n, 10n), + 0n, + 'Atomics.compareExchange(view, 8, 0n, 10n) returns 0n' + ); + + assert.sameValue(view[8], 10n, 'The value of view[8] is 10n'); + view[8] = 0n; + + assert.sameValue( + Atomics.compareExchange(view, 8, 1n, 10n), + 0n, + 'Atomics.compareExchange(view, 8, 1n, 10n) returns 0n' + ); + + assert.sameValue(view[8], 0n, 'The value of view[8] is 0n'); + view[8] = 0n; + + assert.sameValue( + Atomics.compareExchange(view, 8, 0n, -5n), + 0n, + 'Atomics.compareExchange(view, 8, 0n, -5n) returns 0n' + ); + + control[0] = -5n; + + assert.sameValue( + view[8], + control[0], + 'The value of view[8] equals the value of `control[0]` (-5n)' + ); + + view[3] = -5n; + control[0] = -5n; + + assert.sameValue( + Atomics.compareExchange(view, 3, -5n, 0n), + control[0], + 'Atomics.compareExchange(view, 3, -5n, 0n) returns the value of `control[0]` (-5n)' + ); + + assert.sameValue(view[3], 0n, 'The value of view[3] is 0n'); + control[0] = 12345n; + view[3] = 12345n; + + assert.sameValue( + Atomics.compareExchange(view, 3, 12345n, 0n), + control[0], + 'Atomics.compareExchange(view, 3, 12345n, 0n) returns the value of `control[0]` (12345n)' + ); + + assert.sameValue(view[3], 0n, 'The value of view[3] is 0n'); + control[0] = 123456789n; + view[3] = 123456789n; + + assert.sameValue( + Atomics.compareExchange(view, 3, 123456789n, 0n), + control[0], + 'Atomics.compareExchange(view, 3, 123456789n, 0n) returns the value of `control[0]` (123456789n)' + ); + + assert.sameValue(view[3], 0n, 'The value of view[3] is 0n'); + + testWithAtomicsInBoundsIndices(function(IdxGen) { + let Idx = IdxGen(view); + view.fill(0n); + Atomics.store(view, Idx, 37n); + + assert.sameValue( + Atomics.compareExchange(view, Idx, 37n, 0n), + 37n, + 'Atomics.compareExchange(view, Idx, 37n, 0n) returns 37n' + ); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/compareExchange/bigint/non-shared-bufferdata.js b/js/src/tests/test262/built-ins/Atomics/compareExchange/bigint/non-shared-bufferdata.js new file mode 100644 index 0000000000..1952abaff5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/compareExchange/bigint/non-shared-bufferdata.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.compareExchange +description: > + Atomics.compareExchange will operate on TA when TA.buffer is not a SharedArrayBuffer +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ +testWithBigIntTypedArrayConstructors(TA => { + const buffer = new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4); + const view = new TA(buffer); + assert.sameValue(Atomics.compareExchange(view, 0, 0n, 1n), 0n, 'Atomics.compareExchange(view, 0, 0n, 1n) returns 0n'); + assert.sameValue(Atomics.load(view, 0), 1n, 'Atomics.load(view, 0) returns 1n'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/compareExchange/bigint/shell.js b/js/src/tests/test262/built-ins/Atomics/compareExchange/bigint/shell.js new file mode 100644 index 0000000000..90ee9c114d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/compareExchange/bigint/shell.js @@ -0,0 +1,42 @@ +// GENERATED, DO NOT EDIT +// file: testBigIntTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of BigInt TypedArray objects. +defines: + - TypedArray + - testWithBigIntTypedArrayConstructors +---*/ + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithBigIntTypedArrayConstructors(f, selected) { + /** + * Array containing every BigInt typed array constructor. + */ + var constructors = selected || [ + BigInt64Array, + BigUint64Array + ]; + + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} diff --git a/js/src/tests/test262/built-ins/Atomics/compareExchange/browser.js b/js/src/tests/test262/built-ins/Atomics/compareExchange/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/compareExchange/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/compareExchange/descriptor.js b/js/src/tests/test262/built-ins/Atomics/compareExchange/descriptor.js new file mode 100644 index 0000000000..cd273df6c4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/compareExchange/descriptor.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-atomics.compareexchange +description: Testing descriptor property of Atomics.compareExchange +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics, 'compareExchange', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/compareExchange/expected-return-value.js b/js/src/tests/test262/built-ins/Atomics/compareExchange/expected-return-value.js new file mode 100644 index 0000000000..1219bf1bae --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/compareExchange/expected-return-value.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.compareExchange +description: > + Atomics.compareExchange returns the value that existed at the + index prior to the operation. +info: | + Atomics.compareExchange( typedArray, index, expectedValue, replacementValue ) + + ... + 12. Let compareExchange denote a semantic function of two List of + byte values arguments that returns the second argument if the + first argument is element-wise equal to expectedBytes. + 13. Return GetModifySetValueInBuffer(buffer, indexedPosition, + elementType, replacement, compareExchange). + + + GetModifySetValueInBuffer( arrayBuffer, + byteIndex, type, value, op [ , isLittleEndian ] ) + + ... + 16. Return RawBytesToNumber(type, rawBytesRead, isLittleEndian). + +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const buffer = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4); +const i32a = new Int32Array(buffer); +const update = 0b00000001000000001000000010000001; + +i32a[0] = update; + +assert.sameValue( + Atomics.compareExchange(i32a, 0, update, 0), + update, + 'Atomics.compareExchange(i32a, 0, update, 0) returns the value of `update` (0b00000001000000001000000010000001)' +); +assert.sameValue(i32a[0], 0, 'The value of i32a[0] is 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/compareExchange/good-views.js b/js/src/tests/test262/built-ins/Atomics/compareExchange/good-views.js new file mode 100644 index 0000000000..a9a8afc53f --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/compareExchange/good-views.js @@ -0,0 +1,77 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.compareexchange +description: Test Atomics.compareExchange on arrays that allow atomic operations. +includes: [testAtomics.js, testTypedArray.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +const sab = new SharedArrayBuffer(1024); +const ab = new ArrayBuffer(16); +const views = intArrayConstructors.slice(); + +testWithTypedArrayConstructors(function(TA) { + // Make it interesting - use non-zero byteOffsets and non-zero indexes. + + const view = new TA(sab, 32, 20); + const control = new TA(ab, 0, 2); + + // Performs the exchange + view[8] = 0; + assert.sameValue( + Atomics.compareExchange(view, 8, 0, 10), + 0, + 'Atomics.compareExchange(view, 8, 0, 10) returns 0' + ); + assert.sameValue(view[8], 10, 'The value of view[8] is 10'); + + view[8] = 0; + assert.sameValue(Atomics.compareExchange(view, 8, 1, 10), 0, + 'Atomics.compareExchange(view, 8, 1, 10) returns 0'); + assert.sameValue(view[8], 0, 'The value of view[8] is 0'); + + view[8] = 0; + assert.sameValue(Atomics.compareExchange(view, 8, 0, -5), 0, + 'Atomics.compareExchange(view, 8, 0, -5) returns 0'); + control[0] = -5; + assert.sameValue(view[8], control[0], 'The value of view[8] equals the value of `control[0]` (-5)'); + + + view[3] = -5; + control[0] = -5; + assert.sameValue(Atomics.compareExchange(view, 3, -5, 0), control[0], + 'Atomics.compareExchange(view, 3, -5, 0) returns the value of `control[0]` (-5)'); + assert.sameValue(view[3], 0, 'The value of view[3] is 0'); + + + control[0] = 12345; + view[3] = 12345; + assert.sameValue(Atomics.compareExchange(view, 3, 12345, 0), control[0], + 'Atomics.compareExchange(view, 3, 12345, 0) returns the value of `control[0]` (12345)'); + assert.sameValue(view[3], 0, 'The value of view[3] is 0'); + + control[0] = 123456789; + view[3] = 123456789; + assert.sameValue(Atomics.compareExchange(view, 3, 123456789, 0), control[0], + 'Atomics.compareExchange(view, 3, 123456789, 0) returns the value of `control[0]` (123456789)'); + assert.sameValue(view[3], 0, 'The value of view[3] is 0'); + + // In-bounds boundary cases for indexing + testWithAtomicsInBoundsIndices(function(IdxGen) { + let Idx = IdxGen(view); + view.fill(0); + // Atomics.store() computes an index from Idx in the same way as other + // Atomics operations, not quite like view[Idx]. + Atomics.store(view, Idx, 37); + assert.sameValue( + Atomics.compareExchange(view, Idx, 37, 0), + 37, + 'Atomics.compareExchange(view, Idx, 37, 0) returns 37' + ); + }); +}, views); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/compareExchange/length.js b/js/src/tests/test262/built-ins/Atomics/compareExchange/length.js new file mode 100644 index 0000000000..f850703350 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/compareExchange/length.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.compareexchange +description: > + Atomics.compareExchange.length is 4. +info: | + Atomics.compareExchange ( ia, index, expect, replace ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this + value is equal to the largest number of named arguments shown in the + subclause headings for the function description, including optional + parameters. However, rest parameters shown using the form “...name” + are not included in the default argument count. + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.compareExchange, 'length', { + value: 4, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/compareExchange/name.js b/js/src/tests/test262/built-ins/Atomics/compareExchange/name.js new file mode 100644 index 0000000000..df2e3f0643 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/compareExchange/name.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.compareexchange +description: > + Atomics.compareExchange.name is "compareExchange". +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.compareExchange, 'name', { + value: 'compareExchange', + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/compareExchange/non-shared-bufferdata.js b/js/src/tests/test262/built-ins/Atomics/compareExchange/non-shared-bufferdata.js new file mode 100644 index 0000000000..a5d3058801 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/compareExchange/non-shared-bufferdata.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.compareExchange +description: > + Atomics.compareExchange will operate on TA when TA.buffer is not a SharedArrayBuffer +includes: [testTypedArray.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ +testWithAtomicsFriendlyTypedArrayConstructors(TA => { + const view = new TA( + new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4) + ); + + assert.sameValue(Atomics.compareExchange(view, 0, 0, 1), 0, 'Atomics.compareExchange(view, 0, 0, 1) returns 0'); + assert.sameValue(Atomics.load(view, 0), 1, 'Atomics.load(view, 0) returns 1'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/compareExchange/non-shared-int-views-throws.js b/js/src/tests/test262/built-ins/Atomics/compareExchange/non-shared-int-views-throws.js new file mode 100644 index 0000000000..45df6f8cb5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/compareExchange/non-shared-int-views-throws.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.compareExchange +description: > + Atomics.compareExchange throws when operating on non-sharable integer TypedArrays +includes: [testTypedArray.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ +testWithNonAtomicsFriendlyTypedArrayConstructors(TA => { + const buffer = new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4); + const view = new TA(buffer); + + assert.throws(TypeError, function() { + Atomics.compareExchange(view, 0, 0, 0); + }, `Atomics.compareExchange(new ${TA.name}(buffer), 0, 0, 0) throws TypeError`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/compareExchange/non-views.js b/js/src/tests/test262/built-ins/Atomics/compareExchange/non-views.js new file mode 100644 index 0000000000..79c1904ad2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/compareExchange/non-views.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.compareexchange +description: > + Test Atomics.compareExchange on view values other than TypedArrays +includes: [testAtomics.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +testWithAtomicsNonViewValues(function(view) { + assert.throws(TypeError, function() { + Atomics.compareExchange(view, 0, 0, 0); + }, '`Atomics.compareExchange(view, 0, 0, 0)` throws TypeError'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/compareExchange/not-a-constructor.js b/js/src/tests/test262/built-ins/Atomics/compareExchange/not-a-constructor.js new file mode 100644 index 0000000000..7e02ac2a87 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/compareExchange/not-a-constructor.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Atomics.compareExchange does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, Atomics, arrow-function, TypedArray, SharedArrayBuffer] +---*/ + +assert.sameValue( + isConstructor(Atomics.compareExchange), + false, + 'isConstructor(Atomics.compareExchange) must return false' +); + +assert.throws(TypeError, () => { + new Atomics.compareExchange(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT))); +}, '`new Atomics.compareExchange(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT)))` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/compareExchange/shell.js b/js/src/tests/test262/built-ins/Atomics/compareExchange/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/compareExchange/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Atomics/compareExchange/validate-arraytype-before-expectedValue-coercion.js b/js/src/tests/test262/built-ins/Atomics/compareExchange/validate-arraytype-before-expectedValue-coercion.js new file mode 100644 index 0000000000..2db356fecc --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/compareExchange/validate-arraytype-before-expectedValue-coercion.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.compareExchange +description: > + TypedArray type is validated before `expectedValue` argument is coerced. +info: | + 24.4.4 Atomics.compareExchange ( typedArray, index, expectedValue, replacementValue ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var expectedValue = { + valueOf() { + throw new Test262Error("expectedValue coerced"); + } +}; + +var badArrayTypes = [ + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.compareExchange(typedArray, 0, expectedValue, 0); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/compareExchange/validate-arraytype-before-index-coercion.js b/js/src/tests/test262/built-ins/Atomics/compareExchange/validate-arraytype-before-index-coercion.js new file mode 100644 index 0000000000..753cbe0f14 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/compareExchange/validate-arraytype-before-index-coercion.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.compareExchange +description: > + TypedArray type is validated before `index` argument is coerced. +info: | + 24.4.4 Atomics.compareExchange ( typedArray, index, expectedValue, replacementValue ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var index = { + valueOf() { + throw new Test262Error("index coerced"); + } +}; + +var badArrayTypes = [ + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.compareExchange(typedArray, index, 0, 0); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/compareExchange/validate-arraytype-before-replacementValue-coercion.js b/js/src/tests/test262/built-ins/Atomics/compareExchange/validate-arraytype-before-replacementValue-coercion.js new file mode 100644 index 0000000000..09b9be7bdc --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/compareExchange/validate-arraytype-before-replacementValue-coercion.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.compareExchange +description: > + TypedArray type is validated before `replacementValue` argument is coerced. +info: | + 24.4.4 Atomics.compareExchange ( typedArray, index, expectedValue, replacementValue ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var replacementValue = { + valueOf() { + throw new Test262Error("replacementValue coerced"); + } +}; + +var badArrayTypes = [ + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.compareExchange(typedArray, 0, 0, replacementValue); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/exchange/bad-range.js b/js/src/tests/test262/built-ins/Atomics/exchange/bad-range.js new file mode 100644 index 0000000000..a308ea18ec --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/exchange/bad-range.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.exchange +description: > + Test range checking of Atomics.exchange on arrays that allow atomic operations +includes: [testAtomics.js, testTypedArray.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +const buffer = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2); +const views = intArrayConstructors.slice(); + +testWithTypedArrayConstructors(function(TA) { + const view = new TA(buffer); + testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.exchange(view, IdxGen(view), 10, 0); + }, '`Atomics.exchange(view, IdxGen(view), 10, 0)` throws RangeError'); + }); +}, views); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/exchange/bigint/bad-range.js b/js/src/tests/test262/built-ins/Atomics/exchange/bigint/bad-range.js new file mode 100644 index 0000000000..61b2a8472d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/exchange/bigint/bad-range.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.exchange +description: > + Test range checking of Atomics.exchange on arrays that allow atomic operations +includes: [testAtomics.js, testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ +var buffer = new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 2); + +testWithBigIntTypedArrayConstructors(function(TA) { + let view = new TA(buffer); + + testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.exchange(view, IdxGen(view), 10n, 0n); + }, '`Atomics.exchange(view, IdxGen(view), 10n, 0n)` throws RangeError'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/exchange/bigint/browser.js b/js/src/tests/test262/built-ins/Atomics/exchange/bigint/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/exchange/bigint/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/exchange/bigint/good-views.js b/js/src/tests/test262/built-ins/Atomics/exchange/bigint/good-views.js new file mode 100644 index 0000000000..e291f35780 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/exchange/bigint/good-views.js @@ -0,0 +1,74 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.exchange +description: Test Atomics.exchange on arrays that allow atomic operations. +includes: [testAtomics.js, testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ +const sab = new SharedArrayBuffer(1024); +const ab = new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 2); + +testWithBigIntTypedArrayConstructors(function(TA) { + const view = new TA(sab, 32, 20); + const control = new TA(ab, 0, 2); + view[8] = 0n; + assert.sameValue(Atomics.exchange(view, 8, 10n), 0n, 'Atomics.exchange(view, 8, 10n) returns 0n'); + assert.sameValue(view[8], 10n, 'The value of view[8] is 10n'); + + assert.sameValue( + Atomics.exchange(view, 8, -5n), + 10n, + 'Atomics.exchange(view, 8, -5n) returns 10n' + ); + + control[0] = -5n; + + assert.sameValue( + view[8], + control[0], + 'The value of view[8] equals the value of `control[0]` (-5n)' + ); + + view[3] = -5n; + control[0] = -5n; + + assert.sameValue( + Atomics.exchange(view, 3, 0n), + control[0], + 'Atomics.exchange(view, 3, 0n) returns the value of `control[0]` (-5n)' + ); + + control[0] = 12345n; + view[3] = 12345n; + + assert.sameValue( + Atomics.exchange(view, 3, 0n), + control[0], + 'Atomics.exchange(view, 3, 0n) returns the value of `control[0]` (12345n)' + ); + + control[0] = 123456789n; + view[3] = 123456789n; + + assert.sameValue( + Atomics.exchange(view, 3, 0n), + control[0], + 'Atomics.exchange(view, 3, 0n) returns the value of `control[0]` (123456789n)' + ); + + testWithAtomicsInBoundsIndices(function(IdxGen) { + let Idx = IdxGen(view); + view.fill(0n); + Atomics.store(view, Idx, 37n); + + assert.sameValue( + Atomics.exchange(view, Idx, 0n), + 37n, + 'Atomics.exchange(view, Idx, 0n) returns 37n' + ); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/exchange/bigint/non-shared-bufferdata.js b/js/src/tests/test262/built-ins/Atomics/exchange/bigint/non-shared-bufferdata.js new file mode 100644 index 0000000000..8bf7f7a22c --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/exchange/bigint/non-shared-bufferdata.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.exchange +description: > + Atomics.exchange will operate on TA when TA.buffer is not a SharedArrayBuffer +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ +testWithBigIntTypedArrayConstructors(TA => { + const buffer = new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4); + const view = new TA(buffer); + assert.sameValue(Atomics.exchange(view, 0, 1n), 0n, 'Atomics.exchange(view, 0, 1n) returns 0n'); + assert.sameValue(Atomics.load(view, 0), 1n, 'Atomics.load(view, 0) returns 1n'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/exchange/bigint/shell.js b/js/src/tests/test262/built-ins/Atomics/exchange/bigint/shell.js new file mode 100644 index 0000000000..90ee9c114d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/exchange/bigint/shell.js @@ -0,0 +1,42 @@ +// GENERATED, DO NOT EDIT +// file: testBigIntTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of BigInt TypedArray objects. +defines: + - TypedArray + - testWithBigIntTypedArrayConstructors +---*/ + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithBigIntTypedArrayConstructors(f, selected) { + /** + * Array containing every BigInt typed array constructor. + */ + var constructors = selected || [ + BigInt64Array, + BigUint64Array + ]; + + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} diff --git a/js/src/tests/test262/built-ins/Atomics/exchange/browser.js b/js/src/tests/test262/built-ins/Atomics/exchange/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/exchange/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/exchange/descriptor.js b/js/src/tests/test262/built-ins/Atomics/exchange/descriptor.js new file mode 100644 index 0000000000..dbe420715d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/exchange/descriptor.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-atomics.exchange +description: Testing descriptor property of Atomics.exchange +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics, 'exchange', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/exchange/expected-return-value.js b/js/src/tests/test262/built-ins/Atomics/exchange/expected-return-value.js new file mode 100644 index 0000000000..be86e9bb75 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/exchange/expected-return-value.js @@ -0,0 +1,47 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.exchange +description: > + Atomics.and returns the value that existed at the + index prior to the operation. +info: | + Atomics.exchange( typedArray, index, value ) + + 1. Return ? AtomicReadModifyWrite(typedArray, index, value, second). + + AtomicReadModifyWrite( typedArray, index, value, op ) + + ... + 9. Return GetModifySetValueInBuffer(buffer, indexedPosition, + elementType, v, op). + + + GetModifySetValueInBuffer( arrayBuffer, + byteIndex, type, value, op [ , isLittleEndian ] ) + + ... + 16. Return RawBytesToNumber(type, rawBytesRead, isLittleEndian). + +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); +const update = 0b00000001000000001000000010000001; + +assert.sameValue( + Atomics.exchange(i32a, 0, update), + 0, + 'Atomics.exchange(i32a, 0, update) returns 0' +); +assert.sameValue( + i32a[0], + update, + 'The value of i32a[0] equals the value of `update` (0b00000001000000001000000010000001)' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/exchange/good-views.js b/js/src/tests/test262/built-ins/Atomics/exchange/good-views.js new file mode 100644 index 0000000000..99de503ada --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/exchange/good-views.js @@ -0,0 +1,58 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.exchange +description: Test Atomics.exchange on arrays that allow atomic operations. +includes: [testAtomics.js, testTypedArray.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +const sab = new SharedArrayBuffer(1024); +const ab = new ArrayBuffer(16); +const views = intArrayConstructors.slice(); + +testWithTypedArrayConstructors(function(TA) { + // Make it interesting - use non-zero byteOffsets and non-zero indexes. + + const view = new TA(sab, 32, 20); + const control = new TA(ab, 0, 2); + + view[8] = 0; + assert.sameValue(Atomics.exchange(view, 8, 10), 0, + 'Atomics.exchange(view, 8, 10) returns 0'); + assert.sameValue(view[8], 10, 'The value of view[8] is 10'); + + assert.sameValue(Atomics.exchange(view, 8, -5), 10, + 'Atomics.exchange(view, 8, -5) returns 10'); + control[0] = -5; + assert.sameValue(view[8], control[0], 'The value of view[8] equals the value of `control[0]` (-5)'); + + view[3] = -5; + control[0] = -5; + assert.sameValue(Atomics.exchange(view, 3, 0), control[0], + 'Atomics.exchange(view, 3, 0) returns the value of `control[0]` (-5)'); + + control[0] = 12345; + view[3] = 12345; + assert.sameValue(Atomics.exchange(view, 3, 0), control[0], + 'Atomics.exchange(view, 3, 0) returns the value of `control[0]` (12345)'); + + control[0] = 123456789; + view[3] = 123456789; + assert.sameValue(Atomics.exchange(view, 3, 0), control[0], + 'Atomics.exchange(view, 3, 0) returns the value of `control[0]` (123456789)'); + + // In-bounds boundary cases for indexing + testWithAtomicsInBoundsIndices(function(IdxGen) { + let Idx = IdxGen(view); + view.fill(0); + // Atomics.store() computes an index from Idx in the same way as other + // Atomics operations, not quite like view[Idx]. + Atomics.store(view, Idx, 37); + assert.sameValue(Atomics.exchange(view, Idx, 0), 37, 'Atomics.exchange(view, Idx, 0) returns 37'); + }); +}, views); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/exchange/length.js b/js/src/tests/test262/built-ins/Atomics/exchange/length.js new file mode 100644 index 0000000000..4a7bb32ed5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/exchange/length.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.exchange +description: > + Atomics.exchange.length is 3. +info: | + Atomics.exchange ( ia, index, val ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this + value is equal to the largest number of named arguments shown in the + subclause headings for the function description, including optional + parameters. However, rest parameters shown using the form “...name” + are not included in the default argument count. + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.exchange, 'length', { + value: 3, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/exchange/name.js b/js/src/tests/test262/built-ins/Atomics/exchange/name.js new file mode 100644 index 0000000000..127840b85f --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/exchange/name.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.exchange +description: > + Atomics.exchange.name is "exchange". +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.exchange, 'name', { + value: 'exchange', + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/exchange/non-shared-bufferdata.js b/js/src/tests/test262/built-ins/Atomics/exchange/non-shared-bufferdata.js new file mode 100644 index 0000000000..463ae4ebb6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/exchange/non-shared-bufferdata.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.exchange +description: > + Atomics.exchange will operate on TA when TA.buffer is not a SharedArrayBuffer +includes: [testTypedArray.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ +testWithAtomicsFriendlyTypedArrayConstructors(TA => { + const view = new TA( + new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4) + ); + + assert.sameValue(Atomics.exchange(view, 0, 1), 0, 'Atomics.exchange(view, 0, 1) returns 0'); + assert.sameValue(Atomics.load(view, 0), 1, 'Atomics.load(view, 0) returns 1'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/exchange/non-shared-int-views-throws.js b/js/src/tests/test262/built-ins/Atomics/exchange/non-shared-int-views-throws.js new file mode 100644 index 0000000000..e3b53900aa --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/exchange/non-shared-int-views-throws.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.add +description: > + Atomics.add throws when operating on non-sharable integer TypedArrays +includes: [testTypedArray.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ +testWithNonAtomicsFriendlyTypedArrayConstructors(TA => { + const buffer = new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4); + const view = new TA(buffer); + assert.throws(TypeError, function() { + Atomics.add(view, 0, 1); + }, `Atomics.add(new ${TA.name}(buffer), 0, 1) throws TypeError`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/exchange/non-views.js b/js/src/tests/test262/built-ins/Atomics/exchange/non-views.js new file mode 100644 index 0000000000..fd4fe97c8a --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/exchange/non-views.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.exchange +description: > + Test Atomics.exchange on view values other than TypedArrays +includes: [testAtomics.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +testWithAtomicsNonViewValues(function(view) { + assert.throws(TypeError, function() { + Atomics.exchange(view, 0, 0); + }, '`Atomics.exchange(view, 0, 0)` throws TypeError'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/exchange/nonshared-int-views.js b/js/src/tests/test262/built-ins/Atomics/exchange/nonshared-int-views.js new file mode 100644 index 0000000000..5a45151e87 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/exchange/nonshared-int-views.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.exchange +description: > + Atomics.exchange throws when operating on non-sharable integer TypedArrays +includes: [testTypedArray.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ + +testWithNonAtomicsFriendlyTypedArrayConstructors(TA => { + const buffer = new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4); + const view = new TA(buffer); + + assert.throws(TypeError, function() { + Atomics.exchange(view, 0, 0); + }, `Atomics.exchange(new ${TA.name}(buffer), 0, 0) throws TypeError`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/exchange/not-a-constructor.js b/js/src/tests/test262/built-ins/Atomics/exchange/not-a-constructor.js new file mode 100644 index 0000000000..44ef0a7d3d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/exchange/not-a-constructor.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Atomics.exchange does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, Atomics, arrow-function, TypedArray, SharedArrayBuffer] +---*/ + +assert.sameValue(isConstructor(Atomics.exchange), false, 'isConstructor(Atomics.exchange) must return false'); + +assert.throws(TypeError, () => { + new Atomics.exchange(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT))); +}, '`new Atomics.exchange(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT)))` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/exchange/shell.js b/js/src/tests/test262/built-ins/Atomics/exchange/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/exchange/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Atomics/exchange/validate-arraytype-before-index-coercion.js b/js/src/tests/test262/built-ins/Atomics/exchange/validate-arraytype-before-index-coercion.js new file mode 100644 index 0000000000..8d7287617b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/exchange/validate-arraytype-before-index-coercion.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.exchange +description: > + TypedArray type is validated before `index` argument is coerced. +info: | + 24.4.5 Atomics.exchange ( typedArray, index, value ) + 1. Return ? AtomicReadModifyWrite(typedArray, index, value, second). + + 24.4.1.11 AtomicReadModifyWrite ( typedArray, index, value, op ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var index = { + valueOf() { + throw new Test262Error("index coerced"); + } +}; + +var badArrayTypes = [ + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.exchange(typedArray, index, 0); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/exchange/validate-arraytype-before-value-coercion.js b/js/src/tests/test262/built-ins/Atomics/exchange/validate-arraytype-before-value-coercion.js new file mode 100644 index 0000000000..7e09e04684 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/exchange/validate-arraytype-before-value-coercion.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.exchange +description: > + TypedArray type is validated before `value` argument is coerced. +info: | + 24.4.5 Atomics.exchange ( typedArray, index, value ) + 1. Return ? AtomicReadModifyWrite(typedArray, index, value, second). + + 24.4.1.11 AtomicReadModifyWrite ( typedArray, index, value, op ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var value = { + valueOf() { + throw new Test262Error("value coerced"); + } +}; + +var badArrayTypes = [ + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.exchange(typedArray, 0, value); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/isLockFree/bigint/browser.js b/js/src/tests/test262/built-ins/Atomics/isLockFree/bigint/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/isLockFree/bigint/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/isLockFree/bigint/expected-return-value.js b/js/src/tests/test262/built-ins/Atomics/isLockFree/bigint/expected-return-value.js new file mode 100644 index 0000000000..3d9cb376dc --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/isLockFree/bigint/expected-return-value.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.isLockFree +description: > + Atomics.isLockFree returns a boolean that indicates whether + operations on datum of size will be performed without the agent + acquiring a lock outside of size bytes. +info: | + Atomics.isLockFree( size ) + + 1. Let n be ? ToInteger(size). + 2. Let AR be the Agent Record of the surrounding agent. + 3. If n equals 1, return AR.[[IsLockFree1]]. + 4. If n equals 2, return AR.[[IsLockFree2]]. + 5. If n equals 4, return true. + 6. If n equals 8, return AR.[[IsLockFree8]]. + 7. Return false. + +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +includes: [testBigIntTypedArray.js] +---*/ + +testWithBigIntTypedArrayConstructors(function(TA) { + var observed = Atomics.isLockFree(TA.BYTES_PER_ELEMENT); + + assert.sameValue( + Atomics.isLockFree(TA.BYTES_PER_ELEMENT), + observed, + 'Atomics.isLockFree(TA.BYTES_PER_ELEMENT) returns the value of `observed` (Atomics.isLockFree(TA.BYTES_PER_ELEMENT))' + ); +}); + + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/isLockFree/bigint/shell.js b/js/src/tests/test262/built-ins/Atomics/isLockFree/bigint/shell.js new file mode 100644 index 0000000000..90ee9c114d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/isLockFree/bigint/shell.js @@ -0,0 +1,42 @@ +// GENERATED, DO NOT EDIT +// file: testBigIntTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of BigInt TypedArray objects. +defines: + - TypedArray + - testWithBigIntTypedArrayConstructors +---*/ + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithBigIntTypedArrayConstructors(f, selected) { + /** + * Array containing every BigInt typed array constructor. + */ + var constructors = selected || [ + BigInt64Array, + BigUint64Array + ]; + + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} diff --git a/js/src/tests/test262/built-ins/Atomics/isLockFree/browser.js b/js/src/tests/test262/built-ins/Atomics/isLockFree/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/isLockFree/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/isLockFree/corner-cases.js b/js/src/tests/test262/built-ins/Atomics/isLockFree/corner-cases.js new file mode 100644 index 0000000000..f398e06100 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/isLockFree/corner-cases.js @@ -0,0 +1,78 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.islockfree +description: > + Test isLockFree on various non-intuitive arguments +features: [Atomics] +---*/ + +assert.sameValue( + Atomics.isLockFree(hide(3, Number.NaN)), + false, + 'Atomics.isLockFree(hide(3, Number.NaN)) returns false' +); +assert.sameValue( + Atomics.isLockFree(hide(3, -1)), + false, + 'Atomics.isLockFree(hide(3, -1)) returns false' +); +assert.sameValue( + Atomics.isLockFree(hide(3, 3.14)), + false, + 'Atomics.isLockFree(hide(3, 3.14)) returns false' +); +assert.sameValue( + Atomics.isLockFree(hide(3, 0)), + false, + 'Atomics.isLockFree(hide(3, 0)) returns false' +); + +assert.sameValue( + Atomics.isLockFree('1'), + Atomics.isLockFree(1), + 'Atomics.isLockFree(\'1\') returns Atomics.isLockFree(1)' +); +assert.sameValue( + Atomics.isLockFree('3'), + Atomics.isLockFree(3), + 'Atomics.isLockFree(\'3\') returns Atomics.isLockFree(3)' +); + +assert.sameValue( + Atomics.isLockFree(true), + Atomics.isLockFree(1), + 'Atomics.isLockFree(true) returns Atomics.isLockFree(1)' +); + +assert.sameValue( + Atomics.isLockFree(1), + Atomics.isLockFree({valueOf: () => 1}), + 'Atomics.isLockFree(1) returns Atomics.isLockFree({valueOf: () => 1})' +); +assert.sameValue( + Atomics.isLockFree(3), + Atomics.isLockFree({valueOf: () => 3}), + 'Atomics.isLockFree(3) returns Atomics.isLockFree({valueOf: () => 3})' +); +assert.sameValue( + Atomics.isLockFree(1), + Atomics.isLockFree({toString: () => '1'}), + 'Atomics.isLockFree(1) returns Atomics.isLockFree({toString: () => \'1\'})' +); +assert.sameValue( + Atomics.isLockFree(3), + Atomics.isLockFree({toString: () => '3'}), + 'Atomics.isLockFree(3) returns Atomics.isLockFree({toString: () => \'3\'})' +); + +function hide(k, x) { + if (k) { + return hide(k - 3, x) + x; + } + return 0; +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/isLockFree/descriptor.js b/js/src/tests/test262/built-ins/Atomics/isLockFree/descriptor.js new file mode 100644 index 0000000000..48dd04aeb5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/isLockFree/descriptor.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-atomics.islockfree +description: Testing descriptor property of Atomics.add +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics, 'add', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/isLockFree/expected-return-value.js b/js/src/tests/test262/built-ins/Atomics/isLockFree/expected-return-value.js new file mode 100644 index 0000000000..4e0dce72be --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/isLockFree/expected-return-value.js @@ -0,0 +1,114 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.islockfree +description: > + Atomics.isLockFree( size ) + Let n be ? ToInteger(size). + Let AR be the Agent Record of the surrounding agent. + If n equals 1, return AR.[[IsLockFree1]]. + If n equals 2, return AR.[[IsLockFree2]]. + If n equals 4, return true. + If n equals 8, return AR.[[IsLockFree8]]. + Return false. +features: [Atomics] +---*/ + +// These are the only counts that we care about tracking. +var isLockFree1; +var isLockFree2; +var isLockFree8; + +{ + isLockFree1 = Atomics.isLockFree(1); + // + // If n equals 1, return AR.[[IsLockFree1]]. + // + assert.sameValue(typeof isLockFree1, 'boolean', 'The value of `typeof isLockFree1` is "boolean"'); + // Once the values of [[Signifier]], [[IsLockFree1]], [[IsLockFree2]], + // and [[IsLockFree8]] have been observed by any agent in the agent + // cluster they cannot change. + assert.sameValue( + Atomics.isLockFree(1), + isLockFree1, + 'Atomics.isLockFree(1) returns the value of `isLockFree1` (Atomics.isLockFree(1))' + ); +}; +{ + isLockFree2 = Atomics.isLockFree(2); + // + // If n equals 2, return AR.[[IsLockFree2]]. + // + assert.sameValue(typeof isLockFree2, 'boolean', 'The value of `typeof isLockFree2` is "boolean"'); + // Once the values of [[Signifier]], [[IsLockFree1]], [[IsLockFree2]], + // and [[IsLockFree8]] have been observed by any agent in the agent + // cluster they cannot change. + assert.sameValue( + Atomics.isLockFree(2), + isLockFree2, + 'Atomics.isLockFree(2) returns the value of `isLockFree2` (Atomics.isLockFree(2))' + ); +}; +{ + let isLockFree4 = Atomics.isLockFree(4); + // + // If n equals 4, return true. + // + assert.sameValue(typeof isLockFree4, 'boolean', 'The value of `typeof isLockFree4` is "boolean"'); + assert.sameValue(isLockFree4, true, 'The value of `isLockFree4` is true'); +}; + +{ + isLockFree8 = Atomics.isLockFree(8); + // + // If n equals 8, return AR.[[IsLockFree8]]. + // + assert.sameValue(typeof isLockFree8, 'boolean', 'The value of `typeof isLockFree8` is "boolean"'); + // Once the values of [[Signifier]], [[IsLockFree1]], [[IsLockFree2]], + // and [[IsLockFree8]] have been observed by any agent in the agent + // cluster they cannot change. + assert.sameValue( + Atomics.isLockFree(8), + isLockFree8, + 'Atomics.isLockFree(8) returns the value of `isLockFree8` (Atomics.isLockFree(8))' + ); +}; + +{ + for (let i = 0; i < 12; i++) { + if (![1, 2, 4, 8].includes(i)) { + assert.sameValue(Atomics.isLockFree(i), false, 'Atomics.isLockFree(i) returns false'); + } + } +}; + +assert.sameValue( + Atomics.isLockFree(1), + isLockFree1, + 'Atomics.isLockFree(1) returns the value of `isLockFree1` (Atomics.isLockFree(1))' +); +assert.sameValue( + Atomics.isLockFree(2), + isLockFree2, + 'Atomics.isLockFree(2) returns the value of `isLockFree2` (Atomics.isLockFree(2))' +); +assert.sameValue( + Atomics.isLockFree(8), + isLockFree8, + 'Atomics.isLockFree(8) returns the value of `isLockFree8` (Atomics.isLockFree(8))' +); + +// Duplicates behavior created by loop from above +assert.sameValue(Atomics.isLockFree(3), false, 'Atomics.isLockFree(3) returns false'); +assert.sameValue(Atomics.isLockFree(4), true, 'Atomics.isLockFree(4) returns true'); +assert.sameValue(Atomics.isLockFree(5), false, 'Atomics.isLockFree(5) returns false'); +assert.sameValue(Atomics.isLockFree(6), false, 'Atomics.isLockFree(6) returns false'); +assert.sameValue(Atomics.isLockFree(7), false, 'Atomics.isLockFree(7) returns false'); +assert.sameValue(Atomics.isLockFree(9), false, 'Atomics.isLockFree(9) returns false'); +assert.sameValue(Atomics.isLockFree(10), false, 'Atomics.isLockFree(10) returns false'); +assert.sameValue(Atomics.isLockFree(11), false, 'Atomics.isLockFree(11) returns false'); +assert.sameValue(Atomics.isLockFree(12), false, 'Atomics.isLockFree(12) returns false'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/isLockFree/length.js b/js/src/tests/test262/built-ins/Atomics/isLockFree/length.js new file mode 100644 index 0000000000..95f2343657 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/isLockFree/length.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.islockfree +description: > + Atomics.isLockFree.length is 1. +info: | + Atomics.isLockFree ( x ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this + value is equal to the largest number of named arguments shown in the + subclause headings for the function description, including optional + parameters. However, rest parameters shown using the form “...name” + are not included in the default argument count. + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.isLockFree, 'length', { + value: 1, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/isLockFree/name.js b/js/src/tests/test262/built-ins/Atomics/isLockFree/name.js new file mode 100644 index 0000000000..78022fe120 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/isLockFree/name.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.islockfree +description: > + Atomics.isLockFree.name is "isLockFree". +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.isLockFree, 'name', { + value: 'isLockFree', + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/isLockFree/not-a-constructor.js b/js/src/tests/test262/built-ins/Atomics/isLockFree/not-a-constructor.js new file mode 100644 index 0000000000..63054624e2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/isLockFree/not-a-constructor.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Atomics.isLockFree does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, Atomics, arrow-function, TypedArray, SharedArrayBuffer] +---*/ + +assert.sameValue(isConstructor(Atomics.isLockFree), false, 'isConstructor(Atomics.isLockFree) must return false'); + +assert.throws(TypeError, () => { + new Atomics.isLockFree(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT))); +}, '`new Atomics.isLockFree(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT)))` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/isLockFree/shell.js b/js/src/tests/test262/built-ins/Atomics/isLockFree/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/isLockFree/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Atomics/load/bad-range.js b/js/src/tests/test262/built-ins/Atomics/load/bad-range.js new file mode 100644 index 0000000000..016513c68b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/load/bad-range.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.load +description: > + Test range checking of Atomics.load on arrays that allow atomic operations +includes: [testAtomics.js, testTypedArray.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +var buffer = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2); +var views = intArrayConstructors.slice(); + +testWithTypedArrayConstructors(function(TA) { + let view = new TA(buffer); + testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.load(view, IdxGen(view)); + }, '`Atomics.load(view, IdxGen(view))` throws RangeError'); + }); +}, views); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/load/bigint/bad-range.js b/js/src/tests/test262/built-ins/Atomics/load/bigint/bad-range.js new file mode 100644 index 0000000000..4b2f0569ee --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/load/bigint/bad-range.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.load +description: > + Test range checking of Atomics.load on arrays that allow atomic operations +includes: [testAtomics.js, testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +var buffer = new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 2); + +testWithBigIntTypedArrayConstructors(function(TA) { + let view = new TA(buffer); + testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.load(view, IdxGen(view)); + }, '`Atomics.load(view, IdxGen(view))` throws RangeError'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/load/bigint/browser.js b/js/src/tests/test262/built-ins/Atomics/load/bigint/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/load/bigint/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/load/bigint/good-views.js b/js/src/tests/test262/built-ins/Atomics/load/bigint/good-views.js new file mode 100644 index 0000000000..ba8f035bde --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/load/bigint/good-views.js @@ -0,0 +1,51 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.load +description: Test Atomics.load on arrays that allow atomic operations. +includes: [testAtomics.js, testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ +const sab = new SharedArrayBuffer(1024); +const ab = new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 2); + +testWithBigIntTypedArrayConstructors(function(TA) { + const view = new TA(sab, 32, 20); + const control = new TA(ab, 0, 2); + view[3] = -5n; + control[0] = -5n; + + assert.sameValue( + Atomics.load(view, 3), + control[0], + 'Atomics.load(view, 3) returns the value of `control[0]` (-5n)' + ); + + control[0] = 12345n; + view[3] = 12345n; + + assert.sameValue( + Atomics.load(view, 3), + control[0], + 'Atomics.load(view, 3) returns the value of `control[0]` (12345n)' + ); + + control[0] = 123456789n; + view[3] = 123456789n; + + assert.sameValue( + Atomics.load(view, 3), + control[0], + 'Atomics.load(view, 3) returns the value of `control[0]` (123456789n)' + ); + + testWithAtomicsInBoundsIndices(function(IdxGen) { + let Idx = IdxGen(view); + view.fill(0n); + Atomics.store(view, Idx, 37n); + assert.sameValue(Atomics.load(view, Idx), 37n, 'Atomics.load(view, Idx) returns 37n'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/load/bigint/non-shared-bufferdata.js b/js/src/tests/test262/built-ins/Atomics/load/bigint/non-shared-bufferdata.js new file mode 100644 index 0000000000..74d61a6988 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/load/bigint/non-shared-bufferdata.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.load +description: > + Atomics.load will operate on TA when TA.buffer is not a SharedArrayBuffer +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ +testWithBigIntTypedArrayConstructors(TA => { + const buffer = new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4); + const view = new TA(buffer); + assert.sameValue(Atomics.load(view, 0), 0n, 'Atomics.load(view, 0) returns 0n'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/load/bigint/shell.js b/js/src/tests/test262/built-ins/Atomics/load/bigint/shell.js new file mode 100644 index 0000000000..90ee9c114d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/load/bigint/shell.js @@ -0,0 +1,42 @@ +// GENERATED, DO NOT EDIT +// file: testBigIntTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of BigInt TypedArray objects. +defines: + - TypedArray + - testWithBigIntTypedArrayConstructors +---*/ + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithBigIntTypedArrayConstructors(f, selected) { + /** + * Array containing every BigInt typed array constructor. + */ + var constructors = selected || [ + BigInt64Array, + BigUint64Array + ]; + + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} diff --git a/js/src/tests/test262/built-ins/Atomics/load/browser.js b/js/src/tests/test262/built-ins/Atomics/load/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/load/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/load/descriptor.js b/js/src/tests/test262/built-ins/Atomics/load/descriptor.js new file mode 100644 index 0000000000..d3d6899b29 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/load/descriptor.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-atomics.load +description: Testing descriptor property of Atomics.load +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics, 'load', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/load/expected-return-value.js b/js/src/tests/test262/built-ins/Atomics/load/expected-return-value.js new file mode 100644 index 0000000000..60e7d12c4b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/load/expected-return-value.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.load +description: > + Atomics.load returns the value that existed at the + index prior to the operation. +info: | + Atomics.load( typedArray, index, value ) + + 1. Return ? AtomicLoad(typedArray, index). + + AtomicLoad( typedArray, index ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray). + 2. Let i be ? ValidateAtomicAccess(typedArray, index). + 3. Let arrayTypeName be typedArray.[[TypedArrayName]]. + 4. Let elementSize be the Number value of the Element Size value + specified in Table 56 for arrayTypeName. + 5. Let elementType be the String value of the Element Type value + in Table 56 for arrayTypeName. + 6. Let offset be typedArray.[[ByteOffset]]. + 7. Let indexedPosition be (i × elementSize) + offset. + 8. Return GetValueFromBuffer(buffer, indexedPosition, elementType, + true, "SeqCst"). + +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); +const update = 0b00000001000000001000000010000001; + +assert.sameValue(Atomics.load(i32a, 0), 0, 'Atomics.load(i32a, 0) returns 0'); + +i32a[0] = update; + +assert.sameValue( + Atomics.load(i32a, 0), + update, + 'Atomics.load(i32a, 0) returns the value of `update` (0b00000001000000001000000010000001)' +); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/load/good-views.js b/js/src/tests/test262/built-ins/Atomics/load/good-views.js new file mode 100644 index 0000000000..34007adc63 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/load/good-views.js @@ -0,0 +1,49 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.load +description: Test Atomics.load on arrays that allow atomic operations. +includes: [testAtomics.js, testTypedArray.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +const sab = new SharedArrayBuffer(1024); +const ab = new ArrayBuffer(16); + +const views = intArrayConstructors.slice(); + +testWithTypedArrayConstructors(function(TA) { + // Make it interesting - use non-zero byteOffsets and non-zero indexes. + + const view = new TA(sab, 32, 20); + const control = new TA(ab, 0, 2); + + view[3] = -5; + control[0] = -5; + assert.sameValue(Atomics.load(view, 3), control[0], + 'Atomics.load(view, 3) returns the value of `control[0]` (-5)'); + + control[0] = 12345; + view[3] = 12345; + assert.sameValue(Atomics.load(view, 3), control[0], + 'Atomics.load(view, 3) returns the value of `control[0]` (12345)'); + + control[0] = 123456789; + view[3] = 123456789; + assert.sameValue(Atomics.load(view, 3), control[0], + 'Atomics.load(view, 3) returns the value of `control[0]` (123456789)'); + + // In-bounds boundary cases for indexing + testWithAtomicsInBoundsIndices(function(IdxGen) { + let Idx = IdxGen(view); + view.fill(0); + // Atomics.store() computes an index from Idx in the same way as other + // Atomics operations, not quite like view[Idx]. + Atomics.store(view, Idx, 37); + assert.sameValue(Atomics.load(view, Idx), 37, 'Atomics.load(view, Idx) returns 37'); + }); +}, views); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/load/length.js b/js/src/tests/test262/built-ins/Atomics/load/length.js new file mode 100644 index 0000000000..20ca0c90f6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/load/length.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.load +description: > + Atomics.load.length is 2. +info: | + Atomics.load ( ia, index ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this + value is equal to the largest number of named arguments shown in the + subclause headings for the function description, including optional + parameters. However, rest parameters shown using the form “...name” + are not included in the default argument count. + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.load, 'length', { + value: 2, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/load/name.js b/js/src/tests/test262/built-ins/Atomics/load/name.js new file mode 100644 index 0000000000..3b78cfe95b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/load/name.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.load +description: > + Atomics.load.name is "load". +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.load, 'name', { + value: 'load', + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/load/non-shared-bufferdata.js b/js/src/tests/test262/built-ins/Atomics/load/non-shared-bufferdata.js new file mode 100644 index 0000000000..73ae85260c --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/load/non-shared-bufferdata.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.load +description: > + Atomics.load will operate on TA when TA.buffer is not a SharedArrayBuffer +includes: [testTypedArray.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ +testWithAtomicsFriendlyTypedArrayConstructors(TA => { + const view = new TA( + new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4) + ); + + assert.sameValue(Atomics.load(view, 0), 0, 'Atomics.load(view, 0) returns 0'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/load/non-shared-int-views-throws.js b/js/src/tests/test262/built-ins/Atomics/load/non-shared-int-views-throws.js new file mode 100644 index 0000000000..a8bb46083c --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/load/non-shared-int-views-throws.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.load +description: > + Atomics.load throws when operating on non-sharable integer TypedArrays +includes: [testTypedArray.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ +testWithNonAtomicsFriendlyTypedArrayConstructors(TA => { + const buffer = new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4); + const view = new TA(buffer); + assert.throws(TypeError, function() { + Atomics.load(view, 0); + }, `Atomics.load(new ${TA.name}(buffer), 0) throws TypeError`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/load/non-views.js b/js/src/tests/test262/built-ins/Atomics/load/non-views.js new file mode 100644 index 0000000000..27ce355f3f --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/load/non-views.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.load +description: > + Test Atomics.load on view values other than TypedArrays +includes: [testAtomics.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +testWithAtomicsNonViewValues(function(view) { + assert.throws(TypeError, function() { + Atomics.load(view, 0); + }, '`Atomics.load(view, 0)` throws TypeError'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/load/not-a-constructor.js b/js/src/tests/test262/built-ins/Atomics/load/not-a-constructor.js new file mode 100644 index 0000000000..6bce6c4844 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/load/not-a-constructor.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Atomics.load does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, Atomics, arrow-function, TypedArray, SharedArrayBuffer] +---*/ + +assert.sameValue(isConstructor(Atomics.load), false, 'isConstructor(Atomics.load) must return false'); + +assert.throws(TypeError, () => { + new Atomics.load(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT))); +}, '`new Atomics.load(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT)))` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/load/shell.js b/js/src/tests/test262/built-ins/Atomics/load/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/load/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Atomics/load/validate-arraytype-before-index-coercion.js b/js/src/tests/test262/built-ins/Atomics/load/validate-arraytype-before-index-coercion.js new file mode 100644 index 0000000000..12c4e0e1e1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/load/validate-arraytype-before-index-coercion.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.store +description: > + TypedArray type is validated before `index` argument is coerced. +info: | + 24.4.7 Atomics.load ( typedArray, index ) + 1. Return ? AtomicLoad(typedArray, index). + + 24.4.1.12 AtomicLoad ( typedArray, index ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var index = { + valueOf() { + throw new Test262Error("index coerced"); + } +}; + +var badArrayTypes = [ + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.load(typedArray, index); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bad-range.js b/js/src/tests/test262/built-ins/Atomics/notify/bad-range.js new file mode 100644 index 0000000000..cd149aea83 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bad-range.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test range checking of Atomics.notify on arrays that allow atomic operations +info: | + Atomics.notify( typedArray, index, count ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + .. + +includes: [testAtomics.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.notify(i32a, IdxGen(i32a), 0); + }, '`Atomics.notify(i32a, IdxGen(i32a), 0)` throws RangeError'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bigint/bad-range.js b/js/src/tests/test262/built-ins/Atomics/notify/bigint/bad-range.js new file mode 100644 index 0000000000..7479c2fb00 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bigint/bad-range.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test range checking of Atomics.notify on arrays that allow atomic operations +info: | + Atomics.notify( typedArray, index, count ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + .. + +includes: [testAtomics.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 8) +); + +testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.notify(i64a, IdxGen(i64a), 0); + }, '`Atomics.notify(i64a, IdxGen(i64a), 0)` throws RangeError'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bigint/browser.js b/js/src/tests/test262/built-ins/Atomics/notify/bigint/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bigint/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-bigint64-typedarray-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-bigint64-typedarray-throws.js new file mode 100644 index 0000000000..94fc29e40d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-bigint64-typedarray-throws.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Throws a TypeError if typedArray arg is not an BigInt64Array +info: | + Atomics.notify( typedArray, index, count ) + + 1.Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + 5.If onlyInt32 is true, then + If typeName is not "BigInt64Array", throw a TypeError exception. +features: [Atomics, BigInt, TypedArray] +---*/ + +const i64a = new BigUint64Array( + new SharedArrayBuffer(BigUint64Array.BYTES_PER_ELEMENT * 8) +); + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, function() { + Atomics.wait(i64a, 0, 0); +}, '`Atomics.wait(i64a, 0, 0)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.wait(i64a, poisoned, poisoned); +}, '`Atomics.wait(i64a, poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-count-evaluation-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-count-evaluation-throws.js new file mode 100644 index 0000000000..5c5781f429 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-count-evaluation-throws.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.notify +description: > + Evaluates index before returning 0, when TA.buffer is not a SharedArrayBuffer +info: | + Atomics.notify( typedArray, index, count ) + + Let buffer be ? ValidateIntegerTypedArray(typedArray, true). + ... + Else, + Let intCount be ? ToInteger(count). + Let c be max(intCount, 0). + ... + If IsSharedArrayBuffer(buffer) is false, return 0. + +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ + +const i64a = new BigInt64Array( + new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 8) +); + +const poisoned = { + valueOf() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, function() { + Atomics.notify(i64a, poisoned, 0); +}, '`Atomics.notify(i64a, poisoned, 0)` throws Test262Error'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-index-evaluation-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-index-evaluation-throws.js new file mode 100644 index 0000000000..c345fa7265 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-index-evaluation-throws.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.notify +description: > + Evaluates index before returning 0, when TA.buffer is not a SharedArrayBuffer +info: | + Atomics.notify( typedArray, index, count ) + + Let buffer be ? ValidateIntegerTypedArray(typedArray, true). + Let i be ? ValidateAtomicAccess(typedArray, index). + ... + If IsSharedArrayBuffer(buffer) is false, return 0. + +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ + +const i64a = new BigInt64Array( + new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 8) +); + +const poisoned = { + valueOf() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, function() { + Atomics.notify(i64a, 0, poisoned); +}, '`Atomics.notify(i64a, 0, poisoned)` throws Test262Error'); + + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-non-shared-int-views-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-non-shared-int-views-throws.js new file mode 100644 index 0000000000..274bb87374 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-non-shared-int-views-throws.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Atomics.notify throws on non-shared integer TypedArrays +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ + +const nonsab = new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 8); + +const poisoned = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, function() { + Atomics.notify(new BigUint64Array(nonsab), poisoned, poisoned); +}, '`Atomics.notify(new BigUint64Array(nonsab), poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-returns-0.js b/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-returns-0.js new file mode 100644 index 0000000000..2662027e8b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bigint/non-shared-bufferdata-returns-0.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.notify +description: > + Returns 0, when TA.buffer is not a SharedArrayBuffer +info: | + Atomics.notify( typedArray, index, count ) + + Let buffer be ? ValidateIntegerTypedArray(typedArray, true). + ... + If IsSharedArrayBuffer(buffer) is false, return 0. + +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ +const i64a = new BigInt64Array( + new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 8) +); + +assert.sameValue(Atomics.notify(i64a, 0, 0), 0, 'Atomics.notify(i64a, 0, 0) returns 0'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bigint/notify-all-on-loc.js b/js/src/tests/test262/built-ins/Atomics/notify/bigint/notify-all-on-loc.js new file mode 100644 index 0000000000..18ea073bfc --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bigint/notify-all-on-loc.js @@ -0,0 +1,92 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies all waiters on a location, but does not + notify waiters on other locations. +includes: [atomicsHelper.js] +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +---*/ + +const WAIT_INDEX = 0; // Waiters on this will be woken +const WAIT_FAKE = 1; // Waiters on this will not be woken +const RUNNING = 2; // Accounting of live agents +const NOTIFY_INDEX = 3; // Accounting for too early timeouts +const NUMAGENT = 3; +const TIMEOUT_AGENT_MESSAGES = 2; // Number of messages for the timeout agent +const BUFFER_SIZE = 4; + +// Long timeout to ensure the agent doesn't timeout before the main agent calls +// `Atomics.notify`. +const TIMEOUT = $262.agent.timeouts.long; + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * BUFFER_SIZE) +); + +for (var i = 0; i < NUMAGENT; i++) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + $262.agent.report("A " + Atomics.wait(i64a, ${WAIT_INDEX}, 0n)); + $262.agent.leaving(); + }); + `); +} + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + // This will always time out. + $262.agent.report("B " + Atomics.wait(i64a, ${WAIT_FAKE}, 0n, ${TIMEOUT})); + + // If this value is not 1n, then the agent timeout before the main agent + // called Atomics.notify. + const result = Atomics.load(i64a, ${NOTIFY_INDEX}) === 1n + ? "timeout after Atomics.notify" + : "timeout before Atomics.notify"; + $262.agent.report("W " + result); + + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i64a); + +// Wait for agents to be running. +$262.agent.waitUntil(i64a, RUNNING, BigInt(NUMAGENT + 1)); + +// Try to yield control to ensure the agent actually started to wait. If we +// don't, we risk sending the notification before agents are sleeping, and we hang. +$262.agent.tryYield(); + +// Notify all waiting on WAIT_INDEX, should be 3 always, they won't time out. +assert.sameValue( + Atomics.notify(i64a, WAIT_INDEX), + NUMAGENT, + 'Atomics.notify(i64a, WAIT_INDEX) returns the value of `NUMAGENT`' +); + +Atomics.store(i64a, NOTIFY_INDEX, 1n); + +const reports = []; +for (var i = 0; i < NUMAGENT + TIMEOUT_AGENT_MESSAGES; i++) { + reports.push($262.agent.getReport()); +} +reports.sort(); + +for (var i = 0; i < NUMAGENT; i++) { + assert.sameValue(reports[i], 'A ok', 'The value of reports[i] is "A ok"'); +} +assert.sameValue(reports[NUMAGENT], 'B timed-out', 'The value of reports[NUMAGENT] is "B timed-out"'); +assert.sameValue(reports[NUMAGENT + 1], "W timeout after Atomics.notify", + 'The value of reports[NUMAGENT + 1] is "W timeout after Atomics.notify"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bigint/null-bufferdata-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/bigint/null-bufferdata-throws.js new file mode 100644 index 0000000000..38abba2047 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bigint/null-bufferdata-throws.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.notify +description: > + A null value for bufferData throws a TypeError +info: | + Atomics.notify( typedArray, index, count ) + + 1.Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + 9.If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception. + ... + 3.If bufferData is null, return false. +includes: [detachArrayBuffer.js] +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ + +const i64a = new BigInt64Array( + new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 8) +); +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +try { + $DETACHBUFFER(i64a.buffer); // Detaching a non-shared ArrayBuffer sets the [[ArrayBufferData]] value to null +} catch (error) { + $ERROR(`An unexpected error occurred when detaching ArrayBuffer: ${error.message}`); +} + +assert.throws(TypeError, function() { + Atomics.notify(i64a, poisoned, poisoned); +}, '`Atomics.notify(i64a, poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/bigint/shell.js b/js/src/tests/test262/built-ins/Atomics/notify/bigint/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/bigint/shell.js diff --git a/js/src/tests/test262/built-ins/Atomics/notify/browser.js b/js/src/tests/test262/built-ins/Atomics/notify/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/notify/count-boundary-cases.js b/js/src/tests/test262/built-ins/Atomics/notify/count-boundary-cases.js new file mode 100644 index 0000000000..c9975fe467 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/count-boundary-cases.js @@ -0,0 +1,64 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Allowed boundary cases for 'count' argument to Atomics.notify +info: | + Atomics.notify( typedArray, index, count ) + + ... + 3. If count is undefined, let c be +∞. + 4. Else, + a. Let intCount be ? ToInteger(count). + ... + + ToInteger ( argument ) + + 1. Let number be ? ToNumber(argument). + 2. If number is NaN, return +0. + 3. If number is +0, -0, +∞, or -∞, return number. + 4. Return the number value that is the same sign as number + and whose magnitude is floor(abs(number)). + +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +assert.sameValue( + Atomics.notify(i32a, 0, -3), + 0, + 'Atomics.notify(i32a, 0, -3) returns 0' +); +assert.sameValue( + Atomics.notify(i32a, 0, Number.POSITIVE_INFINITY), + 0, + 'Atomics.notify(i32a, 0, Number.POSITIVE_INFINITY) returns 0' +); +assert.sameValue( + Atomics.notify(i32a, 0, undefined), + 0, + 'Atomics.notify(i32a, 0, undefined) returns 0' +); +assert.sameValue( + Atomics.notify(i32a, 0, '33'), + 0, + 'Atomics.notify(i32a, 0, \'33\') returns 0' +); +assert.sameValue( + Atomics.notify(i32a, 0, { valueOf: 8 }), + 0, + 'Atomics.notify(i32a, 0, {valueOf: 8}) returns 0' +); +assert.sameValue( + Atomics.notify(i32a, 0), + 0, + 'Atomics.notify(i32a, 0) returns 0' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/count-defaults-to-infinity-missing.js b/js/src/tests/test262/built-ins/Atomics/notify/count-defaults-to-infinity-missing.js new file mode 100644 index 0000000000..e798141f30 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/count-defaults-to-infinity-missing.js @@ -0,0 +1,69 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Default to +Infinity when missing 'count' argument to Atomics.notify +info: | + Atomics.notify( typedArray, index, count ) + + ... + 3. If count is undefined, let c be +∞. + ... + +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 0; // Index to notify agent has started. +const WAIT_INDEX = 1; // Index all agents are waiting on. +const BUFFER_SIZE = 2; + +const NUMAGENT = 4; // Total number of agents started + +for (var i = 0; i < NUMAGENT; i++) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // Wait until restarted by main thread. + var status = Atomics.wait(i32a, ${WAIT_INDEX}, 0); + + // Report wait status and then exit the agent. + var name = String.fromCharCode(0x41 + ${i}); // "A", "B", "C", or "D" + $262.agent.report(name + " " + status); + $262.agent.leaving(); + }); + `); +} + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * BUFFER_SIZE) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +// An agent may have been interrupted between reporting its initial report +// and the `Atomics.wait` call. Try to yield control to ensure the agent +// actually started to wait. +$262.agent.tryYield(); + +assert.sameValue(Atomics.notify(i32a, WAIT_INDEX /*, count missing */), NUMAGENT, + 'Atomics.notify(i32a, WAIT_INDEX /*, count missing */) returns the value of `NUMAGENT`'); + +const reports = []; +for (var i = 0; i < NUMAGENT; i++) { + reports.push($262.agent.getReport()); +} +reports.sort(); + +assert.sameValue(reports[0], 'A ok', 'The value of reports[0] is "A ok"'); +assert.sameValue(reports[1], 'B ok', 'The value of reports[1] is "B ok"'); +assert.sameValue(reports[2], 'C ok', 'The value of reports[2] is "C ok"'); +assert.sameValue(reports[3], 'D ok', 'The value of reports[3] is "D ok"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/count-defaults-to-infinity-undefined.js b/js/src/tests/test262/built-ins/Atomics/notify/count-defaults-to-infinity-undefined.js new file mode 100644 index 0000000000..c51af98018 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/count-defaults-to-infinity-undefined.js @@ -0,0 +1,67 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Undefined count arg should result in an infinite count +info: | + Atomics.notify( typedArray, index, count ) + + 3.If count is undefined, let c be +∞. + +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 0; // Index to notify agent has started. +const WAIT_INDEX = 1; // Index all agents are waiting on. +const BUFFER_SIZE = 2; + +const NUMAGENT = 4; // Total number of agents started + +for (var i = 0; i < NUMAGENT; i++) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // Wait until restarted by main thread. + var status = Atomics.wait(i32a, ${WAIT_INDEX}, 0); + + // Report wait status and then exit the agent. + var name = String.fromCharCode(0x41 + ${i}); // "A", "B", "C", or "D" + $262.agent.report(name + " " + status); + $262.agent.leaving(); + }); + `); +} + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * BUFFER_SIZE) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +// An agent may have been interrupted between reporting its initial report +// and the `Atomics.wait` call. Try to yield control to ensure the agent +// actually started to wait. +$262.agent.tryYield(); + +assert.sameValue(Atomics.notify(i32a, WAIT_INDEX, undefined), NUMAGENT, + 'Atomics.notify(i32a, WAIT_INDEX, undefined) returns the value of `NUMAGENT`'); + +const reports = []; +for (var i = 0; i < NUMAGENT; i++) { + reports.push($262.agent.getReport()); +} +reports.sort(); + +assert.sameValue(reports[0], 'A ok', 'The value of reports[0] is "A ok"'); +assert.sameValue(reports[1], 'B ok', 'The value of reports[1] is "B ok"'); +assert.sameValue(reports[2], 'C ok', 'The value of reports[2] is "C ok"'); +assert.sameValue(reports[3], 'D ok', 'The value of reports[3] is "D ok"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/count-from-nans.js b/js/src/tests/test262/built-ins/Atomics/notify/count-from-nans.js new file mode 100644 index 0000000000..a8361fd5ed --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/count-from-nans.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + NaNs are converted to 0 for 'count' argument to Atomics.notify +info: | + Atomics.notify( typedArray, index, count ) + + ... + 3. If count is undefined, let c be +∞. + 4. Else, + a. Let intCount be ? ToInteger(count). + ... + + ToInteger ( argument ) + + ... + 2. If number is NaN, return +0. + ... + +includes: [nans.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +NaNs.forEach(nan => { + assert.sameValue(Atomics.notify(i32a, 0, nan), 0, 'Atomics.notify(i32a, 0, nan) returns 0'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/count-symbol-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/count-symbol-throws.js new file mode 100644 index 0000000000..d791756ef8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/count-symbol-throws.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Return abrupt when symbol passed for 'count' argument to Atomics.notify +info: | + Atomics.notify( typedArray, index, count ) + + ... + 3. If count is undefined, let c be +∞. + 4. Else, + a. Let intCount be ? ToInteger(count). + ... + +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +assert.throws(TypeError, function() { + Atomics.notify(i32a, 0, Symbol()); +}, '`Atomics.notify(i32a, 0, Symbol())` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/count-tointeger-throws-then-wake-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/count-tointeger-throws-then-wake-throws.js new file mode 100644 index 0000000000..184c2006d5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/count-tointeger-throws-then-wake-throws.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Return abrupt when ToInteger throws an exception on 'count' argument to Atomics.notify +info: | + Atomics.notify( typedArray, index, count ) + + ... + 3. If count is undefined, let c be +∞. + 4. Else, + a. Let intCount be ? ToInteger(count). + ... + +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(Test262Error, function() { + Atomics.notify(i32a, 0, poisoned); +}, '`Atomics.notify(i32a, 0, poisoned)` throws Test262Error'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/descriptor.js b/js/src/tests/test262/built-ins/Atomics/notify/descriptor.js new file mode 100644 index 0000000000..d293ca94c6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/descriptor.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: Testing descriptor property of Atomics.notify +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics, 'notify', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/length.js b/js/src/tests/test262/built-ins/Atomics/notify/length.js new file mode 100644 index 0000000000..24a3571af5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/length.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Atomics.notify.length is 3. +info: | + Atomics.notify ( ia, index, count ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this + value is equal to the largest number of named arguments shown in the + subclause headings for the function description, including optional + parameters. However, rest parameters shown using the form “...name” + are not included in the default argument count. + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.notify, 'length', { + value: 3, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/name.js b/js/src/tests/test262/built-ins/Atomics/notify/name.js new file mode 100644 index 0000000000..438e54a04d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/name.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Atomics.notify.name is "notify". +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.notify, 'name', { + value: 'notify', + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/negative-count.js b/js/src/tests/test262/built-ins/Atomics/notify/negative-count.js new file mode 100644 index 0000000000..7ed96b1d7f --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/negative-count.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies zero waiters if the count is negative +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.long; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + $262.agent.report(Atomics.wait(i32a, 0, 0, ${TIMEOUT})); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue(Atomics.notify(i32a, 0, -1), 0, 'Atomics.notify(i32a, 0, -1) returns 0'); // Don't actually notify it + +assert.sameValue($262.agent.getReport(), 'timed-out', '$262.agent.getReport() returns "timed-out"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/negative-index-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/negative-index-throws.js new file mode 100644 index 0000000000..a6dc837540 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/negative-index-throws.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Throws a RangeError is index < 0 +info: | + Atomics.notify( typedArray, index, count ) + + 2.Let i be ? ValidateAtomicAccess(typedArray, index). + ... + 2.Let accessIndex be ? ToIndex(requestIndex). + ... + 2.b If integerIndex < 0, throw a RangeError exception +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(RangeError, function() { + Atomics.notify(i32a, -Infinity, poisoned); +}, '`Atomics.notify(i32a, -Infinity, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.notify(i32a, -7.999, poisoned); +}, '`Atomics.notify(i32a, -7.999, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.notify(i32a, -1, poisoned); +}, '`Atomics.notify(i32a, -1, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.notify(i32a, -300, poisoned); +}, '`Atomics.notify(i32a, -300, poisoned)` throws RangeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/non-int32-typedarray-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/non-int32-typedarray-throws.js new file mode 100644 index 0000000000..92d537192a --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/non-int32-typedarray-throws.js @@ -0,0 +1,81 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Throws a TypeError if typedArray arg is not an Int32Array +info: | + Atomics.notify( typedArray, index, count ) + + 1.Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + 5.If onlyInt32 is true, then + If typeName is not "Int32Array", throw a TypeError exception. +features: [Atomics, Float32Array, Float64Array, Int8Array, TypedArray, Uint16Array, Uint8Array, Uint8ClampedArray] +---*/ + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, function() { + const view = new Float64Array( + new SharedArrayBuffer(Float64Array.BYTES_PER_ELEMENT * 8) + ); + Atomics.notify(view, poisoned, poisoned); +}, '`const view = new Float64Array( new SharedArrayBuffer(Float64Array.BYTES_PER_ELEMENT * 8) ); Atomics.notify(view, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Float32Array( + new SharedArrayBuffer(Float32Array.BYTES_PER_ELEMENT * 4) + ); + Atomics.notify(view, poisoned, poisoned); +}, '`const view = new Float32Array( new SharedArrayBuffer(Float32Array.BYTES_PER_ELEMENT * 4) ); Atomics.notify(view, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Int16Array( + new SharedArrayBuffer(Int16Array.BYTES_PER_ELEMENT * 2) + ); + Atomics.notify(view, poisoned, poisoned); +}, '`const view = new Int16Array( new SharedArrayBuffer(Int16Array.BYTES_PER_ELEMENT * 2) ); Atomics.notify(view, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Int8Array( + new SharedArrayBuffer(Int8Array.BYTES_PER_ELEMENT) + ); + Atomics.notify(view, poisoned, poisoned); +}, '`const view = new Int8Array( new SharedArrayBuffer(Int8Array.BYTES_PER_ELEMENT) ); Atomics.notify(view, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Uint32Array( + new SharedArrayBuffer(Uint32Array.BYTES_PER_ELEMENT * 4) + ); + Atomics.notify(new Uint32Array(), poisoned, poisoned); +}, '`const view = new Uint32Array( new SharedArrayBuffer(Uint32Array.BYTES_PER_ELEMENT * 4) ); Atomics.notify(new Uint32Array(), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Uint16Array( + new SharedArrayBuffer(Uint16Array.BYTES_PER_ELEMENT * 2) + ); + Atomics.notify(view, poisoned, poisoned); +}, '`const view = new Uint16Array( new SharedArrayBuffer(Uint16Array.BYTES_PER_ELEMENT * 2) ); Atomics.notify(view, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Uint8Array( + new SharedArrayBuffer(Uint8Array.BYTES_PER_ELEMENT) + ); + Atomics.notify(view, poisoned, poisoned); +}, '`const view = new Uint8Array( new SharedArrayBuffer(Uint8Array.BYTES_PER_ELEMENT) ); Atomics.notify(view, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Uint8ClampedArray( + new SharedArrayBuffer(Uint8ClampedArray.BYTES_PER_ELEMENT) + ); + Atomics.notify(view, poisoned, poisoned); +}, '`const view = new Uint8ClampedArray( new SharedArrayBuffer(Uint8ClampedArray.BYTES_PER_ELEMENT) ); Atomics.notify(view, poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-count-evaluation-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-count-evaluation-throws.js new file mode 100644 index 0000000000..c745669449 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-count-evaluation-throws.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.notify +description: > + Evaluates count before returning 0, when TA.buffer is not a SharedArrayBuffer +info: | + Atomics.notify( typedArray, index, count ) + + Let buffer be ? ValidateIntegerTypedArray(typedArray, true). + ... + Else, + Let intCount be ? ToInteger(count). + Let c be max(intCount, 0). + ... + If IsSharedArrayBuffer(buffer) is false, return 0. + + +features: [ArrayBuffer, Atomics, TypedArray] +---*/ + +const i32a = new Int32Array( + new ArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, function() { + Atomics.notify(i32a, 0, poisoned); +}, '`Atomics.notify(i32a, 0, poisoned)` throws Test262Error'); + + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-index-evaluation-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-index-evaluation-throws.js new file mode 100644 index 0000000000..d2cda0718b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-index-evaluation-throws.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.notify +description: > + Evaluates index before returning 0, when TA.buffer is not a SharedArrayBuffer +info: | + Atomics.notify( typedArray, index, count ) + + Let buffer be ? ValidateIntegerTypedArray(typedArray, true). + Let i be ? ValidateAtomicAccess(typedArray, index). + ... + If IsSharedArrayBuffer(buffer) is false, return 0. + +features: [ArrayBuffer, Atomics, TypedArray] +---*/ + +const i32a = new Int32Array( + new ArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf() { + throw new Test262Error(); + } +}; + +assert.throws(Test262Error, function() { + Atomics.notify(i32a, poisoned, 0); +}, '`Atomics.notify(i32a, poisoned, 0)` throws Test262Error'); + + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-non-shared-int-views-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-non-shared-int-views-throws.js new file mode 100644 index 0000000000..9f9ebd1bb8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-non-shared-int-views-throws.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Atomics.notify throws on non-shared integer TypedArrays +features: [ArrayBuffer, Atomics, TypedArray] +---*/ + +const nonsab = new ArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4); + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, function() { + Atomics.notify(new Int16Array(nonsab), poisoned, poisoned); +}, '`Atomics.notify(new Int16Array(nonsab), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(new Int8Array(nonsab), poisoned, poisoned); +}, '`Atomics.notify(new Int8Array(nonsab), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(new Uint32Array(nonsab), poisoned, poisoned); +}, '`Atomics.notify(new Uint32Array(nonsab), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(new Uint16Array(nonsab), poisoned, poisoned); +}, '`Atomics.notify(new Uint16Array(nonsab), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(new Uint8Array(nonsab), poisoned, poisoned); +}, '`Atomics.notify(new Uint8Array(nonsab), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(new Uint8ClampedArray(nonsab), poisoned, poisoned); +}, '`Atomics.notify(new Uint8ClampedArray(nonsab), poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-returns-0.js b/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-returns-0.js new file mode 100644 index 0000000000..5578c67b0c --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/non-shared-bufferdata-returns-0.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.notify +description: > + Returns 0, when TA.buffer is not a SharedArrayBuffer +info: | + Atomics.notify( typedArray, index, count ) + + Let buffer be ? ValidateIntegerTypedArray(typedArray, true). + ... + If IsSharedArrayBuffer(buffer) is false, return 0. + +features: [ArrayBuffer, Atomics, TypedArray] +---*/ + +const i32a = new Int32Array( + new ArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +assert.sameValue(Atomics.notify(i32a, 0, 0), 0, 'Atomics.notify(i32a, 0, 0) returns 0'); +assert.sameValue(Atomics.notify(i32a, 0, 1), 0, 'Atomics.notify(i32a, 0, 1) returns 0'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/non-shared-int-views.js b/js/src/tests/test262/built-ins/Atomics/notify/non-shared-int-views.js new file mode 100644 index 0000000000..d04f970f4b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/non-shared-int-views.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test Atomics.notify on non-shared integer TypedArrays +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const sab = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4); + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, function() { + Atomics.notify(new Int16Array(sab), poisoned, poisoned); +}, '`Atomics.notify(new Int16Array(sab), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(new Int8Array(sab), poisoned, poisoned); +}, '`Atomics.notify(new Int8Array(sab), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(new Uint32Array(sab), poisoned, poisoned); +}, '`Atomics.notify(new Uint32Array(sab), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(new Uint16Array(sab), poisoned, poisoned); +}, '`Atomics.notify(new Uint16Array(sab), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(new Uint8Array(sab), poisoned, poisoned); +}, '`Atomics.notify(new Uint8Array(sab), poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(new Uint8ClampedArray(sab), poisoned, poisoned); +}, '`Atomics.notify(new Uint8ClampedArray(sab), poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/non-views.js b/js/src/tests/test262/built-ins/Atomics/notify/non-views.js new file mode 100644 index 0000000000..ef42622ab8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/non-views.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test Atomics.notify on view values other than TypedArrays +includes: [testAtomics.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +testWithAtomicsNonViewValues(function(nonView) { + assert.throws(TypeError, function() { + Atomics.notify(nonView, 0, 0); + }, '`Atomics.notify(nonView, 0, 0)` throws TypeError'); // Even with count == 0 +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/not-a-constructor.js b/js/src/tests/test262/built-ins/Atomics/notify/not-a-constructor.js new file mode 100644 index 0000000000..b2b75dcd28 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/not-a-constructor.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Atomics.notify does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, Atomics, arrow-function, TypedArray, SharedArrayBuffer] +---*/ + +assert.sameValue(isConstructor(Atomics.notify), false, 'isConstructor(Atomics.notify) must return false'); + +assert.throws(TypeError, () => { + new Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT))); +}, '`new Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT)))` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/not-a-typedarray-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/not-a-typedarray-throws.js new file mode 100644 index 0000000000..5f9b7e2b08 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/not-a-typedarray-throws.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.notify +description: > + Throws a TypeError if the typedArray arg is not a TypedArray object +info: | + Atomics.notify( typedArray, index, count ) + + 1.Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + 3.If typedArray does not have a [[TypedArrayName]] internal slot, throw a TypeError exception. + +features: [Atomics] +---*/ + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, function() { + Atomics.wait({}, 0, 0, 0); +}, '`Atomics.wait({}, 0, 0, 0)` throws TypeError'); + +assert.throws(TypeError, function () { + Atomics.wait({}, poisoned, poisoned, poisoned); +}, '`Atomics.wait({}, poisoned, poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/not-an-object-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/not-an-object-throws.js new file mode 100644 index 0000000000..c8ca4b2a7f --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/not-an-object-throws.js @@ -0,0 +1,51 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.notify +description: > + Throws a TypeError if typedArray arg is not an Object +info: | + Atomics.notify( typedArray, index, count ) + + 1.Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + 2. if Type(typedArray) is not Object, throw a TypeError exception +features: [Atomics, Symbol] +---*/ + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, function() { + Atomics.notify(null, poisoned, poisoned); +}, '`Atomics.notify(null, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(undefined, poisoned, poisoned); +}, '`Atomics.notify(undefined, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(true, poisoned, poisoned); +}, '`Atomics.notify(true, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(false, poisoned, poisoned); +}, '`Atomics.notify(false, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify('***string***', poisoned, poisoned); +}, '`Atomics.notify(\'***string***\', poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(Number.NEGATIVE_INFINITY, poisoned, poisoned); +}, '`Atomics.notify(Number.NEGATIVE_INFINITY, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(Symbol('***symbol***'), poisoned, poisoned); +}, '`Atomics.notify(Symbol(\'***symbol***\'), poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-all-on-loc.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-all-on-loc.js new file mode 100644 index 0000000000..dbc902b6a1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-all-on-loc.js @@ -0,0 +1,92 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies all waiters on a location, but does not + notify waiters on other locations. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const WAIT_INDEX = 0; // Waiters on this will be woken +const WAIT_FAKE = 1; // Waiters on this will not be woken +const RUNNING = 2; // Accounting of live agents +const NOTIFY_INDEX = 3; // Accounting for too early timeouts +const NUMAGENT = 3; +const TIMEOUT_AGENT_MESSAGES = 2; // Number of messages for the timeout agent +const BUFFER_SIZE = 4; + +// Long timeout to ensure the agent doesn't timeout before the main agent calls +// `Atomics.notify`. +const TIMEOUT = $262.agent.timeouts.long; + +for (var i = 0; i < NUMAGENT; i++) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + $262.agent.report("A " + Atomics.wait(i32a, ${WAIT_INDEX}, 0)); + $262.agent.leaving(); + }); + `); +} + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // This will always time out. + $262.agent.report("B " + Atomics.wait(i32a, ${WAIT_FAKE}, 0, ${TIMEOUT})); + + // If this value is not 1, then the agent timeout before the main agent + // called Atomics.notify. + const result = Atomics.load(i32a, ${NOTIFY_INDEX}) === 1 + ? "timeout after Atomics.notify" + : "timeout before Atomics.notify"; + $262.agent.report("W " + result); + + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * BUFFER_SIZE) +); + +$262.agent.safeBroadcast(i32a); + +// Wait for agents to be running. +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT + 1); + +// Try to yield control to ensure the agent actually started to wait. If we +// don't, we risk sending the notification before agents are sleeping, and we hang. +$262.agent.tryYield(); + +// Notify all waiting on WAIT_INDEX, should be 3 always, they won't time out. +assert.sameValue( + Atomics.notify(i32a, WAIT_INDEX), + NUMAGENT, + 'Atomics.notify(i32a, WAIT_INDEX) returns the value of `NUMAGENT`' +); + +Atomics.store(i32a, NOTIFY_INDEX, 1); + +const reports = []; +for (var i = 0; i < NUMAGENT + TIMEOUT_AGENT_MESSAGES; i++) { + reports.push($262.agent.getReport()); +} +reports.sort(); + +for (var i = 0; i < NUMAGENT; i++) { + assert.sameValue(reports[i], "A ok", 'The value of reports[i] is "A ok"'); +} +assert.sameValue(reports[NUMAGENT], "B timed-out", 'The value of reports[NUMAGENT] is "B timed-out"'); +assert.sameValue(reports[NUMAGENT + 1], "W timeout after Atomics.notify", + 'The value of reports[NUMAGENT + 1] is "W timeout after Atomics.notify"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-all.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-all.js new file mode 100644 index 0000000000..9f283156ff --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-all.js @@ -0,0 +1,54 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies all waiters if that's what the count is. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const WAIT_INDEX = 0; // Waiters on this will be woken +const RUNNING = 1; // Accounting of live agents +const NUMAGENT = 3; +const BUFFER_SIZE = 4; + +for (var i = 0; i < NUMAGENT; i++) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + $262.agent.report("A " + Atomics.wait(i32a, ${WAIT_INDEX}, 0)); + $262.agent.leaving(); + }); + `); +} + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * BUFFER_SIZE) +); + +$262.agent.safeBroadcast(i32a); + +// Wait for agents to be running. +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +// Try to yield control to ensure the agent actually started to wait. If we +// don't, we risk sending the notification before agents are sleeping, and we hang. +$262.agent.tryYield(); + +// Notify all waiting on WAIT_INDEX, should be 3 always, they won't time out. +assert.sameValue( + Atomics.notify(i32a, WAIT_INDEX), + NUMAGENT, + 'Atomics.notify(i32a, WAIT_INDEX) returns the value of `NUMAGENT`' +); + +for (var i = 0; i < NUMAGENT; i++) { + assert.sameValue($262.agent.getReport(), 'A ok', 'The value of reports[i] is "A ok"'); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-in-order-one-time.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-in-order-one-time.js new file mode 100644 index 0000000000..b4abca79d3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-in-order-one-time.js @@ -0,0 +1,82 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies agents in the order they are waiting. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const NUMAGENT = 3; +const WAIT_INDEX = 0; // Waiters on this will be woken +const SPIN = 1; // Worker i (zero-based) spins on location SPIN+i +const RUNNING = SPIN + NUMAGENT; // Accounting of live agents +const BUFFER_SIZE = RUNNING + 1; + +// Create workers and start them all spinning. We set atomic slots to make +// them go into a wait, thus controlling the waiting order. Then we notify them +// one by one and observe the notification order. + +for (var i = 0; i < NUMAGENT; i++) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + while (Atomics.load(i32a, ${SPIN + i}) === 0) { + /* nothing */ + } + + $262.agent.report(${i}); + Atomics.wait(i32a, ${WAIT_INDEX}, 0); + $262.agent.report(${i}); + + $262.agent.leaving(); + }); + `); +} + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * BUFFER_SIZE) +); + +$262.agent.safeBroadcast(i32a); + +// Wait for agents to be running. +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +var waiterlist = []; +for (var i = 0; i < NUMAGENT; i++) { + assert.sameValue( + Atomics.store(i32a, SPIN + i, 1), + 1, + `Atomics.store(i32a, SPIN + ${i}, 1) returns 1` + ); + + waiterlist.push($262.agent.getReport()); + + // Try to yield control to ensure the agent actually started to wait. + $262.agent.tryYield(); +} + +var notified = []; +for (var i = 0; i < NUMAGENT; i++) { + assert.sameValue( + Atomics.notify(i32a, WAIT_INDEX, 1), + 1, + `Atomics.notify(i32a, WAIT_INDEX, 1) returns 1 (${i})` + ); + + notified.push($262.agent.getReport()); +} + +assert.sameValue( + notified.join(''), + waiterlist.join(''), + 'notified.join(\'\') returns waiterlist.join(\'\')' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-in-order.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-in-order.js new file mode 100644 index 0000000000..b4abca79d3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-in-order.js @@ -0,0 +1,82 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies agents in the order they are waiting. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const NUMAGENT = 3; +const WAIT_INDEX = 0; // Waiters on this will be woken +const SPIN = 1; // Worker i (zero-based) spins on location SPIN+i +const RUNNING = SPIN + NUMAGENT; // Accounting of live agents +const BUFFER_SIZE = RUNNING + 1; + +// Create workers and start them all spinning. We set atomic slots to make +// them go into a wait, thus controlling the waiting order. Then we notify them +// one by one and observe the notification order. + +for (var i = 0; i < NUMAGENT; i++) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + while (Atomics.load(i32a, ${SPIN + i}) === 0) { + /* nothing */ + } + + $262.agent.report(${i}); + Atomics.wait(i32a, ${WAIT_INDEX}, 0); + $262.agent.report(${i}); + + $262.agent.leaving(); + }); + `); +} + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * BUFFER_SIZE) +); + +$262.agent.safeBroadcast(i32a); + +// Wait for agents to be running. +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +var waiterlist = []; +for (var i = 0; i < NUMAGENT; i++) { + assert.sameValue( + Atomics.store(i32a, SPIN + i, 1), + 1, + `Atomics.store(i32a, SPIN + ${i}, 1) returns 1` + ); + + waiterlist.push($262.agent.getReport()); + + // Try to yield control to ensure the agent actually started to wait. + $262.agent.tryYield(); +} + +var notified = []; +for (var i = 0; i < NUMAGENT; i++) { + assert.sameValue( + Atomics.notify(i32a, WAIT_INDEX, 1), + 1, + `Atomics.notify(i32a, WAIT_INDEX, 1) returns 1 (${i})` + ); + + notified.push($262.agent.getReport()); +} + +assert.sameValue( + notified.join(''), + waiterlist.join(''), + 'notified.join(\'\') returns waiterlist.join(\'\')' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-nan.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-nan.js new file mode 100644 index 0000000000..909fc9a37c --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-nan.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.nofity nofities zero waiters if the count is NaN +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.long; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + $262.agent.report(Atomics.wait(i32a, 0, 0, ${TIMEOUT})); // We will timeout eventually + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue(Atomics.notify(i32a, 0, NaN), 0, 'Atomics.notify(i32a, 0, NaN) returns 0'); + +// Try to sleep past the timeout. +$262.agent.trySleep(TIMEOUT); + +assert.sameValue($262.agent.getReport(), 'timed-out', '$262.agent.getReport() returns "timed-out"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-one.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-one.js new file mode 100644 index 0000000000..9142d8b4c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-one.js @@ -0,0 +1,72 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies one waiter if that's what the count is. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const WAIT_INDEX = 0; // Agents wait here +const RUNNING = 1; // Accounting of live agents here +const NOTIFYCOUNT = 1; +const NUMAGENT = 3; +const BUFFER_SIZE = 4; + +const TIMEOUT = $262.agent.timeouts.long; + +for (var i = 0; i < NUMAGENT; i++ ) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // Waiters that are not woken will time out eventually. + $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); + $262.agent.leaving(); + }); + `); +} + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * BUFFER_SIZE) +); + +$262.agent.safeBroadcast(i32a); + +// Wait for agents to be running. +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +// There's a slight risk we'll fail to notify the desired count, if the preceding +// tryYield() took much longer than anticipated and workers have started timing +// out. +assert.sameValue( + Atomics.notify(i32a, 0, NOTIFYCOUNT), + NOTIFYCOUNT, + 'Atomics.notify(i32a, 0, NOTIFYCOUNT) returns the value of `NOTIFYCOUNT`' +); + +// Try to sleep past the timeout. +$262.agent.trySleep(TIMEOUT); + +// Collect and check results +const reports = []; +for (var i = 0; i < NUMAGENT; i++) { + reports.push($262.agent.getReport()); +} +reports.sort(); + +for (var i = 0; i < NOTIFYCOUNT; i++) { + assert.sameValue(reports[i], 'ok', 'The value of reports[i] is "ok"'); +} +for (var i = NOTIFYCOUNT; i < NUMAGENT; i++) { + assert.sameValue(reports[i], 'timed-out', 'The value of reports[i] is "timed-out"'); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-renotify-noop.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-renotify-noop.js new file mode 100644 index 0000000000..6aa5bbb186 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-renotify-noop.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify on awoken waiter is a noop. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.long; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + $262.agent.report(Atomics.wait(i32a, 0, 0, ${TIMEOUT})); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2) +); + +$262.agent.safeBroadcast(i32a); + +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue(Atomics.notify(i32a, 0, 1), 1, 'Atomics.notify(i32a, 0, 1) returns 1'); + +assert.sameValue($262.agent.getReport(), 'ok', '$262.agent.getReport() returns "ok"'); + +// Already notified, this should be a noop +assert.sameValue(Atomics.notify(i32a, 0, 1), 0, 'Atomics.notify(i32a, 0, 1) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-two.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-two.js new file mode 100644 index 0000000000..69225a2630 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-two.js @@ -0,0 +1,72 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies two waiters if that's what the count is. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const WAIT_INDEX = 0; // Agents wait here +const RUNNING = 1; // Accounting of live agents here +const NOTIFYCOUNT = 2; +const NUMAGENT = 3; +const BUFFER_SIZE = 4; + +const TIMEOUT = $262.agent.timeouts.long; + +for (var i = 0; i < NUMAGENT; i++ ) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // Waiters that are not woken will time out eventually. + $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); + $262.agent.leaving(); + }) + `); +} + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * BUFFER_SIZE) +); + +$262.agent.safeBroadcast(i32a); + +// Wait for agents to be running. +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +// There's a slight risk we'll fail to notify the desired count, if the preceding +// tryYield() took much longer than anticipated and workers have started timing +// out. +assert.sameValue( + Atomics.notify(i32a, 0, NOTIFYCOUNT), + NOTIFYCOUNT, + 'Atomics.notify(i32a, 0, NOTIFYCOUNT) returns the value of `NOTIFYCOUNT`' +); + +// Try to sleep past the timeout. +$262.agent.trySleep(TIMEOUT); + +// Collect and check results +const reports = []; +for (var i = 0; i < NUMAGENT; i++) { + reports.push($262.agent.getReport()); +} +reports.sort(); + +for (var i = 0; i < NOTIFYCOUNT; i++) { + assert.sameValue(reports[i], 'ok', 'The value of reports[i] is "ok"'); +} +for (var i = NOTIFYCOUNT; i < NUMAGENT; i++) { + assert.sameValue(reports[i], 'timed-out', 'The value of reports[i] is "timed-out"'); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-with-no-agents-waiting.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-with-no-agents-waiting.js new file mode 100644 index 0000000000..870632bfd0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-with-no-agents-waiting.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies zero waiters if there are no agents waiting. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + // THIS WILL NEVER WAIT. + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// There are ZERO agents waiting to notify... +assert.sameValue(Atomics.notify(i32a, 0, 1), 0, 'Atomics.notify(i32a, 0, 1) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-with-no-matching-agents-waiting.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-with-no-matching-agents-waiting.js new file mode 100644 index 0000000000..66f41832a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-with-no-matching-agents-waiting.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies zero waiters if there are no waiters + at the index specified. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 0; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// There are ZERO matching agents waiting on index 1 +assert.sameValue(Atomics.notify(i32a, 1, 1), 0, 'Atomics.notify(i32a, 1, 1) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/notify-zero.js b/js/src/tests/test262/built-ins/Atomics/notify/notify-zero.js new file mode 100644 index 0000000000..56df777715 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/notify-zero.js @@ -0,0 +1,59 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Test that Atomics.notify notifies zero waiters if that's what the count is. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const WAIT_INDEX = 0; // Agents wait here +const RUNNING = 1; // Accounting of live agents here +const NOTIFYCOUNT = 0; +const NUMAGENT = 3; +const BUFFER_SIZE = 4; + +const TIMEOUT = $262.agent.timeouts.long; + +for (var i = 0; i < NUMAGENT; i++) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // Waiters that are not woken will time out eventually. + $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); + $262.agent.leaving(); + }); + `); +} + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * BUFFER_SIZE) +); + +$262.agent.safeBroadcast(i32a); + +// Wait for agents to be running. +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue( + Atomics.notify(i32a, WAIT_INDEX, NOTIFYCOUNT), + NOTIFYCOUNT, + 'Atomics.notify(i32a, WAIT_INDEX, NOTIFYCOUNT) returns the value of `NOTIFYCOUNT`' +); + +// Try to sleep past the timeout. +$262.agent.trySleep(TIMEOUT); + +for (var i = 0; i < NUMAGENT; i++) { + assert.sameValue($262.agent.getReport(), 'timed-out', '$262.agent.getReport() returns "timed-out"'); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/null-bufferdata-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/null-bufferdata-throws.js new file mode 100644 index 0000000000..2f64056757 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/null-bufferdata-throws.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.notify +description: > + A null value for bufferData (detached) throws a TypeError +info: | + Atomics.notify( typedArray, index, count ) + + Let buffer be ? ValidateIntegerTypedArray(typedArray, true). + ... + + Let buffer be ? ValidateTypedArray(typedArray). + ... + + If IsDetachedBuffer(buffer) is true, throw a TypeError exception. + ... + + If arrayBuffer.[[ArrayBufferData]] is null, return true. + +includes: [detachArrayBuffer.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ + +const i32a = new Int32Array( + new ArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +try { + $DETACHBUFFER(i32a.buffer); // Detaching a non-shared ArrayBuffer sets the [[ArrayBufferData]] value to null +} catch (error) { + $ERROR(`An unexpected error occurred when detaching ArrayBuffer: ${error.message}`); +} + +assert.throws(TypeError, function() { + Atomics.notify(i32a, poisoned, poisoned); +}, '`Atomics.notify(i32a, poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/out-of-range-index-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/out-of-range-index-throws.js new file mode 100644 index 0000000000..e4e2d9f809 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/out-of-range-index-throws.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Throws a RangeError if value of index arg is out of range + info: | + Atomics.notify( typedArray, index, count ) + + 2.Let i be ? ValidateAtomicAccess(typedArray, index). + ... + 2.Let accessIndex be ? ToIndex(requestIndex). + ... + 5. If accessIndex ≥ length, throw a RangeError exception. +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +var poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(RangeError, function() { + Atomics.notify(i32a, Infinity, poisoned); +}, '`Atomics.notify(i32a, Infinity, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.notify(i32a, 4, poisoned); +}, '`Atomics.notify(i32a, 4, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.notify(i32a, 200, poisoned); +}, '`Atomics.notify(i32a, 200, poisoned)` throws RangeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/shell.js b/js/src/tests/test262/built-ins/Atomics/notify/shell.js new file mode 100644 index 0000000000..1dfaa33b4e --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/shell.js @@ -0,0 +1,387 @@ +// GENERATED, DO NOT EDIT +// file: atomicsHelper.js +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Collection of functions used to interact with Atomics.* operations across agent boundaries. +defines: + - $262.agent.getReportAsync + - $262.agent.getReport + - $262.agent.safeBroadcastAsync + - $262.agent.safeBroadcast + - $262.agent.setTimeout + - $262.agent.tryYield + - $262.agent.trySleep +---*/ + +/** + * @return {String} A report sent from an agent. + */ +{ + // This is only necessary because the original + // $262.agent.getReport API was insufficient. + // + // All runtimes currently have their own + // $262.agent.getReport which is wrong, so we + // will pave over it with a corrected version. + // + // Binding $262.agent is necessary to prevent + // breaking SpiderMonkey's $262.agent.getReport + let getReport = $262.agent.getReport.bind($262.agent); + + $262.agent.getReport = function() { + var r; + while ((r = getReport()) == null) { + $262.agent.sleep(1); + } + return r; + }; + + if (this.setTimeout === undefined) { + (function(that) { + that.setTimeout = function(callback, delay) { + let p = Promise.resolve(); + let start = Date.now(); + let end = start + delay; + function check() { + if ((end - Date.now()) > 0) { + p.then(check); + } + else { + callback(); + } + } + p.then(check); + } + })(this); + } + + $262.agent.setTimeout = setTimeout; + + $262.agent.getReportAsync = function() { + return new Promise(function(resolve) { + (function loop() { + let result = getReport(); + if (!result) { + setTimeout(loop, 1000); + } else { + resolve(result); + } + })(); + }); + }; +} + +/** + * + * Share a given Int32Array or BigInt64Array to all running agents. Ensure that the + * provided TypedArray is a "shared typed array". + * + * NOTE: Migrating all tests to this API is necessary to prevent tests from hanging + * indefinitely when a SAB is sent to a worker but the code in the worker attempts to + * create a non-sharable TypedArray (something that is not Int32Array or BigInt64Array). + * When that scenario occurs, an exception is thrown and the agent worker can no + * longer communicate with any other threads that control the SAB. If the main + * thread happens to be spinning in the $262.agent.waitUntil() while loop, it will never + * meet its termination condition and the test will hang indefinitely. + * + * Because we've defined $262.agent.broadcast(SAB) in + * https://github.com/tc39/test262/blob/HEAD/INTERPRETING.md, there are host implementations + * that assume compatibility, which must be maintained. + * + * + * $262.agent.safeBroadcast(TA) should not be included in + * https://github.com/tc39/test262/blob/HEAD/INTERPRETING.md + * + * + * @param {(Int32Array|BigInt64Array)} typedArray An Int32Array or BigInt64Array with a SharedArrayBuffer + */ +$262.agent.safeBroadcast = function(typedArray) { + let Constructor = Object.getPrototypeOf(typedArray).constructor; + let temp = new Constructor( + new SharedArrayBuffer(Constructor.BYTES_PER_ELEMENT) + ); + try { + // This will never actually wait, but that's fine because we only + // want to ensure that this typedArray CAN be waited on and is shareable. + Atomics.wait(temp, 0, Constructor === Int32Array ? 1 : BigInt(1)); + } catch (error) { + $ERROR(`${Constructor.name} cannot be used as a shared typed array. (${error})`); + } + + $262.agent.broadcast(typedArray.buffer); +}; + +$262.agent.safeBroadcastAsync = async function(ta, index, expected) { + await $262.agent.broadcast(ta.buffer); + await $262.agent.waitUntil(ta, index, expected); + await $262.agent.tryYield(); + return await Atomics.load(ta, index); +}; + + +/** + * With a given Int32Array or BigInt64Array, wait until the expected number of agents have + * reported themselves by calling: + * + * Atomics.add(typedArray, index, 1); + * + * @param {(Int32Array|BigInt64Array)} typedArray An Int32Array or BigInt64Array with a SharedArrayBuffer + * @param {number} index The index of which all agents will report. + * @param {number} expected The number of agents that are expected to report as active. + */ +$262.agent.waitUntil = function(typedArray, index, expected) { + + var agents = 0; + while ((agents = Atomics.load(typedArray, index)) !== expected) { + /* nothing */ + } + assert.sameValue(agents, expected, "Reporting number of 'agents' equals the value of 'expected'"); +}; + +/** + * Timeout values used throughout the Atomics tests. All timeouts are specified in milliseconds. + * + * @property {number} yield Used for `$262.agent.tryYield`. Must not be used in other functions. + * @property {number} small Used when agents will always timeout and `Atomics.wake` is not part + * of the test semantics. Must be larger than `$262.agent.timeouts.yield`. + * @property {number} long Used when some agents may timeout and `Atomics.wake` is called on some + * agents. The agents are required to wait and this needs to be observable + * by the main thread. + * @property {number} huge Used when `Atomics.wake` is called on all waiting agents. The waiting + * must not timeout. The agents are required to wait and this needs to be + * observable by the main thread. All waiting agents must be woken by the + * main thread. + * + * Usage for `$262.agent.timeouts.small`: + * const WAIT_INDEX = 0; + * const RUNNING = 1; + * const TIMEOUT = $262.agent.timeouts.small; + * const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2)); + * + * $262.agent.start(` + * $262.agent.receiveBroadcast(function(sab) { + * const i32a = new Int32Array(sab); + * Atomics.add(i32a, ${RUNNING}, 1); + * + * $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); + * + * $262.agent.leaving(); + * }); + * `); + * $262.agent.safeBroadcast(i32a.buffer); + * + * // Wait until the agent was started and then try to yield control to increase + * // the likelihood the agent has called `Atomics.wait` and is now waiting. + * $262.agent.waitUntil(i32a, RUNNING, 1); + * $262.agent.tryYield(); + * + * // The agent is expected to time out. + * assert.sameValue($262.agent.getReport(), "timed-out"); + * + * + * Usage for `$262.agent.timeouts.long`: + * const WAIT_INDEX = 0; + * const RUNNING = 1; + * const NUMAGENT = 2; + * const TIMEOUT = $262.agent.timeouts.long; + * const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2)); + * + * for (let i = 0; i < NUMAGENT; i++) { + * $262.agent.start(` + * $262.agent.receiveBroadcast(function(sab) { + * const i32a = new Int32Array(sab); + * Atomics.add(i32a, ${RUNNING}, 1); + * + * $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); + * + * $262.agent.leaving(); + * }); + * `); + * } + * $262.agent.safeBroadcast(i32a.buffer); + * + * // Wait until the agents were started and then try to yield control to increase + * // the likelihood the agents have called `Atomics.wait` and are now waiting. + * $262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + * $262.agent.tryYield(); + * + * // Wake exactly one agent. + * assert.sameValue(Atomics.wake(i32a, WAIT_INDEX, 1), 1); + * + * // When it doesn't matter how many agents were woken at once, a while loop + * // can be used to make the test more resilient against intermittent failures + * // in case even though `tryYield` was called, the agents haven't started to + * // wait. + * // + * // // Repeat until exactly one agent was woken. + * // var woken = 0; + * // while ((woken = Atomics.wake(i32a, WAIT_INDEX, 1)) !== 0) ; + * // assert.sameValue(woken, 1); + * + * // One agent was woken and the other one timed out. + * const reports = [$262.agent.getReport(), $262.agent.getReport()]; + * assert(reports.includes("ok")); + * assert(reports.includes("timed-out")); + * + * + * Usage for `$262.agent.timeouts.huge`: + * const WAIT_INDEX = 0; + * const RUNNING = 1; + * const NUMAGENT = 2; + * const TIMEOUT = $262.agent.timeouts.huge; + * const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2)); + * + * for (let i = 0; i < NUMAGENT; i++) { + * $262.agent.start(` + * $262.agent.receiveBroadcast(function(sab) { + * const i32a = new Int32Array(sab); + * Atomics.add(i32a, ${RUNNING}, 1); + * + * $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); + * + * $262.agent.leaving(); + * }); + * `); + * } + * $262.agent.safeBroadcast(i32a.buffer); + * + * // Wait until the agents were started and then try to yield control to increase + * // the likelihood the agents have called `Atomics.wait` and are now waiting. + * $262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + * $262.agent.tryYield(); + * + * // Wake all agents. + * assert.sameValue(Atomics.wake(i32a, WAIT_INDEX), NUMAGENT); + * + * // When it doesn't matter how many agents were woken at once, a while loop + * // can be used to make the test more resilient against intermittent failures + * // in case even though `tryYield` was called, the agents haven't started to + * // wait. + * // + * // // Repeat until all agents were woken. + * // for (var wokenCount = 0; wokenCount < NUMAGENT; ) { + * // var woken = 0; + * // while ((woken = Atomics.wake(i32a, WAIT_INDEX)) !== 0) ; + * // // Maybe perform an action on the woken agents here. + * // wokenCount += woken; + * // } + * + * // All agents were woken and none timeout. + * for (var i = 0; i < NUMAGENT; i++) { + * assert($262.agent.getReport(), "ok"); + * } + */ +$262.agent.timeouts = { + yield: 100, + small: 200, + long: 1000, + huge: 10000, +}; + +/** + * Try to yield control to the agent threads. + * + * Usage: + * const VALUE = 0; + * const RUNNING = 1; + * const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2)); + * + * $262.agent.start(` + * $262.agent.receiveBroadcast(function(sab) { + * const i32a = new Int32Array(sab); + * Atomics.add(i32a, ${RUNNING}, 1); + * + * Atomics.store(i32a, ${VALUE}, 1); + * + * $262.agent.leaving(); + * }); + * `); + * $262.agent.safeBroadcast(i32a.buffer); + * + * // Wait until agent was started and then try to yield control. + * $262.agent.waitUntil(i32a, RUNNING, 1); + * $262.agent.tryYield(); + * + * // Note: This result is not guaranteed, but should hold in practice most of the time. + * assert.sameValue(Atomics.load(i32a, VALUE), 1); + * + * The default implementation simply waits for `$262.agent.timeouts.yield` milliseconds. + */ +$262.agent.tryYield = function() { + $262.agent.sleep($262.agent.timeouts.yield); +}; + +/** + * Try to sleep the current agent for the given amount of milliseconds. It is acceptable, + * but not encouraged, to ignore this sleep request and directly continue execution. + * + * The default implementation calls `$262.agent.sleep(ms)`. + * + * @param {number} ms Time to sleep in milliseconds. + */ +$262.agent.trySleep = function(ms) { + $262.agent.sleep(ms); +}; + +// file: detachArrayBuffer.js +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + A function used in the process of asserting correctness of TypedArray objects. + + $262.detachArrayBuffer is defined by a host. +defines: [$DETACHBUFFER] +---*/ + +function $DETACHBUFFER(buffer) { + if (!$262 || typeof $262.detachArrayBuffer !== "function") { + throw new Test262Error("No method available to detach an ArrayBuffer"); + } + $262.detachArrayBuffer(buffer); +} + +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} + +// file: nans.js +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + A collection of NaN values produced from expressions that have been observed + to create distinct bit representations on various platforms. These provide a + weak basis for assertions regarding the consistent canonicalization of NaN + values in Array buffers. +defines: [NaNs] +---*/ + +var NaNs = [ + NaN, + Number.NaN, + NaN * 0, + 0/0, + Infinity/Infinity, + -(0/0), + Math.pow(-1, 0.5), + -Math.pow(-1, 0.5), + Number("Not-a-Number"), +]; diff --git a/js/src/tests/test262/built-ins/Atomics/notify/symbol-for-index-throws.js b/js/src/tests/test262/built-ins/Atomics/notify/symbol-for-index-throws.js new file mode 100644 index 0000000000..33bbc00a1b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/symbol-for-index-throws.js @@ -0,0 +1,64 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + Return abrupt when ToInteger throws for 'index' argument to Atomics.notify +info: | + Atomics.notify( typedArray, index, value, timeout ) + + 2. Let i be ? ValidateAtomicAccess(typedArray, index). + + ValidateAtomicAccess( typedArray, requestIndex ) + + 2. Let accessIndex be ? ToIndex(requestIndex). + + ToIndex ( value ) + + 2. Else, + a. Let integerIndex be ? ToInteger(value). + + ToInteger(value) + + 1. Let number be ? ToNumber(argument). + + Symbol --> Throw a TypeError exception. + +features: [Atomics, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisonedValueOf = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +const poisonedToPrimitive = { + [Symbol.toPrimitive]: function() { + throw new Test262Error("passing a poisoned object using @@ToPrimitive"); + } +}; + +assert.throws(Test262Error, function() { + Atomics.notify(i32a, poisonedValueOf, poisonedValueOf); +}, '`Atomics.notify(i32a, poisonedValueOf, poisonedValueOf)` throws Test262Error'); + +assert.throws(Test262Error, function() { + Atomics.notify(i32a, poisonedToPrimitive, poisonedToPrimitive); +}, '`Atomics.notify(i32a, poisonedToPrimitive, poisonedToPrimitive)` throws Test262Error'); + +assert.throws(TypeError, function() { + Atomics.notify(i32a, Symbol("foo"), poisonedValueOf); +}, '`Atomics.notify(i32a, Symbol("foo"), poisonedValueOf)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.notify(i32a, Symbol("foo"), poisonedToPrimitive); +}, '`Atomics.notify(i32a, Symbol("foo"), poisonedToPrimitive)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/undefined-index-defaults-to-zero.js b/js/src/tests/test262/built-ins/Atomics/notify/undefined-index-defaults-to-zero.js new file mode 100644 index 0000000000..7533c65f53 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/undefined-index-defaults-to-zero.js @@ -0,0 +1,76 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + An undefined index arg should translate to 0 +info: | + Atomics.notify( typedArray, index, count ) + + 2.Let i be ? ValidateAtomicAccess(typedArray, index). + ... + 2.Let accessIndex be ? ToIndex(requestIndex). + + 9.If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception. + ... + 3.If bufferData is a Data Block, return false + + If value is undefined, then + Let index be 0. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +var WAIT_INDEX = 0; +var RUNNING = 1; + +var NUMAGENT = 2; + +for (var i = 0; i < NUMAGENT; i++) { + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + + // Notify main thread that the agent was started. + Atomics.add(i32a, ${RUNNING}, 1); + + // Wait until restarted by main thread. + var status = Atomics.wait(i32a, ${WAIT_INDEX}, 0); + + // Report wait status. + $262.agent.report(status); + + $262.agent.leaving(); + }); + `); +} + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcast(i32a); + +// Wait until both agents started. +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +// Try to yield control to ensure the agents actually started to wait. +$262.agent.tryYield(); + +// Notify at index 0, undefined => 0. +var woken = 0; +while ((woken = Atomics.notify(i32a, undefined, 1)) === 0) ; +assert.sameValue(woken, 1, 'Atomics.notify(i32a, undefined, 1) returns 1'); + +assert.sameValue($262.agent.getReport(), 'ok', '$262.agent.getReport() returns "ok"'); + +// Notify again at index 0, default => 0. +var woken = 0; +while ((woken = Atomics.notify(i32a /*, default values used */)) === 0) ; +assert.sameValue(woken, 1, 'Atomics.notify(i32a /*, default values used */) returns 1'); + +assert.sameValue($262.agent.getReport(), 'ok', '$262.agent.getReport() returns "ok"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/validate-arraytype-before-count-coercion.js b/js/src/tests/test262/built-ins/Atomics/notify/validate-arraytype-before-count-coercion.js new file mode 100644 index 0000000000..f47c665879 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/validate-arraytype-before-count-coercion.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + TypedArray type is validated before `count` argument is coerced. +info: | + 24.4.12 Atomics.notify ( typedArray, index, count ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var count = { + valueOf() { + throw new Test262Error("count coerced"); + } +}; + +var badArrayTypes = [ + Int8Array, Uint8Array, Int16Array, Uint16Array, Uint32Array, + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.notify(typedArray, 0, count); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/notify/validate-arraytype-before-index-coercion.js b/js/src/tests/test262/built-ins/Atomics/notify/validate-arraytype-before-index-coercion.js new file mode 100644 index 0000000000..fcc334dd46 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/notify/validate-arraytype-before-index-coercion.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + TypedArray type is validated before `index` argument is coerced. +info: | + 24.4.12 Atomics.notify ( typedArray, index, count ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var index = { + valueOf() { + throw new Test262Error("index coerced"); + } +}; + +var badArrayTypes = [ + Int8Array, Uint8Array, Int16Array, Uint16Array, Uint32Array, + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.notify(typedArray, index, 0); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/or/bad-range.js b/js/src/tests/test262/built-ins/Atomics/or/bad-range.js new file mode 100644 index 0000000000..7782bf6b3f --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/or/bad-range.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.or +description: > + Test range checking of Atomics.or on arrays that allow atomic operations +includes: [testAtomics.js, testTypedArray.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +var buffer = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2); +var views = intArrayConstructors.slice(); + +testWithTypedArrayConstructors(function(TA) { + let view = new TA(buffer); + testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.or(view, IdxGen(view), 10); + }, '`Atomics.or(view, IdxGen(view), 10)` throws RangeError'); + }); +}, views); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/or/bigint/bad-range.js b/js/src/tests/test262/built-ins/Atomics/or/bigint/bad-range.js new file mode 100644 index 0000000000..af5030e173 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/or/bigint/bad-range.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.or +description: > + Test range checking of Atomics.or on arrays that allow atomic operations +includes: [testAtomics.js, testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ +var buffer = new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 2); + +testWithBigIntTypedArrayConstructors(function(TA) { + let view = new TA(buffer); + + testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.or(view, IdxGen(view), 10n); + }, '`Atomics.or(view, IdxGen(view), 10n)` throws RangeError'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/or/bigint/browser.js b/js/src/tests/test262/built-ins/Atomics/or/bigint/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/or/bigint/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/or/bigint/good-views.js b/js/src/tests/test262/built-ins/Atomics/or/bigint/good-views.js new file mode 100644 index 0000000000..0e233fd269 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/or/bigint/good-views.js @@ -0,0 +1,100 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.or +description: Test Atomics.or on arrays that allow atomic operations +includes: [testAtomics.js, testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ +const sab = new SharedArrayBuffer(1024); +const ab = new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 2); + +testWithBigIntTypedArrayConstructors(function(TA) { + const view = new TA(sab, 32, 20); + const control = new TA(ab, 0, 2); + view[8] = 0x33333333n; + control[0] = 0x33333333n; + + assert.sameValue( + Atomics.or(view, 8, 0x55555555n), + control[0], + 'Atomics.or(view, 8, 0x55555555n) returns the value of `control[0]` (0x33333333n)' + ); + + control[0] = 0x77777777n; + + assert.sameValue( + view[8], + control[0], + 'The value of view[8] equals the value of `control[0]` (0x77777777n)' + ); + + assert.sameValue( + Atomics.or(view, 8, 0xF0F0F0F0n), + control[0], + 'Atomics.or(view, 8, 0xF0F0F0F0n) returns the value of `control[0]` (0x77777777n)' + ); + + control[0] = 0xF7F7F7F7n; + + assert.sameValue( + view[8], + control[0], + 'The value of view[8] equals the value of `control[0]` (0xF7F7F7F7n)' + ); + + view[3] = -5n; + control[0] = -5n; + + assert.sameValue( + Atomics.or(view, 3, 0n), + control[0], + 'Atomics.or(view, 3, 0n) returns the value of `control[0]` (-5n)' + ); + + assert.sameValue( + view[3], + control[0], + 'The value of view[3] equals the value of `control[0]` (-5n)' + ); + + control[0] = 12345n; + view[3] = 12345n; + + assert.sameValue( + Atomics.or(view, 3, 0n), + control[0], + 'Atomics.or(view, 3, 0n) returns the value of `control[0]` (12345n)' + ); + + assert.sameValue( + view[3], + control[0], + 'The value of view[3] equals the value of `control[0]` (12345n)' + ); + + control[0] = 123456789n; + view[3] = 123456789n; + + assert.sameValue( + Atomics.or(view, 3, 0n), + control[0], + 'Atomics.or(view, 3, 0n) returns the value of `control[0]` (123456789n)' + ); + + assert.sameValue( + view[3], + control[0], + 'The value of view[3] equals the value of `control[0]` (123456789n)' + ); + + testWithAtomicsInBoundsIndices(function(IdxGen) { + let Idx = IdxGen(view); + view.fill(0n); + Atomics.store(view, Idx, 37n); + assert.sameValue(Atomics.or(view, Idx, 0n), 37n, 'Atomics.or(view, Idx, 0n) returns 37n'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/or/bigint/non-shared-bufferdata.js b/js/src/tests/test262/built-ins/Atomics/or/bigint/non-shared-bufferdata.js new file mode 100644 index 0000000000..1b8642c291 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/or/bigint/non-shared-bufferdata.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.or +description: > + Atomics.or will operate on TA when TA.buffer is not a SharedArrayBuffer +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ +testWithBigIntTypedArrayConstructors(TA => { + const buffer = new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4); + const view = new TA(buffer); + assert.sameValue(Atomics.or(view, 0, 1n), 0n, 'Atomics.or(view, 0, 1n) returns 0n'); + assert.sameValue(Atomics.load(view, 0), 1n, 'Atomics.load(view, 0) returns 1n'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/or/bigint/shell.js b/js/src/tests/test262/built-ins/Atomics/or/bigint/shell.js new file mode 100644 index 0000000000..90ee9c114d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/or/bigint/shell.js @@ -0,0 +1,42 @@ +// GENERATED, DO NOT EDIT +// file: testBigIntTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of BigInt TypedArray objects. +defines: + - TypedArray + - testWithBigIntTypedArrayConstructors +---*/ + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithBigIntTypedArrayConstructors(f, selected) { + /** + * Array containing every BigInt typed array constructor. + */ + var constructors = selected || [ + BigInt64Array, + BigUint64Array + ]; + + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} diff --git a/js/src/tests/test262/built-ins/Atomics/or/browser.js b/js/src/tests/test262/built-ins/Atomics/or/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/or/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/or/descriptor.js b/js/src/tests/test262/built-ins/Atomics/or/descriptor.js new file mode 100644 index 0000000000..7b1cca599e --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/or/descriptor.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-atomics.or +description: Testing descriptor property of Atomics.or +includes: [propertyHelper.js] +features: [Atomics] +---*/ +verifyProperty(Atomics, 'or', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/or/expected-return-value.js b/js/src/tests/test262/built-ins/Atomics/or/expected-return-value.js new file mode 100644 index 0000000000..ed4b4985f9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/or/expected-return-value.js @@ -0,0 +1,49 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.or +description: > + Atomics.and returns the value that existed at the + index prior to the operation. +info: | + Atomics.or( typedArray, index, value ) + + 1. Return ? AtomicReadModifyWrite(typedArray, index, value, or). + + AtomicReadModifyWrite( typedArray, index, value, op ) + + ... + 9. Return GetModifySetValueInBuffer(buffer, indexedPosition, + elementType, v, op). + + + GetModifySetValueInBuffer( arrayBuffer, + byteIndex, type, value, op [ , isLittleEndian ] ) + + ... + 16. Return RawBytesToNumber(type, rawBytesRead, isLittleEndian). + +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); +const a = 0b00000001000000001000000010000001; +const b = 0b00000001111111111000000011111111; +const c = 0b00000001111111111000000011111111; + +i32a[0] = a; + +assert.sameValue( + Atomics.or(i32a, 0, b), + a, + 'Atomics.or(i32a, 0, b) returns the value of `a` (0b00000001000000001000000010000001)' +); + +assert.sameValue(i32a[0], c, 'The value of i32a[0] equals the value of `c` (0b00000001111111111000000011111111)'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/or/good-views.js b/js/src/tests/test262/built-ins/Atomics/or/good-views.js new file mode 100644 index 0000000000..c8c64c4657 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/or/good-views.js @@ -0,0 +1,84 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.or +description: Test Atomics.or on arrays that allow atomic operations +includes: [testAtomics.js, testTypedArray.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +var sab = new SharedArrayBuffer(1024); +var ab = new ArrayBuffer(16); +var views = intArrayConstructors.slice(); + +testWithTypedArrayConstructors(function(TA) { + // Make it interesting - use non-zero byteOffsets and non-zero indexes. + + var view = new TA(sab, 32, 20); + var control = new TA(ab, 0, 2); + + view[8] = 0x33333333; + control[0] = 0x33333333; + assert.sameValue(Atomics.or(view, 8, 0x55555555), control[0], + 'Atomics.or(view, 8, 0x55555555) returns the value of `control[0]` (0x33333333)'); + + control[0] = 0x77777777; + assert.sameValue( + view[8], + control[0], + 'The value of view[8] equals the value of `control[0]` (0x77777777)' + ); + assert.sameValue(Atomics.or(view, 8, 0xF0F0F0F0), control[0], + 'Atomics.or(view, 8, 0xF0F0F0F0) returns the value of `control[0]` (0x77777777)'); + + control[0] = 0xF7F7F7F7; + assert.sameValue( + view[8], + control[0], + 'The value of view[8] equals the value of `control[0]` (0xF7F7F7F7)' + ); + + view[3] = -5; + control[0] = -5; + assert.sameValue(Atomics.or(view, 3, 0), control[0], + 'Atomics.or(view, 3, 0) returns the value of `control[0]` (-5)'); + assert.sameValue( + view[3], + control[0], + 'The value of view[3] equals the value of `control[0]` (-5)' + ); + + control[0] = 12345; + view[3] = 12345; + assert.sameValue(Atomics.or(view, 3, 0), control[0], + 'Atomics.or(view, 3, 0) returns the value of `control[0]` (12345)'); + assert.sameValue( + view[3], + control[0], + 'The value of view[3] equals the value of `control[0]` (12345)' + ); + + control[0] = 123456789; + view[3] = 123456789; + assert.sameValue(Atomics.or(view, 3, 0), control[0], + 'Atomics.or(view, 3, 0) returns the value of `control[0]` (123456789)'); + assert.sameValue( + view[3], + control[0], + 'The value of view[3] equals the value of `control[0]` (123456789)' + ); + + // In-bounds boundary cases for indexing + testWithAtomicsInBoundsIndices(function(IdxGen) { + let Idx = IdxGen(view); + view.fill(0); + // Atomics.store() computes an index from Idx in the same way as other + // Atomics operations, not quite like view[Idx]. + Atomics.store(view, Idx, 37); + assert.sameValue(Atomics.or(view, Idx, 0), 37, 'Atomics.or(view, Idx, 0) returns 37'); + }); +}, views); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/or/length.js b/js/src/tests/test262/built-ins/Atomics/or/length.js new file mode 100644 index 0000000000..8a9d7c30af --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/or/length.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.or +description: > + Atomics.or.length is 3. +info: | + Atomics.or ( ia, index, val ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this + value is equal to the largest number of named arguments shown in the + subclause headings for the function description, including optional + parameters. However, rest parameters shown using the form “...name” + are not included in the default argument count. + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.or, 'length', { + value: 3, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/or/name.js b/js/src/tests/test262/built-ins/Atomics/or/name.js new file mode 100644 index 0000000000..ff455ddb8b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/or/name.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.or +description: > + Atomics.or.name is "or". +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.or, 'name', { + value: 'or', + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/or/non-shared-bufferdata.js b/js/src/tests/test262/built-ins/Atomics/or/non-shared-bufferdata.js new file mode 100644 index 0000000000..8afe735477 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/or/non-shared-bufferdata.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.or +description: > + Atomics.or will operate on TA when TA.buffer is not a SharedArrayBuffer +includes: [testTypedArray.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ +testWithAtomicsFriendlyTypedArrayConstructors(TA => { + const view = new TA( + new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4) + ); + + assert.sameValue(Atomics.or(view, 0, 1), 0, 'Atomics.or(view, 0, 1) returns 0'); + assert.sameValue(Atomics.load(view, 0), 1, 'Atomics.load(view, 0) returns 1'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/or/non-shared-int-views-throws.js b/js/src/tests/test262/built-ins/Atomics/or/non-shared-int-views-throws.js new file mode 100644 index 0000000000..90987ae1ce --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/or/non-shared-int-views-throws.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.and +description: > + Atomics.and throws when operating on non-sharable integer TypedArrays +includes: [testTypedArray.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ +testWithNonAtomicsFriendlyTypedArrayConstructors(TA => { + const buffer = new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4); + const view = new TA(buffer); + + assert.throws(TypeError, function() { + Atomics.and(view, 0, 1); + }, `Atomics.and(new ${TA.name}(buffer), 0, 1) throws TypeError`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/or/non-views.js b/js/src/tests/test262/built-ins/Atomics/or/non-views.js new file mode 100644 index 0000000000..86e860786c --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/or/non-views.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.or +description: > + Test Atomics.or on view values other than TypedArrays +includes: [testAtomics.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +testWithAtomicsNonViewValues(function(view) { + assert.throws(TypeError, function() { + Atomics.or(view, 0, 0); + }, '`Atomics.or(view, 0, 0)` throws TypeError'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/or/not-a-constructor.js b/js/src/tests/test262/built-ins/Atomics/or/not-a-constructor.js new file mode 100644 index 0000000000..14b1aa8976 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/or/not-a-constructor.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Atomics.or does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, Atomics, arrow-function, TypedArray, SharedArrayBuffer] +---*/ + +assert.sameValue(isConstructor(Atomics.or), false, 'isConstructor(Atomics.or) must return false'); + +assert.throws(TypeError, () => { + new Atomics.or(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT))); +}, '`new Atomics.or(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT)))` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/or/shell.js b/js/src/tests/test262/built-ins/Atomics/or/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/or/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Atomics/or/validate-arraytype-before-index-coercion.js b/js/src/tests/test262/built-ins/Atomics/or/validate-arraytype-before-index-coercion.js new file mode 100644 index 0000000000..ac624adcb3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/or/validate-arraytype-before-index-coercion.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.or +description: > + TypedArray type is validated before `index` argument is coerced. +info: | + 24.4.8 Atomics.or ( typedArray, index, value ) + 1. Return ? AtomicReadModifyWrite(typedArray, index, value, or). + + 24.4.1.11 AtomicReadModifyWrite ( typedArray, index, value, op ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var index = { + valueOf() { + throw new Test262Error("index coerced"); + } +}; + +var badArrayTypes = [ + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.or(typedArray, index, 0); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/or/validate-arraytype-before-value-coercion.js b/js/src/tests/test262/built-ins/Atomics/or/validate-arraytype-before-value-coercion.js new file mode 100644 index 0000000000..22b06bbdc8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/or/validate-arraytype-before-value-coercion.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.or +description: > + TypedArray type is validated before `value` argument is coerced. +info: | + 24.4.8 Atomics.or ( typedArray, index, value ) + 1. Return ? AtomicReadModifyWrite(typedArray, index, value, or). + + 24.4.1.11 AtomicReadModifyWrite ( typedArray, index, value, op ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var value = { + valueOf() { + throw new Test262Error("value coerced"); + } +}; + +var badArrayTypes = [ + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.or(typedArray, 0, value); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/prop-desc.js b/js/src/tests/test262/built-ins/Atomics/prop-desc.js new file mode 100644 index 0000000000..ffcbac8fa0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/prop-desc.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2016 The V8 Project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics-object +description: > + Property descriptor of Atomics +info: | + The Atomics Object + + ... + The Atomics object does not have a [[Construct]] internal method; + it is not possible to use the Atomics object as a constructor with the new operator. + + The Atomics object does not have a [[Call]] internal method; + it is not possible to invoke the Atomics object as a function. + + 17 ECMAScript Standard Built-in Objects: + + Every other data property described in clauses 18 through 26 and in Annex B.2 + has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +assert.sameValue(typeof Atomics, "object", 'The value of `typeof Atomics` is "object"'); + +assert.throws(TypeError, function() { + Atomics(); +}, '`Atomics()` throws TypeError'); + +assert.throws(TypeError, function() { + new Atomics(); +}, '`new Atomics()` throws TypeError'); + +verifyProperty(this, "Atomics", { + enumerable: false, + writable: true, + configurable: true +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/proto.js b/js/src/tests/test262/built-ins/Atomics/proto.js new file mode 100644 index 0000000000..859c451b8b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/proto.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2016 The V8 Project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics-object +description: > + The prototype of Atomics is Object.prototype +info: | + The Atomics Object + + The value of the [[Prototype]] internal slot of the Atomics object is the + intrinsic object %ObjectPrototype%. +features: [Atomics] +---*/ + +assert.sameValue( + Object.getPrototypeOf(Atomics), + Object.prototype, + 'Object.getPrototypeOf(Atomics) returns the value of `Object.prototype`' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/shell.js b/js/src/tests/test262/built-ins/Atomics/shell.js new file mode 100644 index 0000000000..23c4c94a0b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/shell.js @@ -0,0 +1,249 @@ +// GENERATED, DO NOT EDIT +// file: testAtomics.js +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of SharedArrayBuffer objects. +defines: + - testWithAtomicsOutOfBoundsIndices + - testWithAtomicsInBoundsIndices + - testWithAtomicsNonViewValues +---*/ + + +/** + * Calls the provided function for a each bad index that should throw a + * RangeError when passed to an Atomics method on a SAB-backed view where + * index 125 is out of range. + * + * @param f - the function to call for each bad index. + */ +function testWithAtomicsOutOfBoundsIndices(f) { + var bad_indices = [ + function(view) { return -1; }, + function(view) { return view.length; }, + function(view) { return view.length * 2; }, + function(view) { return Number.POSITIVE_INFINITY; }, + function(view) { return Number.NEGATIVE_INFINITY; }, + function(view) { return { valueOf: function() { return 125; } }; }, + function(view) { return { toString: function() { return '125'; }, valueOf: false }; }, // non-callable valueOf triggers invocation of toString + ]; + + for (var i = 0; i < bad_indices.length; ++i) { + var IdxGen = bad_indices[i]; + try { + f(IdxGen); + } catch (e) { + e.message += ' (Testing with index gen ' + IdxGen + '.)'; + throw e; + } + } +} + +/** + * Calls the provided function for each good index that should not throw when + * passed to an Atomics method on a SAB-backed view. + * + * The view must have length greater than zero. + * + * @param f - the function to call for each good index. + */ +function testWithAtomicsInBoundsIndices(f) { + // Most of these are eventually coerced to +0 by ToIndex. + var good_indices = [ + function(view) { return 0/-1; }, + function(view) { return '-0'; }, + function(view) { return undefined; }, + function(view) { return NaN; }, + function(view) { return 0.5; }, + function(view) { return '0.5'; }, + function(view) { return -0.9; }, + function(view) { return { password: 'qumquat' }; }, + function(view) { return view.length - 1; }, + function(view) { return { valueOf: function() { return 0; } }; }, + function(view) { return { toString: function() { return '0'; }, valueOf: false }; }, // non-callable valueOf triggers invocation of toString + ]; + + for (var i = 0; i < good_indices.length; ++i) { + var IdxGen = good_indices[i]; + try { + f(IdxGen); + } catch (e) { + e.message += ' (Testing with index gen ' + IdxGen + '.)'; + throw e; + } + } +} + +/** + * Calls the provided function for each value that should throw a TypeError + * when passed to an Atomics method as a view. + * + * @param f - the function to call for each non-view value. + */ + +function testWithAtomicsNonViewValues(f) { + var values = [ + null, + undefined, + true, + false, + new Boolean(true), + 10, + 3.14, + new Number(4), + 'Hi there', + new Date, + /a*utomaton/g, + { password: 'qumquat' }, + new DataView(new ArrayBuffer(10)), + new ArrayBuffer(128), + new SharedArrayBuffer(128), + new Error('Ouch'), + [1,1,2,3,5,8], + function(x) { return -x; }, + Symbol('halleluja'), + // TODO: Proxy? + Object, + Int32Array, + Date, + Math, + Atomics + ]; + + for (var i = 0; i < values.length; ++i) { + var nonView = values[i]; + try { + f(nonView); + } catch (e) { + e.message += ' (Testing with non-view value ' + nonView + '.)'; + throw e; + } + } +} + + +// file: testTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of TypedArray objects. +defines: + - typedArrayConstructors + - floatArrayConstructors + - intArrayConstructors + - TypedArray + - testWithTypedArrayConstructors + - testWithAtomicsFriendlyTypedArrayConstructors + - testWithNonAtomicsFriendlyTypedArrayConstructors + - testTypedArrayConversions +---*/ + +/** + * Array containing every typed array constructor. + */ +var typedArrayConstructors = [ + Float64Array, + Float32Array, + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + Uint8ClampedArray +]; + +var floatArrayConstructors = typedArrayConstructors.slice(0, 2); +var intArrayConstructors = typedArrayConstructors.slice(2, 7); + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Callback for testing a typed array constructor. + * + * @callback typedArrayConstructorCallback + * @param {Function} Constructor the constructor object to test with. + */ + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithTypedArrayConstructors(f, selected) { + var constructors = selected || typedArrayConstructors; + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} + +/** + * Calls the provided function for every non-"Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithNonAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Float64Array, + Float32Array, + Uint8ClampedArray + ]); +} + +/** + * Calls the provided function for every "Atomics Friendly" typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithAtomicsFriendlyTypedArrayConstructors(f) { + testWithTypedArrayConstructors(f, [ + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + ]); +} + +/** + * Helper for conversion operations on TypedArrays, the expected values + * properties are indexed in order to match the respective value for each + * TypedArray constructor + * @param {Function} fn - the function to call for each constructor and value. + * will be called with the constructor, value, expected + * value, and a initial value that can be used to avoid + * a false positive with an equivalent expected value. + */ +function testTypedArrayConversions(byteConversionValues, fn) { + var values = byteConversionValues.values; + var expected = byteConversionValues.expected; + + testWithTypedArrayConstructors(function(TA) { + var name = TA.name.slice(0, -5); + + return values.forEach(function(value, index) { + var exp = expected[name][index]; + var initial = 0; + if (exp === 0) { + initial = 1; + } + fn(TA, value, exp, initial); + }); + }); +} diff --git a/js/src/tests/test262/built-ins/Atomics/store/bad-range.js b/js/src/tests/test262/built-ins/Atomics/store/bad-range.js new file mode 100644 index 0000000000..8a802eeb0a --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/store/bad-range.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.store +description: > + Test range checking of Atomics.store on arrays that allow atomic operations +includes: [testAtomics.js, testTypedArray.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +const buffer = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2); +const views = intArrayConstructors.slice(); + +testWithTypedArrayConstructors(function(TA) { + const view = new TA(buffer); + testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.store(view, IdxGen(view), 10); + }, '`Atomics.store(view, IdxGen(view), 10)` throws RangeError'); + }); +}, views); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/store/bigint/bad-range.js b/js/src/tests/test262/built-ins/Atomics/store/bigint/bad-range.js new file mode 100644 index 0000000000..979c5ca4f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/store/bigint/bad-range.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.store +description: > + Test range checking of Atomics.store on arrays that allow atomic operations +includes: [testAtomics.js, testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ +const buffer = new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 2); + +testWithBigIntTypedArrayConstructors(TA => { + const view = new TA(buffer); + + testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.store(view, IdxGen(view), 10n); + }, '`Atomics.store(view, IdxGen(view), 10n)` throws RangeError'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/store/bigint/browser.js b/js/src/tests/test262/built-ins/Atomics/store/bigint/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/store/bigint/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/store/bigint/good-views.js b/js/src/tests/test262/built-ins/Atomics/store/bigint/good-views.js new file mode 100644 index 0000000000..461376c452 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/store/bigint/good-views.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.store +description: Test Atomics.store on arrays that allow atomic operations. +includes: [testAtomics.js, testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ +// Make it interesting - use non-zero byteOffsets and non-zero indexes. +// In-bounds boundary cases for indexing +const sab = new SharedArrayBuffer(1024); +const ab = new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 2); + +testWithBigIntTypedArrayConstructors(function(TA) { + const view = new TA(sab, 32, 20); + const control = new TA(ab, 0, 2); + + const values = [ + 10n, + -5n, + 12345n, + 123456789n, + BigInt('33'), + { + valueOf: function() { return 33n; } + } + ]; + + for (let i = 0; i < values.length; i++) { + let val = values[i]; + assert.sameValue( + Atomics.store(view, 3, val), + BigInt(val), + 'Atomics.store(view, 3, val) returns BigInt(val)' + ); + + control[0] = val; + + assert.sameValue( + view[3], + control[0], + 'The value of view[3] equals the value of `control[0]` (val)' + ); + } + + testWithAtomicsInBoundsIndices(function(IdxGen) { + let Idx = IdxGen(view); + view.fill(0n); + Atomics.store(view, Idx, 37n); + assert.sameValue(Atomics.load(view, Idx), 37n, 'Atomics.load(view, Idx) returns 37n'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/store/bigint/non-shared-bufferdata.js b/js/src/tests/test262/built-ins/Atomics/store/bigint/non-shared-bufferdata.js new file mode 100644 index 0000000000..12f94006a3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/store/bigint/non-shared-bufferdata.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.store +description: > + Atomics.store will operate on TA when TA.buffer is not a SharedArrayBuffer +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ +testWithBigIntTypedArrayConstructors(TA => { + const buffer = new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4); + const view = new TA(buffer); + assert.sameValue(Atomics.store(view, 0, 1n), 1n, 'Atomics.store(view, 0, 1n) returns 1n'); + assert.sameValue(Atomics.load(view, 0), 1n, 'Atomics.load(view, 0) returns 1n'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/store/bigint/shell.js b/js/src/tests/test262/built-ins/Atomics/store/bigint/shell.js new file mode 100644 index 0000000000..90ee9c114d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/store/bigint/shell.js @@ -0,0 +1,42 @@ +// GENERATED, DO NOT EDIT +// file: testBigIntTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of BigInt TypedArray objects. +defines: + - TypedArray + - testWithBigIntTypedArrayConstructors +---*/ + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithBigIntTypedArrayConstructors(f, selected) { + /** + * Array containing every BigInt typed array constructor. + */ + var constructors = selected || [ + BigInt64Array, + BigUint64Array + ]; + + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} diff --git a/js/src/tests/test262/built-ins/Atomics/store/browser.js b/js/src/tests/test262/built-ins/Atomics/store/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/store/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/store/descriptor.js b/js/src/tests/test262/built-ins/Atomics/store/descriptor.js new file mode 100644 index 0000000000..ea8a0e9951 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/store/descriptor.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-atomics.store +description: Testing descriptor property of Atomics.store +includes: [propertyHelper.js] +features: [Atomics] +---*/ +verifyProperty(Atomics, 'store', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/store/expected-return-value-negative-zero.js b/js/src/tests/test262/built-ins/Atomics/store/expected-return-value-negative-zero.js new file mode 100644 index 0000000000..d49fde2124 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/store/expected-return-value-negative-zero.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2020 Jordan Harband. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.store +description: > + Atomics.store calls ToInteger, which normalizes -0 to +0 +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +assert( + Object.is( + Atomics.store(i32a, 0, -0), + +0 + ), + 'Atomics.store(i32a, 0, -0) normalizes -0 to +0' +); +assert.sameValue( + i32a[0], + +0, + 'The value of i32a[0] is normalized to +0' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/store/expected-return-value.js b/js/src/tests/test262/built-ins/Atomics/store/expected-return-value.js new file mode 100644 index 0000000000..2e4b30fbbb --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/store/expected-return-value.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.store +description: > + Atomics.store returns the newly stored value +info: | + Atomics.store( typedArray, index, value ) + + ... + 3. Let v be ? ToInteger(value). + ... + 9. Perform SetValueInBuffer(buffer, indexedPosition, + elementType, v, true, "SeqCst"). + 10. Return v. + +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); +const update = 0b00000001000000001000000010000001; + +assert.sameValue( + Atomics.store(i32a, 0, update), + update, + 'Atomics.store(i32a, 0, update) returns the value of `update` (0b00000001000000001000000010000001)' +); +assert.sameValue( + i32a[0], + update, + 'The value of i32a[0] equals the value of `update` (0b00000001000000001000000010000001)' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/store/good-views.js b/js/src/tests/test262/built-ins/Atomics/store/good-views.js new file mode 100644 index 0000000000..0248022db9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/store/good-views.js @@ -0,0 +1,71 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.store +description: Test Atomics.store on arrays that allow atomic operations. +includes: [testAtomics.js, testTypedArray.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +const sab = new SharedArrayBuffer(1024); +const ab = new ArrayBuffer(16); +const views = intArrayConstructors.slice(); + +testWithTypedArrayConstructors(function(TA) { + // Make it interesting - use non-zero byteOffsets and non-zero indexes. + + const view = new TA(sab, 32, 20); + const control = new TA(ab, 0, 2); + + const values = [ + 10, + -5, + 12345, + 123456789, + Math.PI, + "33", + { + valueOf: function() { return 33; } + }, + undefined + ]; + + for (let i = 0; i < values.length; i++) { + let val = values[i]; + assert.sameValue(Atomics.store(view, 3, val), ToInteger(val), + 'Atomics.store(view, 3, val) returns ToInteger(val)'); + + control[0] = val; + assert.sameValue( + view[3], + control[0], + 'The value of view[3] equals the value of `control[0]` (val)' + ); + } + + // In-bounds boundary cases for indexing + testWithAtomicsInBoundsIndices(function(IdxGen) { + let Idx = IdxGen(view); + view.fill(0); + Atomics.store(view, Idx, 37); + assert.sameValue(Atomics.load(view, Idx), 37, 'Atomics.load(view, Idx) returns 37'); + }); +}, views); + +function ToInteger(v) { + v = +v; + if (isNaN(v)) { + return 0; + } + if (v == 0 || !isFinite(v)) { + return v; + } + if (v < 0) { + return -Math.floor(Math.abs(v)); + } + return Math.floor(v); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/store/length.js b/js/src/tests/test262/built-ins/Atomics/store/length.js new file mode 100644 index 0000000000..eae6e352f9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/store/length.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.store +description: > + Atomics.store.length is 3. +info: | + Atomics.store ( ia, index, val ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this + value is equal to the largest number of named arguments shown in the + subclause headings for the function description, including optional + parameters. However, rest parameters shown using the form “...name” + are not included in the default argument count. + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.store, 'length', { + value: 3, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/store/name.js b/js/src/tests/test262/built-ins/Atomics/store/name.js new file mode 100644 index 0000000000..580ec46071 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/store/name.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.store +description: > + Atomics.store.name is "store". +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.store, 'name', { + value: 'store', + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/store/non-shared-bufferdata.js b/js/src/tests/test262/built-ins/Atomics/store/non-shared-bufferdata.js new file mode 100644 index 0000000000..78f1dd9ce0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/store/non-shared-bufferdata.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.store +description: > + Atomics.store will operate on TA when TA.buffer is not a SharedArrayBuffer +includes: [testTypedArray.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ +testWithAtomicsFriendlyTypedArrayConstructors(TA => { + const view = new TA( + new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4) + ); + + assert.sameValue(Atomics.store(view, 0, 1), 1, 'Atomics.store(view, 0, 1) returns 1'); + assert.sameValue(Atomics.load(view, 0), 1, 'Atomics.load(view, 0) returns 1'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/store/non-shared-int-views-throws.js b/js/src/tests/test262/built-ins/Atomics/store/non-shared-int-views-throws.js new file mode 100644 index 0000000000..3924de90d3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/store/non-shared-int-views-throws.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.store +description: > + Atomics.store throws when operating on non-sharable integer TypedArrays +includes: [testTypedArray.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ +testWithNonAtomicsFriendlyTypedArrayConstructors(TA => { + const buffer = new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4); + const view = new TA(buffer); + + assert.throws(TypeError, function() { + Atomics.store(view, 0, 1); + }, `Atomics.store(new ${TA.name}(buffer), 0, 1) throws TypeError`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/store/non-views.js b/js/src/tests/test262/built-ins/Atomics/store/non-views.js new file mode 100644 index 0000000000..b857994f6d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/store/non-views.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.store +description: > + Test Atomics.store on view values other than TypedArrays +includes: [testAtomics.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +testWithAtomicsNonViewValues(function(view) { + assert.throws(TypeError, function() { + Atomics.store(view, 0, 0); + }, '`Atomics.store(view, 0, 0)` throws TypeError'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/store/not-a-constructor.js b/js/src/tests/test262/built-ins/Atomics/store/not-a-constructor.js new file mode 100644 index 0000000000..2a68ee7902 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/store/not-a-constructor.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Atomics.store does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, Atomics, arrow-function, TypedArray, SharedArrayBuffer] +---*/ + +assert.sameValue(isConstructor(Atomics.store), false, 'isConstructor(Atomics.store) must return false'); + +assert.throws(TypeError, () => { + new Atomics.store(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT))); +}, '`new Atomics.store(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT)))` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/store/shell.js b/js/src/tests/test262/built-ins/Atomics/store/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/store/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Atomics/store/validate-arraytype-before-index-coercion.js b/js/src/tests/test262/built-ins/Atomics/store/validate-arraytype-before-index-coercion.js new file mode 100644 index 0000000000..8cf96c50b4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/store/validate-arraytype-before-index-coercion.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.store +description: > + TypedArray type is validated before `index` argument is coerced. +info: | + 24.4.9 Atomics.store ( typedArray, index, value ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var index = { + valueOf() { + throw new Test262Error("index coerced"); + } +}; + +var badArrayTypes = [ + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.store(typedArray, index, 0); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/store/validate-arraytype-before-value-coercion.js b/js/src/tests/test262/built-ins/Atomics/store/validate-arraytype-before-value-coercion.js new file mode 100644 index 0000000000..44b55a6414 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/store/validate-arraytype-before-value-coercion.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.store +description: > + TypedArray type is validated before `value` argument is coerced. +info: | + 24.4.9 Atomics.store ( typedArray, index, value ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var value = { + valueOf() { + throw new Test262Error("value coerced"); + } +}; + +var badArrayTypes = [ + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.store(typedArray, 0, value); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/sub/bad-range.js b/js/src/tests/test262/built-ins/Atomics/sub/bad-range.js new file mode 100644 index 0000000000..f167d0e997 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/sub/bad-range.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.sub +description: > + Test range checking of Atomics.sub on arrays that allow atomic operations +includes: [testAtomics.js, testTypedArray.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +var buffer = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2); +var views = intArrayConstructors.slice(); + +testWithTypedArrayConstructors(function(TA) { + let view = new TA(buffer); + testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.sub(view, IdxGen(view), 10); + }, '`Atomics.sub(view, IdxGen(view), 10)` throws RangeError'); + }); +}, views); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/sub/bigint/bad-range.js b/js/src/tests/test262/built-ins/Atomics/sub/bigint/bad-range.js new file mode 100644 index 0000000000..8a106e6d24 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/sub/bigint/bad-range.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.sub +description: > + Test range checking of Atomics.sub on arrays that allow atomic operations +includes: [testAtomics.js, testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ +const buffer = new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 2); + +testWithBigIntTypedArrayConstructors(function(TA) { + const view = new TA(buffer); + + testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.sub(view, IdxGen(view), 10n); + }, '`Atomics.sub(view, IdxGen(view), 10n)` throws RangeError'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/sub/bigint/browser.js b/js/src/tests/test262/built-ins/Atomics/sub/bigint/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/sub/bigint/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/sub/bigint/good-views.js b/js/src/tests/test262/built-ins/Atomics/sub/bigint/good-views.js new file mode 100644 index 0000000000..7ae0a82fbb --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/sub/bigint/good-views.js @@ -0,0 +1,60 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.sub +description: Test Atomics.sub on arrays that allow atomic operations +includes: [testAtomics.js, testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ +// Make it interesting - use non-zero byteOffsets and non-zero indexes. +// In-bounds boundary cases for indexing +// Atomics.store() computes an index from Idx in the same way as other +// Atomics operations, not quite like view[Idx]. +const sab = new SharedArrayBuffer(1024); +const ab = new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 2); + +testWithBigIntTypedArrayConstructors(function(TA) { + const view = new TA(sab, 32, 20); + const control = new TA(ab, 0, 2); + view[8] = 100n; + assert.sameValue(Atomics.sub(view, 8, 10n), 100n, 'Atomics.sub(view, 8, 10n) returns 100n'); + assert.sameValue(view[8], 90n, 'The value of view[8] is 90n'); + assert.sameValue(Atomics.sub(view, 8, -5n), 90n, 'Atomics.sub(view, 8, -5n) returns 90n'); + assert.sameValue(view[8], 95n, 'The value of view[8] is 95'); + view[3] = -5n; + control[0] = -5n; + + assert.sameValue( + Atomics.sub(view, 3, 0n), + control[0], + 'Atomics.sub(view, 3, 0n) returns the value of `control[0]` (-5n)' + ); + + control[0] = 12345n; + view[3] = 12345n; + + assert.sameValue( + Atomics.sub(view, 3, 0n), + control[0], + 'Atomics.sub(view, 3, 0n) returns the value of `control[0]` (12345n)' + ); + + control[0] = 123456789n; + view[3] = 123456789n; + + assert.sameValue( + Atomics.sub(view, 3, 0n), + control[0], + 'Atomics.sub(view, 3, 0n) returns the value of `control[0]` (123456789n)' + ); + + testWithAtomicsInBoundsIndices(function(IdxGen) { + let Idx = IdxGen(view); + view.fill(0n); + Atomics.store(view, Idx, 37n); + assert.sameValue(Atomics.sub(view, Idx, 0n), 37n, 'Atomics.sub(view, Idx, 0n) returns 37n'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/sub/bigint/non-shared-bufferdata.js b/js/src/tests/test262/built-ins/Atomics/sub/bigint/non-shared-bufferdata.js new file mode 100644 index 0000000000..058c160005 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/sub/bigint/non-shared-bufferdata.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.sub +description: > + Atomics.sub will operate on TA when TA.buffer is not a SharedArrayBuffer +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ +testWithBigIntTypedArrayConstructors(TA => { + const buffer = new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4); + const view = new TA(buffer); + assert.sameValue(Atomics.store(view, 0, 1n), 1n, 'Atomics.store(view, 0, 1n) returns 1n'); + assert.sameValue(Atomics.sub(view, 0, 1n), 1n, 'Atomics.sub(view, 0, 1n) returns 1n'); + assert.sameValue(Atomics.load(view, 0), 0n, 'Atomics.load(view, 0) returns 0n'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/sub/bigint/shell.js b/js/src/tests/test262/built-ins/Atomics/sub/bigint/shell.js new file mode 100644 index 0000000000..90ee9c114d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/sub/bigint/shell.js @@ -0,0 +1,42 @@ +// GENERATED, DO NOT EDIT +// file: testBigIntTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of BigInt TypedArray objects. +defines: + - TypedArray + - testWithBigIntTypedArrayConstructors +---*/ + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithBigIntTypedArrayConstructors(f, selected) { + /** + * Array containing every BigInt typed array constructor. + */ + var constructors = selected || [ + BigInt64Array, + BigUint64Array + ]; + + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} diff --git a/js/src/tests/test262/built-ins/Atomics/sub/browser.js b/js/src/tests/test262/built-ins/Atomics/sub/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/sub/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/sub/descriptor.js b/js/src/tests/test262/built-ins/Atomics/sub/descriptor.js new file mode 100644 index 0000000000..72e0241b88 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/sub/descriptor.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-atomics.sub +description: Testing descriptor property of Atomics.sub +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics, 'sub', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/sub/expected-return-value.js b/js/src/tests/test262/built-ins/Atomics/sub/expected-return-value.js new file mode 100644 index 0000000000..d9be3e9144 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/sub/expected-return-value.js @@ -0,0 +1,45 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.sub +description: > + Atomics.and returns the value that existed at the + index prior to the operation. +info: | + Atomics.sub( typedArray, index, value ) + + 1. Return ? AtomicReadModifyWrite(typedArray, index, value, subtract). + + AtomicReadModifyWrite( typedArray, index, value, op ) + + ... + 9. Return GetModifySetValueInBuffer(buffer, indexedPosition, + elementType, v, op). + + + GetModifySetValueInBuffer( arrayBuffer, + byteIndex, type, value, op [ , isLittleEndian ] ) + + ... + 16. Return RawBytesToNumber(type, rawBytesRead, isLittleEndian). + +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); +const update = 0b00000001000000001000000010000001; + +i32a[0] = update; + +assert.sameValue( + Atomics.sub(i32a, 0, update), + update, + 'Atomics.sub(i32a, 0, update) returns the value of `update` (0b00000001000000001000000010000001)' +); +assert.sameValue(i32a[0], 0, 'The value of i32a[0] is 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/sub/good-views.js b/js/src/tests/test262/built-ins/Atomics/sub/good-views.js new file mode 100644 index 0000000000..c99583692e --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/sub/good-views.js @@ -0,0 +1,57 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.sub +description: Test Atomics.sub on arrays that allow atomic operations +includes: [testAtomics.js, testTypedArray.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +var sab = new SharedArrayBuffer(1024); +var ab = new ArrayBuffer(16); +var views = intArrayConstructors.slice(); + +testWithTypedArrayConstructors(function(TA) { + // Make it interesting - use non-zero byteOffsets and non-zero indexes. + + var view = new TA(sab, 32, 20); + var control = new TA(ab, 0, 2); + + view[8] = 100; + assert.sameValue(Atomics.sub(view, 8, 10), 100, + 'Atomics.sub(view, 8, 10) returns 100'); + assert.sameValue(view[8], 90, 'The value of view[8] is 90'); + + assert.sameValue(Atomics.sub(view, 8, -5), 90, + 'Atomics.sub(view, 8, -5) returns 90'); + assert.sameValue(view[8], 95, 'The value of view[8] is 95'); + + view[3] = -5; + control[0] = -5; + assert.sameValue(Atomics.sub(view, 3, 0), control[0], + 'Atomics.sub(view, 3, 0) returns the value of `control[0]` (-5)'); + + control[0] = 12345; + view[3] = 12345; + assert.sameValue(Atomics.sub(view, 3, 0), control[0], + 'Atomics.sub(view, 3, 0) returns the value of `control[0]` (12345)'); + + control[0] = 123456789; + view[3] = 123456789; + assert.sameValue(Atomics.sub(view, 3, 0), control[0], + 'Atomics.sub(view, 3, 0) returns the value of `control[0]` (123456789)'); + + // In-bounds boundary cases for indexing + testWithAtomicsInBoundsIndices(function(IdxGen) { + let Idx = IdxGen(view); + view.fill(0); + // Atomics.store() computes an index from Idx in the same way as other + // Atomics operations, not quite like view[Idx]. + Atomics.store(view, Idx, 37); + assert.sameValue(Atomics.sub(view, Idx, 0), 37, 'Atomics.sub(view, Idx, 0) returns 37'); + }); +}, views); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/sub/length.js b/js/src/tests/test262/built-ins/Atomics/sub/length.js new file mode 100644 index 0000000000..0747138634 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/sub/length.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.sub +description: > + Atomics.sub.length is 3. +info: | + Atomics.sub ( ia, index, val ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this + value is equal to the largest number of named arguments shown in the + subclause headings for the function description, including optional + parameters. However, rest parameters shown using the form “...name” + are not included in the default argument count. + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.sub, 'length', { + value: 3, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/sub/name.js b/js/src/tests/test262/built-ins/Atomics/sub/name.js new file mode 100644 index 0000000000..e8aa2d3d37 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/sub/name.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.sub +description: > + Atomics.sub.name is "sub". +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.sub, 'name', { + value: 'sub', + enumerable: false, + writable: false, + configurable: true, +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/sub/non-shared-bufferdata.js b/js/src/tests/test262/built-ins/Atomics/sub/non-shared-bufferdata.js new file mode 100644 index 0000000000..3f36ea5eea --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/sub/non-shared-bufferdata.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.sub +description: > + Atomics.sub will operate on TA when TA.buffer is not a SharedArrayBuffer +includes: [testTypedArray.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ +testWithAtomicsFriendlyTypedArrayConstructors(TA => { + const view = new TA( + new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4) + ); + + assert.sameValue(Atomics.store(view, 0, 1), 1, 'Atomics.store(view, 0, 1) returns 1'); + assert.sameValue(Atomics.sub(view, 0, 1), 1, 'Atomics.sub(view, 0, 1) returns 1'); + assert.sameValue(Atomics.load(view, 0), 0, 'Atomics.load(view, 0) returns 0'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/sub/non-shared-int-views-throws.js b/js/src/tests/test262/built-ins/Atomics/sub/non-shared-int-views-throws.js new file mode 100644 index 0000000000..c2413ed30b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/sub/non-shared-int-views-throws.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.sub +description: > + Atomics.sub throws when operating on non-sharable integer TypedArrays +includes: [testTypedArray.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ +testWithNonAtomicsFriendlyTypedArrayConstructors(TA => { + const buffer = new ArrayBuffer(16); + const view = new TA(buffer); + + assert.throws(TypeError, function() { + Atomics.sub(view, 0, 1); + }, `Atomics.sub(new ${TA.name}(buffer), 0, 1) throws TypeError`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/sub/non-views.js b/js/src/tests/test262/built-ins/Atomics/sub/non-views.js new file mode 100644 index 0000000000..0e86139b89 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/sub/non-views.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.sub +description: > + Test Atomics.sub on view values other than TypedArrays +includes: [testAtomics.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +testWithAtomicsNonViewValues(function(view) { + assert.throws(TypeError, function() { + Atomics.sub(view, 0, 0); + }, '`Atomics.sub(view, 0, 0)` throws TypeError'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/sub/not-a-constructor.js b/js/src/tests/test262/built-ins/Atomics/sub/not-a-constructor.js new file mode 100644 index 0000000000..a1b4d4c624 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/sub/not-a-constructor.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Atomics.sub does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, Atomics, arrow-function, TypedArray, SharedArrayBuffer] +---*/ + +assert.sameValue(isConstructor(Atomics.sub), false, 'isConstructor(Atomics.sub) must return false'); + +assert.throws(TypeError, () => { + new Atomics.sub(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT))); +}, '`new Atomics.sub(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT)))` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/sub/shell.js b/js/src/tests/test262/built-ins/Atomics/sub/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/sub/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Atomics/sub/validate-arraytype-before-index-coercion.js b/js/src/tests/test262/built-ins/Atomics/sub/validate-arraytype-before-index-coercion.js new file mode 100644 index 0000000000..513e2c65ef --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/sub/validate-arraytype-before-index-coercion.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.sub +description: > + TypedArray type is validated before `index` argument is coerced. +info: | + 24.4.10 Atomics.sub ( typedArray, index, value ) + 1. Return ? AtomicReadModifyWrite(typedArray, index, value, sub). + + 24.4.1.11 AtomicReadModifyWrite ( typedArray, index, value, op ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var index = { + valueOf() { + throw new Test262Error("index coerced"); + } +}; + +var badArrayTypes = [ + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.sub(typedArray, index, 0); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/sub/validate-arraytype-before-value-coercion.js b/js/src/tests/test262/built-ins/Atomics/sub/validate-arraytype-before-value-coercion.js new file mode 100644 index 0000000000..c44751fec3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/sub/validate-arraytype-before-value-coercion.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.sub +description: > + TypedArray type is validated before `value` argument is coerced. +info: | + 24.4.10 Atomics.sub ( typedArray, index, value ) + 1. Return ? AtomicReadModifyWrite(typedArray, index, value, sub). + + 24.4.1.11 AtomicReadModifyWrite ( typedArray, index, value, op ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var value = { + valueOf() { + throw new Test262Error("value coerced"); + } +}; + +var badArrayTypes = [ + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.sub(typedArray, 0, value); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bad-range.js b/js/src/tests/test262/built-ins/Atomics/wait/bad-range.js new file mode 100644 index 0000000000..777d623b65 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bad-range.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Test range checking of Atomics.wait on arrays that allow atomic operations +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + +includes: [testAtomics.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 8) +); + +testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.wait(i32a, IdxGen(i32a), 0, 0); + }, '`Atomics.wait(i32a, IdxGen(i32a), 0, 0)` throws RangeError'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/bad-range.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/bad-range.js new file mode 100644 index 0000000000..ad3310e9a0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/bad-range.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Test range checking of Atomics.wait on arrays that allow atomic operations +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + +includes: [testAtomics.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 8) +); + +testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.wait(i64a, IdxGen(i64a), 0n, 0); + }, '`Atomics.wait(i64a, IdxGen(i64a), 0n, 0)` throws RangeError'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/browser.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/cannot-suspend-throws.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/cannot-suspend-throws.js new file mode 100644 index 0000000000..5b54c68914 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/cannot-suspend-throws.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(xulRuntime.shell||!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- shell can block main thread, Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.wait +description: > + Atomics.wait throws if agent cannot be suspended, CanBlock is false +info: | + Assuming [[CanBlock]] is false for the main host. + + Atomics.wait( typedArray, index, value, timeout ) + + ... (after args validation) + 6. Let B be AgentCanSuspend(). + 7. If B is false, throw a TypeError exception. + ... +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +flags: [CanBlockIsFalse] +---*/ + +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +assert.throws(TypeError, function() { + Atomics.wait(i64a, 0, 0n, 0); +}, '`Atomics.wait(i64a, 0, 0n, 0)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/false-for-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/false-for-timeout-agent.js new file mode 100644 index 0000000000..1b401417e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/false-for-timeout-agent.js @@ -0,0 +1,78 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + False timeout arg should result in an +0 timeout +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 4. Let q be ? ToNumber(timeout). + + Boolean -> If argument is true, return 1. If argument is false, return +0. + +includes: [atomicsHelper.js] +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +---*/ + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +const RUNNING = 1; + +$262.agent.start(` + const valueOf = { + valueOf: function() { + return false; + } + }; + + const toPrimitive = { + [Symbol.toPrimitive]: function() { + return false; + } + }; + + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const status1 = Atomics.wait(i64a, 0, 0n, false); + const status2 = Atomics.wait(i64a, 0, 0n, valueOf); + const status3 = Atomics.wait(i64a, 0, 0n, toPrimitive); + + $262.agent.report(status1); + $262.agent.report(status2); + $262.agent.report(status3); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i64a); +$262.agent.waitUntil(i64a, RUNNING, 1n); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); + +assert.sameValue(Atomics.notify(i64a, 0), 0, 'Atomics.notify(i64a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/false-for-timeout.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/false-for-timeout.js new file mode 100644 index 0000000000..b58907c223 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/false-for-timeout.js @@ -0,0 +1,52 @@ +// |reftest| skip-if(!xulRuntime.shell||!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- browser cannot block main thread, Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + False timeout arg should result in an +0 timeout +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 4. Let q be ? ToNumber(timeout). + + Boolean -> If argument is true, return 1. If argument is false, return +0. + +features: [Atomics, BigInt, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray] +flags: [CanBlockIsTrue] +---*/ + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +const valueOf = { + valueOf: function() { + return false; + } +}; + +const toPrimitive = { + [Symbol.toPrimitive]: function() { + return false; + } +}; + +assert.sameValue( + Atomics.wait(i64a, 0, 0n, false), + "timed-out", + 'Atomics.wait(i64a, 0, 0n, false) returns "timed-out"' +); +assert.sameValue( + Atomics.wait(i64a, 0, 0n, valueOf), + "timed-out", + 'Atomics.wait(i64a, 0, 0n, valueOf) returns "timed-out"' +); +assert.sameValue( + Atomics.wait(i64a, 0, 0n, toPrimitive), + "timed-out", + 'Atomics.wait(i64a, 0, 0n, toPrimitive) returns "timed-out"' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/nan-for-timeout.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/nan-for-timeout.js new file mode 100644 index 0000000000..00ae824330 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/nan-for-timeout.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + NaN timeout arg should result in an infinite timeout +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 4.Let q be ? ToNumber(timeout). + ... + Undefined Return NaN. + 5.If q is NaN, let t be +∞, else let t be max(q, 0) + +includes: [atomicsHelper.js] +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +---*/ + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +const RUNNING = 1; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + $262.agent.report(Atomics.wait(i64a, 0, 0n, NaN)); // NaN => +Infinity + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i64a); +$262.agent.waitUntil(i64a, RUNNING, 1n); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue(Atomics.notify(i64a, 0), 1, 'Atomics.notify(i64a, 0) returns 1'); +assert.sameValue($262.agent.getReport(), 'ok', '$262.agent.getReport() returns "ok"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/negative-index-throws.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/negative-index-throws.js new file mode 100644 index 0000000000..ce31bf301e --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/negative-index-throws.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Throws a RangeError is index < 0 +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 2.Let i be ? ValidateAtomicAccess(typedArray, index). + ... + 2.Let accessIndex be ? ToIndex(requestIndex). + ... + 2.b If integerIndex < 0, throw a RangeError exception +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +---*/ + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 8) +); +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(RangeError, function() { + Atomics.wait(i64a, -Infinity, poisoned, poisoned); +}, '`Atomics.wait(i64a, -Infinity, poisoned, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.wait(i64a, -7.999, poisoned, poisoned); +}, '`Atomics.wait(i64a, -7.999, poisoned, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.wait(i64a, -1, poisoned, poisoned); +}, '`Atomics.wait(i64a, -1, poisoned, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.wait(i64a, -300, poisoned, poisoned); +}, '`Atomics.wait(i64a, -300, poisoned, poisoned)` throws RangeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/negative-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/negative-timeout-agent.js new file mode 100644 index 0000000000..752fc7f8fc --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/negative-timeout-agent.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Test that Atomics.wait times out with a negative timeout +includes: [atomicsHelper.js] +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +---*/ + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +const RUNNING = 1; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + $262.agent.report(Atomics.wait(i64a, 0, 0n, -5)); // -5 => 0 + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i64a); +$262.agent.waitUntil(i64a, RUNNING, 1n); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue(Atomics.notify(i64a, 0), 0, 'Atomics.notify(i64a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/negative-timeout.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/negative-timeout.js new file mode 100644 index 0000000000..e38b9381cc --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/negative-timeout.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!xulRuntime.shell||!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- browser cannot block main thread, Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Test that Atomics.wait times out with a negative timeout +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +flags: [CanBlockIsTrue] +---*/ + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +assert.sameValue( + Atomics.wait(i64a, 0, 0n, -1), + "timed-out", + 'Atomics.wait(i64a, 0, 0n, -1) returns "timed-out"' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-no-operation.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-no-operation.js new file mode 100644 index 0000000000..01202a1efe --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-no-operation.js @@ -0,0 +1,62 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Test that Atomics.wait returns the right result when it timed out and that + the time to time out is reasonable. + info: | + 17. Let awoken be Suspend(WL, W, t). + 18. If awoken is true, then + a. Assert: W is not on the list of waiters in WL. + 19. Else, + a.Perform RemoveWaiter(WL, W). +includes: [atomicsHelper.js] +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const before = $262.agent.monotonicNow(); + const unpark = Atomics.wait(i64a, 0, 0n, ${TIMEOUT}); + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i64a); +$262.agent.waitUntil(i64a, RUNNING, 1n); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +// NO OPERATION OCCURS HERE! + +const lapse = $262.agent.getReport(); +assert( + lapse >= TIMEOUT, + 'The result of `(lapse >= TIMEOUT)` is true' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue(Atomics.notify(i64a, 0), 0, 'Atomics.notify(i64a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-add.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-add.js new file mode 100644 index 0000000000..b822c523d6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-add.js @@ -0,0 +1,57 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Waiter does not spuriously notify on index which is subject to Add operation +includes: [atomicsHelper.js] +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const before = $262.agent.monotonicNow(); + const unpark = Atomics.wait(i64a, 0, 0n, ${TIMEOUT}); + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i64a); +$262.agent.waitUntil(i64a, RUNNING, 1n); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +Atomics.add(i64a, 0, 1n); + +const lapse = $262.agent.getReport(); +assert( + lapse >= TIMEOUT, + 'The result of `(lapse >= TIMEOUT)` is true' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue(Atomics.notify(i64a, 0), 0, 'Atomics.notify(i64a, 0) returns 0'); + + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-and.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-and.js new file mode 100644 index 0000000000..e3d168a11b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-and.js @@ -0,0 +1,57 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Waiter does not spuriously nofity on index which is subject to And operation +includes: [atomicsHelper.js] +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const before = $262.agent.monotonicNow(); + const unpark = Atomics.wait(i64a, 0, 0n, ${TIMEOUT}); + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i64a); +$262.agent.waitUntil(i64a, RUNNING, 1n); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +Atomics.and(i64a, 0, 1n); + +const lapse = $262.agent.getReport(); +assert( + lapse >= TIMEOUT, + 'The result of `(lapse >= TIMEOUT)` is true' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue(Atomics.notify(i64a, 0), 0, 'Atomics.notify(i64a, 0) returns 0'); + + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-compareExchange.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-compareExchange.js new file mode 100644 index 0000000000..0ebe25cd3d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-compareExchange.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Waiter does not spuriously notify on index which is subject to compareExchange operation +includes: [atomicsHelper.js] +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const before = $262.agent.monotonicNow(); + const unpark = Atomics.wait(i64a, 0, 0n, ${TIMEOUT}); + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i64a); +$262.agent.waitUntil(i64a, RUNNING, 1n); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +Atomics.compareExchange(i64a, 0, 0n, 1n); + +const lapse = $262.agent.getReport(); +assert( + lapse >= TIMEOUT, + 'The result of `(lapse >= TIMEOUT)` is true' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue(Atomics.notify(i64a, 0), 0, 'Atomics.notify(i64a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-exchange.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-exchange.js new file mode 100644 index 0000000000..f668ee3611 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-exchange.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Waiter does not spuriously notify on index which is subject to exchange operation +includes: [atomicsHelper.js] +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const before = $262.agent.monotonicNow(); + const unpark = Atomics.wait(i64a, 0, 0n, ${TIMEOUT}); + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i64a); +$262.agent.waitUntil(i64a, RUNNING, 1n); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +Atomics.exchange(i64a, 0, 1n); + +const lapse = $262.agent.getReport(); +assert( + lapse >= TIMEOUT, + 'The result of `(lapse >= TIMEOUT)` is true' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue(Atomics.notify(i64a, 0), 0, 'Atomics.notify(i64a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-or.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-or.js new file mode 100644 index 0000000000..6eebfce7c1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-or.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Waiter does not spuriously notify on index which is subject to Or operation +includes: [atomicsHelper.js] +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const before = $262.agent.monotonicNow(); + const unpark = Atomics.wait(i64a, 0, 0n, ${TIMEOUT}); + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i64a); +$262.agent.waitUntil(i64a, RUNNING, 1n); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +Atomics.or(i64a, 0, 1n); + +const lapse = $262.agent.getReport(); +assert( + lapse >= TIMEOUT, + 'The result of `(lapse >= TIMEOUT)` is true' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue(Atomics.notify(i64a, 0), 0, 'Atomics.notify(i64a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-store.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-store.js new file mode 100644 index 0000000000..3b3630f721 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-store.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Demonstrates that Atomics.store(...) is causing a waiting +includes: [atomicsHelper.js] +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const before = $262.agent.monotonicNow(); + const unpark = Atomics.wait(i64a, 0, 0n, ${TIMEOUT}); + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i64a); +$262.agent.waitUntil(i64a, RUNNING, 1n); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +Atomics.store(i64a, 0, 0x111111n); + +const lapse = $262.agent.getReport(); +assert( + lapse >= TIMEOUT, + 'The result of `(lapse >= TIMEOUT)` is true' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue(Atomics.notify(i64a, 0), 0, 'Atomics.notify(i64a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-sub.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-sub.js new file mode 100644 index 0000000000..0703e2e57e --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-sub.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Waiter does not spuriously notify on index which is subject to Sub operation +includes: [atomicsHelper.js] +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const before = $262.agent.monotonicNow(); + const unpark = Atomics.wait(i64a, 0, 0n, ${TIMEOUT}); + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i64a); +$262.agent.waitUntil(i64a, RUNNING, 1n); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +Atomics.sub(i64a, 0, 1n); + +const lapse = $262.agent.getReport(); +assert( + lapse >= TIMEOUT, + 'The result of `(lapse >= TIMEOUT)` is true' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue(Atomics.notify(i64a, 0), 0, 'Atomics.notify(i64a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-xor.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-xor.js new file mode 100644 index 0000000000..1d6f636d65 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-xor.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Waiter does not spuriously notify on index which is subject to xor operation +includes: [atomicsHelper.js] +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const before = $262.agent.monotonicNow(); + const unpark = Atomics.wait(i64a, 0, 0n, ${TIMEOUT}); + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i64a); +$262.agent.waitUntil(i64a, RUNNING, 1n); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +Atomics.xor(i64a, 0, 1n); + +const lapse = $262.agent.getReport(); +assert( + lapse >= TIMEOUT, + 'The result of `(lapse >= TIMEOUT)` is true' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue(Atomics.notify(i64a, 0), 0, 'Atomics.notify(i64a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/non-bigint64-typedarray-throws.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/non-bigint64-typedarray-throws.js new file mode 100644 index 0000000000..9db40a9a65 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/non-bigint64-typedarray-throws.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-validatesharedintegertypedarray +description: > + Throws a TypeError if typedArray arg is not a BigInt64Array +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 1.Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + + + ValidateSharedIntegerTypedArray(typedArray [ , waitable ] ) + + ... + 5. If waitable is true, then + a. If typeName is not "BigInt64Array", + throw a TypeError exception. + +features: [Atomics, BigInt, SharedArrayBuffer] +---*/ + +const i64a = new BigUint64Array( + new SharedArrayBuffer(BigUint64Array.BYTES_PER_ELEMENT) +); + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, function() { + Atomics.wait(i64a, 0, 0n, 0); +}, '`Atomics.wait(i64a, 0, 0n, 0)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.wait(i64a, poisoned, poisoned, poisoned); +}, '`Atomics.wait(i64a, poisoned, poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/non-shared-bufferdata-throws.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/non-shared-bufferdata-throws.js new file mode 100644 index 0000000000..ec45720916 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/non-shared-bufferdata-throws.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.wait +description: > + Throws a TypeError if typedArray.buffer is not a SharedArrayBuffer +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 1.Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + 9.If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception. + ... + 4.If bufferData is a Data Block, return false. +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ +const i64a = new BigInt64Array(new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT)); + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, function() { + Atomics.wait(i64a, 0, 0n, 0); +}, '`Atomics.wait(i64a, 0, 0n, 0)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.wait(i64a, poisoned, poisoned, poisoned); +}, '`Atomics.wait(i64a, poisoned, poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/null-bufferdata-throws.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/null-bufferdata-throws.js new file mode 100644 index 0000000000..84afbefeda --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/null-bufferdata-throws.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.wait +description: > + A null value for bufferData throws a TypeError +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 1.Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + + ValidateSharedIntegerTypedArray(typedArray [ , onlyInt32 ] ) + + ... + 9.If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception. + + + IsSharedArrayBuffer( obj ) + + ... + 3.If bufferData is null, return false. + +includes: [detachArrayBuffer.js] +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ + +const i64a = new BigInt64Array( + new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +try { + $DETACHBUFFER(i64a.buffer); // Detaching a non-shared ArrayBuffer sets the [[ArrayBufferData]] value to null +} catch (error) { + $ERROR(`An unexpected error occurred when detaching ArrayBuffer: ${error.message}`); +} + +assert.throws(TypeError, function() { + Atomics.wait(i64a, poisoned, poisoned, poisoned); +}, '`Atomics.wait(i64a, poisoned, poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/out-of-range-index-throws.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/out-of-range-index-throws.js new file mode 100644 index 0000000000..7bb3c5ec75 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/out-of-range-index-throws.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Throws a RangeError if value of index arg is out of range +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 2.Let i be ? ValidateAtomicAccess(typedArray, index). + ... + 2.Let accessIndex be ? ToIndex(requestIndex). + ... + 5. If accessIndex ≥ length, throw a RangeError exception. +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +---*/ + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(RangeError, function() { + Atomics.wait(i64a, Infinity, poisoned, poisoned); +}, '`Atomics.wait(i64a, Infinity, poisoned, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.wait(i64a, 8, poisoned, poisoned); +}, '`Atomics.wait(i64a, 8, poisoned, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.wait(i64a, 200, poisoned, poisoned); +}, '`Atomics.wait(i64a, 200, poisoned, poisoned)` throws RangeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/shell.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/shell.js diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/value-not-equal.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/value-not-equal.js new file mode 100644 index 0000000000..a97cd35bcf --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/value-not-equal.js @@ -0,0 +1,62 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Returns "not-equal" when value arg does not match an index in the typedArray +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 3.Let v be ? ToBigInt64(value). + ... + 14.If v is not equal to w, then + a.Perform LeaveCriticalSection(WL). + b. Return the String "not-equal". + +includes: [atomicsHelper.js] +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const value = "42n"; + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + $262.agent.report(Atomics.store(i64a, 0, ${value})); + $262.agent.report(Atomics.wait(i64a, 0, 0n)); + $262.agent.leaving(); + }); +`); + +// NB: We don't actually explicitly need to wait for the agent to start in this +// test case, we only do it for consistency with other test cases which do +// require the main agent to wait and yield control. + +$262.agent.safeBroadcast(i64a); +$262.agent.waitUntil(i64a, RUNNING, 1n); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue( + $262.agent.getReport(), + '42', + '$262.agent.getReport() returns "42"' +); +assert.sameValue( + $262.agent.getReport(), + 'not-equal', + '$262.agent.getReport() returns "not-equal"' +); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/waiterlist-block-indexedposition-wake.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/waiterlist-block-indexedposition-wake.js new file mode 100644 index 0000000000..e1da72ccb0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/waiterlist-block-indexedposition-wake.js @@ -0,0 +1,78 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Get the correct WaiterList +info: | + Atomics.wait( typedArray, index, value, timeout ) + + ... + 11. Let WL be GetWaiterList(block, indexedPosition). + ... + + + GetWaiterList( block, i ) + + ... + 4. Return the WaiterList that is referenced by the pair (block, i). + +includes: [atomicsHelper.js] +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +---*/ + +var NUMAGENT = 2; +var RUNNING = 4; + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 5) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + // Wait on index 0 + $262.agent.report(Atomics.wait(i64a, 0, 0n, Infinity)); + $262.agent.leaving(); + }); +`); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + // Wait on index 2 + $262.agent.report(Atomics.wait(i64a, 2, 0n, Infinity)); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i64a); + +// Wait until all agents started. +$262.agent.waitUntil(i64a, RUNNING, BigInt(NUMAGENT)); + +// Notify index 1, notifies nothing +assert.sameValue(Atomics.notify(i64a, 1), 0, 'Atomics.notify(i64a, 1) returns 0'); + +// Notify index 3, notifies nothing +assert.sameValue(Atomics.notify(i64a, 3), 0, 'Atomics.notify(i64a, 3) returns 0'); + +// Notify index 2, notifies 1 +var woken = 0; +while ((woken = Atomics.notify(i64a, 2)) === 0) ; +assert.sameValue(woken, 1, 'Atomics.notify(i64a, 2) returns 1'); +assert.sameValue($262.agent.getReport(), 'ok', '$262.agent.getReport() returns "ok"'); + +// Notify index 0, notifies 1 +var woken = 0; +while ((woken = Atomics.notify(i64a, 0)) === 0) ; +assert.sameValue(woken, 1, 'Atomics.notify(i64a, 0) returns 1'); +assert.sameValue($262.agent.getReport(), 'ok', '$262.agent.getReport() returns "ok"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/waiterlist-order-of-operations-is-fifo.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/waiterlist-order-of-operations-is-fifo.js new file mode 100644 index 0000000000..f75888e49f --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/waiterlist-order-of-operations-is-fifo.js @@ -0,0 +1,95 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + New waiters should be applied to the end of the list and woken by order they entered the list (FIFO) +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 16.Perform AddWaiter(WL, W). + ... + 3.Add W to the end of the list of waiters in WL. + +includes: [atomicsHelper.js] +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +---*/ + +var WAIT_INDEX = 0; +var RUNNING = 1; +var LOCK_INDEX = 2; +var NUMAGENT = 3; + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +for (var i = 0; i < NUMAGENT; i++) { + var agentNum = i; + + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + // Synchronize workers before reporting the initial report. + while (Atomics.compareExchange(i64a, ${LOCK_INDEX}, 0n, 1n) !== 0n) ; + + // Report the agent number before waiting. + $262.agent.report(${agentNum}); + + // Wait until restarted by main thread. + var status = Atomics.wait(i64a, ${WAIT_INDEX}, 0n); + + // Report wait status. + $262.agent.report(status); + + // Report the agent number after waiting. + $262.agent.report(${agentNum}); + + $262.agent.leaving(); + }); + `); +} + +$262.agent.safeBroadcast(i64a); + +// Wait until all agents started. +$262.agent.waitUntil(i64a, RUNNING, BigInt(NUMAGENT)); + +// Agents may be started in any order. +const started = []; +for (var i = 0; i < NUMAGENT; i++) { + // Wait until an agent entered its critical section. + $262.agent.waitUntil(i64a, LOCK_INDEX, 1n); + + // Record the agent number. + started.push($262.agent.getReport()); + + // The agent may have been interrupted between reporting its initial report + // and the `Atomics.wait` call. Try to yield control to ensure the agent + // actually started to wait. + $262.agent.tryYield(); + + // Now continue with the next agent. + Atomics.store(i64a, LOCK_INDEX, 0n); +} + +// Agents must notify in the order they waited. +for (var i = 0; i < NUMAGENT; i++) { + var woken = 0; + while ((woken = Atomics.notify(i64a, WAIT_INDEX, 1)) === 0) ; + + assert.sameValue(woken, 1, + 'Atomics.notify(i64a, WAIT_INDEX, 1) returns 1, at index = ' + i); + + assert.sameValue($262.agent.getReport(), 'ok', + '$262.agent.getReport() returns "ok", at index = ' + i); + + assert.sameValue($262.agent.getReport(), started[i], + '$262.agent.getReport() returns the value of `started[' + i + ']`'); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/bigint/was-woken-before-timeout.js b/js/src/tests/test262/built-ins/Atomics/wait/bigint/was-woken-before-timeout.js new file mode 100644 index 0000000000..438d9363d4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/bigint/was-woken-before-timeout.js @@ -0,0 +1,64 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.wait +description: > + Test that Atomics.wait returns the right result when it was awoken before + a timeout +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 2.Let i be ? ValidateAtomicAccess(typedArray, index). + ... + 2.Let accessIndex be ? ToIndex(requestIndex). + + 9.If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception. + ... + 3.If bufferData is a Data Block, return false + + If value is undefined, then + Let index be 0. +includes: [atomicsHelper.js] +features: [Atomics, BigInt, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.huge; + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const before = $262.agent.monotonicNow(); + const unpark = Atomics.wait(i64a, 0, 0n, ${TIMEOUT}); + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i64a); +$262.agent.waitUntil(i64a, RUNNING, 1n); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue(Atomics.notify(i64a, 0), 1, 'Atomics.notify(i64a, 0) returns 1'); + +const lapse = $262.agent.getReport(); + +assert( + lapse < TIMEOUT, + 'The result of `(lapse < TIMEOUT)` is true' +); +assert.sameValue($262.agent.getReport(), 'ok', '$262.agent.getReport() returns "ok"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/browser.js b/js/src/tests/test262/built-ins/Atomics/wait/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/wait/cannot-suspend-throws.js b/js/src/tests/test262/built-ins/Atomics/wait/cannot-suspend-throws.js new file mode 100644 index 0000000000..696a86fda4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/cannot-suspend-throws.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(xulRuntime.shell||!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- shell can block main thread, Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Atomics.wait throws if agent cannot be suspended, CanBlock is false +info: | + Assuming [[CanBlock]] is false for the main host. + + Atomics.wait( typedArray, index, value, timeout ) + + ... (after args validation) + 6. Let B be AgentCanSuspend(). + 7. If B is false, throw a TypeError exception. + ... +features: [Atomics, SharedArrayBuffer, TypedArray] +flags: [CanBlockIsFalse] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +assert.throws(TypeError, function() { + Atomics.wait(i32a, 0, 0, 0); +}, '`Atomics.wait(i32a, 0, 0, 0)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/descriptor.js b/js/src/tests/test262/built-ins/Atomics/wait/descriptor.js new file mode 100644 index 0000000000..36a7db4989 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/descriptor.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: Testing descriptor property of Atomics.wait +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics, 'wait', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/false-for-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/wait/false-for-timeout-agent.js new file mode 100644 index 0000000000..32966ed782 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/false-for-timeout-agent.js @@ -0,0 +1,78 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + False timeout arg should result in an +0 timeout +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 4. Let q be ? ToNumber(timeout). + + Boolean -> If argument is true, return 1. If argument is false, return +0. + +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; + +$262.agent.start(` + const valueOf = { + valueOf: function() { + return false; + } + }; + + const toPrimitive = { + [Symbol.toPrimitive]: function() { + return false; + } + }; + + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const status1 = Atomics.wait(i32a, 0, 0, false); + const status2 = Atomics.wait(i32a, 0, 0, valueOf); + const status3 = Atomics.wait(i32a, 0, 0, toPrimitive); + + $262.agent.report(status1); + $262.agent.report(status2); + $262.agent.report(status3); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); + +assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/false-for-timeout.js b/js/src/tests/test262/built-ins/Atomics/wait/false-for-timeout.js new file mode 100644 index 0000000000..c107178601 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/false-for-timeout.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(!xulRuntime.shell||!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- browser cannot block main thread, Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + False timeout arg should result in an +0 timeout +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 4. Let q be ? ToNumber(timeout). + + Boolean -> If argument is true, return 1. If argument is false, return +0. + +features: [Atomics, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray] +flags: [CanBlockIsTrue] +---*/ + +const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)); + +const valueOf = { + valueOf: function() { + return false; + } +}; + +const toPrimitive = { + [Symbol.toPrimitive]: function() { + return false; + } +}; + +assert.sameValue( + Atomics.wait(i32a, 0, 0, false), + 'timed-out', + 'Atomics.wait(i32a, 0, 0, false) returns "timed-out"' +); +assert.sameValue( + Atomics.wait(i32a, 0, 0, valueOf), + 'timed-out', + 'Atomics.wait(i32a, 0, 0, valueOf) returns "timed-out"' +); +assert.sameValue( + Atomics.wait(i32a, 0, 0, toPrimitive), + 'timed-out', + 'Atomics.wait(i32a, 0, 0, toPrimitive) returns "timed-out"' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/good-views.js b/js/src/tests/test262/built-ins/Atomics/wait/good-views.js new file mode 100644 index 0000000000..67e4da6314 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/good-views.js @@ -0,0 +1,69 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Test Atomics.wait on arrays that allow atomic operations, + in an Agent that is allowed to wait. +includes: [atomicsHelper.js] +features: [Atomics] +---*/ + +// Let's assume 'wait' is not allowed on the main thread, +// even in the shell. + +$262.agent.start(` + var sab = new SharedArrayBuffer(1024); + var ab = new ArrayBuffer(16); + + var good_indices = [ (view) => 0/-1, // -0 + (view) => '-0', + (view) => view.length - 1, + (view) => ({ valueOf: () => 0 }), + (view) => ({ toString: () => '0', valueOf: false }) // non-callable valueOf triggers invocation of toString + ]; + + var view = new Int32Array(sab, 32, 20); + + view[0] = 0; + $262.agent.report("A " + Atomics.wait(view, 0, 0, 0)) + $262.agent.report("B " + Atomics.wait(view, 0, 37, 0)); + + // In-bounds boundary cases for indexing + for ( let IdxGen of good_indices ) { + let Idx = IdxGen(view); + view.fill(0); + // Atomics.store() computes an index from Idx in the same way as other + // Atomics operations, not quite like view[Idx]. + Atomics.store(view, Idx, 37); + $262.agent.report("C " + Atomics.wait(view, Idx, 0)); + } + + $262.agent.report("done"); + $262.agent.leaving(); +`); + +assert.sameValue( + $262.agent.getReport(), + 'A timed-out', + '$262.agent.getReport() returns "A timed-out"' +); + +assert.sameValue( + $262.agent.getReport(), + 'B not-equal', + '$262.agent.getReport() returns "B not-equal"' +); + +var r; +while ((r = $262.agent.getReport()) !== "done") { + assert.sameValue( + r, + 'C not-equal', + '$262.agent.getReport() returns "C not-equal"' + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/length.js b/js/src/tests/test262/built-ins/Atomics/wait/length.js new file mode 100644 index 0000000000..0cf786fa59 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/length.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Atomics.wait.length is 4. +info: | + Atomics.wait ( ia, index, expect, timeout ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this + value is equal to the largest number of named arguments shown in the + subclause headings for the function description, including optional + parameters. However, rest parameters shown using the form “...name” + are not included in the default argument count. + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.wait, 'length', { + value: 4, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/name.js b/js/src/tests/test262/built-ins/Atomics/wait/name.js new file mode 100644 index 0000000000..b9a8813627 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/name.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Atomics.wait.name is "wait". +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.wait, 'name', { + value: 'wait', + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/nan-for-timeout.js b/js/src/tests/test262/built-ins/Atomics/wait/nan-for-timeout.js new file mode 100644 index 0000000000..373083aa5a --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/nan-for-timeout.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + NaN timeout arg should result in an infinite timeout +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 4.Let q be ? ToNumber(timeout). + ... + Undefined Return NaN. + 5.If q is NaN, let t be +∞, else let t be max(q, 0) + +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + $262.agent.report(Atomics.wait(i32a, 0, 0, NaN)); // NaN => +Infinity + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue(Atomics.notify(i32a, 0), 1, 'Atomics.notify(i32a, 0) returns 1'); +assert.sameValue($262.agent.getReport(), "ok", '$262.agent.getReport() returns "ok"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/negative-index-throws.js b/js/src/tests/test262/built-ins/Atomics/wait/negative-index-throws.js new file mode 100644 index 0000000000..b7562dd0fd --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/negative-index-throws.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Throws a RangeError is index < 0 +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 2.Let i be ? ValidateAtomicAccess(typedArray, index). + ... + 2.Let accessIndex be ? ToIndex(requestIndex). + ... + 2.b If integerIndex < 0, throw a RangeError exception + +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(RangeError, function() { + Atomics.wait(i32a, -Infinity, poisoned, poisoned); +}, '`Atomics.wait(i32a, -Infinity, poisoned, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.wait(i32a, -7.999, poisoned, poisoned); +}, '`Atomics.wait(i32a, -7.999, poisoned, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.wait(i32a, -1, poisoned, poisoned); +}, '`Atomics.wait(i32a, -1, poisoned, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.wait(i32a, -300, poisoned, poisoned); +}, '`Atomics.wait(i32a, -300, poisoned, poisoned)` throws RangeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/negative-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/wait/negative-timeout-agent.js new file mode 100644 index 0000000000..1bed54bd71 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/negative-timeout-agent.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Test that Atomics.wait times out with a negative timeout +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + var i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + $262.agent.report(Atomics.wait(i32a, 0, 0, -5)); // -5 => 0 + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/negative-timeout.js b/js/src/tests/test262/built-ins/Atomics/wait/negative-timeout.js new file mode 100644 index 0000000000..299f4d307f --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/negative-timeout.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!xulRuntime.shell||!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- browser cannot block main thread, Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Test that Atomics.wait times out with a negative timeout +features: [Atomics, SharedArrayBuffer, TypedArray] +flags: [CanBlockIsTrue] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +assert.sameValue( + Atomics.wait(i32a, 0, 0, -1), + "timed-out", + 'Atomics.wait(i32a, 0, 0, -1) returns "timed-out"' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-no-operation.js b/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-no-operation.js new file mode 100644 index 0000000000..082d1f26dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-no-operation.js @@ -0,0 +1,62 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Test that Atomics.wait returns the right result when it timed out and that + the time to time out is reasonable. + info: | + 17. Let awoken be Suspend(WL, W, t). + 18. If awoken is true, then + a. Assert: W is not on the list of waiters in WL. + 19. Else, + a.Perform RemoveWaiter(WL, W). +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const before = $262.agent.monotonicNow(); + const unpark = Atomics.wait(i32a, 0, 0, ${TIMEOUT}); + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +// NO OPERATION OCCURS HERE! + +const lapse = $262.agent.getReport(); +assert( + lapse >= TIMEOUT, + 'The result of `(lapse >= TIMEOUT)` is true' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-add.js b/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-add.js new file mode 100644 index 0000000000..27a2914b2e --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-add.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Waiter does not spuriously notify on index which is subject to Add operation +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const before = $262.agent.monotonicNow(); + const unpark = Atomics.wait(i32a, 0, 0, ${TIMEOUT}); + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +Atomics.add(i32a, 0, 1); + +const lapse = $262.agent.getReport(); +assert( + lapse >= TIMEOUT, + 'The result of `(lapse >= TIMEOUT)` is true' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-and.js b/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-and.js new file mode 100644 index 0000000000..13dfa1cfb7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-and.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Waiter does not spuriously notify on index which is subject to And operation +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const before = $262.agent.monotonicNow(); + const unpark = Atomics.wait(i32a, 0, 0, ${TIMEOUT}); + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +Atomics.and(i32a, 0, 1); + +const lapse = $262.agent.getReport(); +assert( + lapse >= TIMEOUT, + 'The result of `(lapse >= TIMEOUT)` is true' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-compareExchange.js b/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-compareExchange.js new file mode 100644 index 0000000000..1da28e628f --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-compareExchange.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Waiter does not spuriously notify on index which is subject to compareExchange operation +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const before = $262.agent.monotonicNow(); + const unpark = Atomics.wait(i32a, 0, 0, ${TIMEOUT}); + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +Atomics.compareExchange(i32a, 0, 0, 1); + +const lapse = $262.agent.getReport(); +assert( + lapse >= TIMEOUT, + 'The result of `(lapse >= TIMEOUT)` is true' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-exchange.js b/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-exchange.js new file mode 100644 index 0000000000..88793bf8ef --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-exchange.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Waiter does not spuriously notify on index which is subject to exchange operation +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const before = $262.agent.monotonicNow(); + const unpark = Atomics.wait(i32a, 0, 0, ${TIMEOUT}); + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +Atomics.exchange(i32a, 0, 1); + +const lapse = $262.agent.getReport(); +assert( + lapse >= TIMEOUT, + 'The result of `(lapse >= TIMEOUT)` is true' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-or.js b/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-or.js new file mode 100644 index 0000000000..6b457df301 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-or.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Waiter does not spuriously notify on index which is subject to Or operation +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const before = $262.agent.monotonicNow(); + const unpark = Atomics.wait(i32a, 0, 0, ${TIMEOUT}); + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +Atomics.or(i32a, 0, 1); + +const lapse = $262.agent.getReport(); +assert( + lapse >= TIMEOUT, + 'The result of `(lapse >= TIMEOUT)` is true' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-store.js b/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-store.js new file mode 100644 index 0000000000..0ab8075e14 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-store.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Waiter does not spuriously notify on index which is subject to Store operation +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const before = $262.agent.monotonicNow(); + const unpark = Atomics.wait(i32a, 0, 0, ${TIMEOUT}); + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +Atomics.store(i32a, 0, 0x111111); + +const lapse = $262.agent.getReport(); +assert( + lapse >= TIMEOUT, + 'The result of `(lapse >= TIMEOUT)` is true' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-sub.js b/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-sub.js new file mode 100644 index 0000000000..24bc5127eb --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-sub.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Waiter does not spuriously notify on index which is subject to Sub operation +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const before = $262.agent.monotonicNow(); + const unpark = Atomics.wait(i32a, 0, 0, ${TIMEOUT}); + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +Atomics.sub(i32a, 0, 1); + +const lapse = $262.agent.getReport(); +assert( + lapse >= TIMEOUT, + 'The result of `(lapse >= TIMEOUT)` is true' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-xor.js b/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-xor.js new file mode 100644 index 0000000000..0d0802c42c --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/no-spurious-wakeup-on-xor.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Waiter does not spuriously notify on index which is subject to xor operation +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const before = $262.agent.monotonicNow(); + const unpark = Atomics.wait(i32a, 0, 0, ${TIMEOUT}); + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +Atomics.xor(i32a, 0, 1); + +const lapse = $262.agent.getReport(); +assert( + lapse >= TIMEOUT, + 'The result of `(lapse >= TIMEOUT)` is true' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/non-int32-typedarray-throws.js b/js/src/tests/test262/built-ins/Atomics/wait/non-int32-typedarray-throws.js new file mode 100644 index 0000000000..7ff12e1357 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/non-int32-typedarray-throws.js @@ -0,0 +1,81 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Throws a TypeError if typedArray arg is not an Int32Array +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 1.Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + 5.If onlyInt32 is true, then + If typeName is not "Int32Array", throw a TypeError exception. +features: [Atomics, Float32Array, Float64Array, Int8Array, TypedArray, Uint16Array, Uint8Array, Uint8ClampedArray] +---*/ + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, function() { + const view = new Float64Array( + new SharedArrayBuffer(Float64Array.BYTES_PER_ELEMENT * 8) + ); + Atomics.wait(view, poisoned, poisoned, poisoned); +}, '`const view = new Float64Array( new SharedArrayBuffer(Float64Array.BYTES_PER_ELEMENT * 8) ); Atomics.wait(view, poisoned, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Float32Array( + new SharedArrayBuffer(Float32Array.BYTES_PER_ELEMENT * 4) + ); + Atomics.wait(view, poisoned, poisoned, poisoned); +}, '`const view = new Float32Array( new SharedArrayBuffer(Float32Array.BYTES_PER_ELEMENT * 4) ); Atomics.wait(view, poisoned, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Int16Array( + new SharedArrayBuffer(Int16Array.BYTES_PER_ELEMENT * 2) + ); + Atomics.wait(view, poisoned, poisoned, poisoned); +}, '`const view = new Int16Array( new SharedArrayBuffer(Int16Array.BYTES_PER_ELEMENT * 2) ); Atomics.wait(view, poisoned, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Int8Array( + new SharedArrayBuffer(Int8Array.BYTES_PER_ELEMENT) + ); + Atomics.wait(view, poisoned, poisoned, poisoned); +}, '`const view = new Int8Array( new SharedArrayBuffer(Int8Array.BYTES_PER_ELEMENT) ); Atomics.wait(view, poisoned, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Uint32Array( + new SharedArrayBuffer(Uint32Array.BYTES_PER_ELEMENT * 4) + ); + Atomics.wait(view, poisoned, poisoned, poisoned); +}, '`const view = new Uint32Array( new SharedArrayBuffer(Uint32Array.BYTES_PER_ELEMENT * 4) ); Atomics.wait(view, poisoned, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Uint16Array( + new SharedArrayBuffer(Uint16Array.BYTES_PER_ELEMENT * 2) + ); + Atomics.wait(view, poisoned, poisoned, poisoned); +}, '`const view = new Uint16Array( new SharedArrayBuffer(Uint16Array.BYTES_PER_ELEMENT * 2) ); Atomics.wait(view, poisoned, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Uint8Array( + new SharedArrayBuffer(Uint8Array.BYTES_PER_ELEMENT) + ); + Atomics.wait(view, poisoned, poisoned, poisoned); +}, '`const view = new Uint8Array( new SharedArrayBuffer(Uint8Array.BYTES_PER_ELEMENT) ); Atomics.wait(view, poisoned, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + const view = new Uint8ClampedArray( + new SharedArrayBuffer(Uint8ClampedArray.BYTES_PER_ELEMENT) + ); + Atomics.wait(view, poisoned, poisoned, poisoned); +}, '`const view = new Uint8ClampedArray( new SharedArrayBuffer(Uint8ClampedArray.BYTES_PER_ELEMENT) ); Atomics.wait(view, poisoned, poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/non-shared-bufferdata-throws.js b/js/src/tests/test262/built-ins/Atomics/wait/non-shared-bufferdata-throws.js new file mode 100644 index 0000000000..dcee5b7c34 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/non-shared-bufferdata-throws.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.wait +description: > + Throws a TypeError if typedArray.buffer is not a SharedArrayBuffer +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 1.Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + 9.If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception. + ... + 4.If bufferData is a Data Block, return false. +features: [ArrayBuffer, Atomics, TypedArray] +---*/ + +const i32a = new Int32Array( + new ArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, function() { + Atomics.wait(i32a, 0, 0, 0); +}, '`Atomics.wait(i32a, 0, 0, 0)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.wait(i32a, poisoned, poisoned, poisoned); +}, '`Atomics.wait(i32a, poisoned, poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/not-a-typedarray-throws.js b/js/src/tests/test262/built-ins/Atomics/wait/not-a-typedarray-throws.js new file mode 100644 index 0000000000..484d1affec --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/not-a-typedarray-throws.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.wait +description: > + Throws a TypeError if the typedArray arg is not a TypedArray object +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 1.Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + 3.If typedArray does not have a [[TypedArrayName]] internal slot, throw a TypeError exception. + +features: [Atomics] +---*/ + +var poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, function() { + Atomics.wait({}, 0, 0, 0); +}, '`Atomics.wait({}, 0, 0, 0)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.wait({}, poisoned, poisoned, poisoned); +}, '`Atomics.wait({}, poisoned, poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/not-an-object-throws.js b/js/src/tests/test262/built-ins/Atomics/wait/not-an-object-throws.js new file mode 100644 index 0000000000..64ce6c2277 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/not-an-object-throws.js @@ -0,0 +1,51 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.wait +description: > + Throws a TypeError if typedArray arg is not an Object +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 1.Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + 2. if Type(typedArray) is not Object, throw a TypeError exception +features: [Atomics, Symbol] +---*/ + +var poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, function() { + Atomics.wait(null, poisoned, poisoned, poisoned); +}, '`Atomics.wait(null, poisoned, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.wait(undefined, poisoned, poisoned, poisoned); +}, '`Atomics.wait(undefined, poisoned, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.wait(true, poisoned, poisoned, poisoned); +}, '`Atomics.wait(true, poisoned, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.wait(false, poisoned, poisoned, poisoned); +}, '`Atomics.wait(false, poisoned, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.wait('***string***', poisoned, poisoned, poisoned); +}, '`Atomics.wait(\'***string***\', poisoned, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.wait(Number.NEGATIVE_INFINITY, poisoned, poisoned, poisoned); +}, '`Atomics.wait(Number.NEGATIVE_INFINITY, poisoned, poisoned, poisoned)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.wait(Symbol('***symbol***'), poisoned, poisoned, poisoned); +}, '`Atomics.wait(Symbol(\'***symbol***\'), poisoned, poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/null-bufferdata-throws.js b/js/src/tests/test262/built-ins/Atomics/wait/null-bufferdata-throws.js new file mode 100644 index 0000000000..caab34a54e --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/null-bufferdata-throws.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.wait +description: > + A null value for bufferData (detached) throws a TypeError +info: | + Atomics.wait( typedArray, index, value, timeout ) + + Let buffer be ? ValidateIntegerTypedArray(typedArray, true). + ... + + Let buffer be ? ValidateTypedArray(typedArray). + ... + + If IsDetachedBuffer(buffer) is true, throw a TypeError exception. + ... + + If arrayBuffer.[[ArrayBufferData]] is null, return true. + +includes: [detachArrayBuffer.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ + +const i32a = new Int32Array( + new ArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +try { + $DETACHBUFFER(i32a.buffer); // Detaching a non-shared ArrayBuffer sets the [[ArrayBufferData]] value to null +} catch (error) { + $ERROR(`An unexpected error occurred when detaching ArrayBuffer: ${error.message}`); +} + +assert.throws(TypeError, function() { + Atomics.wait(i32a, poisoned, poisoned, poisoned); +}, '`Atomics.wait(i32a, poisoned, poisoned, poisoned)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/null-for-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/wait/null-for-timeout-agent.js new file mode 100644 index 0000000000..a2cd76790a --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/null-for-timeout-agent.js @@ -0,0 +1,78 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + False timeout arg should result in an +0 timeout +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 4. Let q be ? ToNumber(timeout). + + Null -> Return +0. + +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; + +$262.agent.start(` + const valueOf = { + valueOf: function() { + return null; + } + }; + + const toPrimitive = { + [Symbol.toPrimitive]: function() { + return null; + } + }; + + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const status1 = Atomics.wait(i32a, 0, 0, null); + const status2 = Atomics.wait(i32a, 0, 0, valueOf); + const status3 = Atomics.wait(i32a, 0, 0, toPrimitive); + + $262.agent.report(status1); + $262.agent.report(status2); + $262.agent.report(status3); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); + +assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/null-for-timeout.js b/js/src/tests/test262/built-ins/Atomics/wait/null-for-timeout.js new file mode 100644 index 0000000000..a336e07a7e --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/null-for-timeout.js @@ -0,0 +1,52 @@ +// |reftest| skip-if(!xulRuntime.shell||!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- browser cannot block main thread, Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Throws a TypeError if index arg can not be converted to an Integer +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 4. Let q be ? ToNumber(timeout). + + Null -> Return +0. + +features: [Atomics, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray] +flags: [CanBlockIsTrue] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const valueOf = { + valueOf: function() { + return null; + } +}; + +const toPrimitive = { + [Symbol.toPrimitive]: function() { + return null; + } +}; + +assert.sameValue( + Atomics.wait(i32a, 0, 0, null), + "timed-out", + 'Atomics.wait(i32a, 0, 0, null) returns "timed-out"' +); +assert.sameValue( + Atomics.wait(i32a, 0, 0, valueOf), + "timed-out", + 'Atomics.wait(i32a, 0, 0, valueOf) returns "timed-out"' +); +assert.sameValue( + Atomics.wait(i32a, 0, 0, toPrimitive), + "timed-out", + 'Atomics.wait(i32a, 0, 0, toPrimitive) returns "timed-out"' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/object-for-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/wait/object-for-timeout-agent.js new file mode 100644 index 0000000000..90ecd630e0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/object-for-timeout-agent.js @@ -0,0 +1,84 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + False timeout arg should result in an +0 timeout +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 4. Let q be ? ToNumber(timeout). + + Null -> Return +0. + +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; + +$262.agent.start(` + const valueOf = { + valueOf: function() { + return 0; + } + }; + + const toString = { + toString: function() { + return "0"; + } + }; + + const toPrimitive = { + [Symbol.toPrimitive]: function() { + return 0; + } + }; + + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const status1 = Atomics.wait(i32a, 0, 0, valueOf); + const status2 = Atomics.wait(i32a, 0, 0, toString); + const status3 = Atomics.wait(i32a, 0, 0, toPrimitive); + + $262.agent.report(status1); + $262.agent.report(status2); + $262.agent.report(status3); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); + +assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/object-for-timeout.js b/js/src/tests/test262/built-ins/Atomics/wait/object-for-timeout.js new file mode 100644 index 0000000000..14c99ff248 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/object-for-timeout.js @@ -0,0 +1,61 @@ +// |reftest| skip-if(!xulRuntime.shell||!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- browser cannot block main thread, Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Throws a TypeError if index arg can not be converted to an Integer +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 4. Let q be ? ToNumber(timeout). + + Object -> Apply the following steps: + + Let primValue be ? ToPrimitive(argument, hint Number). + Return ? ToNumber(primValue). + +features: [Atomics, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray] +flags: [CanBlockIsTrue] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const valueOf = { + valueOf: function() { + return 0; + } +}; + +const toString = { + toString: function() { + return "0"; + } +}; + +const toPrimitive = { + [Symbol.toPrimitive]: function() { + return 0; + } +}; + +assert.sameValue( + Atomics.wait(i32a, 0, 0, valueOf), + 'timed-out', + 'Atomics.wait(i32a, 0, 0, valueOf) returns "timed-out"' +); +assert.sameValue( + Atomics.wait(i32a, 0, 0, toString), + 'timed-out', + 'Atomics.wait(i32a, 0, 0, toString) returns "timed-out"' +); +assert.sameValue( + Atomics.wait(i32a, 0, 0, toPrimitive), + 'timed-out', + 'Atomics.wait(i32a, 0, 0, toPrimitive) returns "timed-out"' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/out-of-range-index-throws.js b/js/src/tests/test262/built-ins/Atomics/wait/out-of-range-index-throws.js new file mode 100644 index 0000000000..d2dd3da578 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/out-of-range-index-throws.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Throws a RangeError if value of index arg is out of range +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 2.Let i be ? ValidateAtomicAccess(typedArray, index). + ... + 2.Let accessIndex be ? ToIndex(requestIndex). + ... + 5. If accessIndex ≥ length, throw a RangeError exception. +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(RangeError, function() { + Atomics.wait(i32a, Infinity, poisoned, poisoned); +}, '`Atomics.wait(i32a, Infinity, poisoned, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.wait(i32a, -1, poisoned, poisoned); +}, '`Atomics.wait(i32a, -1, poisoned, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.wait(i32a, 4, poisoned, poisoned); +}, '`Atomics.wait(i32a, 4, poisoned, poisoned)` throws RangeError'); +assert.throws(RangeError, function() { + Atomics.wait(i32a, 200, poisoned, poisoned); +}, '`Atomics.wait(i32a, 200, poisoned, poisoned)` throws RangeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/poisoned-object-for-timeout-throws-agent.js b/js/src/tests/test262/built-ins/Atomics/wait/poisoned-object-for-timeout-throws-agent.js new file mode 100644 index 0000000000..ae1882d4a1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/poisoned-object-for-timeout-throws-agent.js @@ -0,0 +1,82 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + False timeout arg should result in an +0 timeout +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 4. Let q be ? ToNumber(timeout). + + Null -> Return +0. + +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; + +$262.agent.start(` + const poisonedValueOf = { + valueOf: function() { + throw new Error("should not evaluate this code"); + } + }; + + const poisonedToPrimitive = { + [Symbol.toPrimitive]: function() { + throw new Error("passing a poisoned object using @@ToPrimitive"); + } + }; + + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + let status1 = ""; + let status2 = ""; + + try { + Atomics.wait(i32a, 0, 0, poisonedValueOf); + } catch (error) { + status1 = "poisonedValueOf"; + } + try { + Atomics.wait(i32a, 0, 0, poisonedToPrimitive); + } catch (error) { + status2 = "poisonedToPrimitive"; + } + + $262.agent.report(status1); + $262.agent.report(status2); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue( + $262.agent.getReport(), + 'poisonedValueOf', + '$262.agent.getReport() returns "poisonedValueOf"' +); +assert.sameValue( + $262.agent.getReport(), + 'poisonedToPrimitive', + '$262.agent.getReport() returns "poisonedToPrimitive"' +); + +assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/poisoned-object-for-timeout-throws.js b/js/src/tests/test262/built-ins/Atomics/wait/poisoned-object-for-timeout-throws.js new file mode 100644 index 0000000000..cffe81af60 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/poisoned-object-for-timeout-throws.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Throws a TypeError if index arg can not be converted to an Integer +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 4. Let q be ? ToNumber(timeout). + + Object -> Apply the following steps: + + Let primValue be ? ToPrimitive(argument, hint Number). + Return ? ToNumber(primValue). + +features: [Atomics, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisonedValueOf = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +const poisonedToPrimitive = { + [Symbol.toPrimitive]: function() { + throw new Test262Error("passing a poisoned object using @@ToPrimitive"); + } +}; + +assert.throws(Test262Error, function() { + Atomics.wait(i32a, 0, 0, poisonedValueOf); +}, '`Atomics.wait(i32a, 0, 0, poisonedValueOf)` throws Test262Error'); + +assert.throws(Test262Error, function() { + Atomics.wait(i32a, 0, 0, poisonedToPrimitive); +}, '`Atomics.wait(i32a, 0, 0, poisonedToPrimitive)` throws Test262Error'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/shell.js b/js/src/tests/test262/built-ins/Atomics/wait/shell.js new file mode 100644 index 0000000000..bdbc7c38b8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/shell.js @@ -0,0 +1,344 @@ +// GENERATED, DO NOT EDIT +// file: atomicsHelper.js +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Collection of functions used to interact with Atomics.* operations across agent boundaries. +defines: + - $262.agent.getReportAsync + - $262.agent.getReport + - $262.agent.safeBroadcastAsync + - $262.agent.safeBroadcast + - $262.agent.setTimeout + - $262.agent.tryYield + - $262.agent.trySleep +---*/ + +/** + * @return {String} A report sent from an agent. + */ +{ + // This is only necessary because the original + // $262.agent.getReport API was insufficient. + // + // All runtimes currently have their own + // $262.agent.getReport which is wrong, so we + // will pave over it with a corrected version. + // + // Binding $262.agent is necessary to prevent + // breaking SpiderMonkey's $262.agent.getReport + let getReport = $262.agent.getReport.bind($262.agent); + + $262.agent.getReport = function() { + var r; + while ((r = getReport()) == null) { + $262.agent.sleep(1); + } + return r; + }; + + if (this.setTimeout === undefined) { + (function(that) { + that.setTimeout = function(callback, delay) { + let p = Promise.resolve(); + let start = Date.now(); + let end = start + delay; + function check() { + if ((end - Date.now()) > 0) { + p.then(check); + } + else { + callback(); + } + } + p.then(check); + } + })(this); + } + + $262.agent.setTimeout = setTimeout; + + $262.agent.getReportAsync = function() { + return new Promise(function(resolve) { + (function loop() { + let result = getReport(); + if (!result) { + setTimeout(loop, 1000); + } else { + resolve(result); + } + })(); + }); + }; +} + +/** + * + * Share a given Int32Array or BigInt64Array to all running agents. Ensure that the + * provided TypedArray is a "shared typed array". + * + * NOTE: Migrating all tests to this API is necessary to prevent tests from hanging + * indefinitely when a SAB is sent to a worker but the code in the worker attempts to + * create a non-sharable TypedArray (something that is not Int32Array or BigInt64Array). + * When that scenario occurs, an exception is thrown and the agent worker can no + * longer communicate with any other threads that control the SAB. If the main + * thread happens to be spinning in the $262.agent.waitUntil() while loop, it will never + * meet its termination condition and the test will hang indefinitely. + * + * Because we've defined $262.agent.broadcast(SAB) in + * https://github.com/tc39/test262/blob/HEAD/INTERPRETING.md, there are host implementations + * that assume compatibility, which must be maintained. + * + * + * $262.agent.safeBroadcast(TA) should not be included in + * https://github.com/tc39/test262/blob/HEAD/INTERPRETING.md + * + * + * @param {(Int32Array|BigInt64Array)} typedArray An Int32Array or BigInt64Array with a SharedArrayBuffer + */ +$262.agent.safeBroadcast = function(typedArray) { + let Constructor = Object.getPrototypeOf(typedArray).constructor; + let temp = new Constructor( + new SharedArrayBuffer(Constructor.BYTES_PER_ELEMENT) + ); + try { + // This will never actually wait, but that's fine because we only + // want to ensure that this typedArray CAN be waited on and is shareable. + Atomics.wait(temp, 0, Constructor === Int32Array ? 1 : BigInt(1)); + } catch (error) { + $ERROR(`${Constructor.name} cannot be used as a shared typed array. (${error})`); + } + + $262.agent.broadcast(typedArray.buffer); +}; + +$262.agent.safeBroadcastAsync = async function(ta, index, expected) { + await $262.agent.broadcast(ta.buffer); + await $262.agent.waitUntil(ta, index, expected); + await $262.agent.tryYield(); + return await Atomics.load(ta, index); +}; + + +/** + * With a given Int32Array or BigInt64Array, wait until the expected number of agents have + * reported themselves by calling: + * + * Atomics.add(typedArray, index, 1); + * + * @param {(Int32Array|BigInt64Array)} typedArray An Int32Array or BigInt64Array with a SharedArrayBuffer + * @param {number} index The index of which all agents will report. + * @param {number} expected The number of agents that are expected to report as active. + */ +$262.agent.waitUntil = function(typedArray, index, expected) { + + var agents = 0; + while ((agents = Atomics.load(typedArray, index)) !== expected) { + /* nothing */ + } + assert.sameValue(agents, expected, "Reporting number of 'agents' equals the value of 'expected'"); +}; + +/** + * Timeout values used throughout the Atomics tests. All timeouts are specified in milliseconds. + * + * @property {number} yield Used for `$262.agent.tryYield`. Must not be used in other functions. + * @property {number} small Used when agents will always timeout and `Atomics.wake` is not part + * of the test semantics. Must be larger than `$262.agent.timeouts.yield`. + * @property {number} long Used when some agents may timeout and `Atomics.wake` is called on some + * agents. The agents are required to wait and this needs to be observable + * by the main thread. + * @property {number} huge Used when `Atomics.wake` is called on all waiting agents. The waiting + * must not timeout. The agents are required to wait and this needs to be + * observable by the main thread. All waiting agents must be woken by the + * main thread. + * + * Usage for `$262.agent.timeouts.small`: + * const WAIT_INDEX = 0; + * const RUNNING = 1; + * const TIMEOUT = $262.agent.timeouts.small; + * const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2)); + * + * $262.agent.start(` + * $262.agent.receiveBroadcast(function(sab) { + * const i32a = new Int32Array(sab); + * Atomics.add(i32a, ${RUNNING}, 1); + * + * $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); + * + * $262.agent.leaving(); + * }); + * `); + * $262.agent.safeBroadcast(i32a.buffer); + * + * // Wait until the agent was started and then try to yield control to increase + * // the likelihood the agent has called `Atomics.wait` and is now waiting. + * $262.agent.waitUntil(i32a, RUNNING, 1); + * $262.agent.tryYield(); + * + * // The agent is expected to time out. + * assert.sameValue($262.agent.getReport(), "timed-out"); + * + * + * Usage for `$262.agent.timeouts.long`: + * const WAIT_INDEX = 0; + * const RUNNING = 1; + * const NUMAGENT = 2; + * const TIMEOUT = $262.agent.timeouts.long; + * const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2)); + * + * for (let i = 0; i < NUMAGENT; i++) { + * $262.agent.start(` + * $262.agent.receiveBroadcast(function(sab) { + * const i32a = new Int32Array(sab); + * Atomics.add(i32a, ${RUNNING}, 1); + * + * $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); + * + * $262.agent.leaving(); + * }); + * `); + * } + * $262.agent.safeBroadcast(i32a.buffer); + * + * // Wait until the agents were started and then try to yield control to increase + * // the likelihood the agents have called `Atomics.wait` and are now waiting. + * $262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + * $262.agent.tryYield(); + * + * // Wake exactly one agent. + * assert.sameValue(Atomics.wake(i32a, WAIT_INDEX, 1), 1); + * + * // When it doesn't matter how many agents were woken at once, a while loop + * // can be used to make the test more resilient against intermittent failures + * // in case even though `tryYield` was called, the agents haven't started to + * // wait. + * // + * // // Repeat until exactly one agent was woken. + * // var woken = 0; + * // while ((woken = Atomics.wake(i32a, WAIT_INDEX, 1)) !== 0) ; + * // assert.sameValue(woken, 1); + * + * // One agent was woken and the other one timed out. + * const reports = [$262.agent.getReport(), $262.agent.getReport()]; + * assert(reports.includes("ok")); + * assert(reports.includes("timed-out")); + * + * + * Usage for `$262.agent.timeouts.huge`: + * const WAIT_INDEX = 0; + * const RUNNING = 1; + * const NUMAGENT = 2; + * const TIMEOUT = $262.agent.timeouts.huge; + * const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2)); + * + * for (let i = 0; i < NUMAGENT; i++) { + * $262.agent.start(` + * $262.agent.receiveBroadcast(function(sab) { + * const i32a = new Int32Array(sab); + * Atomics.add(i32a, ${RUNNING}, 1); + * + * $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); + * + * $262.agent.leaving(); + * }); + * `); + * } + * $262.agent.safeBroadcast(i32a.buffer); + * + * // Wait until the agents were started and then try to yield control to increase + * // the likelihood the agents have called `Atomics.wait` and are now waiting. + * $262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + * $262.agent.tryYield(); + * + * // Wake all agents. + * assert.sameValue(Atomics.wake(i32a, WAIT_INDEX), NUMAGENT); + * + * // When it doesn't matter how many agents were woken at once, a while loop + * // can be used to make the test more resilient against intermittent failures + * // in case even though `tryYield` was called, the agents haven't started to + * // wait. + * // + * // // Repeat until all agents were woken. + * // for (var wokenCount = 0; wokenCount < NUMAGENT; ) { + * // var woken = 0; + * // while ((woken = Atomics.wake(i32a, WAIT_INDEX)) !== 0) ; + * // // Maybe perform an action on the woken agents here. + * // wokenCount += woken; + * // } + * + * // All agents were woken and none timeout. + * for (var i = 0; i < NUMAGENT; i++) { + * assert($262.agent.getReport(), "ok"); + * } + */ +$262.agent.timeouts = { + yield: 100, + small: 200, + long: 1000, + huge: 10000, +}; + +/** + * Try to yield control to the agent threads. + * + * Usage: + * const VALUE = 0; + * const RUNNING = 1; + * const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2)); + * + * $262.agent.start(` + * $262.agent.receiveBroadcast(function(sab) { + * const i32a = new Int32Array(sab); + * Atomics.add(i32a, ${RUNNING}, 1); + * + * Atomics.store(i32a, ${VALUE}, 1); + * + * $262.agent.leaving(); + * }); + * `); + * $262.agent.safeBroadcast(i32a.buffer); + * + * // Wait until agent was started and then try to yield control. + * $262.agent.waitUntil(i32a, RUNNING, 1); + * $262.agent.tryYield(); + * + * // Note: This result is not guaranteed, but should hold in practice most of the time. + * assert.sameValue(Atomics.load(i32a, VALUE), 1); + * + * The default implementation simply waits for `$262.agent.timeouts.yield` milliseconds. + */ +$262.agent.tryYield = function() { + $262.agent.sleep($262.agent.timeouts.yield); +}; + +/** + * Try to sleep the current agent for the given amount of milliseconds. It is acceptable, + * but not encouraged, to ignore this sleep request and directly continue execution. + * + * The default implementation calls `$262.agent.sleep(ms)`. + * + * @param {number} ms Time to sleep in milliseconds. + */ +$262.agent.trySleep = function(ms) { + $262.agent.sleep(ms); +}; + +// file: detachArrayBuffer.js +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + A function used in the process of asserting correctness of TypedArray objects. + + $262.detachArrayBuffer is defined by a host. +defines: [$DETACHBUFFER] +---*/ + +function $DETACHBUFFER(buffer) { + if (!$262 || typeof $262.detachArrayBuffer !== "function") { + throw new Test262Error("No method available to detach an ArrayBuffer"); + } + $262.detachArrayBuffer(buffer); +} diff --git a/js/src/tests/test262/built-ins/Atomics/wait/symbol-for-index-throws-agent.js b/js/src/tests/test262/built-ins/Atomics/wait/symbol-for-index-throws-agent.js new file mode 100644 index 0000000000..771b497c4e --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/symbol-for-index-throws-agent.js @@ -0,0 +1,95 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Throws a TypeError if index arg can not be converted to an Integer +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 2. Let i be ? ValidateAtomicAccess(typedArray, index). + + ValidateAtomicAccess( typedArray, requestIndex ) + + 2. Let accessIndex be ? ToIndex(requestIndex). + + ToIndex ( value ) + + 2. Else, + a. Let integerIndex be ? ToInteger(value). + + ToInteger(value) + + 1. Let number be ? ToNumber(argument). + + Symbol --> Throw a TypeError exception. + +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray] +---*/ + +const RUNNING = 1; + +$262.agent.start(` + const poisonedValueOf = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } + }; + + const poisonedToPrimitive = { + [Symbol.toPrimitive]: function() { + throw new Test262Error("passing a poisoned object using @@ToPrimitive"); + } + }; + + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + let status1 = ""; + let status2 = ""; + + try { + Atomics.wait(i32a, Symbol("1"), poisonedValueOf, poisonedValueOf); + } catch (error) { + status1 = 'Symbol("1")'; + } + try { + Atomics.wait(i32a, Symbol("2"), poisonedToPrimitive, poisonedToPrimitive); + } catch (error) { + status2 = 'Symbol("2")'; + } + + $262.agent.report(status1); + $262.agent.report(status2); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue( + $262.agent.getReport(), + 'Symbol("1")', + '$262.agent.getReport() returns "Symbol("1")"' +); +assert.sameValue( + $262.agent.getReport(), + 'Symbol("2")', + '$262.agent.getReport() returns "Symbol("2")"' +); + +assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/symbol-for-index-throws.js b/js/src/tests/test262/built-ins/Atomics/wait/symbol-for-index-throws.js new file mode 100644 index 0000000000..d5f12ffbdf --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/symbol-for-index-throws.js @@ -0,0 +1,64 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Throws a TypeError if index arg can not be converted to an Integer +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 2. Let i be ? ValidateAtomicAccess(typedArray, index). + + ValidateAtomicAccess( typedArray, requestIndex ) + + 2. Let accessIndex be ? ToIndex(requestIndex). + + ToIndex ( value ) + + 2. Else, + a. Let integerIndex be ? ToInteger(value). + + ToInteger(value) + + 1. Let number be ? ToNumber(argument). + + Symbol --> Throw a TypeError exception. + +features: [Atomics, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisonedValueOf = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +const poisonedToPrimitive = { + [Symbol.toPrimitive]: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(Test262Error, function() { + Atomics.wait(i32a, poisonedValueOf, poisonedValueOf, poisonedValueOf); +}, '`Atomics.wait(i32a, poisonedValueOf, poisonedValueOf, poisonedValueOf)` throws Test262Error'); + +assert.throws(Test262Error, function() { + Atomics.wait(i32a, poisonedToPrimitive, poisonedToPrimitive, poisonedToPrimitive); +}, '`Atomics.wait(i32a, poisonedToPrimitive, poisonedToPrimitive, poisonedToPrimitive)` throws Test262Error'); + +assert.throws(TypeError, function() { + Atomics.wait(i32a, Symbol('foo'), poisonedValueOf, poisonedValueOf); +}, '`Atomics.wait(i32a, Symbol(\'foo\'), poisonedValueOf, poisonedValueOf)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.wait(i32a, Symbol('foo'), poisonedToPrimitive, poisonedToPrimitive); +}, '`Atomics.wait(i32a, Symbol(\'foo\'), poisonedToPrimitive, poisonedToPrimitive)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/symbol-for-timeout-throws-agent.js b/js/src/tests/test262/built-ins/Atomics/wait/symbol-for-timeout-throws-agent.js new file mode 100644 index 0000000000..d30d0f0488 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/symbol-for-timeout-throws-agent.js @@ -0,0 +1,70 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Throws a TypeError if index arg can not be converted to an Integer +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 4. Let q be ? ToNumber(timeout). + + Symbol --> Throw a TypeError exception. + +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray] +---*/ + +const RUNNING = 1; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + let status1 = ""; + let status2 = ""; + + try { + Atomics.wait(i32a, 0, 0, Symbol("1")); + } catch (error) { + status1 = 'Symbol("1")'; + } + try { + Atomics.wait(i32a, 0, 0, Symbol("2")); + } catch (error) { + status2 = 'Symbol("2")'; + } + + $262.agent.report(status1); + $262.agent.report(status2); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue( + $262.agent.getReport(), + 'Symbol("1")', + '$262.agent.getReport() returns "Symbol("1")"' +); +assert.sameValue( + $262.agent.getReport(), + 'Symbol("2")', + '$262.agent.getReport() returns "Symbol("2")"' +); + +assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/symbol-for-timeout-throws.js b/js/src/tests/test262/built-ins/Atomics/wait/symbol-for-timeout-throws.js new file mode 100644 index 0000000000..a6be3df183 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/symbol-for-timeout-throws.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Throws a TypeError if index arg can not be converted to an Integer +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 4. Let q be ? ToNumber(timeout). + + Symbol --> Throw a TypeError exception. + +features: [Atomics, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray] +---*/ + +var buffer = new SharedArrayBuffer(1024); +var i32a = new Int32Array(buffer); + +var poisonedValueOf = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +var poisonedToPrimitive = { + [Symbol.toPrimitive]: function() { + throw new Test262Error('passing a poisoned object using @@ToPrimitive'); + } +}; + +assert.throws(Test262Error, function() { + Atomics.wait(i32a, 0, 0, poisonedValueOf); +}, '`Atomics.wait(i32a, 0, 0, poisonedValueOf)` throws Test262Error'); + +assert.throws(Test262Error, function() { + Atomics.wait(i32a, 0, 0, poisonedToPrimitive); +}, '`Atomics.wait(i32a, 0, 0, poisonedToPrimitive)` throws Test262Error'); + +assert.throws(TypeError, function() { + Atomics.wait(i32a, 0, 0, Symbol("foo")); +}, '`Atomics.wait(i32a, 0, 0, Symbol("foo"))` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.wait(i32a, 0, 0, Symbol("foo")); +}, '`Atomics.wait(i32a, 0, 0, Symbol("foo"))` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/symbol-for-value-throws-agent.js b/js/src/tests/test262/built-ins/Atomics/wait/symbol-for-value-throws-agent.js new file mode 100644 index 0000000000..5491987f91 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/symbol-for-value-throws-agent.js @@ -0,0 +1,86 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Throws a TypeError if value arg is a Symbol +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 3. Let v be ? ToInt32(value). + + ToInt32(value) + + 1.Let number be ? ToNumber(argument). + + Symbol --> Throw a TypeError exception. + +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray] +---*/ + +const RUNNING = 1; + +$262.agent.start(` + const poisonedValueOf = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } + }; + + const poisonedToPrimitive = { + [Symbol.toPrimitive]: function() { + throw new Test262Error("passing a poisoned object using @@ToPrimitive"); + } + }; + + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + let status1 = ""; + let status2 = ""; + + try { + Atomics.wait(i32a, 0, Symbol("1"), poisonedValueOf); + } catch (error) { + status1 = 'Symbol("1")'; + } + try { + Atomics.wait(i32a, 0, Symbol("2"), poisonedToPrimitive); + } catch (error) { + status2 = 'Symbol("2")'; + } + + $262.agent.report(status1); + $262.agent.report(status2); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue( + $262.agent.getReport(), + 'Symbol("1")', + '$262.agent.getReport() returns "Symbol("1")"' +); +assert.sameValue( + $262.agent.getReport(), + 'Symbol("2")', + '$262.agent.getReport() returns "Symbol("2")"' +); + +assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/symbol-for-value-throws.js b/js/src/tests/test262/built-ins/Atomics/wait/symbol-for-value-throws.js new file mode 100644 index 0000000000..52a0bbfbf0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/symbol-for-value-throws.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Throws a TypeError if value arg is a Symbol +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 3. Let v be ? ToInt32(value). + + ToInt32(value) + + 1.Let number be ? ToNumber(argument). + + Symbol --> Throw a TypeError exception. + +features: [Atomics, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisonedValueOf = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } +}; + +const poisonedToPrimitive = { + [Symbol.toPrimitive]: function() { + throw new Test262Error("passing a poisoned object using @@ToPrimitive"); + } +}; + +assert.throws(Test262Error, function() { + Atomics.wait(i32a, 0, poisonedValueOf, poisonedValueOf); +}, '`Atomics.wait(i32a, 0, poisonedValueOf, poisonedValueOf)` throws Test262Error'); + +assert.throws(Test262Error, function() { + Atomics.wait(i32a, 0, poisonedToPrimitive, poisonedToPrimitive); +}, '`Atomics.wait(i32a, 0, poisonedToPrimitive, poisonedToPrimitive)` throws Test262Error'); + +assert.throws(TypeError, function() { + Atomics.wait(i32a, 0, Symbol("foo"), poisonedValueOf); +}, '`Atomics.wait(i32a, 0, Symbol("foo"), poisonedValueOf)` throws TypeError'); + +assert.throws(TypeError, function() { + Atomics.wait(i32a, 0, Symbol("foo"), poisonedToPrimitive); +}, '`Atomics.wait(i32a, 0, Symbol("foo"), poisonedToPrimitive)` throws TypeError'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/true-for-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/wait/true-for-timeout-agent.js new file mode 100644 index 0000000000..383815abc1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/true-for-timeout-agent.js @@ -0,0 +1,78 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + True timeout arg should result in an +0 timeout +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 4. Let q be ? ToNumber(timeout). + + Boolean -> If argument is true, return 1. If argument is false, return +0. + +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; + +$262.agent.start(` + const valueOf = { + valueOf: function() { + return true; + } + }; + + const toPrimitive = { + [Symbol.toPrimitive]: function() { + return true; + } + }; + + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const status1 = Atomics.wait(i32a, 0, 0, true); + const status2 = Atomics.wait(i32a, 0, 0, valueOf); + const status3 = Atomics.wait(i32a, 0, 0, toPrimitive); + + $262.agent.report(status1); + $262.agent.report(status2); + $262.agent.report(status3); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); +assert.sameValue( + $262.agent.getReport(), + 'timed-out', + '$262.agent.getReport() returns "timed-out"' +); + +assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/true-for-timeout.js b/js/src/tests/test262/built-ins/Atomics/wait/true-for-timeout.js new file mode 100644 index 0000000000..3dbc97048a --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/true-for-timeout.js @@ -0,0 +1,52 @@ +// |reftest| skip-if(!xulRuntime.shell||!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- browser cannot block main thread, Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Throws a TypeError if index arg can not be converted to an Integer +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 4. Let q be ? ToNumber(timeout). + + Boolean -> If argument is true, return 1. If argument is false, return +0. + +features: [Atomics, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray] +flags: [CanBlockIsTrue] +---*/ + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const valueOf = { + valueOf: function() { + return true; + } +}; + +const toPrimitive = { + [Symbol.toPrimitive]: function() { + return true; + } +}; + +assert.sameValue( + Atomics.wait(i32a, 0, 0, true), + 'timed-out', + 'Atomics.wait(i32a, 0, 0, true) returns "timed-out"' +); +assert.sameValue( + Atomics.wait(i32a, 0, 0, valueOf), + 'timed-out', + 'Atomics.wait(i32a, 0, 0, valueOf) returns "timed-out"' +); +assert.sameValue( + Atomics.wait(i32a, 0, 0, toPrimitive), + 'timed-out', + 'Atomics.wait(i32a, 0, 0, toPrimitive) returns "timed-out"' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/undefined-for-timeout.js b/js/src/tests/test262/built-ins/Atomics/wait/undefined-for-timeout.js new file mode 100644 index 0000000000..834b962422 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/undefined-for-timeout.js @@ -0,0 +1,73 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Undefined timeout arg should result in an infinite timeout +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 4.Let q be ? ToNumber(timeout). + ... + Undefined Return NaN. + 5.If q is NaN, let t be +∞, else let t be max(q, 0) + +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const WAIT_INDEX = 0; // Index all agents are waiting on +const RUNNING = 1; +const NUMAGENT = 2; // Total number of agents started +const NOTIFYCOUNT = 2; // Total number of agents to notify up + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + var i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // undefined => NaN => +Infinity + $262.agent.report("A " + Atomics.wait(i32a, 0, 0, undefined)); + $262.agent.leaving(); + }); +`); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + var i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // undefined timeout arg => NaN => +Infinity + $262.agent.report("B " + Atomics.wait(i32a, 0, 0)); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue( + Atomics.notify(i32a, WAIT_INDEX, NOTIFYCOUNT), + NOTIFYCOUNT, + 'Atomics.notify(i32a, WAIT_INDEX, NOTIFYCOUNT) returns the value of `NOTIFYCOUNT` (2)' +); + +const reports = []; +for (var i = 0; i < NUMAGENT; i++) { + reports.push($262.agent.getReport()); +} +reports.sort(); + +assert.sameValue(reports[0], 'A ok', 'The value of reports[0] is "A ok"'); +assert.sameValue(reports[1], 'B ok', 'The value of reports[1] is "B ok"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/undefined-index-defaults-to-zero.js b/js/src/tests/test262/built-ins/Atomics/wait/undefined-index-defaults-to-zero.js new file mode 100644 index 0000000000..3ea0dcc133 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/undefined-index-defaults-to-zero.js @@ -0,0 +1,53 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.wait +description: > + An undefined index arg should translate to 0 +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 2.Let i be ? ValidateAtomicAccess(typedArray, index). + ... + 2.Let accessIndex be ? ToIndex(requestIndex). + + 9.If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception. + ... + 3.If bufferData is a Data Block, return false + + If value is undefined, then + Let index be 0. + +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.long; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + $262.agent.report(Atomics.wait(i32a, undefined, 0, ${TIMEOUT})); // undefined index => 0 + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue(Atomics.notify(i32a, 0), 1, 'Atomics.notify(i32a, 0) returns 1'); // notify at index 0 +assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); // notify again at index 0, and 0 agents should be woken +assert.sameValue($262.agent.getReport(), 'ok', '$262.agent.getReport() returns "ok"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/validate-arraytype-before-index-coercion.js b/js/src/tests/test262/built-ins/Atomics/wait/validate-arraytype-before-index-coercion.js new file mode 100644 index 0000000000..313d965bec --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/validate-arraytype-before-index-coercion.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + TypedArray type is validated before `index` argument is coerced. +info: | + 24.4.11 Atomics.wait ( typedArray, index, value, timeout ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var index = { + valueOf() { + throw new Test262Error("index coerced"); + } +}; + +var badArrayTypes = [ + Int8Array, Uint8Array, Int16Array, Uint16Array, Uint32Array, + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.wait(typedArray, index, 0, 0); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/validate-arraytype-before-timeout-coercion.js b/js/src/tests/test262/built-ins/Atomics/wait/validate-arraytype-before-timeout-coercion.js new file mode 100644 index 0000000000..bed63347e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/validate-arraytype-before-timeout-coercion.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + TypedArray type is validated before `timeout` argument is coerced. +info: | + 24.4.11 Atomics.wait ( typedArray, index, value, timeout ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var timeout = { + valueOf() { + throw new Test262Error("timeout coerced"); + } +}; + +var badArrayTypes = [ + Int8Array, Uint8Array, Int16Array, Uint16Array, Uint32Array, + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.wait(typedArray, 0, 0, timeout); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/validate-arraytype-before-value-coercion.js b/js/src/tests/test262/built-ins/Atomics/wait/validate-arraytype-before-value-coercion.js new file mode 100644 index 0000000000..6b2a6547a7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/validate-arraytype-before-value-coercion.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + TypedArray type is validated before `value` argument is coerced. +info: | + 24.4.11 Atomics.wait ( typedArray, index, value, timeout ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var value = { + valueOf() { + throw new Test262Error("value coerced"); + } +}; + +var badArrayTypes = [ + Int8Array, Uint8Array, Int16Array, Uint16Array, Uint32Array, + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.wait(typedArray, 0, value, 0); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/value-not-equal.js b/js/src/tests/test262/built-ins/Atomics/wait/value-not-equal.js new file mode 100644 index 0000000000..e5ecb4a34b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/value-not-equal.js @@ -0,0 +1,62 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Returns "not-equal" when value arg does not match an index in the typedArray +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 3.Let v be ? ToInt32(value). + ... + 14.If v is not equal to w, then + a.Perform LeaveCriticalSection(WL). + b. Return the String "not-equal". + +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; + +var value = 42; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + $262.agent.report(Atomics.store(i32a, 0, ${value})); + $262.agent.report(Atomics.wait(i32a, 0, 0)); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +// NB: We don't actually explicitly need to wait for the agent to start in this +// test case, we only do it for consistency with other test cases which do +// require the main agent to wait and yield control. + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue( + $262.agent.getReport(), + value.toString(), + '$262.agent.getReport() returns value.toString()' +); +assert.sameValue( + $262.agent.getReport(), + 'not-equal', + '$262.agent.getReport() returns "not-equal"' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/wait-index-value-not-equal.js b/js/src/tests/test262/built-ins/Atomics/wait/wait-index-value-not-equal.js new file mode 100644 index 0000000000..1947cd6a93 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/wait-index-value-not-equal.js @@ -0,0 +1,60 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Returns "not-equal" when value of index is not equal +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 14.If v is not equal to w, then + a.Perform LeaveCriticalSection(WL). + b. Return the String "not-equal". + +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + $262.agent.report(Atomics.wait(i32a, 0, 44, ${TIMEOUT})); + $262.agent.report(Atomics.wait(i32a, 0, 251.4, ${TIMEOUT})); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +// NB: We don't actually explicitly need to wait for the agent to start in this +// test case, we only do it for consistency with other test cases which do +// require the main agent to wait and yield control. + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue( + $262.agent.getReport(), + 'not-equal', + '$262.agent.getReport() returns "not-equal"' +); +assert.sameValue( + $262.agent.getReport(), + 'not-equal', + '$262.agent.getReport() returns "not-equal"' +); +assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/waiterlist-block-indexedposition-wake.js b/js/src/tests/test262/built-ins/Atomics/wait/waiterlist-block-indexedposition-wake.js new file mode 100644 index 0000000000..f3b2a06300 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/waiterlist-block-indexedposition-wake.js @@ -0,0 +1,78 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + Get the correct WaiterList +info: | + Atomics.wait( typedArray, index, value, timeout ) + + ... + 11. Let WL be GetWaiterList(block, indexedPosition). + ... + + + GetWaiterList( block, i ) + + ... + 4. Return the WaiterList that is referenced by the pair (block, i). + +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +var NUMAGENT = 2; +var RUNNING = 4; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // Wait on index 0 + $262.agent.report(Atomics.wait(i32a, 0, 0, Infinity)); + $262.agent.leaving(); + }); +`); + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // Wait on index 2 + $262.agent.report(Atomics.wait(i32a, 2, 0, Infinity)); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 5) +); + +$262.agent.safeBroadcast(i32a); + +// Wait until all agents started. +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +// Notify index 1, notifies nothing +assert.sameValue(Atomics.notify(i32a, 1), 0, 'Atomics.notify(i32a, 1) returns 0'); + +// Notify index 3, notifies nothing +assert.sameValue(Atomics.notify(i32a, 3), 0, 'Atomics.notify(i32a, 3) returns 0'); + +// Notify index 2, notifies 1 +var woken = 0; +while ((woken = Atomics.notify(i32a, 2)) === 0) ; +assert.sameValue(woken, 1, 'Atomics.notify(i32a, 2) returns 1'); +assert.sameValue($262.agent.getReport(), 'ok', '$262.agent.getReport() returns "ok"'); + +// Notify index 0, notifies 1 +var woken = 0; +while ((woken = Atomics.notify(i32a, 0)) === 0) ; +assert.sameValue(woken, 1, 'Atomics.notify(i32a, 0) returns 1'); +assert.sameValue($262.agent.getReport(), 'ok', '$262.agent.getReport() returns "ok"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/waiterlist-order-of-operations-is-fifo.js b/js/src/tests/test262/built-ins/Atomics/wait/waiterlist-order-of-operations-is-fifo.js new file mode 100644 index 0000000000..42fd5d4827 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/waiterlist-order-of-operations-is-fifo.js @@ -0,0 +1,96 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.wait +description: > + New waiters should be applied to the end of the list and woken by order they entered the list (FIFO) +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 16.Perform AddWaiter(WL, W). + ... + 3.Add W to the end of the list of waiters in WL. + +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +var NUMAGENT = 3; + +var WAIT_INDEX = 0; +var RUNNING = 1; +var LOCK_INDEX = 2; + +for (var i = 0; i < NUMAGENT; i++) { + var agentNum = i; + + $262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // Synchronize workers before reporting the initial report. + while (Atomics.compareExchange(i32a, ${LOCK_INDEX}, 0, 1) !== 0) ; + + // Report the agent number before waiting. + $262.agent.report(${agentNum}); + + // Wait until restarted by main thread. + var status = Atomics.wait(i32a, ${WAIT_INDEX}, 0); + + // Report wait status. + $262.agent.report(status); + + // Report the agent number after waiting. + $262.agent.report(${agentNum}); + + $262.agent.leaving(); + }); + `); +} + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcast(i32a); + +// Wait until all agents started. +$262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + +// Agents may be started in any order. +const started = []; +for (var i = 0; i < NUMAGENT; i++) { + // Wait until an agent entered its critical section. + $262.agent.waitUntil(i32a, LOCK_INDEX, 1); + + // Record the agent number. + started.push($262.agent.getReport()); + + // The agent may have been interrupted between reporting its initial report + // and the `Atomics.wait` call. Try to yield control to ensure the agent + // actually started to wait. + $262.agent.tryYield(); + + // Now continue with the next agent. + Atomics.store(i32a, LOCK_INDEX, 0); +} + +// Agents must notify in the order they waited. +for (var i = 0; i < NUMAGENT; i++) { + var woken = 0; + while ((woken = Atomics.notify(i32a, WAIT_INDEX, 1)) === 0) ; + + assert.sameValue(woken, 1, + 'Atomics.notify(i32a, WAIT_INDEX, 1) returns 1, at index = ' + i); + + assert.sameValue($262.agent.getReport(), 'ok', + '$262.agent.getReport() returns "ok", at index = ' + i); + + assert.sameValue($262.agent.getReport(), started[i], + '$262.agent.getReport() returns the value of `started[' + i + ']`'); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/wait/was-woken-before-timeout.js b/js/src/tests/test262/built-ins/Atomics/wait/was-woken-before-timeout.js new file mode 100644 index 0000000000..b1f132660e --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/wait/was-woken-before-timeout.js @@ -0,0 +1,64 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Amal Hussein. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.wait +description: > + Test that Atomics.wait returns the right result when it was awoken before + a timeout +info: | + Atomics.wait( typedArray, index, value, timeout ) + + 2.Let i be ? ValidateAtomicAccess(typedArray, index). + ... + 2.Let accessIndex be ? ToIndex(requestIndex). + + 9.If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception. + ... + 3.If bufferData is a Data Block, return false + + If value is undefined, then + Let index be 0. +includes: [atomicsHelper.js] +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.huge; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const before = $262.agent.monotonicNow(); + const unpark = Atomics.wait(i32a, 0, 0, ${TIMEOUT}); + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcast(i32a); +$262.agent.waitUntil(i32a, RUNNING, 1); + +// Try to yield control to ensure the agent actually started to wait. +$262.agent.tryYield(); + +assert.sameValue(Atomics.notify(i32a, 0), 1, 'Atomics.notify(i32a, 0) returns 1'); + +const lapse = $262.agent.getReport(); + +assert( + lapse < TIMEOUT, + 'The result of `(lapse < TIMEOUT)` is true' +); +assert.sameValue($262.agent.getReport(), 'ok', '$262.agent.getReport() returns "ok"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bad-range.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bad-range.js new file mode 100644 index 0000000000..251bb9384f --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bad-range.js @@ -0,0 +1,36 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Test range checking of Atomics.waitAsync on arrays that allow atomic operations +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + ... + 2. Let i be ? ValidateAtomicAccess(typedArray, index). + ... + +includes: [testAtomics.js] +features: [Atomics.waitAsync, Atomics, SharedArrayBuffer, ArrayBuffer, DataView, Symbol, TypedArray] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 8) +); + +testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.waitAsync(i32a, IdxGen(i32a), 0, 0); + }, '`Atomics.waitAsync(i32a, IdxGen(i32a), 0, 0)` throws a RangeError exception'); +}); + + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/bad-range.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/bad-range.js new file mode 100644 index 0000000000..a2214e5b2b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/bad-range.js @@ -0,0 +1,31 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Test range checking of Atomics.waitAsync on arrays that allow atomic operations +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + ... + 2. Let i be ? ValidateAtomicAccess(typedArray, index). + ... + +includes: [testAtomics.js] +features: [Atomics.waitAsync, Atomics, SharedArrayBuffer, ArrayBuffer, DataView, Symbol, TypedArray, BigInt] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 8)); + +testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.waitAsync(i64a, IdxGen(i64a), 0n, 0); + }, '`Atomics.waitAsync(i64a, IdxGen(i64a), 0n, 0)` throws a RangeError exception'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/browser.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/false-for-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/false-for-timeout-agent.js new file mode 100644 index 0000000000..37bb338b35 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/false-for-timeout-agent.js @@ -0,0 +1,96 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + False timeout arg should result in an +0 timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; + +$262.agent.start(` + const valueOf = { + valueOf() { + return false; + } + }; + + const toPrimitive = { + [Symbol.toPrimitive]() { + return false; + } + }; + + $262.agent.receiveBroadcast(async (sab) => { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + $262.agent.report(await Atomics.waitAsync(i64a, 0, 0n, false).value); + $262.agent.report(await Atomics.waitAsync(i64a, 0, 0n, valueOf).value); + $262.agent.report(await Atomics.waitAsync(i64a, 0, 0n, toPrimitive).value); + $262.agent.report(Atomics.waitAsync(i64a, 0, 0n, false).value); + $262.agent.report(Atomics.waitAsync(i64a, 0, 0n, valueOf).value); + $262.agent.report(Atomics.waitAsync(i64a, 0, 0n, toPrimitive).value); + $262.agent.leaving(); + }); +`); + +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + Atomics.notify(i64a, 0), + 0, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/false-for-timeout.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/false-for-timeout.js new file mode 100644 index 0000000000..78e5cb927c --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/false-for-timeout.js @@ -0,0 +1,61 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + False timeout arg should result in an +0 timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + +flags: [async] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, computed-property-names, Symbol, Symbol.toPrimitive, arrow-function] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +const valueOf = { + valueOf() { + return false; + } +}; + +const toPrimitive = { + [Symbol.toPrimitive]() { + return false; + } +}; + +assert.sameValue( + Atomics.waitAsync(i64a, 0, 0n, false).value, + 'timed-out', + 'The value of Atomics.waitAsync(i64a, 0, 0n, false).value is "timed-out"' +); + +assert.sameValue( + Atomics.waitAsync(i64a, 0, 0n, valueOf).value, + 'timed-out', + 'The value of Atomics.waitAsync(i64a, 0, 0n, valueOf).value is "timed-out"' +); + +assert.sameValue( + Atomics.waitAsync(i64a, 0, 0n, toPrimitive).value, + 'timed-out', + 'The value of Atomics.waitAsync(i64a, 0, 0n, toPrimitive).value is "timed-out"' +); + +Promise.all([ + Atomics.waitAsync(i64a, 0, 0n, false).value, + Atomics.waitAsync(i64a, 0, 0n, valueOf).value, + Atomics.waitAsync(i64a, 0, 0n, toPrimitive).value +]).then(outcomes => { + assert.sameValue(outcomes[0], 'timed-out', 'The value of outcomes[0] is "timed-out"'); + assert.sameValue(outcomes[1], 'timed-out', 'The value of outcomes[1] is "timed-out"'); + assert.sameValue(outcomes[2], 'timed-out', 'The value of outcomes[2] is "timed-out"'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/good-views.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/good-views.js new file mode 100644 index 0000000000..44d6f85d40 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/good-views.js @@ -0,0 +1,71 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Test Atomics.waitAsync on arrays that allow atomic operations +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, Atomics, BigInt] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +$262.agent.start(` + (async () => { + var sab = new SharedArrayBuffer(2048); + var good_indices = [ (view) => 0/-1, // -0 + (view) => '-0', + (view) => view.length - 1, + (view) => ({ valueOf: () => 0 }), + (view) => ({ toString: () => '0', valueOf: false }) // non-callable valueOf triggers invocation of toString + ]; + + var view = new BigInt64Array(sab, 32, 20); + + view[0] = 0n; + $262.agent.report("A " + (await Atomics.waitAsync(view, 0, 0n, 0).value)) + $262.agent.report("B " + (await Atomics.waitAsync(view, 0, 37n, 0).value)); + + const results = []; + // In-bounds boundary cases for indexing + for ( let IdxGen of good_indices ) { + let Idx = IdxGen(view); + view.fill(0n); + // Atomics.store() computes an index from Idx in the same way as other + // Atomics operations, not quite like view[Idx]. + Atomics.store(view, Idx, 37n); + results.push(await Atomics.waitAsync(view, Idx, 0n).value); + } + $262.agent.report("C " + results.join(",")); + + $262.agent.leaving(); + })(); +`); + + +(async () => { + const outcomes = []; + + for (let i = 0; i < 3; i++) { + outcomes.push(await $262.agent.getReportAsync()); + } + + assert.sameValue( + outcomes[0], + 'A timed-out', + 'The value of outcomes[0] is "A timed-out"' + ); + + assert.sameValue( + outcomes[1], + 'B not-equal', + 'The value of outcomes[1] is "B not-equal"' + ); + assert.sameValue( + outcomes[2], + 'C not-equal,not-equal,not-equal,not-equal,not-equal', + 'The value of outcomes[2] is "C not-equal,not-equal,not-equal,not-equal,not-equal"' + ); +})().then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/nan-for-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/nan-for-timeout-agent.js new file mode 100644 index 0000000000..70f79c11e0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/nan-for-timeout-agent.js @@ -0,0 +1,50 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + NaN timeout arg should result in an infinite timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + $262.agent.report(await Atomics.waitAsync(i64a, 0, 0n, NaN).value); // NaN => +Infinity + $262.agent.leaving(); + }); +`); + +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + + assert.sameValue( + Atomics.notify(i64a, 0), + 1, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 1' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'ok', + '(await $262.agent.getReportAsync()) resolves to the value "ok"' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/negative-index-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/negative-index-throws.js new file mode 100644 index 0000000000..0618a9aa71 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/negative-index-throws.js @@ -0,0 +1,46 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Throws a RangeError is index < 0 +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + 2. Let i be ? ValidateAtomicAccess(typedArray, index). + +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(RangeError, function() { + Atomics.waitAsync(i64a, -Infinity, poisoned, poisoned); +}, '`Atomics.waitAsync(i64a, -Infinity, poisoned, poisoned)` throws a RangeError exception'); +assert.throws(RangeError, function() { + Atomics.waitAsync(i64a, -7.999, poisoned, poisoned); +}, '`Atomics.waitAsync(i64a, -7.999, poisoned, poisoned)` throws a RangeError exception'); +assert.throws(RangeError, function() { + Atomics.waitAsync(i64a, -1, poisoned, poisoned); +}, '`Atomics.waitAsync(i64a, -1, poisoned, poisoned)` throws a RangeError exception'); +assert.throws(RangeError, function() { + Atomics.waitAsync(i64a, -300, poisoned, poisoned); +}, '`Atomics.waitAsync(i64a, -300, poisoned, poisoned)` throws a RangeError exception'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/negative-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/negative-timeout-agent.js new file mode 100644 index 0000000000..9ef681c34b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/negative-timeout-agent.js @@ -0,0 +1,49 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Test that Atomics.waitAsync times out with a negative timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + var i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + $262.agent.report(await Atomics.waitAsync(i64a, 0, 0n, -5).value); // -5 => 0 + $262.agent.leaving(); + }); +`); + +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + Atomics.notify(i64a, 0), + 0, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/negative-timeout.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/negative-timeout.js new file mode 100644 index 0000000000..2f0f64af62 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/negative-timeout.js @@ -0,0 +1,25 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Test that Atomics.waitAsync times out with a negative timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + +flags: [async] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, destructuring-binding, arrow-function] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +Promise.all([Atomics.waitAsync(i64a, 0, 0n, -1).value]).then(([outcome]) => { + assert.sameValue(outcome, 'timed-out', 'The value of `outcome` is "timed-out"'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-no-operation.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-no-operation.js new file mode 100644 index 0000000000..a87317a889 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-no-operation.js @@ -0,0 +1,61 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Test that Atomics.waitAsync returns the right result when it timed out and that + the time to time out is reasonable. +info: | + AddWaiter ( WL, waiterRecord ) + + 5. Append waiterRecord as the last element of WL.[[Waiters]] + 6. If waiterRecord.[[Timeout]] is finite, then in parallel, + a. Wait waiterRecord.[[Timeout]] milliseconds. + b. Perform TriggerTimeout(WL, waiterRecord). + + TriggerTimeout( WL, waiterRecord ) + + 3. If waiterRecord is in WL.[[Waiters]], then + a. Set waiterRecord.[[Result]] to "timed-out". + b. Perform RemoveWaiter(WL, waiterRecord). + c. Perform NotifyWaiter(WL, waiterRecord). + 4. Perform LeaveCriticalSection(WL). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const before = $262.agent.monotonicNow(); + const unpark = await Atomics.waitAsync(i64a, 0, 0n, ${TIMEOUT}).value; + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + const lapse = await $262.agent.getReportAsync(); + assert(lapse >= TIMEOUT, 'The result of evaluating `(lapse >= TIMEOUT)` is true'); + const result = await $262.agent.getReportAsync(); + assert.sameValue(result, 'timed-out', 'The value of `result` is "timed-out"'); + + assert.sameValue( + Atomics.notify(i64a, 0), + 0, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-add.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-add.js new file mode 100644 index 0000000000..e15da5a1e2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-add.js @@ -0,0 +1,61 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Waiter does not spuriously notify on index which is subject to Add operation +info: | + AddWaiter ( WL, waiterRecord ) + + 5. Append waiterRecord as the last element of WL.[[Waiters]] + 6. If waiterRecord.[[Timeout]] is finite, then in parallel, + a. Wait waiterRecord.[[Timeout]] milliseconds. + b. Perform TriggerTimeout(WL, waiterRecord). + + TriggerTimeout( WL, waiterRecord ) + + 3. If waiterRecord is in WL.[[Waiters]], then + a. Set waiterRecord.[[Result]] to "timed-out". + b. Perform RemoveWaiter(WL, waiterRecord). + c. Perform NotifyWaiter(WL, waiterRecord). + 4. Perform LeaveCriticalSection(WL). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const before = $262.agent.monotonicNow(); + const unpark = await Atomics.waitAsync(i64a, 0, 0n, ${TIMEOUT}).value; + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + Atomics.add(i64a, 0, 1n); + const lapse = await $262.agent.getReportAsync(); + assert(lapse >= TIMEOUT, 'The result of evaluating `(lapse >= TIMEOUT)` is true'); + const result = await $262.agent.getReportAsync(); + assert.sameValue(result, 'timed-out', 'The value of `result` is "timed-out"'); + + assert.sameValue( + Atomics.notify(i64a, 0), + 0, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-and.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-and.js new file mode 100644 index 0000000000..02ed9ef726 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-and.js @@ -0,0 +1,61 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Waiter does not spuriously notify on index which is subject to And operation +info: | + AddWaiter ( WL, waiterRecord ) + + 5. Append waiterRecord as the last element of WL.[[Waiters]] + 6. If waiterRecord.[[Timeout]] is finite, then in parallel, + a. Wait waiterRecord.[[Timeout]] milliseconds. + b. Perform TriggerTimeout(WL, waiterRecord). + + TriggerTimeout( WL, waiterRecord ) + + 3. If waiterRecord is in WL.[[Waiters]], then + a. Set waiterRecord.[[Result]] to "timed-out". + b. Perform RemoveWaiter(WL, waiterRecord). + c. Perform NotifyWaiter(WL, waiterRecord). + 4. Perform LeaveCriticalSection(WL). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const before = $262.agent.monotonicNow(); + const unpark = await Atomics.waitAsync(i64a, 0, 0n, ${TIMEOUT}).value; + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + Atomics.and(i64a, 0, 1n); + const lapse = await $262.agent.getReportAsync(); + assert(lapse >= TIMEOUT, 'The result of evaluating `(lapse >= TIMEOUT)` is true'); + const result = await $262.agent.getReportAsync(); + assert.sameValue(result, 'timed-out', 'The value of `result` is "timed-out"'); + + assert.sameValue( + Atomics.notify(i64a, 0), + 0, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-compareExchange.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-compareExchange.js new file mode 100644 index 0000000000..36308c49b6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-compareExchange.js @@ -0,0 +1,61 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Waiter does not spuriously notify on index which is subject to compareExchange operation +info: | + AddWaiter ( WL, waiterRecord ) + + 5. Append waiterRecord as the last element of WL.[[Waiters]] + 6. If waiterRecord.[[Timeout]] is finite, then in parallel, + a. Wait waiterRecord.[[Timeout]] milliseconds. + b. Perform TriggerTimeout(WL, waiterRecord). + + TriggerTimeout( WL, waiterRecord ) + + 3. If waiterRecord is in WL.[[Waiters]], then + a. Set waiterRecord.[[Result]] to "timed-out". + b. Perform RemoveWaiter(WL, waiterRecord). + c. Perform NotifyWaiter(WL, waiterRecord). + 4. Perform LeaveCriticalSection(WL). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const before = $262.agent.monotonicNow(); + const unpark = await Atomics.waitAsync(i64a, 0, 0n, ${TIMEOUT}).value; + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + Atomics.compareExchange(i64a, 0, 0n, 1n); + const lapse = await $262.agent.getReportAsync(); + assert(lapse >= TIMEOUT, 'The result of evaluating `(lapse >= TIMEOUT)` is true'); + const result = await $262.agent.getReportAsync(); + assert.sameValue(result, 'timed-out', 'The value of `result` is "timed-out"'); + + assert.sameValue( + Atomics.notify(i64a, 0), + 0, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-exchange.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-exchange.js new file mode 100644 index 0000000000..93e73140bb --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-exchange.js @@ -0,0 +1,61 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Waiter does not spuriously notify on index which is subject to exchange operation +info: | + AddWaiter ( WL, waiterRecord ) + + 5. Append waiterRecord as the last element of WL.[[Waiters]] + 6. If waiterRecord.[[Timeout]] is finite, then in parallel, + a. Wait waiterRecord.[[Timeout]] milliseconds. + b. Perform TriggerTimeout(WL, waiterRecord). + + TriggerTimeout( WL, waiterRecord ) + + 3. If waiterRecord is in WL.[[Waiters]], then + a. Set waiterRecord.[[Result]] to "timed-out". + b. Perform RemoveWaiter(WL, waiterRecord). + c. Perform NotifyWaiter(WL, waiterRecord). + 4. Perform LeaveCriticalSection(WL). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const before = $262.agent.monotonicNow(); + const unpark = await Atomics.waitAsync(i64a, 0, 0n, ${TIMEOUT}).value; + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + Atomics.exchange(i64a, 0, 1n); + const lapse = await $262.agent.getReportAsync(); + assert(lapse >= TIMEOUT, 'The result of evaluating `(lapse >= TIMEOUT)` is true'); + const result = await $262.agent.getReportAsync(); + assert.sameValue(result, 'timed-out', 'The value of `result` is "timed-out"'); + + assert.sameValue( + Atomics.notify(i64a, 0), + 0, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-or.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-or.js new file mode 100644 index 0000000000..321f100417 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-or.js @@ -0,0 +1,61 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Waiter does not spuriously notify on index which is subject to Or operation +info: | + AddWaiter ( WL, waiterRecord ) + + 5. Append waiterRecord as the last element of WL.[[Waiters]] + 6. If waiterRecord.[[Timeout]] is finite, then in parallel, + a. Wait waiterRecord.[[Timeout]] milliseconds. + b. Perform TriggerTimeout(WL, waiterRecord). + + TriggerTimeout( WL, waiterRecord ) + + 3. If waiterRecord is in WL.[[Waiters]], then + a. Set waiterRecord.[[Result]] to "timed-out". + b. Perform RemoveWaiter(WL, waiterRecord). + c. Perform NotifyWaiter(WL, waiterRecord). + 4. Perform LeaveCriticalSection(WL). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const before = $262.agent.monotonicNow(); + const unpark = await Atomics.waitAsync(i64a, 0, 0n, ${TIMEOUT}).value; + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + Atomics.or(i64a, 0, 1n); + const lapse = await $262.agent.getReportAsync(); + assert(lapse >= TIMEOUT, 'The result of evaluating `(lapse >= TIMEOUT)` is true'); + const result = await $262.agent.getReportAsync(); + assert.sameValue(result, 'timed-out', 'The value of `result` is "timed-out"'); + + assert.sameValue( + Atomics.notify(i64a, 0), + 0, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-store.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-store.js new file mode 100644 index 0000000000..74b2a930b2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-store.js @@ -0,0 +1,61 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Waiter does not spuriously notify on index which is subject to Store operation +info: | + AddWaiter ( WL, waiterRecord ) + + 5. Append waiterRecord as the last element of WL.[[Waiters]] + 6. If waiterRecord.[[Timeout]] is finite, then in parallel, + a. Wait waiterRecord.[[Timeout]] milliseconds. + b. Perform TriggerTimeout(WL, waiterRecord). + + TriggerTimeout( WL, waiterRecord ) + + 3. If waiterRecord is in WL.[[Waiters]], then + a. Set waiterRecord.[[Result]] to "timed-out". + b. Perform RemoveWaiter(WL, waiterRecord). + c. Perform NotifyWaiter(WL, waiterRecord). + 4. Perform LeaveCriticalSection(WL). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const before = $262.agent.monotonicNow(); + const unpark = await Atomics.waitAsync(i64a, 0, 0n, ${TIMEOUT}).value; + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + Atomics.store(i64a, 0, 0b1010n); + const lapse = await $262.agent.getReportAsync(); + assert(lapse >= TIMEOUT, 'The result of evaluating `(lapse >= TIMEOUT)` is true'); + const result = await $262.agent.getReportAsync(); + assert.sameValue(result, 'timed-out', 'The value of `result` is "timed-out"'); + + assert.sameValue( + Atomics.notify(i64a, 0), + 0, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-sub.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-sub.js new file mode 100644 index 0000000000..9359795e8b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-sub.js @@ -0,0 +1,61 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Waiter does not spuriously notify on index which is subject to Sub operation +info: | + AddWaiter ( WL, waiterRecord ) + + 5. Append waiterRecord as the last element of WL.[[Waiters]] + 6. If waiterRecord.[[Timeout]] is finite, then in parallel, + a. Wait waiterRecord.[[Timeout]] milliseconds. + b. Perform TriggerTimeout(WL, waiterRecord). + + TriggerTimeout( WL, waiterRecord ) + + 3. If waiterRecord is in WL.[[Waiters]], then + a. Set waiterRecord.[[Result]] to "timed-out". + b. Perform RemoveWaiter(WL, waiterRecord). + c. Perform NotifyWaiter(WL, waiterRecord). + 4. Perform LeaveCriticalSection(WL). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const before = $262.agent.monotonicNow(); + const unpark = await Atomics.waitAsync(i64a, 0, 0n, ${TIMEOUT}).value; + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + Atomics.sub(i64a, 0, 1n); + const lapse = await $262.agent.getReportAsync(); + assert(lapse >= TIMEOUT, 'The result of evaluating `(lapse >= TIMEOUT)` is true'); + const result = await $262.agent.getReportAsync(); + assert.sameValue(result, 'timed-out', 'The value of `result` is "timed-out"'); + + assert.sameValue( + Atomics.notify(i64a, 0), + 0, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-xor.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-xor.js new file mode 100644 index 0000000000..dfc8d00b07 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/no-spurious-wakeup-on-xor.js @@ -0,0 +1,61 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Waiter does not spuriously notify on index which is subject to xor operation +info: | + AddWaiter ( WL, waiterRecord ) + + 5. Append waiterRecord as the last element of WL.[[Waiters]] + 6. If waiterRecord.[[Timeout]] is finite, then in parallel, + a. Wait waiterRecord.[[Timeout]] milliseconds. + b. Perform TriggerTimeout(WL, waiterRecord). + + TriggerTimeout( WL, waiterRecord ) + + 3. If waiterRecord is in WL.[[Waiters]], then + a. Set waiterRecord.[[Result]] to "timed-out". + b. Perform RemoveWaiter(WL, waiterRecord). + c. Perform NotifyWaiter(WL, waiterRecord). + 4. Perform LeaveCriticalSection(WL). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const before = $262.agent.monotonicNow(); + const unpark = await Atomics.waitAsync(i64a, 0, 0n, ${TIMEOUT}).value; + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + Atomics.xor(i64a, 0, 1n); + const lapse = await $262.agent.getReportAsync(); + assert(lapse >= TIMEOUT, 'The result of evaluating `(lapse >= TIMEOUT)` is true'); + const result = await $262.agent.getReportAsync(); + assert.sameValue(result, 'timed-out', 'The value of `result` is "timed-out"'); + + assert.sameValue( + Atomics.notify(i64a, 0), + 0, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/non-bigint64-typedarray-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/non-bigint64-typedarray-throws.js new file mode 100644 index 0000000000..a4e3dd79f7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/non-bigint64-typedarray-throws.js @@ -0,0 +1,38 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if typedArray arg is not an BigInt64Array +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + + ValidateSharedIntegerTypedArray ( typedArray [ , waitable ] ) + + 5. If waitable is true, then + a. If typeName is not "Int32Array" or "BigInt64Array", throw a TypeError exception. + +features: [Atomics.waitAsync, Float32Array, Float64Array, Int8Array, TypedArray, Uint16Array, Uint8Array, Uint8ClampedArray, arrow-function, SharedArrayBuffer, Atomics] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const poisoned = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, () => { + const view = new BigUint64Array(new SharedArrayBuffer(BigUint64Array.BYTES_PER_ELEMENT * 8)); + Atomics.waitAsync(view, poisoned, poisoned, poisoned); +}, '`const view = new BigUint64Array(new SharedArrayBuffer(BigUint64Array.BYTES_PER_ELEMENT * 8)); Atomics.waitAsync(view, poisoned, poisoned, poisoned)` throws a TypeError exception'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/non-shared-bufferdata-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/non-shared-bufferdata-throws.js new file mode 100644 index 0000000000..def8fe86ea --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/non-shared-bufferdata-throws.js @@ -0,0 +1,41 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if typedArray.buffer is not a SharedArrayBuffer +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + + ValidateSharedIntegerTypedArray ( typedArray [ , waitable ] ) + + 5. If waitable is true, then + a. If typeName is not "BigInt64Array" or "BigInt64Array", throw a TypeError exception. + +features: [Atomics.waitAsync, ArrayBuffer, Atomics, TypedArray, BigInt, arrow-function] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i64a = new BigInt64Array(new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +const poisoned = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, () => { + Atomics.waitAsync(i64a, 0, 0n, 0); +}, '`Atomics.waitAsync(i64a, 0, 0n, 0)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + Atomics.waitAsync(i64a, poisoned, poisoned, poisoned); +}, '`Atomics.waitAsync(i64a, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/not-a-typedarray-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/not-a-typedarray-throws.js new file mode 100644 index 0000000000..8fc491f329 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/not-a-typedarray-throws.js @@ -0,0 +1,44 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if the typedArray arg is not a TypedArray object +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + + ValidateSharedIntegerTypedArray ( typedArray [ , waitable ] ) + + 2. Perform ? RequireInternalSlot(typedArray, [[TypedArrayName]]). + + RequireInternalSlot ( O, internalSlot ) + + 1. If Type(O) is not Object, throw a TypeError exception. + 2. If O does not have an internalSlot internal slot, throw a TypeError exception. + +features: [Atomics.waitAsync, arrow-function, Atomics] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const poisoned = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, () => { + Atomics.waitAsync({}, 0, 0n, 0); +}, '`Atomics.waitAsync({}, 0, 0n, 0)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + Atomics.waitAsync({}, poisoned, poisoned, poisoned); +}, '`Atomics.waitAsync({}, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/not-an-object-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/not-an-object-throws.js new file mode 100644 index 0000000000..3f4caa0d05 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/not-an-object-throws.js @@ -0,0 +1,64 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if typedArray arg is not an Object +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + + ValidateSharedIntegerTypedArray ( typedArray [ , waitable ] ) + + 2. Perform ? RequireInternalSlot(typedArray, [[TypedArrayName]]). + + RequireInternalSlot ( O, internalSlot ) + + 1. If Type(O) is not Object, throw a TypeError exception. + 2. If O does not have an internalSlot internal slot, throw a TypeError exception. + +features: [Atomics.waitAsync, Symbol, arrow-function, Atomics] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const poisoned = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, () => { + Atomics.waitAsync(null, poisoned, poisoned, poisoned); +}, '`Atomics.waitAsync(null, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + Atomics.waitAsync(undefined, poisoned, poisoned, poisoned); +}, '`Atomics.waitAsync(undefined, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + Atomics.waitAsync(true, poisoned, poisoned, poisoned); +}, '`Atomics.waitAsync(true, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + Atomics.waitAsync(false, poisoned, poisoned, poisoned); +}, '`Atomics.waitAsync(false, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + Atomics.waitAsync('***string***', poisoned, poisoned, poisoned); +}, '`Atomics.waitAsync("***string***", poisoned, poisoned, poisoned)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + Atomics.waitAsync(Number.NEGATIVE_INFINITY, poisoned, poisoned, poisoned); +}, '`Atomics.waitAsync(Number.NEGATIVE_INFINITY, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + Atomics.waitAsync(Symbol('***symbol***'), poisoned, poisoned, poisoned); +}, '`Atomics.waitAsync(Symbol("***symbol***"), poisoned, poisoned, poisoned)` throws a TypeError exception'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/null-bufferdata-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/null-bufferdata-throws.js new file mode 100644 index 0000000000..07cc52ebb3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/null-bufferdata-throws.js @@ -0,0 +1,51 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + A null value for bufferData throws a TypeError +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + + ValidateSharedIntegerTypedArray ( typedArray [ , waitable ] ) + + 2. Perform ? RequireInternalSlot(typedArray, [[TypedArrayName]]). + + RequireInternalSlot ( O, internalSlot ) + + 1. If Type(O) is not Object, throw a TypeError exception. + 2. If O does not have an internalSlot internal slot, throw a TypeError exception. + +includes: [detachArrayBuffer.js] +features: [Atomics.waitAsync, ArrayBuffer, Atomics, TypedArray, BigInt] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i64a = new BigInt64Array( + new ArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +try { + $DETACHBUFFER(i64a.buffer); // Detaching a non-shared ArrayBuffer sets the [[ArrayBufferData]] value to null +} catch (error) { + $ERROR(`An unexpected error occurred when detaching ArrayBuffer: ${error.message}`); +} + +assert.throws(TypeError, function() { + Atomics.waitAsync(i64a, poisoned, poisoned, poisoned); +}, '`Atomics.waitAsync(i64a, poisoned, poisoned, poisoned)` throws a TypeError exception'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/null-for-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/null-for-timeout-agent.js new file mode 100644 index 0000000000..298f98d34f --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/null-for-timeout-agent.js @@ -0,0 +1,98 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + null timeout arg should result in an +0 timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + + Null -> Return +0. + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; + +$262.agent.start(` + const valueOf = { + valueOf() { + return null; + } + }; + + const toPrimitive = { + [Symbol.toPrimitive]() { + return null; + } + }; + + $262.agent.receiveBroadcast(async (sab) => { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + $262.agent.report(await Atomics.waitAsync(i64a, 0, 0n, null).value); + $262.agent.report(await Atomics.waitAsync(i64a, 0, 0n, valueOf).value); + $262.agent.report(await Atomics.waitAsync(i64a, 0, 0n, toPrimitive).value); + $262.agent.report(Atomics.waitAsync(i64a, 0, 0n, null).value); + $262.agent.report(Atomics.waitAsync(i64a, 0, 0n, valueOf).value); + $262.agent.report(Atomics.waitAsync(i64a, 0, 0n, toPrimitive).value); + $262.agent.leaving(); + }); +`); + +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + Atomics.notify(i64a, 0), + 0, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/null-for-timeout.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/null-for-timeout.js new file mode 100644 index 0000000000..9f50139d06 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/null-for-timeout.js @@ -0,0 +1,54 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + null timeout arg should result in an +0 timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + + Null -> Return +0. + +features: [Atomics.waitAsync, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray, computed-property-names, Atomics, BigInt, arrow-function] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +const valueOf = { + valueOf() { + return null; + } +}; + +const toPrimitive = { + [Symbol.toPrimitive]() { + return null; + } +}; + +assert.sameValue( + Atomics.waitAsync(i64a, 0, 0n, null).value, + 'timed-out', + 'The value of Atomics.waitAsync(i64a, 0, 0n, null).value is "timed-out"' +); + +assert.sameValue( + Atomics.waitAsync(i64a, 0, 0n, valueOf).value, + 'timed-out', + 'The value of Atomics.waitAsync(i64a, 0, 0n, valueOf).value is "timed-out"' +); + +assert.sameValue( + Atomics.waitAsync(i64a, 0, 0n, toPrimitive).value, + 'timed-out', + 'The value of Atomics.waitAsync(i64a, 0, 0n, toPrimitive).value is "timed-out"' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/object-for-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/object-for-timeout-agent.js new file mode 100644 index 0000000000..be0fece5ee --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/object-for-timeout-agent.js @@ -0,0 +1,107 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Object valueOf, toString, toPrimitive Zero timeout arg should result in an +0 timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + + Object -> Apply the following steps: + + Let primValue be ? ToPrimitive(argument, hint Number). + Return ? ToNumber(primValue). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; + +$262.agent.start(` + const valueOf = { + valueOf() { + return 0; + } + }; + + const toString = { + toString() { + return "0"; + } + }; + + const toPrimitive = { + [Symbol.toPrimitive]() { + return 0; + } + }; + + $262.agent.receiveBroadcast(async (sab) => { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + $262.agent.report(await Atomics.waitAsync(i64a, 0, 0n, valueOf).value); + $262.agent.report(await Atomics.waitAsync(i64a, 0, 0n, toString).value); + $262.agent.report(await Atomics.waitAsync(i64a, 0, 0n, toPrimitive).value); + $262.agent.report(Atomics.waitAsync(i64a, 0, 0n, valueOf).value); + $262.agent.report(Atomics.waitAsync(i64a, 0, 0n, toString).value); + $262.agent.report(Atomics.waitAsync(i64a, 0, 0n, toPrimitive).value); + $262.agent.leaving(); + }); +`); + +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + Atomics.notify(i64a, 0), + 0, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/object-for-timeout.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/object-for-timeout.js new file mode 100644 index 0000000000..d46f27436b --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/object-for-timeout.js @@ -0,0 +1,72 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Object valueOf, toString, toPrimitive Zero timeout arg should result in an +0 timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + + Object -> Apply the following steps: + + Let primValue be ? ToPrimitive(argument, hint Number). + Return ? ToNumber(primValue). + +features: [Atomics.waitAsync, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray, computed-property-names, Atomics, BigInt, arrow-function] +flags: [async] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +const valueOf = { + valueOf() { + return 0; + } +}; + +const toString = { + toString() { + return '0'; + } +}; + +const toPrimitive = { + [Symbol.toPrimitive]() { + return 0; + } +}; + +assert.sameValue( + Atomics.waitAsync(i64a, 0, 0n, valueOf).value, + 'timed-out', + 'The value of Atomics.waitAsync(i64a, 0, 0n, valueOf).value is "timed-out"' +); + +assert.sameValue( + Atomics.waitAsync(i64a, 0, 0n, toString).value, + 'timed-out', + 'The value of Atomics.waitAsync(i64a, 0, 0n, toString).value is "timed-out"' +); + +assert.sameValue( + Atomics.waitAsync(i64a, 0, 0n, toPrimitive).value, + 'timed-out', + 'The value of Atomics.waitAsync(i64a, 0, 0n, toPrimitive).value is "timed-out"' +); + +Promise.all([ + Atomics.waitAsync(i64a, 0, 0n, valueOf).value, + Atomics.waitAsync(i64a, 0, 0n, toString).value, + Atomics.waitAsync(i64a, 0, 0n, toPrimitive).value +]).then(outcomes => { + assert.sameValue(outcomes[0], 'timed-out', 'The value of outcomes[0] is "timed-out"'); + assert.sameValue(outcomes[1], 'timed-out', 'The value of outcomes[1] is "timed-out"'); + assert.sameValue(outcomes[2], 'timed-out', 'The value of outcomes[2] is "timed-out"'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/out-of-range-index-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/out-of-range-index-throws.js new file mode 100644 index 0000000000..e129569ae1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/out-of-range-index-throws.js @@ -0,0 +1,49 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Throws a RangeError if value of index arg is out of range +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 2. Let i be ? ValidateAtomicAccess(typedArray, index). + + ... + 2.Let accessIndex be ? ToIndex(requestIndex). + ... + 5. If accessIndex ≥ length, throw a RangeError exception. +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(RangeError, function() { + Atomics.waitAsync(i64a, Infinity, poisoned, poisoned); +}, '`Atomics.waitAsync(i64a, Infinity, poisoned, poisoned)` throws a RangeError exception'); +assert.throws(RangeError, function() { + Atomics.waitAsync(i64a, -1, poisoned, poisoned); +}, '`Atomics.waitAsync(i64a, -1, poisoned, poisoned)` throws a RangeError exception'); +assert.throws(RangeError, function() { + Atomics.waitAsync(i64a, 4, poisoned, poisoned); +}, '`Atomics.waitAsync(i64a, 4, poisoned, poisoned)` throws a RangeError exception'); +assert.throws(RangeError, function() { + Atomics.waitAsync(i64a, 200, poisoned, poisoned); +}, '`Atomics.waitAsync(i64a, 200, poisoned, poisoned)` throws a RangeError exception'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/poisoned-object-for-timeout-throws-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/poisoned-object-for-timeout-throws-agent.js new file mode 100644 index 0000000000..abb3e8d0d1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/poisoned-object-for-timeout-throws-agent.js @@ -0,0 +1,86 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + False timeout arg should result in an +0 timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + + Let primValue be ? ToPrimitive(argument, hint Number). + Return ? ToNumber(primValue). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; + +$262.agent.start(` + const poisonedValueOf = { + valueOf() { + throw new Error('should not evaluate this code'); + } + }; + + const poisonedToPrimitive = { + [Symbol.toPrimitive]() { + throw new Error('passing a poisoned object using @@ToPrimitive'); + } + }; + + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + let status1 = ''; + let status2 = ''; + + try { + Atomics.waitAsync(i64a, 0, 0n, poisonedValueOf); + } catch (error) { + status1 = 'poisonedValueOf'; + } + try { + Atomics.waitAsync(i64a, 0, 0n, poisonedToPrimitive); + } catch (error) { + status2 = 'poisonedToPrimitive'; + } + + $262.agent.report(status1); + $262.agent.report(status2); + $262.agent.leaving(); + }); +`); + +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'poisonedValueOf', + '(await $262.agent.getReportAsync()) resolves to the value "poisonedValueOf"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'poisonedToPrimitive', + '(await $262.agent.getReportAsync()) resolves to the value "poisonedToPrimitive"' + ); + + assert.sameValue( + Atomics.notify(i64a, 0), + 0, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/poisoned-object-for-timeout-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/poisoned-object-for-timeout-throws.js new file mode 100644 index 0000000000..a7878a5ba7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/poisoned-object-for-timeout-throws.js @@ -0,0 +1,45 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if index arg can not be converted to an Integer +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + + Let primValue be ? ToPrimitive(argument, hint Number). + Return ? ToNumber(primValue). + +features: [Atomics.waitAsync, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray, computed-property-names, Atomics, BigInt] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +const poisonedValueOf = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +const poisonedToPrimitive = { + [Symbol.toPrimitive]() { + throw new Test262Error('passing a poisoned object using @@ToPrimitive'); + } +}; + +assert.throws(Test262Error, function() { + Atomics.waitAsync(i64a, 0, 0n, poisonedValueOf); +}, '`Atomics.waitAsync(i64a, 0, 0n, poisonedValueOf)` throws a Test262Error exception'); + +assert.throws(Test262Error, function() { + Atomics.waitAsync(i64a, 0, 0n, poisonedToPrimitive); +}, '`Atomics.waitAsync(i64a, 0, 0n, poisonedToPrimitive)` throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/shell.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/shell.js diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/symbol-for-index-throws-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/symbol-for-index-throws-agent.js new file mode 100644 index 0000000000..41cbde0555 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/symbol-for-index-throws-agent.js @@ -0,0 +1,98 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if index arg can not be converted to an Integer +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 2. Let i be ? ValidateAtomicAccess(typedArray, index). + + ValidateAtomicAccess( typedArray, requestIndex ) + + 2. Let accessIndex be ? ToIndex(requestIndex). + + ToIndex ( value ) + + 2. Else, + a. Let integerIndex be ? ToInteger(value). + + ToInteger(value) + + 1. Let number be ? ToNumber(argument). + + Symbol --> Throw a TypeError exception. + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; + +$262.agent.start(` + const poisonedValueOf = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } + }; + + const poisonedToPrimitive = { + [Symbol.toPrimitive]() { + throw new Test262Error('should not evaluate this code'); + } + }; + + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + let status1 = ''; + let status2 = ''; + + try { + Atomics.waitAsync(i64a, Symbol('1'), poisonedValueOf, poisonedValueOf); + } catch (error) { + status1 = 'A ' + error.name; + } + try { + Atomics.waitAsync(i64a, Symbol('2'), poisonedToPrimitive, poisonedToPrimitive); + } catch (error) { + status2 = 'B ' + error.name; + } + + $262.agent.report(status1); + $262.agent.report(status2); + $262.agent.leaving(); + }); +`); + +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'A TypeError', + '(await $262.agent.getReportAsync()) resolves to the value "A TypeError"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'B TypeError', + '(await $262.agent.getReportAsync()) resolves to the value "B TypeError"' + ); + + assert.sameValue( + Atomics.notify(i64a, 0), + 0, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/symbol-for-index-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/symbol-for-index-throws.js new file mode 100644 index 0000000000..aaa9ae80e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/symbol-for-index-throws.js @@ -0,0 +1,71 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if index arg can not be converted to an Integer +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 2. Let i be ? ValidateAtomicAccess(typedArray, index). + + ValidateAtomicAccess( typedArray, requestIndex ) + + 2. Let accessIndex be ? ToIndex(requestIndex). + + ToIndex ( value ) + + 2. Else, + a. Let integerIndex be ? ToInteger(value). + + ToInteger(value) + + 1. Let number be ? ToNumber(argument). + + Symbol --> Throw a TypeError exception. + +features: [Atomics.waitAsync, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray, computed-property-names, Atomics, BigInt] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +const poisonedValueOf = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +const poisonedToPrimitive = { + [Symbol.toPrimitive]() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(Test262Error, function() { + Atomics.waitAsync(i64a, poisonedValueOf, poisonedValueOf, poisonedValueOf); +}, '`Atomics.waitAsync(i64a, poisonedValueOf, poisonedValueOf, poisonedValueOf)` throws a Test262Error exception'); + +assert.throws(Test262Error, function() { + Atomics.waitAsync(i64a, poisonedToPrimitive, poisonedToPrimitive, poisonedToPrimitive); +}, '`Atomics.waitAsync(i64a, poisonedToPrimitive, poisonedToPrimitive, poisonedToPrimitive)` throws a Test262Error exception'); + +assert.throws(TypeError, function() { + Atomics.waitAsync(i64a, Symbol('1'), poisonedValueOf, poisonedValueOf); +}, '`Atomics.waitAsync(i64a, Symbol("1"), poisonedValueOf, poisonedValueOf)` throws a TypeError exception'); + +assert.throws(TypeError, function() { + Atomics.waitAsync(i64a, Symbol('2'), poisonedToPrimitive, poisonedToPrimitive); +}, '`Atomics.waitAsync(i64a, Symbol("2"), poisonedToPrimitive, poisonedToPrimitive)` throws a TypeError exception'); + + + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/symbol-for-timeout-throws-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/symbol-for-timeout-throws-agent.js new file mode 100644 index 0000000000..2ef1e36e59 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/symbol-for-timeout-throws-agent.js @@ -0,0 +1,73 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if index arg can not be converted to an Integer +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + + Symbol --> Throw a TypeError exception. + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + let status1 = ''; + let status2 = ''; + + try { + Atomics.waitAsync(i64a, 0, 0n, Symbol('1')); + } catch (error) { + status1 = 'A ' + error.name; + } + try { + Atomics.waitAsync(i64a, 0, 0n, Symbol('2')); + } catch (error) { + status2 = 'B ' + error.name; + } + + $262.agent.report(status1); + $262.agent.report(status2); + $262.agent.leaving(); + }); +`); + +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'A TypeError', + '(await $262.agent.getReportAsync()) resolves to the value "A TypeError"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'B TypeError', + '(await $262.agent.getReportAsync()) resolves to the value "B TypeError"' + ); + + assert.sameValue( + Atomics.notify(i64a, 0), + 0, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/symbol-for-timeout-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/symbol-for-timeout-throws.js new file mode 100644 index 0000000000..55dbafc489 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/symbol-for-timeout-throws.js @@ -0,0 +1,52 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if index arg can not be converted to an Integer +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + + Symbol --> Throw a TypeError exception. + +features: [Atomics.waitAsync, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray, computed-property-names, Atomics, BigInt] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +const poisonedValueOf = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +const poisonedToPrimitive = { + [Symbol.toPrimitive]() { + throw new Test262Error('passing a poisoned object using @@ToPrimitive'); + } +}; + +assert.throws(Test262Error, function() { + Atomics.waitAsync(i64a, 0, 0n, poisonedValueOf); +}, '`Atomics.waitAsync(i64a, 0, 0n, poisonedValueOf)` throws a Test262Error exception'); + +assert.throws(Test262Error, function() { + Atomics.waitAsync(i64a, 0, 0n, poisonedToPrimitive); +}, '`Atomics.waitAsync(i64a, 0, 0n, poisonedToPrimitive)` throws a Test262Error exception'); + +assert.throws(TypeError, function() { + Atomics.waitAsync(i64a, 0, 0n, Symbol('foo')); +}, '`Atomics.waitAsync(i64a, 0, 0n, Symbol("foo"))` throws a TypeError exception'); + +assert.throws(TypeError, function() { + Atomics.waitAsync(i64a, 0, 0n, Symbol('foo')); +}, '`Atomics.waitAsync(i64a, 0, 0n, Symbol("foo"))` throws a TypeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/symbol-for-value-throws-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/symbol-for-value-throws-agent.js new file mode 100644 index 0000000000..70bcc8d273 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/symbol-for-value-throws-agent.js @@ -0,0 +1,89 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if value arg is a Symbol +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 5. Otherwise, let v be ? ToInt32(value). + + ToInt32(value) + + 1.Let number be ? ToNumber(argument). + + Symbol --> Throw a TypeError exception. + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; + +$262.agent.start(` + const poisonedValueOf = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } + }; + + const poisonedToPrimitive = { + [Symbol.toPrimitive]: function() { + throw new Test262Error("passing a poisoned object using @@ToPrimitive"); + } + }; + + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + let status1 = ""; + let status2 = ""; + + try { + Atomics.waitAsync(i64a, 0, Symbol("1"), poisonedValueOf); + } catch (error) { + status1 = 'A ' + error.name; + } + try { + Atomics.waitAsync(i64a, 0, Symbol("2"), poisonedToPrimitive); + } catch (error) { + status2 = 'B ' + error.name; + } + + $262.agent.report(status1); + $262.agent.report(status2); + $262.agent.leaving(); + }); +`); + +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'A TypeError', + '(await $262.agent.getReportAsync()) resolves to the value "A TypeError"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'B TypeError', + '(await $262.agent.getReportAsync()) resolves to the value "B TypeError"' + ); + + assert.sameValue( + Atomics.notify(i64a, 0), + 0, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/symbol-for-value-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/symbol-for-value-throws.js new file mode 100644 index 0000000000..552928e077 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/symbol-for-value-throws.js @@ -0,0 +1,60 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if value arg is a Symbol +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 5. Otherwise, let v be ? ToInt32(value). + + ToInt32(value) + + 1.Let number be ? ToNumber(argument). + + Symbol --> Throw a TypeError exception. + +features: [Atomics.waitAsync, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray, computed-property-names, Atomics, BigInt] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +const poisonedValueOf = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +const poisonedToPrimitive = { + [Symbol.toPrimitive]() { + throw new Test262Error("passing a poisoned object using @@ToPrimitive"); + } +}; + +assert.throws(Test262Error, function() { + Atomics.waitAsync(i64a, 0, poisonedValueOf, poisonedValueOf); +}, '`Atomics.waitAsync(i64a, 0, poisonedValueOf, poisonedValueOf)` throws a Test262Error exception'); + +assert.throws(Test262Error, function() { + Atomics.waitAsync(i64a, 0, poisonedToPrimitive, poisonedToPrimitive); +}, '`Atomics.waitAsync(i64a, 0, poisonedToPrimitive, poisonedToPrimitive)` throws a Test262Error exception'); + +assert.throws(TypeError, function() { + Atomics.waitAsync(i64a, 0, Symbol("foo"), poisonedValueOf); +}, '`Atomics.waitAsync(i64a, 0, Symbol("foo"), poisonedValueOf)` throws a TypeError exception'); + +assert.throws(TypeError, function() { + Atomics.waitAsync(i64a, 0, Symbol("foo"), poisonedToPrimitive); +}, '`Atomics.waitAsync(i64a, 0, Symbol("foo"), poisonedToPrimitive)` throws a TypeError exception'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/true-for-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/true-for-timeout-agent.js new file mode 100644 index 0000000000..af48ef70d9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/true-for-timeout-agent.js @@ -0,0 +1,75 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + True timeout arg should result in an +0 timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; + +$262.agent.start(` + const valueOf = { + valueOf() { + return true; + } + }; + + const toPrimitive = { + [Symbol.toPrimitive]() { + return true; + } + }; + + $262.agent.receiveBroadcast(async (sab) => { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + $262.agent.report(await Atomics.waitAsync(i64a, 0, 0n, true).value); + $262.agent.report(await Atomics.waitAsync(i64a, 0, 0n, valueOf).value); + $262.agent.report(await Atomics.waitAsync(i64a, 0, 0n, toPrimitive).value); + $262.agent.leaving(); + }); +`); + +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue( + Atomics.notify(i64a, 0), + 0, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/true-for-timeout.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/true-for-timeout.js new file mode 100644 index 0000000000..884acd3219 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/true-for-timeout.js @@ -0,0 +1,65 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if index arg can not be converted to an Integer +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + + Boolean -> If argument is true, return 1. If argument is false, return +0. + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, computed-property-names, Symbol, Symbol.toPrimitive, arrow-function] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +const valueOf = { + valueOf() { + return true; + } +}; + +const toPrimitive = { + [Symbol.toPrimitive]() { + return true; + } +}; + +let outcomes = []; +let lifespan = 1000; +let start = $262.agent.monotonicNow(); + +(function wait() { + let elapsed = $262.agent.monotonicNow() - start; + + if (elapsed > lifespan) { + $DONE('Test timed out'); + return; + } + + if (outcomes.length) { + assert.sameValue(outcomes[0], 'timed-out', 'The value of outcomes[0] is "timed-out"'); + assert.sameValue(outcomes[1], 'timed-out', 'The value of outcomes[1] is "timed-out"'); + assert.sameValue(outcomes[2], 'timed-out', 'The value of outcomes[2] is "timed-out"'); + $DONE(); + return; + } + + $262.agent.setTimeout(wait, 0); +})(); + +Promise.all([ + Atomics.waitAsync(i64a, 0, 0n, true).value, + Atomics.waitAsync(i64a, 0, 0n, valueOf).value, + Atomics.waitAsync(i64a, 0, 0n, toPrimitive).value +]).then(results => outcomes = results, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/undefined-for-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/undefined-for-timeout-agent.js new file mode 100644 index 0000000000..9ccc4e03c8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/undefined-for-timeout-agent.js @@ -0,0 +1,82 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Undefined timeout arg is coerced to zero +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + ... + Undefined Return NaN. + + 5.If q is NaN, let t be +∞, else let t be max(q, 0) + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const WAIT_INDEX = 0; +const RUNNING = 1; +const NUMAGENT = 2; +const NOTIFYCOUNT = 2; + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + var i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + // undefined => NaN => +Infinity + $262.agent.report("A " + (await Atomics.waitAsync(i64a, 0, 0n, undefined).value)); + $262.agent.leaving(); + }); +`); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + var i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + // undefined timeout arg => NaN => +Infinity + $262.agent.report("B " + (await Atomics.waitAsync(i64a, 0, 0n).value)); + $262.agent.leaving(); + }); +`); + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, BigInt(NUMAGENT)).then(async (agentCount) => { + + assert.sameValue( + agentCount, + BigInt(NUMAGENT), + 'The value of `agentCount` must return the same value returned by BigInt(NUMAGENT)' + ); + + assert.sameValue( + Atomics.notify(i64a, WAIT_INDEX, NOTIFYCOUNT), + NOTIFYCOUNT, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0, 2) must return the value of NOTIFYCOUNT' + ); + + const reports = [ + await $262.agent.getReportAsync(), + await $262.agent.getReportAsync(), + ]; + + reports.sort(); + assert.sameValue(reports[0], 'A ok', 'The value of reports[0] is "A ok"'); + assert.sameValue(reports[1], 'B ok', 'The value of reports[1] is "B ok"'); +}).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/undefined-for-timeout.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/undefined-for-timeout.js new file mode 100644 index 0000000000..0b9deb11d2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/undefined-for-timeout.js @@ -0,0 +1,51 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Undefined timeout arg is coerced to zero +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + ... + Undefined Return NaN. + + 5.If q is NaN, let t be +∞, else let t be max(q, 0) + +flags: [async] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, computed-property-names, Symbol, Symbol.toPrimitive, arrow-function] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +const valueOf = { + valueOf() { + return undefined; + } +}; + +const toPrimitive = { + [Symbol.toPrimitive]() { + return undefined; + } +}; + +Promise.all([ + Atomics.waitAsync(i64a, 0, 0n).value, + Atomics.waitAsync(i64a, 0, 0n, undefined).value, + Atomics.waitAsync(i64a, 0, 0n, valueOf).value, + Atomics.waitAsync(i64a, 0, 0n, toPrimitive).value +]).then(outcomes => { + assert.sameValue(outcomes[0], 'ok', 'The value of outcomes[0] is "ok"'); + assert.sameValue(outcomes[1], 'ok', 'The value of outcomes[1] is "ok"'); + assert.sameValue(outcomes[2], 'ok', 'The value of outcomes[2] is "ok"'); + assert.sameValue(outcomes[3], 'ok', 'The value of outcomes[3] is "ok"'); +}).then($DONE, $DONE); + +Atomics.notify(i64a, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/undefined-index-defaults-to-zero-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/undefined-index-defaults-to-zero-agent.js new file mode 100644 index 0000000000..0eb729af68 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/undefined-index-defaults-to-zero-agent.js @@ -0,0 +1,84 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Undefined index arg is coerced to zero +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 2. Let i be ? ValidateAtomicAccess(typedArray, index). + ... + 2.Let accessIndex be ? ToIndex(requestIndex). + + 9.If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception. + ... + 3.If bufferData is a Data Block, return false + + If value is undefined, then + Let index be 0. + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const WAIT_INDEX = 0; +const RUNNING = 1; +const NUMAGENT = 2; +const NOTIFYCOUNT = 2; + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + var i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + $262.agent.report("A " + (await Atomics.waitAsync(i64a, undefined, 0n).value)); + $262.agent.leaving(); + }); +`); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + var i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + $262.agent.report("B " + (await Atomics.waitAsync(i64a, undefined, 0n).value)); + $262.agent.leaving(); + }); +`); + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, BigInt(NUMAGENT)).then(async (agentCount) => { + + assert.sameValue( + agentCount, + BigInt(NUMAGENT), + 'The value of `agentCount` must return the same value returned by BigInt(NUMAGENT)' + ); + + assert.sameValue( + Atomics.notify(i64a, WAIT_INDEX, NOTIFYCOUNT), + NOTIFYCOUNT, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0, 2) must return the value of NOTIFYCOUNT' + ); + + const reports = [ + await $262.agent.getReportAsync(), + await $262.agent.getReportAsync(), + ]; + + reports.sort(); + assert.sameValue(reports[0], 'A ok', 'The value of reports[0] is "A ok"'); + assert.sameValue(reports[1], 'B ok', 'The value of reports[1] is "B ok"'); +}).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/value-not-equal-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/value-not-equal-agent.js new file mode 100644 index 0000000000..6c0922fcf8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/value-not-equal-agent.js @@ -0,0 +1,63 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Returns "not-equal" when value arg does not match an index in the typedArray +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 16. Let w be ! AtomicLoad(typedArray, i). + 17. If v is not equal to w, then + a. Perform LeaveCriticalSection(WL). + b. If mode is sync, then + i. Return the String "not-equal". + c. Perform ! Call(capability.[[Resolve]], undefined, « "not-equal" »). + d. Return promiseCapability.[[Promise]]. + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; +const value = 42n; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + $262.agent.report(Atomics.store(i64a, 0, 42n)); + $262.agent.report(Atomics.waitAsync(i64a, 0, 0n).value); + $262.agent.leaving(); + }); +`); + +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + + assert.sameValue( + await $262.agent.getReportAsync(), + value.toString(), + '(await $262.agent.getReportAsync()) must return the same value returned by value.toString()' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'not-equal', + '(await $262.agent.getReportAsync()) resolves to the value "not-equal"' + ); + + assert.sameValue( + Atomics.notify(i64a, 0, 1), + 0, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0, 1) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/value-not-equal.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/value-not-equal.js new file mode 100644 index 0000000000..adc2bc69a2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/value-not-equal.js @@ -0,0 +1,44 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Returns "not-equal" when value arg does not match an index in the typedArray +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 16. Let w be ! AtomicLoad(typedArray, i). + 17. If v is not equal to w, then + a. Perform LeaveCriticalSection(WL). + b. If mode is sync, then + i. Return the String "not-equal". + c. Perform ! Call(capability.[[Resolve]], undefined, « "not-equal" »). + d. Return promiseCapability.[[Promise]]. + +flags: [async] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, BigInt, computed-property-names, Symbol, Symbol.toPrimitive, Atomics, arrow-function] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +const valueOf = { + valueOf() { + return undefined; + } +}; + +const toPrimitive = { + [Symbol.toPrimitive]() { + return undefined; + } +}; + +Promise.all([Atomics.store(i64a, 0, 42n), Atomics.waitAsync(i64a, 0, 0n).value]).then(outcomes => { + assert.sameValue(outcomes[0], 42n, 'The value of outcomes[0] is 42n'); + assert.sameValue(outcomes[1], 'not-equal', 'The value of outcomes[1] is "not-equal"'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/waiterlist-block-indexedposition-wake.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/waiterlist-block-indexedposition-wake.js new file mode 100644 index 0000000000..bde4046ecd --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/waiterlist-block-indexedposition-wake.js @@ -0,0 +1,90 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Get the correct WaiterList +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 11. Let indexedPosition be (i × 4) + offset. + 12. Let WL be GetWaiterList(block, indexedPosition). + + GetWaiterList( block, i ) + + ... + 4. Return the WaiterList that is referenced by the pair (block, i). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const NUMAGENT = 2; +const RUNNING = 4; + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + // Wait on index 0 + $262.agent.report(await Atomics.waitAsync(i64a, 0, 0n, Infinity).value); + $262.agent.leaving(); + }); +`); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + // Wait on index 2 + $262.agent.report(await Atomics.waitAsync(i64a, 2, 0n, Infinity).value); + $262.agent.leaving(); + }); +`); + +const i64a = new BigInt64Array( + new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 5) +); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, BigInt(NUMAGENT)).then(async (agentCount) => { + + assert.sameValue( + agentCount, + BigInt(NUMAGENT), + 'The value of `agentCount` must return the same value returned by BigInt(NUMAGENT)' + ); + + // Notify index 1, notifies nothing + assert.sameValue(Atomics.notify(i64a, 1), 0, 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 5)), 1) must return 0'); + + // Notify index 3, notifies nothing + assert.sameValue(Atomics.notify(i64a, 3), 0, 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 5)), 3) must return 0'); + + // Notify index 2, notifies 1 + assert.sameValue(Atomics.notify(i64a, 2), 1, 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 5)), 2) must return 1'); + assert.sameValue( + await $262.agent.getReportAsync(), + 'ok', + '(await $262.agent.getReportAsync()) resolves to the value "ok"' + ); + + // Notify index 0, notifies 1 + assert.sameValue(Atomics.notify(i64a, 0), 1, 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 5)), 0) must return 1'); + assert.sameValue( + await $262.agent.getReportAsync(), + 'ok', + '(await $262.agent.getReportAsync()) resolves to the value "ok"' + ); + +}).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/was-woken-before-timeout.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/was-woken-before-timeout.js new file mode 100644 index 0000000000..ba8807b68d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/bigint/was-woken-before-timeout.js @@ -0,0 +1,53 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Test that Atomics.waitAsync returns the right result when it was awoken before + a timeout +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, BigInt, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.huge; +const i64a = new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i64a = new BigInt64Array(sab); + Atomics.add(i64a, ${RUNNING}, 1n); + + const before = $262.agent.monotonicNow(); + const unpark = await Atomics.waitAsync(i64a, 0, 0n, ${TIMEOUT}).value; + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcastAsync(i64a, RUNNING, 1n).then(async agentCount => { + assert.sameValue(agentCount, 1n, 'The value of `agentCount` is 1n'); + + assert.sameValue( + Atomics.notify(i64a, 0), + 1, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 1' + ); + + const lapse = await $262.agent.getReportAsync(); + assert(lapse < TIMEOUT, 'The result of evaluating `(lapse < TIMEOUT)` is true'); + const result = await $262.agent.getReportAsync(); + assert.sameValue(result, 'ok', 'The value of `result` is "ok"'); + assert.sameValue(result, 'ok', 'The value of `result` is "ok"'); + + assert.sameValue( + Atomics.notify(i64a, 0), + 0, + 'Atomics.notify(new BigInt64Array(new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 4)), 0) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/browser.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/descriptor.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/descriptor.js new file mode 100644 index 0000000000..3d08175e3c --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/descriptor.js @@ -0,0 +1,24 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: Atomics.waitAsync property descriptor +info: | + ES Section 17 + + Every other data property described in clauses 18 through 26 and in Annex + B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false, + [[Configurable]]: true } unless otherwise specified. +includes: [propertyHelper.js] +features: [Atomics.waitAsync, Atomics] +---*/ + +verifyProperty(Atomics, 'waitAsync', { + configurable: true, + writable: true, + enumerable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/false-for-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/false-for-timeout-agent.js new file mode 100644 index 0000000000..05f0311793 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/false-for-timeout-agent.js @@ -0,0 +1,94 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + False timeout arg should result in an +0 timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; + +$262.agent.start(` + const valueOf = { + valueOf() { + return false; + } + }; + + const toPrimitive = { + [Symbol.toPrimitive]() { + return false; + } + }; + + $262.agent.receiveBroadcast(async (sab) => { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + $262.agent.report(await Atomics.waitAsync(i32a, 0, 0, false).value); + $262.agent.report(await Atomics.waitAsync(i32a, 0, 0, valueOf).value); + $262.agent.report(await Atomics.waitAsync(i32a, 0, 0, toPrimitive).value); + $262.agent.report(Atomics.waitAsync(i32a, 0, 0, false).value); + $262.agent.report(Atomics.waitAsync(i32a, 0, 0, valueOf).value); + $262.agent.report(Atomics.waitAsync(i32a, 0, 0, toPrimitive).value); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 0'); + +}).then($DONE, $DONE); + + diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/false-for-timeout.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/false-for-timeout.js new file mode 100644 index 0000000000..cfb66b3dd3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/false-for-timeout.js @@ -0,0 +1,64 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + False timeout arg should result in an +0 timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + +flags: [async] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, computed-property-names, Symbol, Symbol.toPrimitive, arrow-function] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const valueOf = { + valueOf() { + return false; + } +}; + +const toPrimitive = { + [Symbol.toPrimitive]() { + return false; + } +}; + +assert.sameValue( + Atomics.waitAsync(i32a, 0, 0, false).value, + 'timed-out', + 'The value of Atomics.waitAsync(i32a, 0, 0, false).value is "timed-out"' +); + +assert.sameValue( + Atomics.waitAsync(i32a, 0, 0, valueOf).value, + 'timed-out', + 'The value of Atomics.waitAsync(i32a, 0, 0, valueOf).value is "timed-out"' +); + +assert.sameValue( + Atomics.waitAsync(i32a, 0, 0, toPrimitive).value, + 'timed-out', + 'The value of Atomics.waitAsync(i32a, 0, 0, toPrimitive).value is "timed-out"' +); + +Promise.all([ + Atomics.waitAsync(i32a, 0, 0, false).value, + Atomics.waitAsync(i32a, 0, 0, valueOf).value, + Atomics.waitAsync(i32a, 0, 0, toPrimitive).value, + ]).then(outcomes => { + assert.sameValue(outcomes[0], 'timed-out', 'The value of outcomes[0] is "timed-out"'); + assert.sameValue(outcomes[1], 'timed-out', 'The value of outcomes[1] is "timed-out"'); + assert.sameValue(outcomes[2], 'timed-out', 'The value of outcomes[2] is "timed-out"'); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/good-views.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/good-views.js new file mode 100644 index 0000000000..428bb806bd --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/good-views.js @@ -0,0 +1,70 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Test Atomics.waitAsync on arrays that allow atomic operations +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, Atomics] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +$262.agent.start(` + (async () => { + var sab = new SharedArrayBuffer(1024); + var good_indices = [ (view) => 0/-1, // -0 + (view) => '-0', + (view) => view.length - 1, + (view) => ({ valueOf: () => 0 }), + (view) => ({ toString: () => '0', valueOf: false }) // non-callable valueOf triggers invocation of toString + ]; + + var view = new Int32Array(sab, 32, 20); + + view[0] = 0; + $262.agent.report("A " + (await Atomics.waitAsync(view, 0, 0, 0).value)) + $262.agent.report("B " + (await Atomics.waitAsync(view, 0, 37, 0).value)); + + const results = []; + // In-bounds boundary cases for indexing + for ( let IdxGen of good_indices ) { + let Idx = IdxGen(view); + view.fill(0); + // Atomics.store() computes an index from Idx in the same way as other + // Atomics operations, not quite like view[Idx]. + Atomics.store(view, Idx, 37); + results.push(await Atomics.waitAsync(view, Idx, 0).value); + } + $262.agent.report("C " + results.join(",")); + $262.agent.leaving(); + })(); +`); + + +(async () => { + const outcomes = []; + + for (let i = 0; i < 3; i++) { + outcomes.push(await $262.agent.getReportAsync()); + } + + assert.sameValue( + outcomes[0], + 'A timed-out', + 'The value of outcomes[0] is "A timed-out"' + ); + + assert.sameValue( + outcomes[1], + 'B not-equal', + 'The value of outcomes[1] is "B not-equal"' + ); + assert.sameValue( + outcomes[2], + 'C not-equal,not-equal,not-equal,not-equal,not-equal', + 'The value of outcomes[2] is "C not-equal,not-equal,not-equal,not-equal,not-equal"' + ); +})().then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/implicit-infinity-for-timeout.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/implicit-infinity-for-timeout.js new file mode 100644 index 0000000000..2c4baf0a85 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/implicit-infinity-for-timeout.js @@ -0,0 +1,39 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Undefined timeout arg is coerced to zero +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + ... + Undefined Return NaN. + + 5.If q is NaN, let t be +∞, else let t be max(q, 0) + +flags: [async] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, computed-property-names, Symbol, Symbol.toPrimitive, arrow-function] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +let {async, value} = Atomics.waitAsync(i32a, 0, 0); + +value.then(result => { + + assert.sameValue(result, "ok", 'The value of `result` is "ok"'); + +}, $DONE).then($DONE, $DONE); + +Atomics.notify(i32a, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/is-function.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/is-function.js new file mode 100644 index 0000000000..96a8a74f60 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/is-function.js @@ -0,0 +1,13 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: Atomics.waitAsync is callable +features: [Atomics.waitAsync, Atomics] +---*/ + +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/length.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/length.js new file mode 100644 index 0000000000..b02c6027b3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/length.js @@ -0,0 +1,34 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Atomics.waitAsync.length is 4. +info: | + Atomics.waitAsync ( ia, index, expect, timeout ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this + value is equal to the largest number of named arguments shown in the + subclause headings for the function description, including optional + parameters. However, rest parameters shown using the form “...name” + are not included in the default argument count. + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Atomics.waitAsync, Atomics] +---*/ + +verifyProperty(Atomics.waitAsync, 'length', { + value: 4, + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/name.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/name.js new file mode 100644 index 0000000000..6a558f8464 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/name.js @@ -0,0 +1,20 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Atomics.waitAsync.name is "waitAsync". +includes: [propertyHelper.js] +features: [Atomics.waitAsync, Atomics] +---*/ + +verifyProperty(Atomics.waitAsync, 'name', { + value: 'waitAsync', + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/nan-for-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/nan-for-timeout-agent.js new file mode 100644 index 0000000000..3aac20d767 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/nan-for-timeout-agent.js @@ -0,0 +1,54 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + NaN timeout arg should result in an infinite timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + $262.agent.report(await Atomics.waitAsync(i32a, 0, 0, NaN).value); // NaN => +Infinity + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + + assert.sameValue(Atomics.notify(i32a, 0), 1, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 1'); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'ok', + '(await $262.agent.getReportAsync()) resolves to the value "ok"' + ); + +}).then($DONE, $DONE); + + diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/negative-index-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/negative-index-throws.js new file mode 100644 index 0000000000..4d6c2b2526 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/negative-index-throws.js @@ -0,0 +1,45 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Throws a RangeError is index < 0 +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + 2. Let i be ? ValidateAtomicAccess(typedArray, index). + +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(RangeError, function() { + Atomics.waitAsync(i32a, -Infinity, poisoned, poisoned); +}, '`Atomics.waitAsync(i32a, -Infinity, poisoned, poisoned)` throws a RangeError exception'); +assert.throws(RangeError, function() { + Atomics.waitAsync(i32a, -7.999, poisoned, poisoned); +}, '`Atomics.waitAsync(i32a, -7.999, poisoned, poisoned)` throws a RangeError exception'); +assert.throws(RangeError, function() { + Atomics.waitAsync(i32a, -1, poisoned, poisoned); +}, '`Atomics.waitAsync(i32a, -1, poisoned, poisoned)` throws a RangeError exception'); +assert.throws(RangeError, function() { + Atomics.waitAsync(i32a, -300, poisoned, poisoned); +}, '`Atomics.waitAsync(i32a, -300, poisoned, poisoned)` throws a RangeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/negative-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/negative-timeout-agent.js new file mode 100644 index 0000000000..317bcdf268 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/negative-timeout-agent.js @@ -0,0 +1,52 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Test that Atomics.waitAsync times out with a negative timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + var i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + $262.agent.report(await Atomics.waitAsync(i32a, 0, 0, -5).value); // -5 => 0 + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 0'); + +}).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/negative-timeout.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/negative-timeout.js new file mode 100644 index 0000000000..f2d611acee --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/negative-timeout.js @@ -0,0 +1,34 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Test that Atomics.waitAsync times out with a negative timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + +flags: [async] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, destructuring-binding, arrow-function] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +Promise.all([ + Atomics.waitAsync(i32a, 0, 0, -1).value, + ]).then(([outcome]) => { + assert.sameValue( + outcome, + 'timed-out', + 'The value of `outcome` is "timed-out"' + ); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-no-operation.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-no-operation.js new file mode 100644 index 0000000000..30462d4816 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-no-operation.js @@ -0,0 +1,73 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Test that Atomics.waitAsync returns the right result when it timed out and that + the time to time out is reasonable. +info: | + AddWaiter ( WL, waiterRecord ) + + 5. Append waiterRecord as the last element of WL.[[Waiters]] + 6. If waiterRecord.[[Timeout]] is finite, then in parallel, + a. Wait waiterRecord.[[Timeout]] milliseconds. + b. Perform TriggerTimeout(WL, waiterRecord). + + TriggerTimeout( WL, waiterRecord ) + + 3. If waiterRecord is in WL.[[Waiters]], then + a. Set waiterRecord.[[Result]] to "timed-out". + b. Perform RemoveWaiter(WL, waiterRecord). + c. Perform NotifyWaiter(WL, waiterRecord). + 4. Perform LeaveCriticalSection(WL). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const before = $262.agent.monotonicNow(); + const unpark = await Atomics.waitAsync(i32a, 0, 0, ${TIMEOUT}).value; + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + + const lapse = await $262.agent.getReportAsync(); + + assert( + lapse >= TIMEOUT, + 'The result of evaluating `(lapse >= TIMEOUT)` is true' + ); + + const result = await $262.agent.getReportAsync(); + + assert.sameValue( + result, + 'timed-out', + 'The value of `result` is "timed-out"' + ); + assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 0'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-add.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-add.js new file mode 100644 index 0000000000..57cd10a192 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-add.js @@ -0,0 +1,74 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Waiter does not spuriously notify on index which is subject to Add operation +info: | + AddWaiter ( WL, waiterRecord ) + + 5. Append waiterRecord as the last element of WL.[[Waiters]] + 6. If waiterRecord.[[Timeout]] is finite, then in parallel, + a. Wait waiterRecord.[[Timeout]] milliseconds. + b. Perform TriggerTimeout(WL, waiterRecord). + + TriggerTimeout( WL, waiterRecord ) + + 3. If waiterRecord is in WL.[[Waiters]], then + a. Set waiterRecord.[[Result]] to "timed-out". + b. Perform RemoveWaiter(WL, waiterRecord). + c. Perform NotifyWaiter(WL, waiterRecord). + 4. Perform LeaveCriticalSection(WL). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const before = $262.agent.monotonicNow(); + const unpark = await Atomics.waitAsync(i32a, 0, 0, ${TIMEOUT}).value; + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + + Atomics.add(i32a, 0, 1); + + const lapse = await $262.agent.getReportAsync(); + + assert( + lapse >= TIMEOUT, + 'The result of evaluating `(lapse >= TIMEOUT)` is true' + ); + + const result = await $262.agent.getReportAsync(); + + assert.sameValue( + result, + 'timed-out', + 'The value of `result` is "timed-out"' + ); + assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 0'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-and.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-and.js new file mode 100644 index 0000000000..339ab3a329 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-and.js @@ -0,0 +1,74 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Waiter does not spuriously notify on index which is subject to And operation +info: | + AddWaiter ( WL, waiterRecord ) + + 5. Append waiterRecord as the last element of WL.[[Waiters]] + 6. If waiterRecord.[[Timeout]] is finite, then in parallel, + a. Wait waiterRecord.[[Timeout]] milliseconds. + b. Perform TriggerTimeout(WL, waiterRecord). + + TriggerTimeout( WL, waiterRecord ) + + 3. If waiterRecord is in WL.[[Waiters]], then + a. Set waiterRecord.[[Result]] to "timed-out". + b. Perform RemoveWaiter(WL, waiterRecord). + c. Perform NotifyWaiter(WL, waiterRecord). + 4. Perform LeaveCriticalSection(WL). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const before = $262.agent.monotonicNow(); + const unpark = await Atomics.waitAsync(i32a, 0, 0, ${TIMEOUT}).value; + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + + Atomics.and(i32a, 0, 1); + + const lapse = await $262.agent.getReportAsync(); + + assert( + lapse >= TIMEOUT, + 'The result of evaluating `(lapse >= TIMEOUT)` is true' + ); + + const result = await $262.agent.getReportAsync(); + + assert.sameValue( + result, + 'timed-out', + 'The value of `result` is "timed-out"' + ); + assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 0'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-compareExchange.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-compareExchange.js new file mode 100644 index 0000000000..3802faddc4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-compareExchange.js @@ -0,0 +1,74 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Waiter does not spuriously notify on index which is subject to compareExchange operation +info: | + AddWaiter ( WL, waiterRecord ) + + 5. Append waiterRecord as the last element of WL.[[Waiters]] + 6. If waiterRecord.[[Timeout]] is finite, then in parallel, + a. Wait waiterRecord.[[Timeout]] milliseconds. + b. Perform TriggerTimeout(WL, waiterRecord). + + TriggerTimeout( WL, waiterRecord ) + + 3. If waiterRecord is in WL.[[Waiters]], then + a. Set waiterRecord.[[Result]] to "timed-out". + b. Perform RemoveWaiter(WL, waiterRecord). + c. Perform NotifyWaiter(WL, waiterRecord). + 4. Perform LeaveCriticalSection(WL). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const before = $262.agent.monotonicNow(); + const unpark = await Atomics.waitAsync(i32a, 0, 0, ${TIMEOUT}).value; + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + + Atomics.compareExchange(i32a, 0, 0, 1); + + const lapse = await $262.agent.getReportAsync(); + + assert( + lapse >= TIMEOUT, + 'The result of evaluating `(lapse >= TIMEOUT)` is true' + ); + + const result = await $262.agent.getReportAsync(); + + assert.sameValue( + result, + 'timed-out', + 'The value of `result` is "timed-out"' + ); + assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 0'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-exchange.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-exchange.js new file mode 100644 index 0000000000..e68a1821f6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-exchange.js @@ -0,0 +1,74 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Waiter does not spuriously notify on index which is subject to exchange operation +info: | + AddWaiter ( WL, waiterRecord ) + + 5. Append waiterRecord as the last element of WL.[[Waiters]] + 6. If waiterRecord.[[Timeout]] is finite, then in parallel, + a. Wait waiterRecord.[[Timeout]] milliseconds. + b. Perform TriggerTimeout(WL, waiterRecord). + + TriggerTimeout( WL, waiterRecord ) + + 3. If waiterRecord is in WL.[[Waiters]], then + a. Set waiterRecord.[[Result]] to "timed-out". + b. Perform RemoveWaiter(WL, waiterRecord). + c. Perform NotifyWaiter(WL, waiterRecord). + 4. Perform LeaveCriticalSection(WL). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const before = $262.agent.monotonicNow(); + const unpark = await Atomics.waitAsync(i32a, 0, 0, ${TIMEOUT}).value; + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + + Atomics.exchange(i32a, 0, 1); + + const lapse = await $262.agent.getReportAsync(); + + assert( + lapse >= TIMEOUT, + 'The result of evaluating `(lapse >= TIMEOUT)` is true' + ); + + const result = await $262.agent.getReportAsync(); + + assert.sameValue( + result, + 'timed-out', + 'The value of `result` is "timed-out"' + ); + assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 0'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-or.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-or.js new file mode 100644 index 0000000000..bec800415d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-or.js @@ -0,0 +1,74 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Waiter does not spuriously notify on index which is subject to Or operation +info: | + AddWaiter ( WL, waiterRecord ) + + 5. Append waiterRecord as the last element of WL.[[Waiters]] + 6. If waiterRecord.[[Timeout]] is finite, then in parallel, + a. Wait waiterRecord.[[Timeout]] milliseconds. + b. Perform TriggerTimeout(WL, waiterRecord). + + TriggerTimeout( WL, waiterRecord ) + + 3. If waiterRecord is in WL.[[Waiters]], then + a. Set waiterRecord.[[Result]] to "timed-out". + b. Perform RemoveWaiter(WL, waiterRecord). + c. Perform NotifyWaiter(WL, waiterRecord). + 4. Perform LeaveCriticalSection(WL). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const before = $262.agent.monotonicNow(); + const unpark = await Atomics.waitAsync(i32a, 0, 0, ${TIMEOUT}).value; + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + + Atomics.or(i32a, 0, 1); + + const lapse = await $262.agent.getReportAsync(); + + assert( + lapse >= TIMEOUT, + 'The result of evaluating `(lapse >= TIMEOUT)` is true' + ); + + const result = await $262.agent.getReportAsync(); + + assert.sameValue( + result, + 'timed-out', + 'The value of `result` is "timed-out"' + ); + assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 0'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-store.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-store.js new file mode 100644 index 0000000000..b60ce4f767 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-store.js @@ -0,0 +1,74 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Waiter does not spuriously notify on index which is subject to Store operation +info: | + AddWaiter ( WL, waiterRecord ) + + 5. Append waiterRecord as the last element of WL.[[Waiters]] + 6. If waiterRecord.[[Timeout]] is finite, then in parallel, + a. Wait waiterRecord.[[Timeout]] milliseconds. + b. Perform TriggerTimeout(WL, waiterRecord). + + TriggerTimeout( WL, waiterRecord ) + + 3. If waiterRecord is in WL.[[Waiters]], then + a. Set waiterRecord.[[Result]] to "timed-out". + b. Perform RemoveWaiter(WL, waiterRecord). + c. Perform NotifyWaiter(WL, waiterRecord). + 4. Perform LeaveCriticalSection(WL). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const before = $262.agent.monotonicNow(); + const unpark = await Atomics.waitAsync(i32a, 0, 0, ${TIMEOUT}).value; + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + + Atomics.store(i32a, 0, 0b1010); + + const lapse = await $262.agent.getReportAsync(); + + assert( + lapse >= TIMEOUT, + 'The result of evaluating `(lapse >= TIMEOUT)` is true' + ); + + const result = await $262.agent.getReportAsync(); + + assert.sameValue( + result, + 'timed-out', + 'The value of `result` is "timed-out"' + ); + assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 0'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-sub.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-sub.js new file mode 100644 index 0000000000..c60beab60e --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-sub.js @@ -0,0 +1,74 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Waiter does not spuriously notify on index which is subject to Sub operation +info: | + AddWaiter ( WL, waiterRecord ) + + 5. Append waiterRecord as the last element of WL.[[Waiters]] + 6. If waiterRecord.[[Timeout]] is finite, then in parallel, + a. Wait waiterRecord.[[Timeout]] milliseconds. + b. Perform TriggerTimeout(WL, waiterRecord). + + TriggerTimeout( WL, waiterRecord ) + + 3. If waiterRecord is in WL.[[Waiters]], then + a. Set waiterRecord.[[Result]] to "timed-out". + b. Perform RemoveWaiter(WL, waiterRecord). + c. Perform NotifyWaiter(WL, waiterRecord). + 4. Perform LeaveCriticalSection(WL). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const before = $262.agent.monotonicNow(); + const unpark = await Atomics.waitAsync(i32a, 0, 0, ${TIMEOUT}).value; + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + + Atomics.sub(i32a, 0, 1); + + const lapse = await $262.agent.getReportAsync(); + + assert( + lapse >= TIMEOUT, + 'The result of evaluating `(lapse >= TIMEOUT)` is true' + ); + + const result = await $262.agent.getReportAsync(); + + assert.sameValue( + result, + 'timed-out', + 'The value of `result` is "timed-out"' + ); + assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 0'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-xor.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-xor.js new file mode 100644 index 0000000000..f00bfadda5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/no-spurious-wakeup-on-xor.js @@ -0,0 +1,74 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Waiter does not spuriously notify on index which is subject to xor operation +info: | + AddWaiter ( WL, waiterRecord ) + + 5. Append waiterRecord as the last element of WL.[[Waiters]] + 6. If waiterRecord.[[Timeout]] is finite, then in parallel, + a. Wait waiterRecord.[[Timeout]] milliseconds. + b. Perform TriggerTimeout(WL, waiterRecord). + + TriggerTimeout( WL, waiterRecord ) + + 3. If waiterRecord is in WL.[[Waiters]], then + a. Set waiterRecord.[[Result]] to "timed-out". + b. Perform RemoveWaiter(WL, waiterRecord). + c. Perform NotifyWaiter(WL, waiterRecord). + 4. Perform LeaveCriticalSection(WL). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.small; + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const before = $262.agent.monotonicNow(); + const unpark = await Atomics.waitAsync(i32a, 0, 0, ${TIMEOUT}).value; + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + + Atomics.xor(i32a, 0, 1); + + const lapse = await $262.agent.getReportAsync(); + + assert( + lapse >= TIMEOUT, + 'The result of evaluating `(lapse >= TIMEOUT)` is true' + ); + + const result = await $262.agent.getReportAsync(); + + assert.sameValue( + result, + 'timed-out', + 'The value of `result` is "timed-out"' + ); + assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 0'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/non-int32-typedarray-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/non-int32-typedarray-throws.js new file mode 100644 index 0000000000..13ee2c67aa --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/non-int32-typedarray-throws.js @@ -0,0 +1,88 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if typedArray arg is not an Int32Array +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + + ValidateSharedIntegerTypedArray ( typedArray [ , waitable ] ) + + 5. If waitable is true, then + a. If typeName is not "Int32Array" or "BigInt64Array", throw a TypeError exception. + +features: [Atomics.waitAsync, Float32Array, Float64Array, Int8Array, TypedArray, Uint16Array, Uint8Array, Uint8ClampedArray, arrow-function, SharedArrayBuffer, Atomics] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const poisoned = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, () => { + const view = new Float64Array( + new SharedArrayBuffer(Float64Array.BYTES_PER_ELEMENT * 8) + ); + Atomics.waitAsync(view, poisoned, poisoned, poisoned); +}, '`const view = new Float64Array( new SharedArrayBuffer(Float64Array.BYTES_PER_ELEMENT * 8) ); Atomics.waitAsync(view, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + const view = new Float32Array( + new SharedArrayBuffer(Float32Array.BYTES_PER_ELEMENT * 4) + ); + Atomics.waitAsync(view, poisoned, poisoned, poisoned); +}, '`const view = new Float32Array( new SharedArrayBuffer(Float32Array.BYTES_PER_ELEMENT * 4) ); Atomics.waitAsync(view, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + const view = new Int16Array( + new SharedArrayBuffer(Int16Array.BYTES_PER_ELEMENT * 2) + ); + Atomics.waitAsync(view, poisoned, poisoned, poisoned); +}, '`const view = new Int16Array( new SharedArrayBuffer(Int16Array.BYTES_PER_ELEMENT * 2) ); Atomics.waitAsync(view, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + const view = new Int8Array( + new SharedArrayBuffer(Int8Array.BYTES_PER_ELEMENT) + ); + Atomics.waitAsync(view, poisoned, poisoned, poisoned); +}, '`const view = new Int8Array( new SharedArrayBuffer(Int8Array.BYTES_PER_ELEMENT) ); Atomics.waitAsync(view, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + const view = new Uint32Array( + new SharedArrayBuffer(Uint32Array.BYTES_PER_ELEMENT * 4) + ); + Atomics.waitAsync(view, poisoned, poisoned, poisoned); +}, '`const view = new Uint32Array( new SharedArrayBuffer(Uint32Array.BYTES_PER_ELEMENT * 4) ); Atomics.waitAsync(view, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + const view = new Uint16Array( + new SharedArrayBuffer(Uint16Array.BYTES_PER_ELEMENT * 2) + ); + Atomics.waitAsync(view, poisoned, poisoned, poisoned); +}, '`const view = new Uint16Array( new SharedArrayBuffer(Uint16Array.BYTES_PER_ELEMENT * 2) ); Atomics.waitAsync(view, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + const view = new Uint8Array( + new SharedArrayBuffer(Uint8Array.BYTES_PER_ELEMENT) + ); + Atomics.waitAsync(view, poisoned, poisoned, poisoned); +}, '`const view = new Uint8Array( new SharedArrayBuffer(Uint8Array.BYTES_PER_ELEMENT) ); Atomics.waitAsync(view, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + const view = new Uint8ClampedArray( + new SharedArrayBuffer(Uint8ClampedArray.BYTES_PER_ELEMENT) + ); + Atomics.waitAsync(view, poisoned, poisoned, poisoned); +}, '`const view = new Uint8ClampedArray( new SharedArrayBuffer(Uint8ClampedArray.BYTES_PER_ELEMENT) ); Atomics.waitAsync(view, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/non-shared-bufferdata-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/non-shared-bufferdata-throws.js new file mode 100644 index 0000000000..889bfd676e --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/non-shared-bufferdata-throws.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if typedArray.buffer is not a SharedArrayBuffer +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + + ValidateSharedIntegerTypedArray ( typedArray [ , waitable ] ) + + 5. If waitable is true, then + a. If typeName is not "Int32Array" or "BigInt64Array", throw a TypeError exception. + +features: [Atomics.waitAsync, ArrayBuffer, Atomics, TypedArray, arrow-function] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i32a = new Int32Array( + new ArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, () => { + Atomics.waitAsync(i32a, 0, 0, 0); +}, '`Atomics.waitAsync(i32a, 0, 0, 0)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + Atomics.waitAsync(i32a, poisoned, poisoned, poisoned); +}, '`Atomics.waitAsync(i32a, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/not-a-typedarray-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/not-a-typedarray-throws.js new file mode 100644 index 0000000000..25be13fbbd --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/not-a-typedarray-throws.js @@ -0,0 +1,43 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if the typedArray arg is not a TypedArray object +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + + ValidateSharedIntegerTypedArray ( typedArray [ , waitable ] ) + + 2. Perform ? RequireInternalSlot(typedArray, [[TypedArrayName]]). + + RequireInternalSlot ( O, internalSlot ) + + 1. If Type(O) is not Object, throw a TypeError exception. + 2. If O does not have an internalSlot internal slot, throw a TypeError exception. + +features: [Atomics.waitAsync, arrow-function, Atomics] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const poisoned = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, () => { + Atomics.waitAsync({}, 0, 0, 0); +}, '`Atomics.waitAsync({}, 0, 0, 0)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + Atomics.waitAsync({}, poisoned, poisoned, poisoned); +}, '`Atomics.waitAsync({}, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/not-an-object-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/not-an-object-throws.js new file mode 100644 index 0000000000..9ea6b9f392 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/not-an-object-throws.js @@ -0,0 +1,63 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if typedArray arg is not an Object +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + + ValidateSharedIntegerTypedArray ( typedArray [ , waitable ] ) + + 2. Perform ? RequireInternalSlot(typedArray, [[TypedArrayName]]). + + RequireInternalSlot ( O, internalSlot ) + + 1. If Type(O) is not Object, throw a TypeError exception. + 2. If O does not have an internalSlot internal slot, throw a TypeError exception. + +features: [Atomics.waitAsync, Symbol, arrow-function, Atomics] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const poisoned = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(TypeError, () => { + Atomics.waitAsync(null, poisoned, poisoned, poisoned); +}, '`Atomics.waitAsync(null, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + Atomics.waitAsync(undefined, poisoned, poisoned, poisoned); +}, '`Atomics.waitAsync(undefined, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + Atomics.waitAsync(true, poisoned, poisoned, poisoned); +}, '`Atomics.waitAsync(true, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + Atomics.waitAsync(false, poisoned, poisoned, poisoned); +}, '`Atomics.waitAsync(false, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + Atomics.waitAsync('***string***', poisoned, poisoned, poisoned); +}, '`Atomics.waitAsync("***string***", poisoned, poisoned, poisoned)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + Atomics.waitAsync(Number.NEGATIVE_INFINITY, poisoned, poisoned, poisoned); +}, '`Atomics.waitAsync(Number.NEGATIVE_INFINITY, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +assert.throws(TypeError, () => { + Atomics.waitAsync(Symbol('***symbol***'), poisoned, poisoned, poisoned); +}, '`Atomics.waitAsync(Symbol("***symbol***"), poisoned, poisoned, poisoned)` throws a TypeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/null-bufferdata-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/null-bufferdata-throws.js new file mode 100644 index 0000000000..e1bcdcb8be --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/null-bufferdata-throws.js @@ -0,0 +1,50 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + A null value for bufferData throws a TypeError +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + + ValidateSharedIntegerTypedArray ( typedArray [ , waitable ] ) + + 2. Perform ? RequireInternalSlot(typedArray, [[TypedArrayName]]). + + RequireInternalSlot ( O, internalSlot ) + + 1. If Type(O) is not Object, throw a TypeError exception. + 2. If O does not have an internalSlot internal slot, throw a TypeError exception. + +includes: [detachArrayBuffer.js] +features: [Atomics.waitAsync, ArrayBuffer, Atomics, TypedArray] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i32a = new Int32Array( + new ArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +try { + $DETACHBUFFER(i32a.buffer); // Detaching a non-shared ArrayBuffer sets the [[ArrayBufferData]] value to null +} catch (error) { + $ERROR(`An unexpected error occurred when detaching ArrayBuffer: ${error.message}`); +} + +assert.throws(TypeError, function() { + Atomics.waitAsync(i32a, poisoned, poisoned, poisoned); +}, '`Atomics.waitAsync(i32a, poisoned, poisoned, poisoned)` throws a TypeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/null-for-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/null-for-timeout-agent.js new file mode 100644 index 0000000000..09f8191896 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/null-for-timeout-agent.js @@ -0,0 +1,95 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + null timeout arg should result in an +0 timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + + Null -> Return +0. + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; + +$262.agent.start(` + const valueOf = { + valueOf() { + return null; + } + }; + + const toPrimitive = { + [Symbol.toPrimitive]() { + return null; + } + }; + + $262.agent.receiveBroadcast(async (sab) => { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + $262.agent.report(await Atomics.waitAsync(i32a, 0, 0, null).value); + $262.agent.report(await Atomics.waitAsync(i32a, 0, 0, valueOf).value); + $262.agent.report(await Atomics.waitAsync(i32a, 0, 0, toPrimitive).value); + $262.agent.report(Atomics.waitAsync(i32a, 0, 0, null).value); + $262.agent.report(Atomics.waitAsync(i32a, 0, 0, valueOf).value); + $262.agent.report(Atomics.waitAsync(i32a, 0, 0, toPrimitive).value); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 0'); + +}).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/null-for-timeout.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/null-for-timeout.js new file mode 100644 index 0000000000..6567c2c7d8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/null-for-timeout.js @@ -0,0 +1,56 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + null timeout arg should result in an +0 timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + + Null -> Return +0. + +features: [Atomics.waitAsync, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray, computed-property-names, Atomics, arrow-function] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const valueOf = { + valueOf() { + return null; + } +}; + +const toPrimitive = { + [Symbol.toPrimitive]() { + return null; + } +}; + +assert.sameValue( + Atomics.waitAsync(i32a, 0, 0, null).value, + 'timed-out', + 'The value of Atomics.waitAsync(i32a, 0, 0, null).value is "timed-out"' +); +assert.sameValue( + Atomics.waitAsync(i32a, 0, 0, valueOf).value, + 'timed-out', + 'The value of Atomics.waitAsync(i32a, 0, 0, valueOf).value is "timed-out"' +); +assert.sameValue( + Atomics.waitAsync(i32a, 0, 0, toPrimitive).value, + 'timed-out', + 'The value of Atomics.waitAsync(i32a, 0, 0, toPrimitive).value is "timed-out"' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/object-for-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/object-for-timeout-agent.js new file mode 100644 index 0000000000..ae681bf391 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/object-for-timeout-agent.js @@ -0,0 +1,105 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Object valueOf, toString, toPrimitive Zero timeout arg should result in an +0 timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + + Object -> Apply the following steps: + + Let primValue be ? ToPrimitive(argument, hint Number). + Return ? ToNumber(primValue). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; + +$262.agent.start(` + const valueOf = { + valueOf() { + return 0; + } + }; + + const toString = { + toString() { + return "0"; + } + }; + + const toPrimitive = { + [Symbol.toPrimitive]() { + return 0; + } + }; + + $262.agent.receiveBroadcast(async (sab) => { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + $262.agent.report(await Atomics.waitAsync(i32a, 0, 0, valueOf).value); + $262.agent.report(await Atomics.waitAsync(i32a, 0, 0, toString).value); + $262.agent.report(await Atomics.waitAsync(i32a, 0, 0, toPrimitive).value); + $262.agent.report(Atomics.waitAsync(i32a, 0, 0, valueOf).value); + $262.agent.report(Atomics.waitAsync(i32a, 0, 0, toString).value); + $262.agent.report(Atomics.waitAsync(i32a, 0, 0, toPrimitive).value); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 0'); + +}).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/object-for-timeout.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/object-for-timeout.js new file mode 100644 index 0000000000..cd1dc8f596 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/object-for-timeout.js @@ -0,0 +1,73 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Object valueOf, toString, toPrimitive Zero timeout arg should result in an +0 timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + + Object -> Apply the following steps: + + Let primValue be ? ToPrimitive(argument, hint Number). + Return ? ToNumber(primValue). + +features: [Atomics.waitAsync, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray, computed-property-names, Atomics, arrow-function] +flags: [async] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const valueOf = { + valueOf() { + return 0; + } +}; + +const toString = { + toString() { + return "0"; + } +}; + +const toPrimitive = { + [Symbol.toPrimitive]() { + return 0; + } +}; + +assert.sameValue( + Atomics.waitAsync(i32a, 0, 0, valueOf).value, + 'timed-out', + 'The value of Atomics.waitAsync(i32a, 0, 0, valueOf).value is "timed-out"' +); +assert.sameValue( + Atomics.waitAsync(i32a, 0, 0, toString).value, + 'timed-out', + 'The value of Atomics.waitAsync(i32a, 0, 0, toString).value is "timed-out"' +); +assert.sameValue( + Atomics.waitAsync(i32a, 0, 0, toPrimitive).value, + 'timed-out', + 'The value of Atomics.waitAsync(i32a, 0, 0, toPrimitive).value is "timed-out"' +); + +Promise.all([ + Atomics.waitAsync(i32a, 0, 0, valueOf).value, + Atomics.waitAsync(i32a, 0, 0, toString).value, + Atomics.waitAsync(i32a, 0, 0, toPrimitive).value, + ]).then(outcomes => { + assert.sameValue(outcomes[0], "timed-out", 'The value of outcomes[0] is "timed-out"'); + assert.sameValue(outcomes[1], "timed-out", 'The value of outcomes[1] is "timed-out"'); + assert.sameValue(outcomes[2], "timed-out", 'The value of outcomes[2] is "timed-out"'); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/out-of-range-index-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/out-of-range-index-throws.js new file mode 100644 index 0000000000..72ae3b0fb4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/out-of-range-index-throws.js @@ -0,0 +1,48 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Throws a RangeError if value of index arg is out of range +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 2. Let i be ? ValidateAtomicAccess(typedArray, index). + + ... + 2.Let accessIndex be ? ToIndex(requestIndex). + ... + 5. If accessIndex ≥ length, throw a RangeError exception. +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisoned = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(RangeError, function() { + Atomics.waitAsync(i32a, Infinity, poisoned, poisoned); +}, '`Atomics.waitAsync(i32a, Infinity, poisoned, poisoned)` throws a RangeError exception'); +assert.throws(RangeError, function() { + Atomics.waitAsync(i32a, -1, poisoned, poisoned); +}, '`Atomics.waitAsync(i32a, -1, poisoned, poisoned)` throws a RangeError exception'); +assert.throws(RangeError, function() { + Atomics.waitAsync(i32a, 4, poisoned, poisoned); +}, '`Atomics.waitAsync(i32a, 4, poisoned, poisoned)` throws a RangeError exception'); +assert.throws(RangeError, function() { + Atomics.waitAsync(i32a, 200, poisoned, poisoned); +}, '`Atomics.waitAsync(i32a, 200, poisoned, poisoned)` throws a RangeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/poisoned-object-for-timeout-throws-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/poisoned-object-for-timeout-throws-agent.js new file mode 100644 index 0000000000..b2e606d77f --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/poisoned-object-for-timeout-throws-agent.js @@ -0,0 +1,89 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + False timeout arg should result in an +0 timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + + Let primValue be ? ToPrimitive(argument, hint Number). + Return ? ToNumber(primValue). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; + +$262.agent.start(` + const poisonedValueOf = { + valueOf() { + throw new Error('should not evaluate this code'); + } + }; + + const poisonedToPrimitive = { + [Symbol.toPrimitive]() { + throw new Error('passing a poisoned object using @@ToPrimitive'); + } + }; + + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + let status1 = ''; + let status2 = ''; + + try { + Atomics.waitAsync(i32a, 0, 0, poisonedValueOf); + } catch (error) { + status1 = 'poisonedValueOf'; + } + try { + Atomics.waitAsync(i32a, 0, 0, poisonedToPrimitive); + } catch (error) { + status2 = 'poisonedToPrimitive'; + } + + $262.agent.report(status1); + $262.agent.report(status2); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'poisonedValueOf', + '(await $262.agent.getReportAsync()) resolves to the value "poisonedValueOf"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'poisonedToPrimitive', + '(await $262.agent.getReportAsync()) resolves to the value "poisonedToPrimitive"' + ); + + assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 0'); + +}).then($DONE, $DONE); + diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/poisoned-object-for-timeout-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/poisoned-object-for-timeout-throws.js new file mode 100644 index 0000000000..3a084108e5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/poisoned-object-for-timeout-throws.js @@ -0,0 +1,49 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if index arg can not be converted to an Integer +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + + Let primValue be ? ToPrimitive(argument, hint Number). + Return ? ToNumber(primValue). + +features: [Atomics.waitAsync, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray, computed-property-names, Atomics] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisonedValueOf = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +const poisonedToPrimitive = { + [Symbol.toPrimitive]() { + throw new Test262Error('passing a poisoned object using @@ToPrimitive'); + } +}; + +assert.throws(Test262Error, function() { + Atomics.waitAsync(i32a, 0, 0, poisonedValueOf); +}, '`Atomics.waitAsync(i32a, 0, 0, poisonedValueOf)` throws a Test262Error exception'); + +assert.throws(Test262Error, function() { + Atomics.waitAsync(i32a, 0, 0, poisonedToPrimitive); +}, '`Atomics.waitAsync(i32a, 0, 0, poisonedToPrimitive)` throws a Test262Error exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/returns-result-object-value-is-promise-resolves-to-ok.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/returns-result-object-value-is-promise-resolves-to-ok.js new file mode 100644 index 0000000000..41fb6ae31c --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/returns-result-object-value-is-promise-resolves-to-ok.js @@ -0,0 +1,52 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Atomics.waitAsync returns a result object containing a property named "value" whose value is a promise that resolves to "ok" and async is true. +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + ... + 13. Let promiseCapability be undefined. + 14. If mode is async, then + a. Set promiseCapability to ! NewPromiseCapability(%Promise%). + + ... + Perform ! CreateDataPropertyOrThrow(_resultObject_, *"async"*, *true*). + Perform ! CreateDataPropertyOrThrow(_resultObject_, *"value"*, _promiseCapability_.[[Promise]]). + Return _resultObject_. + +flags: [async] +features: [Atomics.waitAsync, TypedArray, SharedArrayBuffer, destructuring-binding, Atomics, arrow-function] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 8) +); + +let {async, value} = Atomics.waitAsync(i32a, 0, 0, 1000); +assert.sameValue(async, true, 'The value of `async` is true'); +assert(value instanceof Promise, 'The result of evaluating `(value instanceof Promise)` is true'); +assert.sameValue( + Object.getPrototypeOf(value), + Promise.prototype, + 'Object.getPrototypeOf(value) must return the value of Promise.prototype' +); + +value.then(outcome => { + assert.sameValue(outcome, "ok", 'The value of `outcome` is "ok"'); +}).then(() => $DONE(), $DONE); + +Atomics.add(i32a, 0, 1); +Atomics.notify(i32a, 0, 1); + + + diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/returns-result-object-value-is-promise-resolves-to-timed-out.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/returns-result-object-value-is-promise-resolves-to-timed-out.js new file mode 100644 index 0000000000..9cd01f3200 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/returns-result-object-value-is-promise-resolves-to-timed-out.js @@ -0,0 +1,57 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Atomics.waitAsync returns a result object containing a promise that resolves to "timed-out" and async is true. +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + ... + 13. Let promiseCapability be undefined. + 14. If mode is async, then + a. Set promiseCapability to ! NewPromiseCapability(%Promise%). + + ... + Perform ! CreateDataPropertyOrThrow(_resultObject_, *"async"*, *true*). + Perform ! CreateDataPropertyOrThrow(_resultObject_, *"value"*, _promiseCapability_.[[Promise]]). + Return _resultObject_. + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, TypedArray, SharedArrayBuffer, destructuring-binding, Atomics, arrow-function] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 8) +); + +let {async, value} = Atomics.waitAsync(i32a, 0, 0, 1); +let outcome = null; +let lifespan = 1000; +let start = $262.agent.monotonicNow(); + +function wait() { + let elapsed = $262.agent.monotonicNow() - start; + if (elapsed > lifespan) { + $DONE("Test timed out"); + return; + } + if (outcome === "timed-out") { + $DONE(); + return; + } + + $262.agent.setTimeout(wait, 0); +} + +wait(); + +value.then(result => (outcome = result), $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/returns-result-object-value-is-string-not-equal.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/returns-result-object-value-is-string-not-equal.js new file mode 100644 index 0000000000..f981109bb7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/returns-result-object-value-is-string-not-equal.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Atomics.waitAsync returns a result object containing a string "not-equal" and async is false. +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + ... + 13. Let promiseCapability be undefined. + 14. If mode is async, then + a. Set promiseCapability to ! NewPromiseCapability(%Promise%). + + ... + Perform ! CreateDataPropertyOrThrow(_resultObject_, *"async"*, *true*). + Perform ! CreateDataPropertyOrThrow(_resultObject_, *"value"*, _promiseCapability_.[[Promise]]). + Return _resultObject_. + +features: [Atomics.waitAsync, TypedArray, SharedArrayBuffer, destructuring-binding, Atomics] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 8) +); + +let {async, value} = Atomics.waitAsync(i32a, 0, 1); + +assert.sameValue(async, false, 'The value of `async` is false'); +assert.sameValue(value, "not-equal", 'The value of `value` is "not-equal"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/returns-result-object-value-is-string-timed-out.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/returns-result-object-value-is-string-timed-out.js new file mode 100644 index 0000000000..85fed2b5ad --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/returns-result-object-value-is-string-timed-out.js @@ -0,0 +1,39 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Atomics.waitAsync returns a result object containing a string "not-equal" and async is false. +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + ... + 13. Let promiseCapability be undefined. + 14. If mode is async, then + a. Set promiseCapability to ! NewPromiseCapability(%Promise%). + + ... + Perform ! CreateDataPropertyOrThrow(_resultObject_, *"async"*, *true*). + Perform ! CreateDataPropertyOrThrow(_resultObject_, *"value"*, _promiseCapability_.[[Promise]]). + Return _resultObject_. + +features: [Atomics.waitAsync, TypedArray, SharedArrayBuffer, destructuring-binding, Atomics] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 8) +); + +let {async, value} = Atomics.waitAsync(i32a, 0, 0, 0); + +assert.sameValue(async, false, 'The value of `async` is false'); +assert.sameValue(value, "timed-out", 'The value of `value` is "timed-out"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/shell.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/shell.js new file mode 100644 index 0000000000..bdbc7c38b8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/shell.js @@ -0,0 +1,344 @@ +// GENERATED, DO NOT EDIT +// file: atomicsHelper.js +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Collection of functions used to interact with Atomics.* operations across agent boundaries. +defines: + - $262.agent.getReportAsync + - $262.agent.getReport + - $262.agent.safeBroadcastAsync + - $262.agent.safeBroadcast + - $262.agent.setTimeout + - $262.agent.tryYield + - $262.agent.trySleep +---*/ + +/** + * @return {String} A report sent from an agent. + */ +{ + // This is only necessary because the original + // $262.agent.getReport API was insufficient. + // + // All runtimes currently have their own + // $262.agent.getReport which is wrong, so we + // will pave over it with a corrected version. + // + // Binding $262.agent is necessary to prevent + // breaking SpiderMonkey's $262.agent.getReport + let getReport = $262.agent.getReport.bind($262.agent); + + $262.agent.getReport = function() { + var r; + while ((r = getReport()) == null) { + $262.agent.sleep(1); + } + return r; + }; + + if (this.setTimeout === undefined) { + (function(that) { + that.setTimeout = function(callback, delay) { + let p = Promise.resolve(); + let start = Date.now(); + let end = start + delay; + function check() { + if ((end - Date.now()) > 0) { + p.then(check); + } + else { + callback(); + } + } + p.then(check); + } + })(this); + } + + $262.agent.setTimeout = setTimeout; + + $262.agent.getReportAsync = function() { + return new Promise(function(resolve) { + (function loop() { + let result = getReport(); + if (!result) { + setTimeout(loop, 1000); + } else { + resolve(result); + } + })(); + }); + }; +} + +/** + * + * Share a given Int32Array or BigInt64Array to all running agents. Ensure that the + * provided TypedArray is a "shared typed array". + * + * NOTE: Migrating all tests to this API is necessary to prevent tests from hanging + * indefinitely when a SAB is sent to a worker but the code in the worker attempts to + * create a non-sharable TypedArray (something that is not Int32Array or BigInt64Array). + * When that scenario occurs, an exception is thrown and the agent worker can no + * longer communicate with any other threads that control the SAB. If the main + * thread happens to be spinning in the $262.agent.waitUntil() while loop, it will never + * meet its termination condition and the test will hang indefinitely. + * + * Because we've defined $262.agent.broadcast(SAB) in + * https://github.com/tc39/test262/blob/HEAD/INTERPRETING.md, there are host implementations + * that assume compatibility, which must be maintained. + * + * + * $262.agent.safeBroadcast(TA) should not be included in + * https://github.com/tc39/test262/blob/HEAD/INTERPRETING.md + * + * + * @param {(Int32Array|BigInt64Array)} typedArray An Int32Array or BigInt64Array with a SharedArrayBuffer + */ +$262.agent.safeBroadcast = function(typedArray) { + let Constructor = Object.getPrototypeOf(typedArray).constructor; + let temp = new Constructor( + new SharedArrayBuffer(Constructor.BYTES_PER_ELEMENT) + ); + try { + // This will never actually wait, but that's fine because we only + // want to ensure that this typedArray CAN be waited on and is shareable. + Atomics.wait(temp, 0, Constructor === Int32Array ? 1 : BigInt(1)); + } catch (error) { + $ERROR(`${Constructor.name} cannot be used as a shared typed array. (${error})`); + } + + $262.agent.broadcast(typedArray.buffer); +}; + +$262.agent.safeBroadcastAsync = async function(ta, index, expected) { + await $262.agent.broadcast(ta.buffer); + await $262.agent.waitUntil(ta, index, expected); + await $262.agent.tryYield(); + return await Atomics.load(ta, index); +}; + + +/** + * With a given Int32Array or BigInt64Array, wait until the expected number of agents have + * reported themselves by calling: + * + * Atomics.add(typedArray, index, 1); + * + * @param {(Int32Array|BigInt64Array)} typedArray An Int32Array or BigInt64Array with a SharedArrayBuffer + * @param {number} index The index of which all agents will report. + * @param {number} expected The number of agents that are expected to report as active. + */ +$262.agent.waitUntil = function(typedArray, index, expected) { + + var agents = 0; + while ((agents = Atomics.load(typedArray, index)) !== expected) { + /* nothing */ + } + assert.sameValue(agents, expected, "Reporting number of 'agents' equals the value of 'expected'"); +}; + +/** + * Timeout values used throughout the Atomics tests. All timeouts are specified in milliseconds. + * + * @property {number} yield Used for `$262.agent.tryYield`. Must not be used in other functions. + * @property {number} small Used when agents will always timeout and `Atomics.wake` is not part + * of the test semantics. Must be larger than `$262.agent.timeouts.yield`. + * @property {number} long Used when some agents may timeout and `Atomics.wake` is called on some + * agents. The agents are required to wait and this needs to be observable + * by the main thread. + * @property {number} huge Used when `Atomics.wake` is called on all waiting agents. The waiting + * must not timeout. The agents are required to wait and this needs to be + * observable by the main thread. All waiting agents must be woken by the + * main thread. + * + * Usage for `$262.agent.timeouts.small`: + * const WAIT_INDEX = 0; + * const RUNNING = 1; + * const TIMEOUT = $262.agent.timeouts.small; + * const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2)); + * + * $262.agent.start(` + * $262.agent.receiveBroadcast(function(sab) { + * const i32a = new Int32Array(sab); + * Atomics.add(i32a, ${RUNNING}, 1); + * + * $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); + * + * $262.agent.leaving(); + * }); + * `); + * $262.agent.safeBroadcast(i32a.buffer); + * + * // Wait until the agent was started and then try to yield control to increase + * // the likelihood the agent has called `Atomics.wait` and is now waiting. + * $262.agent.waitUntil(i32a, RUNNING, 1); + * $262.agent.tryYield(); + * + * // The agent is expected to time out. + * assert.sameValue($262.agent.getReport(), "timed-out"); + * + * + * Usage for `$262.agent.timeouts.long`: + * const WAIT_INDEX = 0; + * const RUNNING = 1; + * const NUMAGENT = 2; + * const TIMEOUT = $262.agent.timeouts.long; + * const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2)); + * + * for (let i = 0; i < NUMAGENT; i++) { + * $262.agent.start(` + * $262.agent.receiveBroadcast(function(sab) { + * const i32a = new Int32Array(sab); + * Atomics.add(i32a, ${RUNNING}, 1); + * + * $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); + * + * $262.agent.leaving(); + * }); + * `); + * } + * $262.agent.safeBroadcast(i32a.buffer); + * + * // Wait until the agents were started and then try to yield control to increase + * // the likelihood the agents have called `Atomics.wait` and are now waiting. + * $262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + * $262.agent.tryYield(); + * + * // Wake exactly one agent. + * assert.sameValue(Atomics.wake(i32a, WAIT_INDEX, 1), 1); + * + * // When it doesn't matter how many agents were woken at once, a while loop + * // can be used to make the test more resilient against intermittent failures + * // in case even though `tryYield` was called, the agents haven't started to + * // wait. + * // + * // // Repeat until exactly one agent was woken. + * // var woken = 0; + * // while ((woken = Atomics.wake(i32a, WAIT_INDEX, 1)) !== 0) ; + * // assert.sameValue(woken, 1); + * + * // One agent was woken and the other one timed out. + * const reports = [$262.agent.getReport(), $262.agent.getReport()]; + * assert(reports.includes("ok")); + * assert(reports.includes("timed-out")); + * + * + * Usage for `$262.agent.timeouts.huge`: + * const WAIT_INDEX = 0; + * const RUNNING = 1; + * const NUMAGENT = 2; + * const TIMEOUT = $262.agent.timeouts.huge; + * const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2)); + * + * for (let i = 0; i < NUMAGENT; i++) { + * $262.agent.start(` + * $262.agent.receiveBroadcast(function(sab) { + * const i32a = new Int32Array(sab); + * Atomics.add(i32a, ${RUNNING}, 1); + * + * $262.agent.report(Atomics.wait(i32a, ${WAIT_INDEX}, 0, ${TIMEOUT})); + * + * $262.agent.leaving(); + * }); + * `); + * } + * $262.agent.safeBroadcast(i32a.buffer); + * + * // Wait until the agents were started and then try to yield control to increase + * // the likelihood the agents have called `Atomics.wait` and are now waiting. + * $262.agent.waitUntil(i32a, RUNNING, NUMAGENT); + * $262.agent.tryYield(); + * + * // Wake all agents. + * assert.sameValue(Atomics.wake(i32a, WAIT_INDEX), NUMAGENT); + * + * // When it doesn't matter how many agents were woken at once, a while loop + * // can be used to make the test more resilient against intermittent failures + * // in case even though `tryYield` was called, the agents haven't started to + * // wait. + * // + * // // Repeat until all agents were woken. + * // for (var wokenCount = 0; wokenCount < NUMAGENT; ) { + * // var woken = 0; + * // while ((woken = Atomics.wake(i32a, WAIT_INDEX)) !== 0) ; + * // // Maybe perform an action on the woken agents here. + * // wokenCount += woken; + * // } + * + * // All agents were woken and none timeout. + * for (var i = 0; i < NUMAGENT; i++) { + * assert($262.agent.getReport(), "ok"); + * } + */ +$262.agent.timeouts = { + yield: 100, + small: 200, + long: 1000, + huge: 10000, +}; + +/** + * Try to yield control to the agent threads. + * + * Usage: + * const VALUE = 0; + * const RUNNING = 1; + * const i32a = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2)); + * + * $262.agent.start(` + * $262.agent.receiveBroadcast(function(sab) { + * const i32a = new Int32Array(sab); + * Atomics.add(i32a, ${RUNNING}, 1); + * + * Atomics.store(i32a, ${VALUE}, 1); + * + * $262.agent.leaving(); + * }); + * `); + * $262.agent.safeBroadcast(i32a.buffer); + * + * // Wait until agent was started and then try to yield control. + * $262.agent.waitUntil(i32a, RUNNING, 1); + * $262.agent.tryYield(); + * + * // Note: This result is not guaranteed, but should hold in practice most of the time. + * assert.sameValue(Atomics.load(i32a, VALUE), 1); + * + * The default implementation simply waits for `$262.agent.timeouts.yield` milliseconds. + */ +$262.agent.tryYield = function() { + $262.agent.sleep($262.agent.timeouts.yield); +}; + +/** + * Try to sleep the current agent for the given amount of milliseconds. It is acceptable, + * but not encouraged, to ignore this sleep request and directly continue execution. + * + * The default implementation calls `$262.agent.sleep(ms)`. + * + * @param {number} ms Time to sleep in milliseconds. + */ +$262.agent.trySleep = function(ms) { + $262.agent.sleep(ms); +}; + +// file: detachArrayBuffer.js +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + A function used in the process of asserting correctness of TypedArray objects. + + $262.detachArrayBuffer is defined by a host. +defines: [$DETACHBUFFER] +---*/ + +function $DETACHBUFFER(buffer) { + if (!$262 || typeof $262.detachArrayBuffer !== "function") { + throw new Test262Error("No method available to detach an ArrayBuffer"); + } + $262.detachArrayBuffer(buffer); +} diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/symbol-for-index-throws-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/symbol-for-index-throws-agent.js new file mode 100644 index 0000000000..937bad77ae --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/symbol-for-index-throws-agent.js @@ -0,0 +1,100 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if index arg can not be converted to an Integer +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 2. Let i be ? ValidateAtomicAccess(typedArray, index). + + ValidateAtomicAccess( typedArray, requestIndex ) + + 2. Let accessIndex be ? ToIndex(requestIndex). + + ToIndex ( value ) + + 2. Else, + a. Let integerIndex be ? ToInteger(value). + + ToInteger(value) + + 1. Let number be ? ToNumber(argument). + + Symbol --> Throw a TypeError exception. + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; + +$262.agent.start(` + const poisonedValueOf = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } + }; + + const poisonedToPrimitive = { + [Symbol.toPrimitive]() { + throw new Test262Error('should not evaluate this code'); + } + }; + + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + let status1 = ''; + let status2 = ''; + + try { + Atomics.waitAsync(i32a, Symbol('1'), poisonedValueOf, poisonedValueOf); + } catch (error) { + status1 = 'A ' + error.name; + } + try { + Atomics.waitAsync(i32a, Symbol('2'), poisonedToPrimitive, poisonedToPrimitive); + } catch (error) { + status2 = 'B ' + error.name; + } + + $262.agent.report(status1); + $262.agent.report(status2); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'A TypeError', + '(await $262.agent.getReportAsync()) resolves to the value "A TypeError"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'B TypeError', + '(await $262.agent.getReportAsync()) resolves to the value "B TypeError"' + ); + + assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 0'); + +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/symbol-for-index-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/symbol-for-index-throws.js new file mode 100644 index 0000000000..58127afa98 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/symbol-for-index-throws.js @@ -0,0 +1,71 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if index arg can not be converted to an Integer +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 2. Let i be ? ValidateAtomicAccess(typedArray, index). + + ValidateAtomicAccess( typedArray, requestIndex ) + + 2. Let accessIndex be ? ToIndex(requestIndex). + + ToIndex ( value ) + + 2. Else, + a. Let integerIndex be ? ToInteger(value). + + ToInteger(value) + + 1. Let number be ? ToNumber(argument). + + Symbol --> Throw a TypeError exception. + +features: [Atomics.waitAsync, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray, computed-property-names, Atomics] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisonedValueOf = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +const poisonedToPrimitive = { + [Symbol.toPrimitive]() { + throw new Test262Error('should not evaluate this code'); + } +}; + +assert.throws(Test262Error, function() { + Atomics.waitAsync(i32a, poisonedValueOf, poisonedValueOf, poisonedValueOf); +}, '`Atomics.waitAsync(i32a, poisonedValueOf, poisonedValueOf, poisonedValueOf)` throws a Test262Error exception'); + +assert.throws(Test262Error, function() { + Atomics.waitAsync(i32a, poisonedToPrimitive, poisonedToPrimitive, poisonedToPrimitive); +}, '`Atomics.waitAsync(i32a, poisonedToPrimitive, poisonedToPrimitive, poisonedToPrimitive)` throws a Test262Error exception'); + +assert.throws(TypeError, function() { + Atomics.waitAsync(i32a, Symbol('1'), poisonedValueOf, poisonedValueOf); +}, '`Atomics.waitAsync(i32a, Symbol("1"), poisonedValueOf, poisonedValueOf)` throws a TypeError exception'); + +assert.throws(TypeError, function() { + Atomics.waitAsync(i32a, Symbol('2'), poisonedToPrimitive, poisonedToPrimitive); +}, '`Atomics.waitAsync(i32a, Symbol("2"), poisonedToPrimitive, poisonedToPrimitive)` throws a TypeError exception'); + + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/symbol-for-timeout-throws-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/symbol-for-timeout-throws-agent.js new file mode 100644 index 0000000000..dc5c01c221 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/symbol-for-timeout-throws-agent.js @@ -0,0 +1,77 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if index arg can not be converted to an Integer +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + + Symbol --> Throw a TypeError exception. + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + let status1 = ''; + let status2 = ''; + + try { + Atomics.waitAsync(i32a, 0, 0, Symbol('1')); + } catch (error) { + status1 = 'A ' + error.name; + } + try { + Atomics.waitAsync(i32a, 0, 0, Symbol('2')); + } catch (error) { + status2 = 'B ' + error.name; + } + + $262.agent.report(status1); + $262.agent.report(status2); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'A TypeError', + '(await $262.agent.getReportAsync()) resolves to the value "A TypeError"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'B TypeError', + '(await $262.agent.getReportAsync()) resolves to the value "B TypeError"' + ); + + assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 0'); + +}).then($DONE, $DONE); + + diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/symbol-for-timeout-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/symbol-for-timeout-throws.js new file mode 100644 index 0000000000..1659f517e3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/symbol-for-timeout-throws.js @@ -0,0 +1,55 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if index arg can not be converted to an Integer +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + + Symbol --> Throw a TypeError exception. + +features: [Atomics.waitAsync, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray, computed-property-names, Atomics] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisonedValueOf = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +const poisonedToPrimitive = { + [Symbol.toPrimitive]() { + throw new Test262Error('passing a poisoned object using @@ToPrimitive'); + } +}; + +assert.throws(Test262Error, function() { + Atomics.waitAsync(i32a, 0, 0, poisonedValueOf); +}, '`Atomics.waitAsync(i32a, 0, 0, poisonedValueOf)` throws a Test262Error exception'); + +assert.throws(Test262Error, function() { + Atomics.waitAsync(i32a, 0, 0, poisonedToPrimitive); +}, '`Atomics.waitAsync(i32a, 0, 0, poisonedToPrimitive)` throws a Test262Error exception'); + +assert.throws(TypeError, function() { + Atomics.waitAsync(i32a, 0, 0, Symbol("foo")); +}, '`Atomics.waitAsync(i32a, 0, 0, Symbol("foo"))` throws a TypeError exception'); + +assert.throws(TypeError, function() { + Atomics.waitAsync(i32a, 0, 0, Symbol("foo")); +}, '`Atomics.waitAsync(i32a, 0, 0, Symbol("foo"))` throws a TypeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/symbol-for-value-throws-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/symbol-for-value-throws-agent.js new file mode 100644 index 0000000000..4de2105353 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/symbol-for-value-throws-agent.js @@ -0,0 +1,93 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if value arg is a Symbol +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 5. Otherwise, let v be ? ToInt32(value). + + ToInt32(value) + + 1.Let number be ? ToNumber(argument). + + Symbol --> Throw a TypeError exception. + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; + +$262.agent.start(` + const poisonedValueOf = { + valueOf: function() { + throw new Test262Error('should not evaluate this code'); + } + }; + + const poisonedToPrimitive = { + [Symbol.toPrimitive]: function() { + throw new Test262Error("passing a poisoned object using @@ToPrimitive"); + } + }; + + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + let status1 = ""; + let status2 = ""; + + try { + Atomics.waitAsync(i32a, 0, Symbol("1"), poisonedValueOf); + } catch (error) { + status1 = 'A ' + error.name; + } + try { + Atomics.waitAsync(i32a, 0, Symbol("2"), poisonedToPrimitive); + } catch (error) { + status2 = 'B ' + error.name; + } + + $262.agent.report(status1); + $262.agent.report(status2); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'A TypeError', + '(await $262.agent.getReportAsync()) resolves to the value "A TypeError"' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'B TypeError', + '(await $262.agent.getReportAsync()) resolves to the value "B TypeError"' + ); + + assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 0'); + +}).then($DONE, $DONE); + + diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/symbol-for-value-throws.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/symbol-for-value-throws.js new file mode 100644 index 0000000000..1d0c98ad8c --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/symbol-for-value-throws.js @@ -0,0 +1,59 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if value arg is a Symbol +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 5. Otherwise, let v be ? ToInt32(value). + + ToInt32(value) + + 1.Let number be ? ToNumber(argument). + + Symbol --> Throw a TypeError exception. + +features: [Atomics.waitAsync, SharedArrayBuffer, Symbol, Symbol.toPrimitive, TypedArray, computed-property-names, Atomics] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const poisonedValueOf = { + valueOf() { + throw new Test262Error('should not evaluate this code'); + } +}; + +const poisonedToPrimitive = { + [Symbol.toPrimitive]() { + throw new Test262Error("passing a poisoned object using @@ToPrimitive"); + } +}; + +assert.throws(Test262Error, function() { + Atomics.waitAsync(i32a, 0, poisonedValueOf, poisonedValueOf); +}, '`Atomics.waitAsync(i32a, 0, poisonedValueOf, poisonedValueOf)` throws a Test262Error exception'); + +assert.throws(Test262Error, function() { + Atomics.waitAsync(i32a, 0, poisonedToPrimitive, poisonedToPrimitive); +}, '`Atomics.waitAsync(i32a, 0, poisonedToPrimitive, poisonedToPrimitive)` throws a Test262Error exception'); + +assert.throws(TypeError, function() { + Atomics.waitAsync(i32a, 0, Symbol("foo"), poisonedValueOf); +}, '`Atomics.waitAsync(i32a, 0, Symbol("foo"), poisonedValueOf)` throws a TypeError exception'); + +assert.throws(TypeError, function() { + Atomics.waitAsync(i32a, 0, Symbol("foo"), poisonedToPrimitive); +}, '`Atomics.waitAsync(i32a, 0, Symbol("foo"), poisonedToPrimitive)` throws a TypeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/true-for-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/true-for-timeout-agent.js new file mode 100644 index 0000000000..240c3c07fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/true-for-timeout-agent.js @@ -0,0 +1,76 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + True timeout arg should result in an +0 timeout +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; + +$262.agent.start(` + const valueOf = { + valueOf() { + return true; + } + }; + + const toPrimitive = { + [Symbol.toPrimitive]() { + return true; + } + }; + + $262.agent.receiveBroadcast(async (sab) => { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + $262.agent.report(await Atomics.waitAsync(i32a, 0, 0, true).value); + $262.agent.report(await Atomics.waitAsync(i32a, 0, 0, valueOf).value); + $262.agent.report(await Atomics.waitAsync(i32a, 0, 0, toPrimitive).value); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + assert.sameValue( + await $262.agent.getReportAsync(), + 'timed-out', + '(await $262.agent.getReportAsync()) resolves to the value "timed-out"' + ); + + assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 0'); + +}).then($DONE, $DONE); + + diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/true-for-timeout.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/true-for-timeout.js new file mode 100644 index 0000000000..86a2be28fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/true-for-timeout.js @@ -0,0 +1,66 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Throws a TypeError if index arg can not be converted to an Integer +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + + Boolean -> If argument is true, return 1. If argument is false, return +0. + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, computed-property-names, Symbol, Symbol.toPrimitive, arrow-function] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const valueOf = { + valueOf() { + return true; + } +}; + +const toPrimitive = { + [Symbol.toPrimitive]() { + return true; + } +}; + +let outcomes = []; +let lifespan = 1000; +let start = $262.agent.monotonicNow(); + +(function wait() { + let elapsed = $262.agent.monotonicNow() - start; + if (elapsed > lifespan) { + $DONE("Test timed out"); + return; + } + if (outcomes.length) { + assert.sameValue(outcomes[0], 'timed-out', 'The value of outcomes[0] is "timed-out"'); + assert.sameValue(outcomes[1], 'timed-out', 'The value of outcomes[1] is "timed-out"'); + assert.sameValue(outcomes[2], 'timed-out', 'The value of outcomes[2] is "timed-out"'); + $DONE(); + return; + } + + $262.agent.setTimeout(wait, 0); +})(); + +Promise.all([ + Atomics.waitAsync(i32a, 0, 0, true).value, + Atomics.waitAsync(i32a, 0, 0, valueOf).value, + Atomics.waitAsync(i32a, 0, 0, toPrimitive).value, + ]).then(results => (outcomes = results), $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/undefined-for-timeout-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/undefined-for-timeout-agent.js new file mode 100644 index 0000000000..b50ef05dce --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/undefined-for-timeout-agent.js @@ -0,0 +1,77 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Undefined timeout arg is coerced to zero +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + ... + Undefined Return NaN. + + 5.If q is NaN, let t be +∞, else let t be max(q, 0) + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const WAIT_INDEX = 0; +const RUNNING = 1; +const NUMAGENT = 2; +const NOTIFYCOUNT = 2; + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + var i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // undefined => NaN => +Infinity + $262.agent.report("A " + (await Atomics.waitAsync(i32a, 0, 0, undefined).value)); + $262.agent.leaving(); + }); +`); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + var i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // undefined timeout arg => NaN => +Infinity + $262.agent.report("B " + (await Atomics.waitAsync(i32a, 0, 0).value)); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, NUMAGENT).then(async (agentCount) => { + + assert.sameValue(agentCount, NUMAGENT, 'The value of `agentCount` is expected to equal the value of NUMAGENT'); + + assert.sameValue( + Atomics.notify(i32a, WAIT_INDEX, NOTIFYCOUNT), + NOTIFYCOUNT, + 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0, 2) must return the value of NOTIFYCOUNT' + ); + + const reports = [ + await $262.agent.getReportAsync(), + await $262.agent.getReportAsync(), + ]; + + reports.sort(); + assert.sameValue(reports[0], 'A ok', 'The value of reports[0] is "A ok"'); + assert.sameValue(reports[1], 'B ok', 'The value of reports[1] is "B ok"'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/undefined-for-timeout.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/undefined-for-timeout.js new file mode 100644 index 0000000000..89038c7ab5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/undefined-for-timeout.js @@ -0,0 +1,54 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Undefined timeout arg is coerced to zero +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 6. Let q be ? ToNumber(timeout). + ... + Undefined Return NaN. + + 5.If q is NaN, let t be +∞, else let t be max(q, 0) + +flags: [async] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, computed-property-names, Symbol, Symbol.toPrimitive, arrow-function] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const valueOf = { + valueOf() { + return undefined; + } +}; + +const toPrimitive = { + [Symbol.toPrimitive]() { + return undefined; + } +}; + +Promise.all([ + Atomics.waitAsync(i32a, 0, 0).value, + Atomics.waitAsync(i32a, 0, 0, undefined).value, + Atomics.waitAsync(i32a, 0, 0, valueOf).value, + Atomics.waitAsync(i32a, 0, 0, toPrimitive).value + ]).then(outcomes => { + assert.sameValue(outcomes[0], 'ok', 'The value of outcomes[0] is "ok"'); + assert.sameValue(outcomes[1], 'ok', 'The value of outcomes[1] is "ok"'); + assert.sameValue(outcomes[2], 'ok', 'The value of outcomes[2] is "ok"'); + assert.sameValue(outcomes[3], 'ok', 'The value of outcomes[3] is "ok"'); + }).then($DONE, $DONE); + +Atomics.notify(i32a, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/undefined-index-defaults-to-zero-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/undefined-index-defaults-to-zero-agent.js new file mode 100644 index 0000000000..294e871035 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/undefined-index-defaults-to-zero-agent.js @@ -0,0 +1,79 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Undefined index arg is coerced to zero +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 2. Let i be ? ValidateAtomicAccess(typedArray, index). + ... + 2.Let accessIndex be ? ToIndex(requestIndex). + + 9.If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception. + ... + 3.If bufferData is a Data Block, return false + + If value is undefined, then + Let index be 0. + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const WAIT_INDEX = 0; +const RUNNING = 1; +const NUMAGENT = 2; +const NOTIFYCOUNT = 2; + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + var i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + $262.agent.report("A " + (await Atomics.waitAsync(i32a, undefined, 0).value)); + $262.agent.leaving(); + }); +`); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + var i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + $262.agent.report("B " + (await Atomics.waitAsync(i32a, undefined, 0).value)); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, NUMAGENT).then(async (agentCount) => { + + assert.sameValue(agentCount, NUMAGENT, 'The value of `agentCount` is expected to equal the value of NUMAGENT'); + + assert.sameValue( + Atomics.notify(i32a, WAIT_INDEX, NOTIFYCOUNT), + NOTIFYCOUNT, + 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0, 2) must return the value of NOTIFYCOUNT' + ); + + const reports = [ + await $262.agent.getReportAsync(), + await $262.agent.getReportAsync(), + ]; + + reports.sort(); + assert.sameValue(reports[0], 'A ok', 'The value of reports[0] is "A ok"'); + assert.sameValue(reports[1], 'B ok', 'The value of reports[1] is "B ok"'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/validate-arraytype-before-index-coercion.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/validate-arraytype-before-index-coercion.js new file mode 100644 index 0000000000..97c45cc86d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/validate-arraytype-before-index-coercion.js @@ -0,0 +1,53 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + TypedArray type is validated before `index` argument is coerced. +info: | + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + + ValidateSharedIntegerTypedArray ( typedArray [ , waitable ] ) + + 1. If waitable is not present, set waitable to false. + 2. Perform ? RequireInternalSlot(typedArray, [[TypedArrayName]]). + 3. Let typeName be typedArray.[[TypedArrayName]]. + 4. Let type be the Element Type value in Table 61 for typeName. + 5. If waitable is true, then + a. If typeName is not "Int32Array" or "BigInt64Array", throw a TypeError exception. + 6. Else, + a. If ! IsUnclampedIntegerElementType(type) is false and ! IsBigIntElementType(type) is false, throw a TypeError exception. + 7. Assert: typedArray has a [[ViewedArrayBuffer]] internal slot. + 8. Let buffer be typedArray.[[ViewedArrayBuffer]]. + 9. If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception. + 10. Return buffer. + +features: [Atomics.waitAsync, Atomics, TypedArray, SharedArrayBuffer] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const index = { + valueOf() { + throw new Test262Error(); + } +}; + +const nonSharedArrayTypes = [ + Int8Array, Uint8Array, Int16Array, Uint16Array, Uint32Array, + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (const nonSharedArrayType of nonSharedArrayTypes) { + const typedArray = new nonSharedArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.waitAsync(typedArray, index, 0, 0); + }, '`Atomics.waitAsync(typedArray, index, 0, 0)` throws a TypeError exception'); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/validate-arraytype-before-timeout-coercion.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/validate-arraytype-before-timeout-coercion.js new file mode 100644 index 0000000000..68297a551c --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/validate-arraytype-before-timeout-coercion.js @@ -0,0 +1,53 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + TypedArray type is validated before `timeout` argument is coerced. +info: | + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + + ValidateSharedIntegerTypedArray ( typedArray [ , waitable ] ) + + 1. If waitable is not present, set waitable to false. + 2. Perform ? RequireInternalSlot(typedArray, [[TypedArrayName]]). + 3. Let typeName be typedArray.[[TypedArrayName]]. + 4. Let type be the Element Type value in Table 61 for typeName. + 5. If waitable is true, then + a. If typeName is not "Int32Array" or "BigInt64Array", throw a TypeError exception. + 6. Else, + a. If ! IsUnclampedIntegerElementType(type) is false and ! IsBigIntElementType(type) is false, throw a TypeError exception. + 7. Assert: typedArray has a [[ViewedArrayBuffer]] internal slot. + 8. Let buffer be typedArray.[[ViewedArrayBuffer]]. + 9. If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception. + 10. Return buffer. + +features: [Atomics.waitAsync, Atomics, TypedArray, SharedArrayBuffer] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const timeout = { + valueOf() { + throw new Test262Error(); + } +}; + +const nonSharedArrayTypes = [ + Int8Array, Uint8Array, Int16Array, Uint16Array, Uint32Array, + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (const nonSharedArrayType of nonSharedArrayTypes) { + const typedArray = new nonSharedArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.waitAsync(typedArray, 0, 0, timeout); + }, '`Atomics.waitAsync(typedArray, 0, 0, timeout)` throws a TypeError exception'); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/validate-arraytype-before-value-coercion.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/validate-arraytype-before-value-coercion.js new file mode 100644 index 0000000000..575ff360e3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/validate-arraytype-before-value-coercion.js @@ -0,0 +1,53 @@ +// |reftest| skip -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.notify +description: > + TypedArray type is validated before `value` argument is coerced. +info: | + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray, true). + + ValidateSharedIntegerTypedArray ( typedArray [ , waitable ] ) + + 1. If waitable is not present, set waitable to false. + 2. Perform ? RequireInternalSlot(typedArray, [[TypedArrayName]]). + 3. Let typeName be typedArray.[[TypedArrayName]]. + 4. Let type be the Element Type value in Table 61 for typeName. + 5. If waitable is true, then + a. If typeName is not "Int32Array" or "BigInt64Array", throw a TypeError exception. + 6. Else, + a. If ! IsUnclampedIntegerElementType(type) is false and ! IsBigIntElementType(type) is false, throw a TypeError exception. + 7. Assert: typedArray has a [[ViewedArrayBuffer]] internal slot. + 8. Let buffer be typedArray.[[ViewedArrayBuffer]]. + 9. If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception. + 10. Return buffer. + +features: [Atomics.waitAsync, Atomics, TypedArray, SharedArrayBuffer] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const value = { + valueOf() { + throw new Test262Error(); + } +}; + +const nonSharedArrayTypes = [ + Int8Array, Uint8Array, Int16Array, Uint16Array, Uint32Array, + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (const nonSharedArrayType of nonSharedArrayTypes) { + const typedArray = new nonSharedArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.waitAsync(typedArray, 0, value, 0); + }, '`Atomics.waitAsync(typedArray, 0, value, 0)` throws a TypeError exception'); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/value-not-equal-agent.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/value-not-equal-agent.js new file mode 100644 index 0000000000..852162a856 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/value-not-equal-agent.js @@ -0,0 +1,67 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Returns "not-equal" when value arg does not match an index in the typedArray +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 16. Let w be ! AtomicLoad(typedArray, i). + 17. If v is not equal to w, then + a. Perform LeaveCriticalSection(WL). + b. If mode is sync, then + i. Return the String "not-equal". + c. Perform ! Call(capability.[[Resolve]], undefined, « "not-equal" »). + d. Return promiseCapability.[[Promise]]. + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; +const value = 42; + +$262.agent.start(` + $262.agent.receiveBroadcast(function(sab) { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + $262.agent.report(Atomics.store(i32a, 0, ${value})); + $262.agent.report(Atomics.waitAsync(i32a, 0, 0).value); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + + assert.sameValue( + await $262.agent.getReportAsync(), + '42', + '(await $262.agent.getReportAsync()) resolves to the value "42"' + ); + assert.sameValue( + await $262.agent.getReportAsync(), + 'not-equal', + '(await $262.agent.getReportAsync()) resolves to the value "not-equal"' + ); + assert.sameValue( + Atomics.notify(i32a, 0, 1), + 0, + 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0, 1) must return 0' + ); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/value-not-equal.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/value-not-equal.js new file mode 100644 index 0000000000..324fc4fc90 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/value-not-equal.js @@ -0,0 +1,50 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Returns "not-equal" when value arg does not match an index in the typedArray +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 16. Let w be ! AtomicLoad(typedArray, i). + 17. If v is not equal to w, then + a. Perform LeaveCriticalSection(WL). + b. If mode is sync, then + i. Return the String "not-equal". + c. Perform ! Call(capability.[[Resolve]], undefined, « "not-equal" »). + d. Return promiseCapability.[[Promise]]. + +flags: [async] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, computed-property-names, Symbol, Symbol.toPrimitive, Atomics, arrow-function] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +const valueOf = { + valueOf() { + return undefined; + } +}; + +const toPrimitive = { + [Symbol.toPrimitive]() { + return undefined; + } +}; + +Promise.all([ + Atomics.store(i32a, 0, 42), + Atomics.waitAsync(i32a, 0, 0).value, + ]).then(outcomes => { + assert.sameValue(outcomes[0], 42, 'The value of outcomes[0] is 42'); + assert.sameValue(outcomes[1], 'not-equal', 'The value of outcomes[1] is "not-equal"'); + }).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/waiterlist-block-indexedposition-wake.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/waiterlist-block-indexedposition-wake.js new file mode 100644 index 0000000000..eaef023ecd --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/waiterlist-block-indexedposition-wake.js @@ -0,0 +1,85 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.waitasync +description: > + Get the correct WaiterList +info: | + Atomics.waitAsync( typedArray, index, value, timeout ) + + 1. Return DoWait(async, typedArray, index, value, timeout). + + DoWait ( mode, typedArray, index, value, timeout ) + + 11. Let indexedPosition be (i × 4) + offset. + 12. Let WL be GetWaiterList(block, indexedPosition). + + GetWaiterList( block, i ) + + ... + 4. Return the WaiterList that is referenced by the pair (block, i). + +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const NUMAGENT = 2; +const RUNNING = 4; + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // Wait on index 0 + $262.agent.report(await Atomics.waitAsync(i32a, 0, 0, Infinity).value); + $262.agent.leaving(); + }); +`); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + // Wait on index 2 + $262.agent.report(await Atomics.waitAsync(i32a, 2, 0, Infinity).value); + $262.agent.leaving(); + }); +`); + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 5) +); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, NUMAGENT).then(async (agentCount) => { + + assert.sameValue(agentCount, NUMAGENT, 'The value of `agentCount` is expected to equal the value of NUMAGENT'); + + // Notify index 1, notifies nothing + assert.sameValue(Atomics.notify(i32a, 1), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 5)), 1) must return 0'); + + // Notify index 3, notifies nothing + assert.sameValue(Atomics.notify(i32a, 3), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 5)), 3) must return 0'); + + // Notify index 2, notifies 1 + assert.sameValue(Atomics.notify(i32a, 2), 1, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 5)), 2) must return 1'); + assert.sameValue( + await $262.agent.getReportAsync(), + 'ok', + '(await $262.agent.getReportAsync()) resolves to the value "ok"' + ); + + // Notify index 0, notifies 1 + assert.sameValue(Atomics.notify(i32a, 0), 1, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 5)), 0) must return 1'); + assert.sameValue( + await $262.agent.getReportAsync(), + 'ok', + '(await $262.agent.getReportAsync()) resolves to the value "ok"' + ); + +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/waitAsync/was-woken-before-timeout.js b/js/src/tests/test262/built-ins/Atomics/waitAsync/was-woken-before-timeout.js new file mode 100644 index 0000000000..e45f0ef896 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/waitAsync/was-woken-before-timeout.js @@ -0,0 +1,55 @@ +// |reftest| skip async -- Atomics.waitAsync is not supported +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.waitasync +description: > + Test that Atomics.waitAsync returns the right result when it was awoken before + a timeout +flags: [async] +includes: [atomicsHelper.js] +features: [Atomics.waitAsync, SharedArrayBuffer, TypedArray, Atomics, arrow-function, async-functions] +---*/ +assert.sameValue(typeof Atomics.waitAsync, 'function', 'The value of `typeof Atomics.waitAsync` is "function"'); + +const RUNNING = 1; +const TIMEOUT = $262.agent.timeouts.huge; + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + const i32a = new Int32Array(sab); + Atomics.add(i32a, ${RUNNING}, 1); + + const before = $262.agent.monotonicNow(); + const unpark = await Atomics.waitAsync(i32a, 0, 0, ${TIMEOUT}).value; + const duration = $262.agent.monotonicNow() - before; + + $262.agent.report(duration); + $262.agent.report(unpark); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcastAsync(i32a, RUNNING, 1).then(async (agentCount) => { + + assert.sameValue(agentCount, 1, 'The value of `agentCount` is 1'); + assert.sameValue(Atomics.notify(i32a, 0), 1, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 1'); + + let lapse = await $262.agent.getReportAsync(); + + assert( + lapse < TIMEOUT, + 'The result of evaluating `(lapse < TIMEOUT)` is true' + ); + + assert.sameValue( + await $262.agent.getReportAsync(), + 'ok', + '(await $262.agent.getReportAsync()) resolves to the value "ok"' + ); + assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4)), 0) must return 0'); +}).then($DONE, $DONE); diff --git a/js/src/tests/test262/built-ins/Atomics/xor/bad-range.js b/js/src/tests/test262/built-ins/Atomics/xor/bad-range.js new file mode 100644 index 0000000000..4aae0e925f --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/xor/bad-range.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.xor +description: > + Test range checking of Atomics.xor on arrays that allow atomic operations +includes: [testAtomics.js, testTypedArray.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +var sab = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 2); +var views = intArrayConstructors.slice(); + +testWithTypedArrayConstructors(function(TA) { + let view = new TA(sab); + testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.xor(view, IdxGen(view), 0); + }, '`Atomics.xor(view, IdxGen(view), 0)` throws RangeError'); + }); +}, views); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/xor/bigint/bad-range.js b/js/src/tests/test262/built-ins/Atomics/xor/bigint/bad-range.js new file mode 100644 index 0000000000..e1f576554e --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/xor/bigint/bad-range.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.xor +description: > + Test range checking of Atomics.xor on arrays that allow atomic operations +includes: [testAtomics.js, testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +var buffer = new SharedArrayBuffer(BigInt64Array.BYTES_PER_ELEMENT * 2); + +testWithBigIntTypedArrayConstructors(function(TA) { + let view = new TA(buffer); + testWithAtomicsOutOfBoundsIndices(function(IdxGen) { + assert.throws(RangeError, function() { + Atomics.xor(view, IdxGen(view), 10); + }, '`Atomics.xor(view, IdxGen(view), 10)` throws RangeError'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/xor/bigint/browser.js b/js/src/tests/test262/built-ins/Atomics/xor/bigint/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/xor/bigint/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/xor/bigint/good-views.js b/js/src/tests/test262/built-ins/Atomics/xor/bigint/good-views.js new file mode 100644 index 0000000000..326539197d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/xor/bigint/good-views.js @@ -0,0 +1,105 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.xor +description: Test Atomics.xor on arrays that allow atomic operations +includes: [testAtomics.js, testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ +// Make it interesting - use non-zero byteOffsets and non-zero indexes. +// And again +// In-bounds boundary cases for indexing +// Atomics.store() computes an index from Idx in the same way as other +// Atomics operations, not quite like view[Idx]. +const sab = new SharedArrayBuffer(1024); +const ab = new ArrayBuffer(16); + +testWithBigIntTypedArrayConstructors(function(TA) { + const view = new TA(sab, 32, 20); + const control = new TA(ab, 0, 2); + view[8] = 0x33333333n; + control[0] = 0x33333333n; + + assert.sameValue( + Atomics.xor(view, 8, 0x55555555n), + control[0], + 'Atomics.xor(view, 8, 0x55555555n) returns the value of `control[0]` (0x33333333n)' + ); + + control[0] = 0x66666666n; + + assert.sameValue( + view[8], + control[0], + 'The value of view[8] equals the value of `control[0]` (0x66666666n)' + ); + + assert.sameValue( + Atomics.xor(view, 8, 0xF0F0F0F0n), + control[0], + 'Atomics.xor(view, 8, 0xF0F0F0F0) returns the value of `control[0]` (0x66666666n)' + ); + + control[0] = 0x96969696n; + + assert.sameValue( + view[8], + control[0], + 'The value of view[8] equals the value of `control[0]` (0x96969696n)' + ); + + view[3] = -5n; + control[0] = -5n; + + assert.sameValue( + Atomics.xor(view, 3, 0n), + control[0], + 'Atomics.xor(view, 3, 0n) returns the value of `control[0]` (-5n)' + ); + + assert.sameValue( + view[3], + control[0], + 'The value of view[3] equals the value of `control[0]` (-5n)' + ); + + control[0] = 12345n; + view[3] = 12345n; + + assert.sameValue( + Atomics.xor(view, 3, 0n), + control[0], + 'Atomics.xor(view, 3, 0n) returns the value of `control[0]` (12345n)' + ); + + assert.sameValue( + view[3], + control[0], + 'The value of view[3] equals the value of `control[0]` (12345n)' + ); + + control[0] = 123456789n; + view[3] = 123456789n; + + assert.sameValue( + Atomics.xor(view, 3, 0n), + control[0], + 'Atomics.xor(view, 3, 0n) returns the value of `control[0]` (123456789n)' + ); + + assert.sameValue( + view[3], + control[0], + 'The value of view[3] equals the value of `control[0]` (123456789n)' + ); + + testWithAtomicsInBoundsIndices(function(IdxGen) { + let Idx = IdxGen(view); + view.fill(0n); + Atomics.store(view, Idx, 37n); + assert.sameValue(Atomics.xor(view, Idx, 0n), 37n, 'Atomics.xor(view, Idx, 0n) returns 37n'); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/xor/bigint/non-shared-bufferdata.js b/js/src/tests/test262/built-ins/Atomics/xor/bigint/non-shared-bufferdata.js new file mode 100644 index 0000000000..75843f227d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/xor/bigint/non-shared-bufferdata.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-atomics.xor +description: > + Atomics.xor will operate on TA when TA.buffer is not a SharedArrayBuffer +includes: [testBigIntTypedArray.js] +features: [ArrayBuffer, Atomics, BigInt, TypedArray] +---*/ +testWithBigIntTypedArrayConstructors(TA => { + const buffer = new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4); + const view = new TA(buffer); + assert.sameValue(Atomics.xor(view, 0, 1n), 0n, 'Atomics.xor(view, 0, 1n) returns 0n'); + assert.sameValue(Atomics.load(view, 0), 1n, 'Atomics.load(view, 0) returns 1n'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/xor/bigint/shell.js b/js/src/tests/test262/built-ins/Atomics/xor/bigint/shell.js new file mode 100644 index 0000000000..90ee9c114d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/xor/bigint/shell.js @@ -0,0 +1,42 @@ +// GENERATED, DO NOT EDIT +// file: testBigIntTypedArray.js +// Copyright (C) 2015 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of functions used to assert the correctness of BigInt TypedArray objects. +defines: + - TypedArray + - testWithBigIntTypedArrayConstructors +---*/ + +/** + * The %TypedArray% intrinsic constructor function. + */ +var TypedArray = Object.getPrototypeOf(Int8Array); + +/** + * Calls the provided function for every typed array constructor. + * + * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor. + * @param {Array} selected - An optional Array with filtered typed arrays + */ +function testWithBigIntTypedArrayConstructors(f, selected) { + /** + * Array containing every BigInt typed array constructor. + */ + var constructors = selected || [ + BigInt64Array, + BigUint64Array + ]; + + for (var i = 0; i < constructors.length; ++i) { + var constructor = constructors[i]; + try { + f(constructor); + } catch (e) { + e.message += " (Testing with " + constructor.name + ".)"; + throw e; + } + } +} diff --git a/js/src/tests/test262/built-ins/Atomics/xor/browser.js b/js/src/tests/test262/built-ins/Atomics/xor/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/xor/browser.js diff --git a/js/src/tests/test262/built-ins/Atomics/xor/descriptor.js b/js/src/tests/test262/built-ins/Atomics/xor/descriptor.js new file mode 100644 index 0000000000..7ea7b10e0d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/xor/descriptor.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the license found in the LICENSE file. + +/*--- +esid: sec-atomics.xor +description: Testing descriptor property of Atomics.xor +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics, 'xor', { + enumerable: false, + writable: true, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/xor/expected-return-value.js b/js/src/tests/test262/built-ins/Atomics/xor/expected-return-value.js new file mode 100644 index 0000000000..9ebcd51663 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/xor/expected-return-value.js @@ -0,0 +1,49 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2018 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.xor +description: > + Atomics.xor returns the value that existed at the + index prior to the operation. +info: | + Atomics.xor( typedArray, index, value ) + + 1. Return ? AtomicReadModifyWrite(typedArray, index, value, xor). + + AtomicReadModifyWrite( typedArray, index, value, op ) + + ... + 9. Return GetModifySetValueInBuffer(buffer, indexedPosition, + elementType, v, op). + + + GetModifySetValueInBuffer( arrayBuffer, + byteIndex, type, value, op [ , isLittleEndian ] ) + + ... + 16. Return RawBytesToNumber(type, rawBytesRead, isLittleEndian). + +features: [Atomics, SharedArrayBuffer, TypedArray] +---*/ + + +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); +const a = 0b00000001000000001000000010000001; +const b = 0b00000001111111111000000011111111; +const c = 0b00000000111111110000000001111110; + +i32a[0] = a; + +assert.sameValue( + Atomics.xor(i32a, 0, b), + a, + 'Atomics.xor(i32a, 0, b) returns the value of `a` (0b00000001000000001000000010000001)' +); + +assert.sameValue(i32a[0], c, 'The value of i32a[0] equals the value of `c` (0b00000000111111110000000001111110)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/xor/good-views.js b/js/src/tests/test262/built-ins/Atomics/xor/good-views.js new file mode 100644 index 0000000000..f881f87dee --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/xor/good-views.js @@ -0,0 +1,85 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.xor +description: Test Atomics.xor on arrays that allow atomic operations +includes: [testAtomics.js, testTypedArray.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +var sab = new SharedArrayBuffer(1024); +var ab = new ArrayBuffer(16); +var views = intArrayConstructors.slice(); + +testWithTypedArrayConstructors(function(TA) { + // Make it interesting - use non-zero byteOffsets and non-zero indexes. + + var view = new TA(sab, 32, 20); + var control = new TA(ab, 0, 2); + + view[8] = 0x33333333; + control[0] = 0x33333333; + assert.sameValue(Atomics.xor(view, 8, 0x55555555), control[0], + 'Atomics.xor(view, 8, 0x55555555) returns the value of `control[0]` (0x33333333)'); + + control[0] = 0x66666666; + assert.sameValue( + view[8], + control[0], + 'The value of view[8] equals the value of `control[0]` (0x66666666)' + ); + assert.sameValue(Atomics.xor(view, 8, 0xF0F0F0F0), control[0], + 'Atomics.xor(view, 8, 0xF0F0F0F0) returns the value of `control[0]` (0x66666666)'); + + control[0] = 0x96969696; + assert.sameValue( + view[8], + control[0], + 'The value of view[8] equals the value of `control[0]` (0x96969696)' + ); + + view[3] = -5; + control[0] = -5; + assert.sameValue(Atomics.xor(view, 3, 0), control[0], + 'Atomics.xor(view, 3, 0) returns the value of `control[0]` (-5)'); + assert.sameValue( + view[3], + control[0], + 'The value of view[3] equals the value of `control[0]` (-5)' + ); + + control[0] = 12345; + view[3] = 12345; + assert.sameValue(Atomics.xor(view, 3, 0), control[0], + 'Atomics.xor(view, 3, 0) returns the value of `control[0]` (12345)'); + assert.sameValue( + view[3], + control[0], + 'The value of view[3] equals the value of `control[0]` (12345)' + ); + + // And again + control[0] = 123456789; + view[3] = 123456789; + assert.sameValue(Atomics.xor(view, 3, 0), control[0], + 'Atomics.xor(view, 3, 0) returns the value of `control[0]` (123456789)'); + assert.sameValue( + view[3], + control[0], + 'The value of view[3] equals the value of `control[0]` (123456789)' + ); + + // In-bounds boundary cases for indexing + testWithAtomicsInBoundsIndices(function(IdxGen) { + let Idx = IdxGen(view); + view.fill(0); + // Atomics.store() computes an index from Idx in the same way as other + // Atomics operations, not quite like view[Idx]. + Atomics.store(view, Idx, 37); + assert.sameValue(Atomics.xor(view, Idx, 0), 37, 'Atomics.xor(view, Idx, 0) returns 37'); + }); +}, views); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/xor/length.js b/js/src/tests/test262/built-ins/Atomics/xor/length.js new file mode 100644 index 0000000000..1509b7b6f1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/xor/length.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.xor +description: > + Atomics.xor.length is 3. +info: | + Atomics.xor ( ia, index, val ) + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, has a length + property whose value is an integer. Unless otherwise specified, this + value is equal to the largest number of named arguments shown in the + subclause headings for the function description, including optional + parameters. However, rest parameters shown using the form “...name” + are not included in the default argument count. + + Unless otherwise specified, the length property of a built-in Function + object has the attributes { [[Writable]]: false, [[Enumerable]]: false, + [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.xor, 'length', { + value: 3, + enumerable: false, + writable: false, + configurable: true, +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/xor/name.js b/js/src/tests/test262/built-ins/Atomics/xor/name.js new file mode 100644 index 0000000000..f28f95387d --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/xor/name.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2015 André Bargull. All rights reserved. +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.xor +description: > + Atomics.xor.name is "xor". +includes: [propertyHelper.js] +features: [Atomics] +---*/ + +verifyProperty(Atomics.xor, 'name', { + value: 'xor', + enumerable: false, + writable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/xor/non-shared-bufferdata.js b/js/src/tests/test262/built-ins/Atomics/xor/non-shared-bufferdata.js new file mode 100644 index 0000000000..b8b4ec7bf2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/xor/non-shared-bufferdata.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.and +description: > + Atomics.and will operate on TA when TA.buffer is not a SharedArrayBuffer +includes: [testTypedArray.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ +testWithAtomicsFriendlyTypedArrayConstructors(TA => { + const view = new TA( + new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4) + ); + + assert.sameValue(Atomics.and(view, 0, 1), 0, 'Atomics.and(view, 0, 1) returns 0'); + assert.sameValue(Atomics.load(view, 0), 0, 'Atomics.load(view, 0) returns 0'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/xor/non-shared-int-views-throws.js b/js/src/tests/test262/built-ins/Atomics/xor/non-shared-int-views-throws.js new file mode 100644 index 0000000000..d3f1dedbd8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/xor/non-shared-int-views-throws.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.and +description: > + Atomics.and throws when operating on non-sharable integer TypedArrays +includes: [testTypedArray.js] +features: [ArrayBuffer, Atomics, TypedArray] +---*/ +testWithNonAtomicsFriendlyTypedArrayConstructors(TA => { + const buffer = new ArrayBuffer(TA.BYTES_PER_ELEMENT * 4); + const view = new TA(buffer); + + assert.throws(TypeError, function() { + Atomics.and(view, 0, 1); + }, `Atomics.and(new ${TA.name}(buffer), 0, 1) throws TypeError`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/xor/non-views.js b/js/src/tests/test262/built-ins/Atomics/xor/non-views.js new file mode 100644 index 0000000000..d23ca3ec64 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/xor/non-views.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2017 Mozilla Corporation. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.xor +description: > + Test Atomics.xor on view values other than TypedArrays +includes: [testAtomics.js] +features: [ArrayBuffer, Atomics, DataView, SharedArrayBuffer, Symbol, TypedArray] +---*/ + +testWithAtomicsNonViewValues(function(view) { + assert.throws(TypeError, function() { + Atomics.xor(view, 0, 0); + }, '`Atomics.xor(view, 0, 0)` throws TypeError'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/xor/not-a-constructor.js b/js/src/tests/test262/built-ins/Atomics/xor/not-a-constructor.js new file mode 100644 index 0000000000..37b0b0147a --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/xor/not-a-constructor.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')||!this.hasOwnProperty('SharedArrayBuffer')||(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration()['arm64-simulator'])) -- Atomics,SharedArrayBuffer is not enabled unconditionally, ARM64 Simulator cannot emulate atomics +// Copyright (C) 2020 Rick Waldron. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-ecmascript-standard-built-in-objects +description: > + Atomics.xor does not implement [[Construct]], is not new-able +info: | + ECMAScript Function Objects + + Built-in function objects that are not identified as constructors do not + implement the [[Construct]] internal method unless otherwise specified in + the description of a particular function. + + sec-evaluatenew + + ... + 7. If IsConstructor(constructor) is false, throw a TypeError exception. + ... +includes: [isConstructor.js] +features: [Reflect.construct, Atomics, arrow-function, TypedArray, SharedArrayBuffer] +---*/ + +assert.sameValue(isConstructor(Atomics.xor), false, 'isConstructor(Atomics.xor) must return false'); + +assert.throws(TypeError, () => { + new Atomics.xor(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT))); +}, '`new Atomics.xor(new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT)))` throws TypeError'); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/xor/shell.js b/js/src/tests/test262/built-ins/Atomics/xor/shell.js new file mode 100644 index 0000000000..54371b7789 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/xor/shell.js @@ -0,0 +1,19 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +---*/ + +function isConstructor(f) { + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Atomics/xor/validate-arraytype-before-index-coercion.js b/js/src/tests/test262/built-ins/Atomics/xor/validate-arraytype-before-index-coercion.js new file mode 100644 index 0000000000..b2dcd0b415 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/xor/validate-arraytype-before-index-coercion.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.xor +description: > + TypedArray type is validated before `index` argument is coerced. +info: | + 24.4.13 Atomics.xor ( typedArray, index, value ) + 1. Return ? AtomicReadModifyWrite(typedArray, index, value, xor). + + 24.4.1.11 AtomicReadModifyWrite ( typedArray, index, value, op ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var index = { + valueOf() { + throw new Test262Error("index coerced"); + } +}; + +var badArrayTypes = [ + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.xor(typedArray, index, 0); + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Atomics/xor/validate-arraytype-before-value-coercion.js b/js/src/tests/test262/built-ins/Atomics/xor/validate-arraytype-before-value-coercion.js new file mode 100644 index 0000000000..c569faed82 --- /dev/null +++ b/js/src/tests/test262/built-ins/Atomics/xor/validate-arraytype-before-value-coercion.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Atomics')) -- Atomics is not enabled unconditionally +// Copyright (C) 2019 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-atomics.xor +description: > + TypedArray type is validated before `value` argument is coerced. +info: | + 24.4.13 Atomics.xor ( typedArray, index, value ) + 1. Return ? AtomicReadModifyWrite(typedArray, index, value, xor). + + 24.4.1.11 AtomicReadModifyWrite ( typedArray, index, value, op ) + 1. Let buffer be ? ValidateSharedIntegerTypedArray(typedArray). + ... + + 24.4.1.1 ValidateSharedIntegerTypedArray ( typedArray [ , onlyInt32 ] ) + ... + 4. Let typeName be typedArray.[[TypedArrayName]]. + 5. If onlyInt32 is true, then + a. If typeName is not "Int32Array", throw a TypeError exception. + 6. Else, + a. If typeName is not "Int8Array", "Uint8Array", "Int16Array", "Uint16Array", "Int32Array", + or "Uint32Array", throw a TypeError exception. + ... +features: [Atomics] +---*/ + +var value = { + valueOf() { + throw new Test262Error("value coerced"); + } +}; + +var badArrayTypes = [ + Uint8ClampedArray, Float32Array, Float64Array +]; + +for (var badArrayType of badArrayTypes) { + var typedArray = new badArrayType(new SharedArrayBuffer(8)); + assert.throws(TypeError, function() { + Atomics.xor(typedArray, 0, value); + }); +} + +reportCompare(0, 0); |