This commit is contained in:
Iliyan Angelov
2025-09-14 23:24:25 +03:00
commit c67067a2a4
71311 changed files with 6800714 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
'use strict';
var $TypeError = require('es-errors/type');
var GeneratorStart = require('./GeneratorStart');
var IsArray = require('es-abstract/2024/IsArray');
var IsCallable = require('es-abstract/2024/IsCallable');
var OrdinaryObjectCreate = require('es-abstract/2024/OrdinaryObjectCreate');
var every = require('es-abstract/helpers/every');
var SLOT = require('internal-slot');
var safeConcat = require('safe-array-concat');
var isString = function isString(slot) {
return typeof slot === 'string';
};
module.exports = function CreateIteratorFromClosure(closure, generatorBrand, proto) {
if (!IsCallable(closure)) {
throw new $TypeError('`closure` must be a function');
}
if (typeof generatorBrand !== 'string') {
throw new $TypeError('`generatorBrand` must be a string');
}
var extraSlots = arguments.length > 3 ? arguments[3] : [];
if (arguments.length > 3) {
if (!IsArray(extraSlots) || !every(extraSlots, isString)) {
throw new $TypeError('`extraSlots` must be a List of String internal slot names');
}
}
var internalSlotsList = safeConcat(extraSlots, ['[[GeneratorContext]]', '[[GeneratorBrand]]', '[[GeneratorState]]']); // step 3
var generator = OrdinaryObjectCreate(proto, internalSlotsList); // steps 4, 6
SLOT.set(generator, '[[GeneratorBrand]]', generatorBrand); // step 5
SLOT.assert(closure, '[[Sentinel]]'); // our userland slot
SLOT.set(generator, '[[Sentinel]]', SLOT.get(closure, '[[Sentinel]]')); // our userland slot
SLOT.assert(closure, '[[CloseIfAbrupt]]'); // our second userland slot
SLOT.set(generator, '[[CloseIfAbrupt]]', SLOT.get(closure, '[[CloseIfAbrupt]]')); // our second userland slot
GeneratorStart(generator, closure); // step 13
return generator; // step 15
};

View File

@@ -0,0 +1,27 @@
'use strict';
var $TypeError = require('es-errors/type');
var CreateIterResultObject = require('es-abstract/2024/CreateIterResultObject');
var GeneratorValidate = require('./GeneratorValidate');
var SLOT = require('internal-slot');
module.exports = function GeneratorResume(generator, value, generatorBrand) {
var state = GeneratorValidate(generator, generatorBrand); // step 1
if (state === 'completed') {
return CreateIterResultObject(void undefined, true); // step 2
}
if (state !== 'suspendedStart' && state !== 'suspendedYield') {
throw new $TypeError('Assertion failed: generator state is unexpected: ' + state); // step 3
}
var genContext = SLOT.get(generator, '[[GeneratorContext]]');
SLOT.set(generator, '[[GeneratorState]]', 'executing'); // step 7
var result = genContext(value); // steps 5-6, 8-10
return result;
};

View File

@@ -0,0 +1,46 @@
'use strict';
var $TypeError = require('es-errors/type');
var CompletionRecord = require('es-abstract/2024/CompletionRecord');
var CreateIterResultObject = require('es-abstract/2024/CreateIterResultObject');
var GeneratorValidate = require('./GeneratorValidate');
var NormalCompletion = require('es-abstract/2024/NormalCompletion');
var SLOT = require('internal-slot');
module.exports = function GeneratorResumeAbrupt(generator, abruptCompletion, generatorBrand) {
if (!(abruptCompletion instanceof CompletionRecord)) {
throw new $TypeError('Assertion failed: abruptCompletion must be a Completion Record');
}
var state = GeneratorValidate(generator, generatorBrand); // step 1
if (state === 'suspendedStart') { // step 2
SLOT.set(generator, '[[GeneratorState]]', 'completed'); // step 3.a
SLOT.set(generator, '[[GeneratorContext]]', null); // step 3.b
state = 'completed'; // step 3.c
}
var value = abruptCompletion.value();
if (state === 'completed') { // step 3
return CreateIterResultObject(value, true); // steps 3.a-b
}
if (state !== 'suspendedYield') {
throw new $TypeError('Assertion failed: generator state is unexpected: ' + state); // step 4
}
if (abruptCompletion.type() === 'return') {
// due to representing `GeneratorContext` as a function, we can't safely re-invoke it, so we can't support sending it a return completion
return CreateIterResultObject(SLOT.get(generator, '[[CloseIfAbrupt]]')(NormalCompletion(abruptCompletion.value())), true);
}
var genContext = SLOT.get(generator, '[[GeneratorContext]]'); // step 5
SLOT.set(generator, '[[GeneratorState]]', 'executing'); // step 8
var result = genContext(value); // steps 6-7, 8-11
return result; // step 12
};

