From 42400297454909ddccc899a012dc55bbd403eb8b Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Tue, 21 Mar 2023 13:23:14 -0700 Subject: [PATCH] [Fix] validate arguments first See https://github.com/tc39/proposal-iterator-helpers/pull/265 --- Iterator.prototype.drop/implementation.js | 8 ++- Iterator.prototype.every/implementation.js | 28 ++++++---- Iterator.prototype.filter/implementation.js | 34 +++++++----- Iterator.prototype.find/implementation.js | 29 +++++++---- Iterator.prototype.flatMap/implementation.js | 54 +++++++++++--------- Iterator.prototype.forEach/implementation.js | 26 ++++++---- Iterator.prototype.map/implementation.js | 34 +++++++----- Iterator.prototype.reduce/implementation.js | 38 ++++++++------ Iterator.prototype.some/implementation.js | 28 ++++++---- Iterator.prototype.take/implementation.js | 40 +++++++++------ Iterator.prototype.toArray/implementation.js | 28 ++++++---- aos/GetIteratorDirect.js | 2 +- test/Iterator.prototype.drop.js | 4 +- test/Iterator.prototype.take.js | 4 +- 14 files changed, 214 insertions(+), 143 deletions(-) diff --git a/Iterator.prototype.drop/implementation.js b/Iterator.prototype.drop/implementation.js index 980d14d..049856f 100644 --- a/Iterator.prototype.drop/implementation.js +++ b/Iterator.prototype.drop/implementation.js @@ -14,6 +14,7 @@ var IteratorValue = require('es-abstract/2022/IteratorValue'); var ThrowCompletion = require('es-abstract/2022/ThrowCompletion'); var ToIntegerOrInfinity = require('es-abstract/2022/ToIntegerOrInfinity'); var ToNumber = require('es-abstract/2022/ToNumber'); +var Type = require('es-abstract/2022/Type'); var iterHelperProto = require('../IteratorHelperPrototype'); @@ -22,13 +23,18 @@ var isNaN = require('es-abstract/helpers/isNaN'); var SLOT = require('internal-slot'); module.exports = function drop(limit) { - var iterated = GetIteratorDirect(this); // step 1 + var O = this; // step 1 + if (Type(O) !== 'Object') { + throw new $TypeError('`this` value must be an Object'); // step 2 + } var numLimit = ToNumber(limit); // step 2 if (isNaN(numLimit)) { throw new $RangeError('`limit` must be a non-NaN number'); // step 3 } + var iterated = GetIteratorDirect(O); // step 4 + var integerLimit = ToIntegerOrInfinity(numLimit); // step 4 if (integerLimit < 0) { throw new $RangeError('`limit` must be a >= 0'); // step 5 diff --git a/Iterator.prototype.every/implementation.js b/Iterator.prototype.every/implementation.js index 7ae928a..c74d6e5 100644 --- a/Iterator.prototype.every/implementation.js +++ b/Iterator.prototype.every/implementation.js @@ -13,40 +13,46 @@ var IteratorValue = require('es-abstract/2022/IteratorValue'); var NormalCompletion = require('es-abstract/2022/NormalCompletion'); var ThrowCompletion = require('es-abstract/2022/ThrowCompletion'); var ToBoolean = require('es-abstract/2022/ToBoolean'); +var Type = require('es-abstract/2022/Type'); module.exports = function every(predicate) { - var iterated = GetIteratorDirect(this); // step 1 + var O = this; // step 1 + if (Type(O) !== 'Object') { + throw new $TypeError('`this` value must be an Object'); // step 2 + } if (!IsCallable(predicate)) { - throw new $TypeError('`predicate` must be a function'); // step 2 + throw new $TypeError('`predicate` must be a function'); // step 3 } - var counter = 0; // step 3 + var iterated = GetIteratorDirect(O); // step 4 + + var counter = 0; // step 5 // eslint-disable-next-line no-constant-condition - while (true) { // step 4 - var next = IteratorStep(iterated); // step 4.a + while (true) { // step 6 + var next = IteratorStep(iterated); // step 6.a if (!next) { - return true; // step 4.b + return true; // step 6.b } - var value = IteratorValue(next); // step 4.c + var value = IteratorValue(next); // step 6.c var result; try { - result = Call(predicate, void undefined, [value, counter]); // step 4.d + result = Call(predicate, void undefined, [value, counter]); // step 6.d } catch (e) { - // close iterator // step 4.e + // close iterator // step 6.e IteratorClose( iterated, ThrowCompletion(e) ); } finally { - counter += 1; // step 4.g + counter += 1; // step 6.g } if (!ToBoolean(result)) { return IteratorClose( iterated, NormalCompletion(false) - ); // step 4.f + ); // step 6.f } } }; diff --git a/Iterator.prototype.filter/implementation.js b/Iterator.prototype.filter/implementation.js index 5f814b0..2c7714e 100644 --- a/Iterator.prototype.filter/implementation.js +++ b/Iterator.prototype.filter/implementation.js @@ -14,18 +14,24 @@ var IteratorStep = require('../aos/IteratorStep'); var IteratorValue = require('es-abstract/2022/IteratorValue'); var ThrowCompletion = require('es-abstract/2022/ThrowCompletion'); var ToBoolean = require('es-abstract/2022/ToBoolean'); +var Type = require('es-abstract/2022/Type'); var iterHelperProto = require('../IteratorHelperPrototype'); var SLOT = require('internal-slot'); module.exports = function filter(predicate) { - var iterated = GetIteratorDirect(this); // step 1 + var O = this; // step 1 + if (Type(O) !== 'Object') { + throw new $TypeError('`this` value must be an Object'); // step 2 + } if (!IsCallable(predicate)) { - throw new $TypeError('`predicate` must be a function'); // step 2 + throw new $TypeError('`predicate` must be a function'); // step 3 } + var iterated = GetIteratorDirect(O); // step 4 + var closeIfAbrupt = function (abruptCompletion) { if (!(abruptCompletion instanceof CompletionRecord)) { throw new $TypeError('`abruptCompletion` must be a Completion Record'); @@ -37,38 +43,38 @@ module.exports = function filter(predicate) { }; var sentinel = {}; - var counter = 0; // step 3.a + var counter = 0; // step 6.a var closure = function () { // eslint-disable-next-line no-constant-condition - while (true) { // step 3.b - var next = IteratorStep(iterated); // step 3.b.i + while (true) { // step 6.b + var next = IteratorStep(iterated); // step 6.b.i if (!next) { - // return void undefined; // step 3.b.ii + // return void undefined; // step 6.b.ii return sentinel; } - var value = IteratorValue(next); // step 3.b.iii + var value = IteratorValue(next); // step 6.b.iii var selected; try { - selected = Call(predicate, void undefined, [value, counter]); // step 3.b.iv - // yield mapped // step 3.b.vi + selected = Call(predicate, void undefined, [value, counter]); // step 6.b.iv + // yield mapped // step 6.b.vi if (ToBoolean(selected)) { return value; } } catch (e) { - // close iterator // step 3.b.v, 3.b.vii + // close iterator // step 6.b.v, 6.b.vii closeIfAbrupt(ThrowCompletion(e)); throw e; } finally { - counter += 1; // step 3.b.viii + counter += 1; // step 6.b.viii } } }; SLOT.set(closure, '[[Sentinel]]', sentinel); // for the userland implementation SLOT.set(closure, '[[CloseIfAbrupt]]', closeIfAbrupt); // for the userland implementation - var result = CreateIteratorFromClosure(closure, 'Iterator Helper', iterHelperProto, ['[[UnderlyingIterator]]']); // step 4 + var result = CreateIteratorFromClosure(closure, 'Iterator Helper', iterHelperProto, ['[[UnderlyingIterator]]']); // step 7 - SLOT.set(result, '[[UnderlyingIterator]]', iterated); // step 5 + SLOT.set(result, '[[UnderlyingIterator]]', iterated); // step 8 - return result; // step 6 + return result; // step 9 }; diff --git a/Iterator.prototype.find/implementation.js b/Iterator.prototype.find/implementation.js index 1788eb3..60e065e 100644 --- a/Iterator.prototype.find/implementation.js +++ b/Iterator.prototype.find/implementation.js @@ -13,40 +13,47 @@ var IteratorValue = require('es-abstract/2022/IteratorValue'); var NormalCompletion = require('es-abstract/2022/NormalCompletion'); var ThrowCompletion = require('es-abstract/2022/ThrowCompletion'); var ToBoolean = require('es-abstract/2022/ToBoolean'); +var Type = require('es-abstract/2022/Type'); module.exports = function find(predicate) { - var iterated = GetIteratorDirect(this); // step 1 + var O = this; // step 1 + + if (Type(O) !== 'Object') { + throw new $TypeError('`this` value must be an Object'); // step 2 + } if (!IsCallable(predicate)) { - throw new $TypeError('`predicate` must be a function'); // step 2 + throw new $TypeError('`predicate` must be a function'); // step 3 } - var counter = 0; // step 3 + var iterated = GetIteratorDirect(O); // step 4 + + var counter = 0; // step 5 // eslint-disable-next-line no-constant-condition - while (true) { // step 4 - var next = IteratorStep(iterated); // step 4.a + while (true) { // step 6 + var next = IteratorStep(iterated); // step 6.a if (!next) { - return void undefined; // step 4.b + return void undefined; // step 6.b } - var value = IteratorValue(next); // step 4.c + var value = IteratorValue(next); // step 6.c var result; try { - result = Call(predicate, void undefined, [value, counter]); // step 4.d + result = Call(predicate, void undefined, [value, counter]); // step 6.d } catch (e) { - // close iterator // step 4.e + // close iterator // step 6.e IteratorClose( iterated, ThrowCompletion(e) ); } finally { - counter += 1; // step 4.g + counter += 1; // step 6.g } if (ToBoolean(result)) { return IteratorClose( iterated, NormalCompletion(value) - ); // step 4.f + ); // step 6.f } } }; diff --git a/Iterator.prototype.flatMap/implementation.js b/Iterator.prototype.flatMap/implementation.js index 99556de..efee790 100644 --- a/Iterator.prototype.flatMap/implementation.js +++ b/Iterator.prototype.flatMap/implementation.js @@ -14,18 +14,24 @@ var IteratorClose = require('../aos/IteratorClose'); var IteratorStep = require('../aos/IteratorStep'); var IteratorValue = require('es-abstract/2022/IteratorValue'); var ThrowCompletion = require('es-abstract/2022/ThrowCompletion'); +var Type = require('es-abstract/2022/Type'); var iterHelperProto = require('../IteratorHelperPrototype'); var SLOT = require('internal-slot'); module.exports = function flatMap(mapper) { - var iterated = GetIteratorDirect(this); // step 1 + var O = this; // step 1 + if (Type(O) !== 'Object') { + throw new $TypeError('`this` value must be an Object'); // step 2 + } if (!IsCallable(mapper)) { - throw new $TypeError('`mapper` must be a function'); // step 2 + throw new $TypeError('`mapper` must be a function'); // step 3 } + var iterated = GetIteratorDirect(O); // step 4 + var closeIfAbrupt = function (abruptCompletion) { if (!(abruptCompletion instanceof CompletionRecord)) { throw new $TypeError('`abruptCompletion` must be a Completion Record'); @@ -37,46 +43,46 @@ module.exports = function flatMap(mapper) { }; var sentinel = {}; - var counter = 0; // step 3.a + var counter = 0; // step 6.a var closure = function () { - // while (true) { // step 3.b - var next = IteratorStep(iterated); // step 3.b.i + // while (true) { // step 6.b + var next = IteratorStep(iterated); // step 6.b.i if (!next) { - // return void undefined; // step 3.b.ii + // return void undefined; // step 6.b.ii return sentinel; } - var value = IteratorValue(next); // step 3.b.iii + var value = IteratorValue(next); // step 6.b.iii var mapped; var innerIterator; try { try { - mapped = Call(mapper, void undefined, [value, counter]); // step 3.b.iv - // yield mapped // step 3.b.vi - innerIterator = GetIteratorFlattenable(mapped, 'sync'); // step 3.b.vi + mapped = Call(mapper, void undefined, [value, counter]); // step 6.b.iv + // yield mapped // step 6.b.vi + innerIterator = GetIteratorFlattenable(mapped, 'sync'); // step 6.b.vi } catch (e) { - closeIfAbrupt(ThrowCompletion(e)); // steps 3.b.v, 3.b.vii + closeIfAbrupt(ThrowCompletion(e)); // steps 6.b.v, 6.b.vii } - var innerAlive = true; // step 3.b.viii - while (innerAlive) { // step 3.b.ix + var innerAlive = true; // step 6.b.viii + while (innerAlive) { // step 6.b.ix try { - var innerNext = IteratorStep(innerIterator); // step 3.b.ix.1 + var innerNext = IteratorStep(innerIterator); // step 6.b.ix.1 } catch (e) { - closeIfAbrupt(ThrowCompletion(e)); // step 3.b.ix.2 + closeIfAbrupt(ThrowCompletion(e)); // step 6.b.ix.2 } if (!innerNext) { - innerAlive = false; // step 3.b.ix.3.a - } else { // step 3.b.ix.4 + innerAlive = false; // step 6.b.ix.3.a + } else { // step 6.b.ix.4 var innerValue; try { - innerValue = IteratorValue(innerNext); // step 3.b.ix.4.a + innerValue = IteratorValue(innerNext); // step 6.b.ix.4.a } catch (e) { - closeIfAbrupt(ThrowCompletion(e)); // step 3.b.ix.4.b + closeIfAbrupt(ThrowCompletion(e)); // step 6.b.ix.4.b } - return innerValue; // step 3.b.ix.4.c + return innerValue; // step 6.b.ix.4.c } } } finally { - counter += 1; // step 3.b.x + counter += 1; // step 6.b.x } // } return void undefined; @@ -84,9 +90,9 @@ module.exports = function flatMap(mapper) { SLOT.set(closure, '[[Sentinel]]', sentinel); // for the userland implementation SLOT.set(closure, '[[CloseIfAbrupt]]', closeIfAbrupt); // for the userland implementation - var result = CreateIteratorFromClosure(closure, 'Iterator Helper', iterHelperProto, ['[[UnderlyingIterator]]']); // step 4 + var result = CreateIteratorFromClosure(closure, 'Iterator Helper', iterHelperProto, ['[[UnderlyingIterator]]']); // step 7 - SLOT.set(result, '[[UnderlyingIterator]]', iterated); // step 5 + SLOT.set(result, '[[UnderlyingIterator]]', iterated); // step 8 - return result; // step 6 + return result; // step 9 }; diff --git a/Iterator.prototype.forEach/implementation.js b/Iterator.prototype.forEach/implementation.js index 147fceb..9414f79 100644 --- a/Iterator.prototype.forEach/implementation.js +++ b/Iterator.prototype.forEach/implementation.js @@ -11,33 +11,39 @@ var IteratorClose = require('../aos/IteratorClose'); var IteratorStep = require('../aos/IteratorStep'); var IteratorValue = require('es-abstract/2022/IteratorValue'); var ThrowCompletion = require('es-abstract/2022/ThrowCompletion'); +var Type = require('es-abstract/2022/Type'); module.exports = function forEach(fn) { - var iterated = GetIteratorDirect(this); // step 1 + var O = this; // step 1 + if (Type(O) !== 'Object') { + throw new $TypeError('`this` value must be an Object'); // step 2 + } if (!IsCallable(fn)) { - throw new $TypeError('`fn` must be a function'); // step 2 + throw new $TypeError('`fn` must be a function'); // step 3 } - var counter = 0; // step 3 + var iterated = GetIteratorDirect(O); // step 4 + + var counter = 0; // step 5 // eslint-disable-next-line no-constant-condition - while (true) { // step 4 - var next = IteratorStep(iterated); // step 4.a + while (true) { // step 6 + var next = IteratorStep(iterated); // step 6.a if (!next) { - return void undefined; // step 4.b + return void undefined; // step 6.b } - var value = IteratorValue(next); // step 4.c + var value = IteratorValue(next); // step 6.c try { - Call(fn, void undefined, [value, counter]); // step 4.d + Call(fn, void undefined, [value, counter]); // step 6.d } catch (e) { IteratorClose( iterated, ThrowCompletion(e) - ); // steps 4.e + ); // steps 6.e throw e; } finally { - counter += 1; // step 4.f + counter += 1; // step 6.f } } }; diff --git a/Iterator.prototype.map/implementation.js b/Iterator.prototype.map/implementation.js index 2d2da32..bf7ae5e 100644 --- a/Iterator.prototype.map/implementation.js +++ b/Iterator.prototype.map/implementation.js @@ -13,18 +13,24 @@ var IteratorClose = require('../aos/IteratorClose'); var IteratorStep = require('../aos/IteratorStep'); var IteratorValue = require('es-abstract/2022/IteratorValue'); var ThrowCompletion = require('es-abstract/2022/ThrowCompletion'); +var Type = require('es-abstract/2022/Type'); var iterHelperProto = require('../IteratorHelperPrototype'); var SLOT = require('internal-slot'); module.exports = function map(mapper) { - var iterated = GetIteratorDirect(this); // step 1 + var O = this; // step 1 + if (Type(O) !== 'Object') { + throw new $TypeError('`this` value must be an Object'); // step 2 + } if (!IsCallable(mapper)) { - throw new $TypeError('`mapper` must be a function'); // step 2 + throw new $TypeError('`mapper` must be a function'); // step 3 } + var iterated = GetIteratorDirect(O); // step 4 + var closeIfAbrupt = function (abruptCompletion) { if (!(abruptCompletion instanceof CompletionRecord)) { throw new $TypeError('`abruptCompletion` must be a Completion Record'); @@ -36,36 +42,36 @@ module.exports = function map(mapper) { }; var sentinel = {}; - var counter = 0; // step 3.a + var counter = 0; // step 6.a var closure = function () { - // while (true) { // step 3.b - var next = IteratorStep(iterated); // step 3.b.i + // while (true) { // step 6.b + var next = IteratorStep(iterated); // step 6.b.i if (!next) { - // return void undefined; // step 3.b.ii + // return void undefined; // step 6.b.ii return sentinel; } - var value = IteratorValue(next); // step 3.b.iii + var value = IteratorValue(next); // step 6.b.iii var mapped; try { - mapped = Call(mapper, void undefined, [value, counter]); // step 3.b.iv - // yield mapped // step 3.b.vi + mapped = Call(mapper, void undefined, [value, counter]); // step 6.b.iv + // yield mapped // step 6.b.vi return mapped; } catch (e) { - // close iterator // step 3.b.v, 3.b.vii + // close iterator // step 6.b.v, 6.b.vii closeIfAbrupt(ThrowCompletion(e)); throw e; } finally { - counter += 1; // step 3.b.viii + counter += 1; // step 6.b.viii } // } }; SLOT.set(closure, '[[Sentinel]]', sentinel); // for the userland implementation SLOT.set(closure, '[[CloseIfAbrupt]]', closeIfAbrupt); // for the userland implementation - var result = CreateIteratorFromClosure(closure, 'Iterator Helper', iterHelperProto, ['[[UnderlyingIterator]]']); // step 4 + var result = CreateIteratorFromClosure(closure, 'Iterator Helper', iterHelperProto, ['[[UnderlyingIterator]]']); // step 7 - SLOT.set(result, '[[UnderlyingIterator]]', iterated); // step 5 + SLOT.set(result, '[[UnderlyingIterator]]', iterated); // step 8 - return result; // step 6 + return result; // step 9 }; diff --git a/Iterator.prototype.reduce/implementation.js b/Iterator.prototype.reduce/implementation.js index 5e1ff8d..1ff87e7 100644 --- a/Iterator.prototype.reduce/implementation.js +++ b/Iterator.prototype.reduce/implementation.js @@ -11,46 +11,52 @@ var IteratorClose = require('../aos/IteratorClose'); var IteratorStep = require('../aos/IteratorStep'); var IteratorValue = require('es-abstract/2022/IteratorValue'); var ThrowCompletion = require('es-abstract/2022/ThrowCompletion'); +var Type = require('es-abstract/2022/Type'); module.exports = function reduce(reducer) { - var iterated = GetIteratorDirect(this); // step 1 + var O = this; // step 1 + if (Type(O) !== 'Object') { + throw new $TypeError('`this` value must be an Object'); // step 2 + } if (!IsCallable(reducer)) { - throw new $TypeError('`reducer` must be a function'); // step 2 + throw new $TypeError('`reducer` must be a function'); // step 3 } + var iterated = GetIteratorDirect(O); // step 4 + var accumulator; var counter; var next; - if (arguments.length < 2) { // step 3 - next = IteratorStep(iterated); // step 3.a + if (arguments.length < 2) { // step 6 + next = IteratorStep(iterated); // step 6.a if (!next) { - throw new $TypeError('Reduce of empty iterator with no initial value'); // step 3.b + throw new $TypeError('Reduce of empty iterator with no initial value'); // step 6.b } - accumulator = IteratorValue(next); // step 3.c + accumulator = IteratorValue(next); // step 6.c counter = 1; - } else { // step 4 - accumulator = arguments[1]; // step 4.a + } else { // step 7 + accumulator = arguments[1]; // step 7.a counter = 0; } // eslint-disable-next-line no-constant-condition - while (true) { // step 5 - next = IteratorStep(iterated); // step 5.a + while (true) { // step 8 + next = IteratorStep(iterated); // step 8.a if (!next) { - return accumulator; // step 5.b + return accumulator; // step 8.b } - var value = IteratorValue(next); // step 5.c + var value = IteratorValue(next); // step 8.c try { - var result = Call(reducer, void undefined, [accumulator, value, counter]); // step 5.d - accumulator = result; // step 5.f + var result = Call(reducer, void undefined, [accumulator, value, counter]); // step 8.d + accumulator = result; // step 8.f } catch (e) { - // close iterator // step 5.e + // close iterator // step 8.e IteratorClose( iterated, ThrowCompletion(e) ); } - counter += 1; // step 5.g + counter += 1; // step 8.g } }; diff --git a/Iterator.prototype.some/implementation.js b/Iterator.prototype.some/implementation.js index e9dfd35..1836da5 100644 --- a/Iterator.prototype.some/implementation.js +++ b/Iterator.prototype.some/implementation.js @@ -13,40 +13,46 @@ var IteratorValue = require('es-abstract/2022/IteratorValue'); var NormalCompletion = require('es-abstract/2022/NormalCompletion'); var ThrowCompletion = require('es-abstract/2022/ThrowCompletion'); var ToBoolean = require('es-abstract/2022/ToBoolean'); +var Type = require('es-abstract/2022/Type'); module.exports = function some(predicate) { - var iterated = GetIteratorDirect(this); // step 1 + var O = this; // step 1 + if (Type(O) !== 'Object') { + throw new $TypeError('`this` value must be an Object'); // step 2 + } if (!IsCallable(predicate)) { - throw new $TypeError('`predicate` must be a function'); // step 2 + throw new $TypeError('`predicate` must be a function'); // step 3 } - var counter = 0; // step 3 + var iterated = GetIteratorDirect(O); // step 4 + + var counter = 0; // step 5 // eslint-disable-next-line no-constant-condition - while (true) { // step 4 - var next = IteratorStep(iterated); // step 4.a + while (true) { // step 6 + var next = IteratorStep(iterated); // step 6.a if (!next) { - return false; // step 4.b + return false; // step 6.b } - var value = IteratorValue(next); // step 4.c + var value = IteratorValue(next); // step 6.c var result; try { - result = Call(predicate, void undefined, [value, counter]); // step 4.d + result = Call(predicate, void undefined, [value, counter]); // step 6.d } catch (e) { - // close iterator // step 4.e + // close iterator // step 6.e IteratorClose( iterated, ThrowCompletion(e) ); } finally { - counter += 1; // step 4.g + counter += 1; // step 6.g } if (ToBoolean(result)) { return IteratorClose( iterated, NormalCompletion(true) - ); // step 4.f + ); // step 6.f } } }; diff --git a/Iterator.prototype.take/implementation.js b/Iterator.prototype.take/implementation.js index 124bcd8..b1ea903 100644 --- a/Iterator.prototype.take/implementation.js +++ b/Iterator.prototype.take/implementation.js @@ -14,6 +14,7 @@ var IteratorValue = require('es-abstract/2022/IteratorValue'); var NormalCompletion = require('es-abstract/2022/NormalCompletion'); var ToIntegerOrInfinity = require('es-abstract/2022/ToIntegerOrInfinity'); var ToNumber = require('es-abstract/2022/ToNumber'); +var Type = require('es-abstract/2022/Type'); var iterHelperProto = require('../IteratorHelperPrototype'); @@ -22,16 +23,21 @@ var isNaN = require('es-abstract/helpers/isNaN'); var SLOT = require('internal-slot'); module.exports = function take(limit) { - var iterated = GetIteratorDirect(this); // step 1 + var O = this; // step 1 + if (Type(O) !== 'Object') { + throw new $TypeError('`this` value must be an Object'); // step 2 + } var numLimit = ToNumber(limit); // step 2 if (isNaN(numLimit)) { throw new $RangeError('`limit` must be a non-NaN number'); // step 3 } - var integerLimit = ToIntegerOrInfinity(numLimit); // step 4 + var iterated = GetIteratorDirect(O); // step 4 + + var integerLimit = ToIntegerOrInfinity(numLimit); // step 7 if (integerLimit < 0) { - throw new $RangeError('`limit` must be a >= 0'); // step 5 + throw new $RangeError('`limit` must be a >= 0'); // step 8 } var closeIfAbrupt = function (abruptCompletion) { @@ -45,35 +51,35 @@ module.exports = function take(limit) { }; var sentinel = {}; - var remaining = integerLimit; // step 6.a - var closure = function () { // step 6 - // while (true) { // step 6.b - if (remaining === 0) { // step 6.b.i - return IteratorClose( // step 6.b.i.1 + var remaining = integerLimit; // step 9.a + var closure = function () { // step 9 + // while (true) { // step 9.b + if (remaining === 0) { // step 9.b.i + return IteratorClose( // step 9.b.i.1 iterated, NormalCompletion(sentinel) ); } - if (remaining !== Infinity) { // step 6.b.ii - remaining -= 1; // step 6.b.ii.1 + if (remaining !== Infinity) { // step 9.b.ii + remaining -= 1; // step 9.b.ii.1 } - var next = IteratorStep(iterated); // step 6.b.iii + var next = IteratorStep(iterated); // step 9.b.iii if (!next) { - // return void undefined; // step 6.b.iv + // return void undefined; // step 9.b.iv return sentinel; } - var value = IteratorValue(next); // step 3.b.iii - return value; // step 3.b.iv + var value = IteratorValue(next); // step 9.b.iii + return value; // step 9.b.iv // } }; SLOT.set(closure, '[[Sentinel]]', sentinel); // for the userland implementation SLOT.set(closure, '[[CloseIfAbrupt]]', closeIfAbrupt); // for the userland implementation - var result = CreateIteratorFromClosure(closure, 'Iterator Helper', iterHelperProto, ['[[UnderlyingIterator]]']); // step 4 + var result = CreateIteratorFromClosure(closure, 'Iterator Helper', iterHelperProto, ['[[UnderlyingIterator]]']); // step 7 - SLOT.set(result, '[[UnderlyingIterator]]', iterated); // step 5 + SLOT.set(result, '[[UnderlyingIterator]]', iterated); // step 8 - return result; // step 6 + return result; // step 9 }; diff --git a/Iterator.prototype.toArray/implementation.js b/Iterator.prototype.toArray/implementation.js index c2f758e..eab6d5b 100644 --- a/Iterator.prototype.toArray/implementation.js +++ b/Iterator.prototype.toArray/implementation.js @@ -1,26 +1,36 @@ 'use strict'; -var IteratorStep = require('../aos/IteratorStep'); -var IteratorValue = require('es-abstract/2022/IteratorValue'); +var GetIntrinsic = require('get-intrinsic'); + +var $TypeError = GetIntrinsic('%TypeError%'); var GetIteratorDirect = require('../aos/GetIteratorDirect'); +var IteratorStep = require('../aos/IteratorStep'); +var IteratorValue = require('es-abstract/2022/IteratorValue'); +var Type = require('es-abstract/2022/Type'); var callBound = require('call-bind/callBound'); var $push = callBound('Array.prototype.push'); module.exports = function toArray() { - var iterated = GetIteratorDirect(this); // step 1 + var O = this; // step 1 + + if (Type(O) !== 'Object') { + throw new $TypeError('`this` value must be an Object'); // step 2 + } + + var iterated = GetIteratorDirect(O); // step 3 - var items = []; // step 2 + var items = []; // step 4 // eslint-disable-next-line no-constant-condition - while (true) { // step 3 - var next = IteratorStep(iterated); // step 3.a + while (true) { // step 5 + var next = IteratorStep(iterated); // step 5.a if (!next) { - return items; // step 3.b + return items; // step 5.b } - var value = IteratorValue(next); // step 3.c - $push(items, value); // step 3.d + var value = IteratorValue(next); // step 5.c + $push(items, value); // step 5.d } }; diff --git a/aos/GetIteratorDirect.js b/aos/GetIteratorDirect.js index c010ee4..4e560e0 100644 --- a/aos/GetIteratorDirect.js +++ b/aos/GetIteratorDirect.js @@ -10,7 +10,7 @@ var Type = require('es-abstract/2022/Type'); module.exports = function GetIteratorDirect(obj) { if (Type(obj) !== 'Object') { - throw new $TypeError('`obj` must be an Object'); // step 1 + throw new $TypeError('Assertion failed: `obj` must be an Object'); } var nextMethod = Get(obj, 'next'); // step 2 diff --git a/test/Iterator.prototype.drop.js b/test/Iterator.prototype.drop.js index c61a52d..0669f0a 100644 --- a/test/Iterator.prototype.drop.js +++ b/test/Iterator.prototype.drop.js @@ -24,14 +24,14 @@ module.exports = { tests: function (drop, name, t) { forEach(v.primitives.concat(v.objects), function (nonIterator) { t['throws']( - function () { drop(nonIterator); }, + function () { drop(nonIterator, 0); }, TypeError, debug(nonIterator) + ' is not an Object with a callable `next` method' ); var badNext = { next: nonIterator }; t['throws']( - function () { drop(badNext); }, + function () { drop(badNext, 0); }, TypeError, debug(badNext) + ' is not an Object with a callable `next` method' ); diff --git a/test/Iterator.prototype.take.js b/test/Iterator.prototype.take.js index 1670b0f..ff82793 100644 --- a/test/Iterator.prototype.take.js +++ b/test/Iterator.prototype.take.js @@ -23,14 +23,14 @@ module.exports = { tests: function (take, name, t) { forEach(v.primitives.concat(v.objects), function (nonIterator) { t['throws']( - function () { take(nonIterator); }, + function () { take(nonIterator, 0); }, TypeError, debug(nonIterator) + ' is not an Object with a callable `next` method' ); var badNext = { next: nonIterator }; t['throws']( - function () { take(badNext); }, + function () { take(badNext, 0); }, TypeError, debug(badNext) + ' is not an Object with a callable `next` method' );