Clone engine262 in /engine262

This commit is contained in:
2020-09-07 10:19:00 +05:30
parent 7688de2e5c
commit 66c1aeb9e0
313 changed files with 46014 additions and 0 deletions
@@ -0,0 +1,211 @@
import { surroundingAgent } from '../engine.mjs';
import {
Q, X,
Await,
Completion,
EnsureCompletion,
NormalCompletion,
AbruptCompletion,
} from '../completion.mjs';
import { Evaluate } from '../evaluator.mjs';
import { Value, Type } from '../value.mjs';
import { resume, handleInResume } from '../helpers.mjs';
import {
Assert,
Call,
CreateBuiltinFunction,
CreateIterResultObject,
GetGeneratorKind,
NewPromiseCapability,
PerformPromiseThen,
PromiseResolve,
} from './all.mjs';
// This file covers abstract operations defined in
// 25.5 #sec-asyncgenerator-objects
// 25.5.3.1 #sec-asyncgeneratorrequest-records
class AsyncGeneratorRequestRecord {
constructor(completion, promiseCapability) {
this.Completion = completion;
this.Capability = promiseCapability;
}
}
// 25.5.3.2 #sec-asyncgeneratorstart
export function AsyncGeneratorStart(generator, generatorBody) {
// Assert: generator is an AsyncGenerator instance.
Assert(generator.AsyncGeneratorState === Value.undefined);
const genContext = surroundingAgent.runningExecutionContext;
genContext.Generator = generator;
genContext.codeEvaluationState = (function* resumer() {
const result = EnsureCompletion(yield* Evaluate(generatorBody));
// Assert: If we return here, the async generator either threw an exception or performed either an implicit or explicit return.
surroundingAgent.executionContextStack.pop(genContext);
generator.AsyncGeneratorState = 'completed';
let resultValue;
if (result instanceof NormalCompletion) {
resultValue = Value.undefined;
} else {
resultValue = result.Value;
if (result.Type !== 'return') {
return X(AsyncGeneratorReject(generator, resultValue));
}
}
return X(AsyncGeneratorResolve(generator, resultValue, Value.true));
}());
generator.AsyncGeneratorContext = genContext;
generator.AsyncGeneratorState = 'suspendedStart';
generator.AsyncGeneratorQueue = [];
return Value.undefined;
}
// 25.5.3.3 #sec-asyncgeneratorresolve
function AsyncGeneratorResolve(generator, value, done) {
// Assert: generator is an AsyncGenerator instance.
const queue = generator.AsyncGeneratorQueue;
Assert(queue.length > 0);
const next = queue.shift();
const promiseCapability = next.Capability;
const iteratorResult = X(CreateIterResultObject(value, done));
X(Call(promiseCapability.Resolve, Value.undefined, [iteratorResult]));
X(AsyncGeneratorResumeNext(generator));
return Value.undefined;
}
// 25.5.3.4 #sec-asyncgeneratorreject
function AsyncGeneratorReject(generator, exception) {
// Assert: generator is an AsyncGenerator instance.
const queue = generator.AsyncGeneratorQueue;
Assert(queue.length > 0);
const next = queue.shift();
const promiseCapability = next.Capability;
X(Call(promiseCapability.Reject, Value.undefined, [exception]));
X(AsyncGeneratorResumeNext(generator));
return Value.undefined;
}
// 25.5.3.5.1 #async-generator-resume-next-return-processor-fulfilled
function AsyncGeneratorResumeNextReturnProcessorFulfilledFunctions([value = Value.undefined]) {
const F = surroundingAgent.activeFunctionObject;
F.Generator.AsyncGeneratorState = 'completed';
return X(AsyncGeneratorResolve(F.Generator, value, Value.true));
}
// 25.5.3.5.2 #async-generator-resume-next-return-processor-rejected
function AsyncGeneratorResumeNextReturnProcessorRejectedFunctions([reason = Value.undefined]) {
const F = surroundingAgent.activeFunctionObject;
F.Generator.AsyncGeneratorState = 'completed';
return X(AsyncGeneratorReject(F.Generator, reason));
}
// 25.5.3.5 #sec-asyncgeneratorresumenext
function AsyncGeneratorResumeNext(generator) {
// Assert: generator is an AsyncGenerator instance.
let state = generator.AsyncGeneratorState;
Assert(state !== 'executing');
if (state === 'awaiting-return') {
return Value.undefined;
}
const queue = generator.AsyncGeneratorQueue;
if (queue.length === 0) {
return Value.undefined;
}
const next = queue[0];
Assert(next instanceof AsyncGeneratorRequestRecord);
const completion = next.Completion;
if (completion instanceof AbruptCompletion) {
if (state === 'suspendedStart') {
generator.AsyncGeneratorState = 'completed';
state = 'completed';
}
if (state === 'completed') {
if (completion.Type === 'return') {
generator.AsyncGeneratorState = 'awaiting-return';
const promise = Q(PromiseResolve(surroundingAgent.intrinsic('%Promise%'), completion.Value));
const stepsFulfilled = AsyncGeneratorResumeNextReturnProcessorFulfilledFunctions;
const onFulfilled = X(CreateBuiltinFunction(stepsFulfilled, ['Generator']));
onFulfilled.Generator = generator;
const stepsRejected = AsyncGeneratorResumeNextReturnProcessorRejectedFunctions;
const onRejected = X(CreateBuiltinFunction(stepsRejected, ['Generator']));
onRejected.Generator = generator;
X(PerformPromiseThen(promise, onFulfilled, onRejected));
return Value.undefined;
} else {
Assert(completion.Type === 'throw');
X(AsyncGeneratorReject(generator, completion.Value));
return Value.undefined;
}
}
} else if (state === 'completed') {
return X(AsyncGeneratorResolve(generator, Value.undefined, Value.true));
}
Assert(state === 'suspendedStart' || state === 'suspendedYield');
const genContext = generator.AsyncGeneratorContext;
const callerContext = surroundingAgent.runningExecutionContext;
// Suspend callerContext
generator.AsyncGeneratorState = 'executing';
surroundingAgent.executionContextStack.push(genContext);
const result = resume(genContext, completion);
Assert(!(result instanceof AbruptCompletion));
Assert(surroundingAgent.runningExecutionContext === callerContext);
return Value.undefined;
}
// 25.5.3.6 #sec-asyncgeneratorenqueue
export function AsyncGeneratorEnqueue(generator, completion) {
Assert(completion instanceof Completion);
const promiseCapability = X(NewPromiseCapability(surroundingAgent.intrinsic('%Promise%')));
if (Type(generator) !== 'Object' || !('AsyncGeneratorState' in generator)) {
const badGeneratorError = surroundingAgent.Throw('TypeError', 'NotATypeObject', 'AsyncGenerator', generator).Value;
X(Call(promiseCapability.Reject, Value.undefined, [badGeneratorError]));
return promiseCapability.Promise;
}
const queue = generator.AsyncGeneratorQueue;
const request = new AsyncGeneratorRequestRecord(completion, promiseCapability);
queue.push(request);
const state = generator.AsyncGeneratorState;
if (state !== 'executing') {
X(AsyncGeneratorResumeNext(generator));
}
return promiseCapability.Promise;
}
// #sec-asyncgeneratoryield
export function* AsyncGeneratorYield(value) {
// 1. Let genContext be the running execution context.
const genContext = surroundingAgent.runningExecutionContext;
// 2. Assert: genContext is the execution context of a generator.
Assert(genContext.Generator !== Value.undefined);
// 3. Let generator be the value of the Generator component of genContext.
const generator = genContext.Generator;
// 4. Assert: GetGeneratorKind() is async.
Assert(GetGeneratorKind() === 'async');
// 5. Set value to ? Await(value).
value = Q(yield* Await(value));
// 6. Set generator.[[AsyncGeneratorState]] to suspendedYield.
generator.AsyncGeneratorState = 'suspendedYield';
// 7. Remove genContext from the execution context stack and restore the execution context that is at the top of the execution context stack as the running execution context.
surroundingAgent.executionContextStack.pop(genContext);
// 8. Set the code evaluation state of genContext such that when evaluation is resumed with a Completion resumptionValue the following steps will be performed:
const resumptionValue = EnsureCompletion(yield handleInResume(AsyncGeneratorResolve, generator, value, Value.false));
// a. If resumptionValue.[[Type]] is not return, return Completion(resumptionValue).
if (resumptionValue.Type !== 'return') {
return Completion(resumptionValue);
}
// b. Let awaited be Await(resumptionValue.[[Value]]).
const awaited = EnsureCompletion(yield* Await(resumptionValue.Value));
// c. If awaited.[[Type]] is throw, return Completion(awaited).
if (awaited.Type === 'Throw') {
return Completion(awaited);
}
// d. Assert: awaited.[[Type]] is normal.
Assert(awaited.Type === 'normal');
// e. Return Completion { [[Type]]: return, [[Value]]: awaited.[[Value]], [[Target]]: empty }.
return new Completion({ Type: 'return', Value: awaited.Value, Target: undefined });
// f. NOTE: When one of the above steps returns, it returns to the evaluation of the YieldExpression production that originally called this abstract operation.
// 9. Return ! AsyncGeneratorResolve(generator, value, false).
// 10. NOTE: This returns to the evaluation of the operation that had most previously resumed evaluation of genContext.
}