import { Evaluate, type ExpressionEvaluator } from '../evaluator.mts'; import { ReferenceRecord, Value, } from '../value.mts'; import { StringValue } from '../static-semantics/all.mts'; import { Q } from '../completion.mts'; import type { ParseNode } from '../parser/ParseNode.mts'; import { Assert, GetThisEnvironment, GetValue, FunctionEnvironmentRecord, } from '#self'; /** https://tc39.es/ecma262/#sec-makesuperpropertyreference */ function MakeSuperPropertyReference(actualThis: Value, propertyKey: Value, strict: boolean) { // 1. Let env be GetThisEnvironment(). const env = GetThisEnvironment(); // 2. Assert: env.HasSuperBinding() is true. Assert(env.HasSuperBinding() === Value.true); // 3. Assert: env is a Function Environment Record. Assert(env instanceof FunctionEnvironmentRecord); // 4. Let baseValue be ? env.GetSuperBase(). const baseValue = Q(env.GetSuperBase()); // 5. Return the Reference Record { [[Base]]: baseValue, [[ReferencedName]]: propertyKey, [[Strict]]: strict, [[ThisValue]]: actualThis }. return new ReferenceRecord({ Base: baseValue, ReferencedName: propertyKey, Strict: strict ? Value.true : Value.false, ThisValue: actualThis, }); } /** https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation */ // SuperProperty : // `super` `[` Expression `]` // `super` `.` IdentifierName export function* Evaluate_SuperProperty({ Expression, IdentifierName, strict }: ParseNode.SuperProperty): ExpressionEvaluator { // 1. Let env be GetThisEnvironment(). const env = GetThisEnvironment(); // 2. Let actualThis be ? env.GetThisBinding(). const actualThis = Q(env.GetThisBinding()); if (Expression) { // 3. Let propertyNameReference be the result of evaluating Expression. const propertyNameReference = Q(yield* Evaluate(Expression)); // 4. Let propertyNameReference be the result of evaluating Expression. const propertyNameValue = Q(yield* GetValue(propertyNameReference)); // 6. If the code matched by this SuperProperty is strict mode code, let strict be true; else let strict be false. // 7. Return ? MakeSuperPropertyReference(actualThis, propertyKey, strict). return Q(MakeSuperPropertyReference(actualThis, propertyNameValue, strict)); } else { // 3. Let propertyKey be StringValue of IdentifierName. const propertyKey = StringValue(IdentifierName!); // 4. const strict = SuperProperty.strict; // 5. Return ? MakeSuperPropertyReference(actualThis, propertyKey, strict). return Q(MakeSuperPropertyReference(actualThis, propertyKey, strict)); } }