From d993d87766f790880a01b3b9d21581925d05d3b0 Mon Sep 17 00:00:00 2001 From: Alexey Shvayka Date: Sun, 6 Sep 2020 05:45:10 +0300 Subject: [PATCH] Test "length" [[Value]] coercion order in ArraySetLength --- ...fine-own-prop-length-coercion-order-set.js | 43 ++++++++++++++ .../define-own-prop-length-coercion-order.js | 58 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 test/built-ins/Array/length/define-own-prop-length-coercion-order-set.js create mode 100644 test/built-ins/Array/length/define-own-prop-length-coercion-order.js diff --git a/test/built-ins/Array/length/define-own-prop-length-coercion-order-set.js b/test/built-ins/Array/length/define-own-prop-length-coercion-order-set.js new file mode 100644 index 0000000000..0133117cec --- /dev/null +++ b/test/built-ins/Array/length/define-own-prop-length-coercion-order-set.js @@ -0,0 +1,43 @@ +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: André Bargull +esid: sec-arraysetlength +description: > + [[Value]] is coerced to number before current descriptor's [[Writable]] check. +info: | + ArraySetLength ( A, Desc ) + + [...] + 3. Let newLen be ? ToUint32(Desc.[[Value]]). + 4. Let numberLen be ? ToNumber(Desc.[[Value]]). + [...] + 7. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length"). + [...] + 12. If oldLenDesc.[[Writable]] is false, return false. +features: [Symbol, Symbol.toPrimitive, Reflect, Reflect.set] +includes: [compareArray.js] +---*/ + +var array = [1, 2, 3]; +var hints = []; +var length = {}; +length[Symbol.toPrimitive] = function(hint) { + hints.push(hint); + Object.defineProperty(array, "length", {writable: false}); + return 0; +}; + +assert.throws(TypeError, function() { + "use strict"; + array.length = length; +}); +assert.compareArray(hints, ["number", "number"]); + + +array = [1, 2, 3]; +hints = []; + +assert(!Reflect.set(array, "length", length)); +assert.compareArray(hints, ["number", "number"]); diff --git a/test/built-ins/Array/length/define-own-prop-length-coercion-order.js b/test/built-ins/Array/length/define-own-prop-length-coercion-order.js new file mode 100644 index 0000000000..dccb456a26 --- /dev/null +++ b/test/built-ins/Array/length/define-own-prop-length-coercion-order.js @@ -0,0 +1,58 @@ +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +author: André Bargull +esid: sec-arraysetlength +description: > + [[Value]] is coerced to number before descriptor validation. +info: | + ArraySetLength ( A, Desc ) + + [...] + 3. Let newLen be ? ToUint32(Desc.[[Value]]). + 4. Let numberLen be ? ToNumber(Desc.[[Value]]). + [...] + 7. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length"). + [...] + 11. If newLen ≥ oldLen, then + a. Return OrdinaryDefineOwnProperty(A, "length", newLenDesc). + + OrdinaryDefineOwnProperty ( O, P, Desc ) + + [...] + 3. Return ValidateAndApplyPropertyDescriptor(O, P, extensible, Desc, current). + + ValidateAndApplyPropertyDescriptor ( O, P, extensible, Desc, current ) + + [...] + 7. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both true, then + a. If current.[[Configurable]] is false and current.[[Writable]] is false, then + i. If Desc.[[Writable]] is present and Desc.[[Writable]] is true, return false. +features: [Reflect] +---*/ + +var array = [1, 2]; +var valueOfCalls = 0; +var length = { + valueOf: function() { + valueOfCalls += 1; + if (valueOfCalls !== 1) { + // skip first coercion at step 3 + Object.defineProperty(array, "length", {writable: false}); + } + return array.length; + }, +}; + +assert.throws(TypeError, function() { + Object.defineProperty(array, "length", {value: length, writable: true}); +}); +assert.sameValue(valueOfCalls, 2); + + +array = [1, 2]; +valueOfCalls = 0; + +assert(!Reflect.defineProperty(array, "length", {value: length, writable: true})); +assert.sameValue(valueOfCalls, 2);