From d7e4de148442b063dbb8503726661926a8b7d11b Mon Sep 17 00:00:00 2001 From: Rick Waldron Date: Wed, 15 Apr 2020 16:55:47 -0400 Subject: [PATCH] Atomics.waitAsync: validate array type; waiter list position, notify before timeout --- .../Atomics/waitAsync/false-for-timeout.js | 4 +- .../Atomics/waitAsync/negative-timeout.js | 4 +- .../Atomics/waitAsync/null-for-timeout.js | 4 +- .../Atomics/waitAsync/object-for-timeout.js | 4 +- ...oisoned-object-for-timeout-throws-agent.js | 4 +- .../Atomics/waitAsync/true-for-timeout.js | 4 +- .../waitAsync/undefined-for-timeout-agent.js | 18 ++-- .../waitAsync/undefined-for-timeout.js | 62 ++++++++++++++ .../undefined-index-defaults-to-zero-agent.js | 76 +++++++++++++++++ ...alidate-arraytype-before-index-coercion.js | 49 +++++++++++ ...idate-arraytype-before-timeout-coercion.js | 48 +++++++++++ ...alidate-arraytype-before-value-coercion.js | 49 +++++++++++ .../waitAsync/value-not-equal-agent.js | 64 +++++++++++++++ .../Atomics/waitAsync/value-not-equal.js | 49 +++++++++++ .../waiterlist-block-indexedposition-wake.js | 82 +++++++++++++++++++ .../waitAsync/was-woken-before-timeout.js | 54 ++++++++++++ 16 files changed, 554 insertions(+), 21 deletions(-) create mode 100644 test/built-ins/Atomics/waitAsync/undefined-for-timeout.js create mode 100644 test/built-ins/Atomics/waitAsync/undefined-index-defaults-to-zero-agent.js create mode 100644 test/built-ins/Atomics/waitAsync/validate-arraytype-before-index-coercion.js create mode 100644 test/built-ins/Atomics/waitAsync/validate-arraytype-before-timeout-coercion.js create mode 100644 test/built-ins/Atomics/waitAsync/validate-arraytype-before-value-coercion.js create mode 100644 test/built-ins/Atomics/waitAsync/value-not-equal-agent.js create mode 100644 test/built-ins/Atomics/waitAsync/value-not-equal.js create mode 100644 test/built-ins/Atomics/waitAsync/waiterlist-block-indexedposition-wake.js create mode 100644 test/built-ins/Atomics/waitAsync/was-woken-before-timeout.js diff --git a/test/built-ins/Atomics/waitAsync/false-for-timeout.js b/test/built-ins/Atomics/waitAsync/false-for-timeout.js index c745b32b73..444a4c8cab 100644 --- a/test/built-ins/Atomics/waitAsync/false-for-timeout.js +++ b/test/built-ins/Atomics/waitAsync/false-for-timeout.js @@ -58,6 +58,6 @@ Promise.all([ Atomics.waitAsync(i32a, 0, 0, toPrimitive).value, ]).then(outcomes => { assert.sameValue(outcomes[0], 'timed-out'); - assert.sameValue(outcomes[0], 'timed-out'); - assert.sameValue(outcomes[0], 'timed-out'); + assert.sameValue(outcomes[1], 'timed-out'); + assert.sameValue(outcomes[2], 'timed-out'); }, $DONE).then($DONE, $DONE); diff --git a/test/built-ins/Atomics/waitAsync/negative-timeout.js b/test/built-ins/Atomics/waitAsync/negative-timeout.js index 9f365e9e46..c75ca5a4c8 100644 --- a/test/built-ins/Atomics/waitAsync/negative-timeout.js +++ b/test/built-ins/Atomics/waitAsync/negative-timeout.js @@ -23,9 +23,9 @@ const i32a = new Int32Array( Promise.all([ Atomics.waitAsync(i32a, 0, 0, -1).value, - ]).then(outcomes => { + ]).then(([outcome]) => { assert.sameValue( - outcomes[0], + outcome, 'timed-out', 'Atomics.waitAsync(i32a, 0, 0, -1).value resolves to "timed-out"' ); diff --git a/test/built-ins/Atomics/waitAsync/null-for-timeout.js b/test/built-ins/Atomics/waitAsync/null-for-timeout.js index 34b8f06bc4..08be72e69b 100644 --- a/test/built-ins/Atomics/waitAsync/null-for-timeout.js +++ b/test/built-ins/Atomics/waitAsync/null-for-timeout.js @@ -58,6 +58,6 @@ Promise.all([ Atomics.waitAsync(i32a, 0, 0, toPrimitive).value, ]).then(outcomes => { assert.sameValue(outcomes[0], "timed-out"); - assert.sameValue(outcomes[0], "timed-out"); - assert.sameValue(outcomes[0], "timed-out"); + assert.sameValue(outcomes[1], "timed-out"); + assert.sameValue(outcomes[2], "timed-out"); }, $DONE).then($DONE, $DONE); diff --git a/test/built-ins/Atomics/waitAsync/object-for-timeout.js b/test/built-ins/Atomics/waitAsync/object-for-timeout.js index d4b0f561e5..0213c860b3 100644 --- a/test/built-ins/Atomics/waitAsync/object-for-timeout.js +++ b/test/built-ins/Atomics/waitAsync/object-for-timeout.js @@ -66,6 +66,6 @@ Promise.all([ Atomics.waitAsync(i32a, 0, 0, toPrimitive).value, ]).then(outcomes => { assert.sameValue(outcomes[0], "timed-out"); - assert.sameValue(outcomes[0], "timed-out"); - assert.sameValue(outcomes[0], "timed-out"); + assert.sameValue(outcomes[1], "timed-out"); + assert.sameValue(outcomes[2], "timed-out"); }, $DONE).then($DONE, $DONE); diff --git a/test/built-ins/Atomics/waitAsync/poisoned-object-for-timeout-throws-agent.js b/test/built-ins/Atomics/waitAsync/poisoned-object-for-timeout-throws-agent.js index a86d30e8d1..9cf832c525 100644 --- a/test/built-ins/Atomics/waitAsync/poisoned-object-for-timeout-throws-agent.js +++ b/test/built-ins/Atomics/waitAsync/poisoned-object-for-timeout-throws-agent.js @@ -41,8 +41,8 @@ $262.agent.start(` const i32a = new Int32Array(sab); Atomics.add(i32a, ${RUNNING}, 1); - let status1 = '; - let status2 = '; + let status1 = ''; + let status2 = ''; try { Atomics.wait(i32a, 0, 0, poisonedValueOf); diff --git a/test/built-ins/Atomics/waitAsync/true-for-timeout.js b/test/built-ins/Atomics/waitAsync/true-for-timeout.js index 542fa01227..5ce12cb11d 100644 --- a/test/built-ins/Atomics/waitAsync/true-for-timeout.js +++ b/test/built-ins/Atomics/waitAsync/true-for-timeout.js @@ -42,6 +42,6 @@ Promise.all([ Atomics.waitAsync(i32a, 0, 0, toPrimitive).value, ]).then(outcomes => { assert.sameValue(outcomes[0], 'timed-out'); - assert.sameValue(outcomes[0], 'timed-out'); - assert.sameValue(outcomes[0], 'timed-out'); + assert.sameValue(outcomes[1], 'timed-out'); + assert.sameValue(outcomes[2], 'timed-out'); }, $DONE).then($DONE, $DONE); diff --git a/test/built-ins/Atomics/waitAsync/undefined-for-timeout-agent.js b/test/built-ins/Atomics/waitAsync/undefined-for-timeout-agent.js index a70c1b2d04..d596e3fab8 100644 --- a/test/built-ins/Atomics/waitAsync/undefined-for-timeout-agent.js +++ b/test/built-ins/Atomics/waitAsync/undefined-for-timeout-agent.js @@ -4,7 +4,7 @@ /*--- esid: sec-atomics.waitasync description: > - Undefined timeout arg should result in an infinite timeout + Undefined timeout arg is coerced to zero info: | Atomics.waitAsync( typedArray, index, value, timeout ) @@ -64,12 +64,12 @@ $262.agent.safeBroadcastAsync(i32a, RUNNING, NUMAGENT).then(async (agentCount) = 'Atomics.notify(i32a, WAIT_INDEX, NOTIFYCOUNT) returns the value of `NOTIFYCOUNT` (2)' ); - Promise.all([ - $262.agent.getReportAsync(), - $262.agent.getReportAsync(), - ]).then(reports => { - 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); + 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/test/built-ins/Atomics/waitAsync/undefined-for-timeout.js b/test/built-ins/Atomics/waitAsync/undefined-for-timeout.js new file mode 100644 index 0000000000..fa761d85ed --- /dev/null +++ b/test/built-ins/Atomics/waitAsync/undefined-for-timeout.js @@ -0,0 +1,62 @@ +// 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] +---*/ +const i32a = new Int32Array( + new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 4) +); + +$262.agent.start(` + $262.agent.receiveBroadcast(async (sab) => { + var i32a = new Int32Array(sab); + $262.agent.sleep(1000); + Atomics.notify(i32a, 0, 4); + $262.agent.leaving(); + }); +`); + +$262.agent.safeBroadcast(i32a); + +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'); + assert.sameValue(outcomes[1], 'ok'); + assert.sameValue(outcomes[2], 'ok'); + assert.sameValue(outcomes[3], 'ok'); + }, $DONE).then($DONE, $DONE); diff --git a/test/built-ins/Atomics/waitAsync/undefined-index-defaults-to-zero-agent.js b/test/built-ins/Atomics/waitAsync/undefined-index-defaults-to-zero-agent.js new file mode 100644 index 0000000000..ec6c64e865 --- /dev/null +++ b/test/built-ins/Atomics/waitAsync/undefined-index-defaults-to-zero-agent.js @@ -0,0 +1,76 @@ +// 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] +---*/ +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); + + assert.sameValue( + Atomics.notify(i32a, WAIT_INDEX, NOTIFYCOUNT), + NOTIFYCOUNT, + 'Atomics.notify(i32a, WAIT_INDEX, NOTIFYCOUNT) returns the value of `NOTIFYCOUNT` (2)' + ); + + 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/test/built-ins/Atomics/waitAsync/validate-arraytype-before-index-coercion.js b/test/built-ins/Atomics/waitAsync/validate-arraytype-before-index-coercion.js new file mode 100644 index 0000000000..ee4f099010 --- /dev/null +++ b/test/built-ins/Atomics/waitAsync/validate-arraytype-before-index-coercion.js @@ -0,0 +1,49 @@ +// 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] +---*/ + +const index = { + valueOf() { + throw new Test262Error("index coerced"); + } +}; + +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); + }); +} diff --git a/test/built-ins/Atomics/waitAsync/validate-arraytype-before-timeout-coercion.js b/test/built-ins/Atomics/waitAsync/validate-arraytype-before-timeout-coercion.js new file mode 100644 index 0000000000..8a40b09372 --- /dev/null +++ b/test/built-ins/Atomics/waitAsync/validate-arraytype-before-timeout-coercion.js @@ -0,0 +1,48 @@ +// 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] +---*/ +const timeout = { + valueOf() { + throw new Test262Error("timeout coerced"); + } +}; + +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); + }); +} diff --git a/test/built-ins/Atomics/waitAsync/validate-arraytype-before-value-coercion.js b/test/built-ins/Atomics/waitAsync/validate-arraytype-before-value-coercion.js new file mode 100644 index 0000000000..4241075018 --- /dev/null +++ b/test/built-ins/Atomics/waitAsync/validate-arraytype-before-value-coercion.js @@ -0,0 +1,49 @@ +// 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] +---*/ + +const value = { + valueOf() { + throw new Test262Error("value coerced"); + } +}; + +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.wait(typedArray, 0, value, 0); + }); +} diff --git a/test/built-ins/Atomics/waitAsync/value-not-equal-agent.js b/test/built-ins/Atomics/waitAsync/value-not-equal-agent.js new file mode 100644 index 0000000000..09e0e10db0 --- /dev/null +++ b/test/built-ins/Atomics/waitAsync/value-not-equal-agent.js @@ -0,0 +1,64 @@ +// 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] +---*/ +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); + + assert.sameValue( + await $262.agent.getReportAsync(), + value.toString(), + 'Atomics.store(i32a, 0, ${value}) returns 42' + ); + assert.sameValue( + await $262.agent.getReportAsync(), + 'not-equal', + 'Atomics.waitAsync(i32a, 0, 0).value resolves to "not-equal"' + ); + assert.sameValue( + Atomics.notify(i32a, 0, 1), + 0, + 'Atomics.notify(i32a, 0, 1) returns 0 (nothing to notify)' + ); +}).then($DONE, $DONE); diff --git a/test/built-ins/Atomics/waitAsync/value-not-equal.js b/test/built-ins/Atomics/waitAsync/value-not-equal.js new file mode 100644 index 0000000000..b5c0c9ae79 --- /dev/null +++ b/test/built-ins/Atomics/waitAsync/value-not-equal.js @@ -0,0 +1,49 @@ +// 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] +---*/ +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); + assert.sameValue(outcomes[1], 'not-equal'); + }, $DONE).then($DONE, $DONE); diff --git a/test/built-ins/Atomics/waitAsync/waiterlist-block-indexedposition-wake.js b/test/built-ins/Atomics/waitAsync/waiterlist-block-indexedposition-wake.js new file mode 100644 index 0000000000..f183bff6e8 --- /dev/null +++ b/test/built-ins/Atomics/waitAsync/waiterlist-block-indexedposition-wake.js @@ -0,0 +1,82 @@ +// 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] +---*/ +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); + + // 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 + assert.sameValue(Atomics.notify(i32a, 2), 1, 'Atomics.notify(i32a, 2) returns 1'); + assert.sameValue( + await $262.agent.getReportAsync(), + 'ok', + 'await Atomics.waitAsync(i32a, 0, 0, Infinity).value resolves to "ok"' + ); + + // Notify index 0, notifies 1 + assert.sameValue(Atomics.notify(i32a, 0), 1, 'Atomics.notify(i32a, 0) returns 1'); + assert.sameValue( + await $262.agent.getReportAsync(), + 'ok', + 'await Atomics.waitAsync(i32a, 2, 0, Infinity).value resolves to "ok"' + ); + +}).then($DONE, $DONE); diff --git a/test/built-ins/Atomics/waitAsync/was-woken-before-timeout.js b/test/built-ins/Atomics/waitAsync/was-woken-before-timeout.js new file mode 100644 index 0000000000..b1087b04fe --- /dev/null +++ b/test/built-ins/Atomics/waitAsync/was-woken-before-timeout.js @@ -0,0 +1,54 @@ +// 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] +---*/ +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); + assert.sameValue(Atomics.notify(i32a, 0), 1, 'Atomics.notify(i32a, 0) returns 1'); + + const lapse = await $262.agent.getReportAsync(); + + assert( + lapse < TIMEOUT, + 'The result of `(lapse >= TIMEOUT)` is true' + ); + + const result = await $262.agent.getReportAsync(); + + assert.sameValue( + result, + 'ok', + 'await Atomics.waitAsync(i32a, 0, 0, ${TIMEOUT}).value resolves to "ok"' + ); + assert.sameValue(Atomics.notify(i32a, 0), 0, 'Atomics.notify(i32a, 0) returns 0'); +}).then($DONE, $DONE);