View File

@@ -0,0 +1,44 @@
'use strict';
var $TypeError = require('es-errors/type');
var CreateIterResultObject = require('es-abstract/2024/CreateIterResultObject');
var IsCallable = require('es-abstract/2024/IsCallable');
var Type = require('es-abstract/2024/Type');
var SLOT = require('internal-slot');
module.exports = function GeneratorStart(generator, closure) {
SLOT.assert(generator, '[[GeneratorState]]');
SLOT.assert(generator, '[[GeneratorContext]]');
SLOT.assert(generator, '[[GeneratorBrand]]');
SLOT.assert(generator, '[[Sentinel]]'); // our userland slot
SLOT.assert(generator, '[[CloseIfAbrupt]]'); // our second userland slot
if (!IsCallable(closure) || closure.length !== 0) {
throw new $TypeError('`closure` must be a function that takes no arguments');
}
var sentinel = SLOT.get(closure, '[[Sentinel]]');
if (Type(sentinel) !== 'Object') {
throw new $TypeError('`closure.[[Sentinel]]` must be an object');
}
SLOT.set(generator, '[[GeneratorContext]]', function () { // steps 2-5
try {
var result = closure();
if (result === sentinel) {
SLOT.set(generator, '[[GeneratorState]]', 'completed');
SLOT.set(generator, '[[GeneratorContext]]', null);
return CreateIterResultObject(void undefined, true);
}
SLOT.set(generator, '[[GeneratorState]]', 'suspendedYield');
return CreateIterResultObject(result, false);
} catch (e) {
SLOT.set(generator, '[[GeneratorState]]', 'completed');
SLOT.set(generator, '[[GeneratorContext]]', null);
throw e;
}
});
SLOT.set(generator, '[[GeneratorState]]', 'suspendedStart'); // step 6
};

View File

@@ -0,0 +1,22 @@
'use strict';
var $TypeError = require('es-errors/type');
var SLOT = require('internal-slot');
module.exports = function GeneratorValidate(generator, generatorBrand) {
SLOT.assert(generator, '[[GeneratorState]]'); // step 1
SLOT.assert(generator, '[[GeneratorBrand]]'); // step 2
var brand = SLOT.get(generator, '[[GeneratorBrand]]');
if (brand !== generatorBrand) {
throw new $TypeError('Assertion failed: generator brand is unexpected: ' + brand);
}
SLOT.assert(generator, '[[GeneratorContext]]'); // step 4
var state = SLOT.get(generator, '[[GeneratorState]]'); // step 5
if (state === 'executing') {
throw new $TypeError('generator is executing');
}
return state; // step 7
};

View File

@@ -0,0 +1,18 @@
'use strict';
var $TypeError = require('es-errors/type');
var Get = require('es-abstract/2024/Get');
var Type = require('es-abstract/2024/Type');
module.exports = function GetIteratorDirect(obj) {
if (Type(obj) !== 'Object') {
throw new $TypeError('Assertion failed: `obj` must be an Object');
}
var nextMethod = Get(obj, 'next'); // step 2
var iteratorRecord = { '[[Iterator]]': obj, '[[NextMethod]]': nextMethod, '[[Done]]': false }; // step 3
return iteratorRecord; // step 4
};

View File

@@ -0,0 +1,50 @@
'use strict';
var $TypeError = require('es-errors/type');
var AdvanceStringIndex = require('es-abstract/2024/AdvanceStringIndex');
var Call = require('es-abstract/2024/Call');
var GetIteratorDirect = require('./GetIteratorDirect');
var GetMethod = require('es-abstract/2024/GetMethod');
var IsArray = require('es-abstract/2024/IsArray');
var Type = require('es-abstract/2024/Type');
var getIteratorMethod = require('es-abstract/helpers/getIteratorMethod');
// https://tc39.es/proposal-iterator-helpers/#sec-getiteratorflattenable
module.exports = function GetIteratorFlattenable(obj, stringHandling) {
if (stringHandling !== 'REJECT-STRINGS' && stringHandling !== 'ITERATE-STRINGS') {
throw new $TypeError('Assertion failed: `stringHandling` must be "REJECT-STRINGS" or "ITERATE-STRINGS"');
}
if (Type(obj) !== 'Object') {
if (stringHandling === 'REJECT-STRINGS' || typeof obj !== 'string') {
throw new $TypeError('obj must be an Object'); // step 1.a
}
}
var method = void undefined; // step 2
// method = GetMethod(obj, Symbol.iterator); // step 5.a
method = getIteratorMethod(
{
AdvanceStringIndex: AdvanceStringIndex,
GetMethod: GetMethod,
IsArray: IsArray
},
obj
);
var iterator;
if (typeof method === 'undefined') { // step 3
iterator = obj; // step 3.a
} else { // step 4
iterator = Call(method, obj); // step 4.a
}
if (Type(iterator) !== 'Object') {
throw new $TypeError('iterator must be an Object'); // step 5
}
return GetIteratorDirect(iterator); // step 6
};

