-
-
Notifications
You must be signed in to change notification settings - Fork 560
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
775 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
using Jint.Native.Function; | ||
using Jint.Native.Iterator; | ||
using Jint.Native.Object; | ||
using Jint.Runtime; | ||
using Jint.Runtime.Descriptors; | ||
|
||
namespace Jint.Native.Generator; | ||
|
||
/// <summary> | ||
/// https://tc39.es/ecma262/#sec-generatorfunction-constructor | ||
/// </summary> | ||
internal sealed class GeneratorFunctionConstructor : FunctionInstance, IConstructor | ||
{ | ||
private static readonly JsString _functionName = new("GeneratorFunction"); | ||
|
||
internal GeneratorFunctionConstructor( | ||
Engine engine, | ||
Realm realm, | ||
FunctionPrototype prototype, | ||
IteratorPrototype iteratorPrototype) | ||
: base(engine, realm, _functionName) | ||
{ | ||
PrototypeObject = new GeneratorFunctionPrototype(engine, this, prototype, iteratorPrototype); | ||
_prototype = PrototypeObject; | ||
_prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden); | ||
_length = new PropertyDescriptor(JsNumber.PositiveOne, PropertyFlag.Configurable); | ||
} | ||
|
||
public GeneratorFunctionPrototype PrototypeObject { get; } | ||
|
||
protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments) | ||
{ | ||
return Construct(arguments, thisObject); | ||
} | ||
|
||
public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget) | ||
{ | ||
var function = _realm.Intrinsics.Function.CreateDynamicFunction( | ||
this, | ||
newTarget, | ||
FunctionKind.Generator, | ||
arguments); | ||
|
||
return function; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
using Jint.Collections; | ||
using Jint.Native.Function; | ||
using Jint.Native.Iterator; | ||
using Jint.Native.Object; | ||
using Jint.Native.Symbol; | ||
using Jint.Runtime.Descriptors; | ||
|
||
namespace Jint.Native.Generator; | ||
|
||
/// <summary> | ||
/// https://tc39.es/ecma262/#sec-properties-of-the-generatorfunction-prototype-object | ||
/// </summary> | ||
internal sealed class GeneratorFunctionPrototype : ObjectInstance | ||
{ | ||
private readonly GeneratorFunctionConstructor? _constructor; | ||
|
||
internal GeneratorFunctionPrototype( | ||
Engine engine, | ||
GeneratorFunctionConstructor constructor, | ||
FunctionPrototype prototype, | ||
IteratorPrototype iteratorPrototype) : base(engine) | ||
{ | ||
_constructor = constructor; | ||
_prototype = prototype; | ||
PrototypeObject = new GeneratorPrototype(engine, this, iteratorPrototype); | ||
} | ||
|
||
public GeneratorPrototype PrototypeObject { get; } | ||
|
||
protected override void Initialize() | ||
{ | ||
var properties = new PropertyDictionary(2, checkExistingKeys: false) | ||
{ | ||
["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.Configurable), | ||
["prototype"] = new PropertyDescriptor(PrototypeObject, PropertyFlag.Configurable) | ||
}; | ||
SetProperties(properties); | ||
var symbols = new SymbolDictionary(1) | ||
{ | ||
[GlobalSymbolRegistry.ToStringTag] = new PropertyDescriptor("GeneratorFunction", PropertyFlag.Configurable) | ||
}; | ||
SetSymbols(symbols); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
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 = null; | ||
private JintStatementList _generatorBody = null!; | ||
|
||
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 JsValue GeneratorResume(JsValue value, JsValue? generatorBrand) | ||
{ | ||
var state = GeneratorValidate(generatorBrand); | ||
if (state == GeneratorState.Completed) | ||
{ | ||
return new IteratorResult(_engine, value, JsBoolean.True); | ||
} | ||
|
||
var genContext = _generatorContext; | ||
var methodContext = _engine.ExecutionContext; | ||
|
||
// 6. Suspend methodContext. | ||
|
||
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); | ||
} | ||
|
||
return abruptCompletion.Value; | ||
} | ||
|
||
var genContext = _generatorContext; | ||
var methodContext = _engine.ExecutionContext; | ||
|
||
// Suspend methodContext. | ||
|
||
return ResumeExecution(genContext, new EvaluationContext(_engine, abruptCompletion)); | ||
} | ||
|
||
private JsValue 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; | ||
var value = context.ResumedCompletion.GetValueOrDefault(); | ||
resultValue = IteratorInstance.ValueIteratorPosition.Done(_engine, value); | ||
} | ||
else if (result.Type == CompletionType.Return) | ||
{ | ||
resultValue = new IteratorInstance.ValueIteratorPosition(_engine, result.Value, false); | ||
if (_generatorBody.Completed) | ||
{ | ||
_generatorState = GeneratorState.Completed; | ||
} | ||
} | ||
|
||
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,8 @@ | ||
namespace Jint.Native.Generator | ||
namespace Jint.Native.Generator; | ||
|
||
internal enum GeneratorKind | ||
{ | ||
internal enum GeneratorKind | ||
{ | ||
NonGenerator, | ||
Sync, | ||
Async | ||
} | ||
} | ||
NonGenerator, | ||
Sync, | ||
Async | ||
} |
Oops, something went wrong.