Skip to content

Commit

Permalink
[Fix] validate arguments first
Browse files Browse the repository at this point in the history
  • Loading branch information
ljharb committed Mar 21, 2023
1 parent f5372c7 commit 4240029
Show file tree
Hide file tree
Showing 14 changed files with 214 additions and 143 deletions.
8 changes: 7 additions & 1 deletion Iterator.prototype.drop/implementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand All @@ -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
Expand Down
28 changes: 17 additions & 11 deletions Iterator.prototype.every/implementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
};
34 changes: 20 additions & 14 deletions Iterator.prototype.filter/implementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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
};
29 changes: 18 additions & 11 deletions Iterator.prototype.find/implementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
};
54 changes: 30 additions & 24 deletions Iterator.prototype.flatMap/implementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -37,56 +43,56 @@ 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;
};
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
};
26 changes: 16 additions & 10 deletions Iterator.prototype.forEach/implementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
};
Loading

0 comments on commit 4240029

Please sign in to comment.