View File

@@ -0,0 +1,20 @@
'use strict';
var $TypeError = require('es-errors/type');
// var OrdinaryObjectCreate = require('es-abstract/2024/OrdinaryObjectCreate');
var Type = require('es-abstract/2024/Type');
// https://tc39.es/proposal-joint-iteration/#sec-getoptionsobject
module.exports = function GetOptionsObject(options) {
if (typeof options === 'undefined') { // step 1
// return OrdinaryObjectCreate(null); // step 1.a
return { __proto__: null }; // step 1.a
}
if (Type(options) === 'Object') { // step 2
return options; // step 2.a
}
throw new $TypeError('`options` must be an Object or undefined'); // step 3
};

View File

@@ -0,0 +1,19 @@
'use strict';
var $TypeError = require('es-errors/type');
var CompletionRecord = require('es-abstract/2024/CompletionRecord');
var IteratorCloseAll = require('./IteratorCloseAll');
// https://tc39.es/proposal-joint-iteration/#sec-ifabruptcloseiterators
module.exports = function IfAbruptCloseIterators(value, iteratorRecords) {
if (!(value instanceof CompletionRecord)) {
throw new $TypeError('Assertion failed: `value` must be a Completion Record'); // step 1
}
if (value.type() === 'throw') {
return IteratorCloseAll(iteratorRecords, value); // step 2
}
return value['!'](); // step
};

View File

@@ -0,0 +1,34 @@
'use strict';
var $TypeError = require('es-errors/type');
var CompletionRecord = require('es-abstract/2024/CompletionRecord');
var IteratorClose = require('es-abstract/2024/IteratorClose');
var ThrowCompletion = require('es-abstract/2024/ThrowCompletion');
var IsArray = require('es-abstract/helpers/IsArray');
var every = require('es-abstract/helpers/every');
var isIteratorRecord = require('es-abstract/helpers/records/iterator-record');
// https://tc39.es/proposal-joint-iteration/#sec-closeall
module.exports = function IteratorCloseAll(iters, completion) {
if (!IsArray(iters) || !every(iters, isIteratorRecord)) {
throw new $TypeError('Assertion failed: `iters` must be a List of IteratorRecords');
}
if (!(completion instanceof CompletionRecord)) {
throw new $TypeError('Assertion failed: `completion` must be a Completion Record');
}
for (var i = iters.length - 1; i >= 0; i -= 1) { // step 1
try {
IteratorClose(iters[i], completion); // step 1.a
} catch (e) {
// eslint-disable-next-line no-param-reassign
completion = ThrowCompletion(e); // step 1.a
}
}
return completion['?'](); // step 2
};

View File

