Merge commit '6e92d2345e8231a44556ce7d416451f5f3e6c398' as 'engine262'

This commit is contained in:
2026-03-27 10:07:29 +05:30
433 changed files with 90478 additions and 0 deletions
@@ -0,0 +1,212 @@
import { Value } from '../value.mts';
import {
NormalCompletion,
Q, X,
} from '../completion.mts';
import { Evaluate, type PlainEvaluator } from '../evaluator.mts';
import {
StringValue,
IsAnonymousFunctionDefinition,
} from '../static-semantics/all.mts';
import type { ParseNode } from '../parser/ParseNode.mts';
import { __ts_cast__ } from '../helpers.mts';
import { NamedEvaluation, BindingInitialization } from './all.mts';
import {
Assert,
GetValue,
InitializeReferencedBinding,
IteratorStep,
PutValue,
ResolveBinding,
ArrayCreate,
CreateDataPropertyOrThrow,
ToString,
F,
type IteratorRecord,
IteratorStepValue,
UndefinedValue, type EnvironmentRecord, type FunctionDeclaration,
} from '#self';
/** https://tc39.es/ecma262/#sec-function-definitions-runtime-semantics-iteratorbindinginitialization */
// FormalParameters :
// [empty]
// FormalParameterList `,` FunctionRestParameter
export function* IteratorBindingInitialization_FormalParameters(FormalParameters: ParseNode.FormalParameters, iteratorRecord: IteratorRecord, environment: EnvironmentRecord | UndefinedValue) {
if (FormalParameters.length === 0) {
// 1. Return NormalCompletion(empty).
return NormalCompletion(undefined);
}
for (const FormalParameter of FormalParameters.slice(0, -1)) {
Q(yield* IteratorBindingInitialization_FormalParameter(FormalParameter, iteratorRecord, environment));
}
const last = FormalParameters[FormalParameters.length - 1];
if (last.type === 'BindingRestElement') {
return yield* IteratorBindingInitialization_FunctionRestParameter(last, iteratorRecord, environment);
}
return yield* IteratorBindingInitialization_FormalParameter(last, iteratorRecord, environment);
}
// FormalParameter : BindingElement
function IteratorBindingInitialization_FormalParameter(BindingElement: ParseNode.FormalParametersElement, iteratorRecord: IteratorRecord, environment: EnvironmentRecord | UndefinedValue) {
// TODO
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return IteratorBindingInitialization_BindingElement(BindingElement as any, iteratorRecord, environment);
}
// FunctionRestParameter : BindingRestElement
function IteratorBindingInitialization_FunctionRestParameter(FunctionRestParameter: ParseNode.FunctionRestParameter, iteratorRecord: IteratorRecord, environment: EnvironmentRecord | UndefinedValue) {
return IteratorBindingInitialization_BindingRestElement(FunctionRestParameter, iteratorRecord, environment);
}
// BindingElement :
// SingleNameBinding
// BindingPattern
function IteratorBindingInitialization_BindingElement(BindingElement: ParseNode.BindingElement, iteratorRecord: IteratorRecord, environment: EnvironmentRecord | UndefinedValue) {
if ('BindingPattern' in BindingElement) {
return IteratorBindingInitialization_BindingPattern(BindingElement, iteratorRecord, environment);
}
return IteratorBindingInitialization_SingleNameBinding(BindingElement, iteratorRecord, environment);
}
// SingleNameBinding : BindingIdentifier Initializer?
function* IteratorBindingInitialization_SingleNameBinding({ BindingIdentifier, Initializer }: ParseNode.SingleNameBinding, iteratorRecord: IteratorRecord, environment: EnvironmentRecord | UndefinedValue): PlainEvaluator {
// 1. Let bindingId be StringValue of BindingIdentifier.
const bindingId = StringValue(BindingIdentifier);
// 2. Let lhs be ? ResolveBinding(bindingId, environment).
const lhs = Q(yield* ResolveBinding(bindingId, environment, BindingIdentifier.strict));
let v: Value = Value.undefined;
// 3. If iteratorRecord.[[Done]] is false, then
if (iteratorRecord.Done === Value.false) {
// a. Let next be ? IteratorStepValue(iteratorRecord).
const next = Q(yield* IteratorStepValue(iteratorRecord));
// d. If next is not DONE,
if (next !== 'done') {
v = next;
}
}
// 5. If Initializer is present and v is undefined, then
if (Initializer && v === Value.undefined) {
if (IsAnonymousFunctionDefinition(Initializer)) {
v = Q(yield* NamedEvaluation(Initializer as FunctionDeclaration, bindingId));
} else {
const defaultValue = Q(yield* Evaluate(Initializer));
v = Q(yield* GetValue(defaultValue));
}
}
// 6. If environment is undefined, return ? PutValue(lhs, v).
if (environment === Value.undefined) {
return Q(yield* PutValue(lhs, v));
}
// 7. Return InitializeReferencedBinding(lhs, v).
return yield* InitializeReferencedBinding(lhs, X(v));
}
// BindingRestElement :
// `...` BindingIdentifier
// `...` BindingPattern
function* IteratorBindingInitialization_BindingRestElement({ BindingIdentifier, BindingPattern }: ParseNode.BindingRestElement, iteratorRecord: IteratorRecord, environment: EnvironmentRecord | UndefinedValue) {
if (BindingIdentifier) {
// 1. Let lhs be ? ResolveBinding(StringValue of BindingIdentifier, environment).
const lhs = Q(yield* ResolveBinding(StringValue(BindingIdentifier), environment, BindingIdentifier.strict));
// 2. Let A be ! ArrayCreate(0).
const A = X(ArrayCreate(0));
// 3. Let n be 0.
let n = 0;
// 4. Repeat,
while (true) {
let next: 'done' | Value = 'done';
// a. If iteratorRecord.[[Done]] is false, then
if (iteratorRecord.Done === Value.false) {
// i. Let next be ? IteratorStepValue(iteratorRecord).
next = Q(yield* IteratorStepValue(iteratorRecord));
}
if (next === 'done') {
// i. If environment is undefined, return ? PutValue(lhs, A).
if (environment === Value.undefined) {
return Q(yield* PutValue(lhs, A));
}
// ii. Return InitializeReferencedBinding(lhs, A).
return yield* InitializeReferencedBinding(lhs, A);
}
// f. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), next).
X(CreateDataPropertyOrThrow(A, X(ToString(F(n))), next));
// g. Set n to n + 1.
n += 1;
}
} else {
// 1. Let A be ! ArrayCreate(0).
const A = X(ArrayCreate(0));
// 2. Let n be 0.
let n = 0;
// 3. Repeat,
while (true) {
let next: 'done' | Value = 'done';
// a. If iteratorRecord.[[Done]] is false, then
if (iteratorRecord.Done === Value.false) {
// i. Let next be ? IteratorStepValue(iteratorRecord).
next = Q(yield* IteratorStepValue(iteratorRecord));
}
// b. If next is done, then
if (next === 'done') {
// i. Return the result of performing BindingInitialization of BindingPattern with A and environment as the arguments.
return yield* BindingInitialization(BindingPattern!, A, environment);
}
// f. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), next).
X(CreateDataPropertyOrThrow(A, X(ToString(F(n))), Q(next)));
// g. Set n to n + 1.
n += 1;
}
}
}
function* IteratorBindingInitialization_BindingPattern({ BindingPattern, Initializer }: ParseNode.BindingElement, iteratorRecord: IteratorRecord, environment: EnvironmentRecord | UndefinedValue) {
let v: Value = Value.undefined;
// 1. If iteratorRecord.[[Done]] is false, then
if (iteratorRecord.Done === Value.false) {
// a. Let next be ? IteratorStepValue(iteratorRecord).
const next = Q(yield* IteratorStepValue(iteratorRecord));
if (next !== 'done') {
v = next;
}
}
// 3. If Initializer is present and v is undefined, then
if (Initializer && v instanceof UndefinedValue) {
// a. Let defaultValue be the result of evaluating Initializer.
const defaultValue = Q(yield* Evaluate(Initializer));
// b. Set v to ? GetValue(defaultValue).
v = Q(yield* GetValue(defaultValue));
}
// 4. Return the result of performing BindingInitialization of BindingPattern with v and environment as the arguments.
return yield* BindingInitialization(BindingPattern, X(v), environment);
}
function* IteratorDestructuringAssignmentEvaluation(node: ParseNode.Elision, iteratorRecord: IteratorRecord): PlainEvaluator {
Assert(node.type === 'Elision');
// 1. If iteratorRecord.[[Done]] is false, then
if (iteratorRecord.Done === Value.false) {
// a. Perform ? IteratorStep(iteratorRecord).
Q(yield* IteratorStep(iteratorRecord));
}
// 2. Return NormalCompletion(empty).
return NormalCompletion(undefined);
}
export function* IteratorBindingInitialization_ArrayBindingPattern({ BindingElementList, BindingRestElement }: ParseNode.ArrayBindingPattern, iteratorRecord: IteratorRecord, environment: EnvironmentRecord | UndefinedValue): PlainEvaluator {
for (const BindingElement of BindingElementList) {
if (BindingElement.type === 'Elision') {
Q(yield* IteratorDestructuringAssignmentEvaluation(BindingElement, iteratorRecord));
} else {
// TODO
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Q(yield* IteratorBindingInitialization_BindingElement(BindingElement as any, iteratorRecord, environment));
}
}
if (BindingRestElement) {
return Q(yield* IteratorBindingInitialization_BindingRestElement(BindingRestElement, iteratorRecord, environment));
}
return NormalCompletion(undefined);
}