123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- using Jint.Native.Iterator;
- using Jint.Native.Object;
- using Jint.Runtime;
- using Jint.Runtime.Environments;
- using Jint.Runtime.Interpreter;
- namespace Jint.Native.Generator;
- /// <summary>
- /// https://tc39.es/ecma262/#sec-properties-of-generator-instances
- /// </summary>
- internal sealed class GeneratorInstance : ObjectInstance
- {
- internal GeneratorState _generatorState;
- private ExecutionContext _generatorContext;
- private readonly JsValue? _generatorBrand;
- private JintStatementList _generatorBody = null!;
- public JsValue? _nextValue;
- public JsValue? _error;
- public GeneratorInstance(Engine engine) : base(engine)
- {
- }
- /// <summary>
- /// https://tc39.es/ecma262/#sec-generatorstart
- /// </summary>
- public JsValue GeneratorStart(JintStatementList generatorBody)
- {
- var genContext = _engine.UpdateGenerator(this);
- _generatorBody = generatorBody;
- _generatorContext = genContext;
- _generatorState = GeneratorState.SuspendedStart;
- return Undefined;
- }
- /// <summary>
- /// https://tc39.es/ecma262/#sec-generatorresume
- /// </summary>
- public ObjectInstance GeneratorResume(JsValue? value, JsValue? generatorBrand)
- {
- var state = GeneratorValidate(generatorBrand);
- if (state == GeneratorState.Completed)
- {
- return new IteratorResult(_engine, Undefined, JsBoolean.True);
- }
- var genContext = _generatorContext;
- var methodContext = _engine.ExecutionContext;
- // 6. Suspend methodContext.
- _nextValue = value;
- var context = _engine._activeEvaluationContext;
- return ResumeExecution(genContext, context!);
- }
- /// <summary>
- /// https://tc39.es/ecma262/#sec-generatorresumeabrupt
- /// </summary>
- public JsValue GeneratorResumeAbrupt(in Completion abruptCompletion, JsValue? generatorBrand)
- {
- var state = GeneratorValidate(generatorBrand);
- if (state == GeneratorState.SuspendedStart)
- {
- _generatorState = GeneratorState.Completed;
- state = GeneratorState.Completed;
- }
- if (state == GeneratorState.Completed)
- {
- if (abruptCompletion.Type == CompletionType.Return)
- {
- return new IteratorResult(_engine, abruptCompletion.Value, JsBoolean.True);
- }
- ExceptionHelper.ThrowJavaScriptException(_engine, abruptCompletion.Value, (SourceLocation) default);
- }
- var genContext = _generatorContext;
- var methodContext = _engine.ExecutionContext;
- // Suspend methodContext
- _nextValue = abruptCompletion.Type == CompletionType.Return
- ? abruptCompletion.Value
- : null;
- _error = abruptCompletion.Type == CompletionType.Throw
- ? abruptCompletion.Value
- : null;
- if (_error is not null)
- {
- ExceptionHelper.ThrowJavaScriptException(_engine, _error, (SourceLocation) default);
- }
- return ResumeExecution(genContext, new EvaluationContext(_engine));
- }
- private ObjectInstance ResumeExecution(ExecutionContext genContext, EvaluationContext context)
- {
- _generatorState = GeneratorState.Executing;
- _engine.EnterExecutionContext(genContext);
- var result = _generatorBody.Execute(context);
- _engine.LeaveExecutionContext();
- ObjectInstance? resultValue = null;
- if (result.Type == CompletionType.Normal)
- {
- _generatorState = GeneratorState.Completed;
- resultValue = IteratorResult.CreateValueIteratorPosition(_engine, result.Value, done: JsBoolean.True);
- }
- else if (result.Type == CompletionType.Return)
- {
- if (_generatorState == GeneratorState.SuspendedYield)
- {
- resultValue = IteratorResult.CreateValueIteratorPosition(_engine, result.Value, done: JsBoolean.False);
- }
- else
- {
- _generatorState = GeneratorState.Completed;
- resultValue = IteratorResult.CreateValueIteratorPosition(_engine, result.Value, done: JsBoolean.True);
- }
- }
- if (result.Type == CompletionType.Throw)
- {
- _generatorState = GeneratorState.Completed;
- ExceptionHelper.ThrowJavaScriptException(_engine, result.Value, result);
- }
- return resultValue!;
- }
- private GeneratorState GeneratorValidate(JsValue? generatorBrand)
- {
- if (!ReferenceEquals(generatorBrand, _generatorBrand))
- {
- ExceptionHelper.ThrowTypeError(_engine.Realm, "Generator brand differs from attached brand");
- }
- if (_generatorState == GeneratorState.Executing)
- {
- ExceptionHelper.ThrowTypeError(_engine.Realm, "Generator state was unexpectedly executing");
- }
- return _generatorState;
- }
- }
|