@@ -0,0 +1,147 @@
'use strict';
var $TypeError = require('es-errors/type');
var CreateIteratorFromClosure = require('./CreateIteratorFromClosure');
var IteratorCloseAll = require('./IteratorCloseAll');
var IteratorStep = require('es-abstract/2024/IteratorStep');
var IteratorStepValue = require('es-abstract/2024/IteratorStepValue');
var NormalCompletion = require('es-abstract/2024/NormalCompletion');
var ThrowCompletion = require('es-abstract/2024/ThrowCompletion');
var isAbstractClosure = require('es-abstract/helpers/isAbstractClosure');
var IsArray = require('es-abstract/helpers/IsArray');
var isIteratorRecord = require('es-abstract/helpers/records/iterator-record');
var every = require('es-abstract/helpers/every');
var callBound = require('call-bound');
var $indexOf = callBound('Array.prototype.indexOf');
var $slice = callBound('Array.prototype.slice');
var $splice = callBound('Array.prototype.splice');
var iterHelperProto = require('../IteratorHelperPrototype');
var SLOT = require('internal-slot');
// https://tc39.es/proposal-joint-iteration/#sec-IteratorZip
module.exports = function IteratorZip(iters, mode, padding, finishResults) {
if (!IsArray(iters) || !every(iters, isIteratorRecord)) {
throw new $TypeError('`iters` must be a List of IteratorRecords');
}
if (mode !== 'shortest' && mode !== 'longest' && mode !== 'strict') {
throw new $TypeError('`mode` must be one of "shortest", "longest", or "strict"');
}
if (!IsArray(padding)) {
throw new $TypeError('`padding` must be a List');
}
if (!isAbstractClosure(finishResults)) {
throw new $TypeError('`finishResults` must be an Abstract Closure');
}
var iterCount = iters.length; // step 1
var openIters = $slice(iters); // step 2
var sentinel = {};
var closure = function () {
if (iterCount === 0) {
// 1. If iterCount = 0, return ReturnCompletion(undefined).
return sentinel; // step 1
}
// while (true) {
{ // eslint-disable-line no-lone-blocks
var results = []; // step 3.b.i
if (openIters.length === 0) {
throw new $TypeError('Assertion failed: `openIters` is empty'); // step 3.b.ii
}
for (var i = 0; i < iterCount; ++i) { // step 3.b.iii
// for (var i = 0; i < iterCount; i += 1) { // step 3.b.iii
var result;
var iter = iters[i];
if (iter === null) { // step 3.b.iii.1
if (mode !== 'longest') {
throw new $TypeError('Assertion failed: `mode` is not "longest"'); // step 3.b.iii.1.a
}
result = padding[i]; // step 3.b.iii.1.b
} else { // step 2
try {
result = IteratorStepValue(iter); // step 3.b.iii.2.a, 3.b.iii.2.c
} catch (e) { // step 3.b.iii.2.b
$splice(openIters, $indexOf(openIters, iter), 1); // step 3.b.iii.2.b.i
return IteratorCloseAll(openIters, ThrowCompletion(e)); // step 3.b.iii.2.b.ii
}
if (iter['[[Done]]']) { // step 3.b.iii.2.d
$splice(openIters, $indexOf(openIters, iter), 1); // step 3.b.iii.2.d.i
if (mode === 'shortest') { // step 3.b.iii.2.d.ii
IteratorCloseAll(openIters, NormalCompletion(undefined)); // step 3.b.iii.2.d.ii.i
return sentinel;
} else if (mode === 'strict') { // step 3.b.iii.2.d.iii
if (i !== 0) { // step 3.b.iii.2.d.iii.i
return IteratorCloseAll(
openIters,
ThrowCompletion(new $TypeError('Assertion failed: `i` is not 0'))
); // step 3.b.iii.2.d.iii.i.i
}
for (var k = 1; k < iterCount; k += 1) { // step 3.b.iii.2.d.iii.ii
if (iters[k] === null) {
throw new $TypeError('Assertion failed: `iters[k]` is `null`'); // step 3.b.iii.2.d.iii.ii.i
}
try {
result = IteratorStep(iters[k]); // step 3.b.iii.2.d.iii.ii.ii, 3.b.iii.2.d.iii.ii.iii.ii.iv
} catch (e) { // step 3.b.iii.2.d.iii.ii.iii
return IteratorCloseAll(openIters, ThrowCompletion(e)); // step 3.b.iii.2.d.iii.ii.iii.ii
}
// if (open === false) { // step 3.b.iii.2.d.iii.ii.v
if (iters[k]['[[Done]]']) { // step 3.b.iii.2.d.iii.ii.v
$splice(openIters, $indexOf(openIters, iters[k]), 1); // step 3.b.iii.2.d.iii.ii.v.i
} else { // step 3.b.iii.2.d.iii.ii.vi
return IteratorCloseAll(
openIters,
ThrowCompletion(new $TypeError('Assertion failed: `open` is not `false`'))
); // step 3.b.iii.2.d.iii.ii.vi.i
}
}
} else { // step 3.b.iii.2.d.iv
if (mode !== 'longest') {
throw new $TypeError('Assertion failed: `mode` is not "longest"'); // step 3.b.iii.2.d.iv.i
}
if (openIters.length === 0) {
return sentinel; // ReturnCompletion(undefined); // step 3.b.iii.2.d.iv.ii
}
// eslint-disable-next-line no-param-reassign
iters[i] = null; // step 3.b.iii.2.d.iv.iii
// i += 1;
result = padding[i]; // step 3.b.iii.2.d.iv.iv
}
}
}
results[results.length] = result; // step 3.b.iii.3
// 5. Let completion be Completion(Yield(results)).
// 6. If completion is an abrupt completion, then
// 1. Return ? IteratorCloseAll(openIters, completion).
}
}
return finishResults(results); // step 3.b.iv
};
SLOT.set(closure, '[[Sentinel]]', sentinel); // for the userland implementation
SLOT.set(closure, '[[CloseIfAbrupt]]', finishResults); // for the userland implementation
var gen = CreateIteratorFromClosure(closure, 'Iterator Helper', iterHelperProto, ['[[UnderlyingIterators]]']); // step 4
SLOT.set(gen, '[[UnderlyingIterators]]', openIters); // step 5
return gen; // step 6
};

View File

@@ -0,0 +1,9 @@
'use strict';
var CompletionRecord = require('es-abstract/2024/CompletionRecord');
// https://tc39.es/ecma262/#sec-returncompletion
module.exports = function ReturnCompletion(value) {
return new CompletionRecord('return', value);
};