internal IteratorInstance ConstructValueIterator(MapInstance map) { var instance = new IteratorInstance(Engine, map._map.Values) { _prototype = this }; return(instance); }
public ArraySpreadProtocol( Engine engine, ArrayInstance instance, IteratorInstance iterator, long startIndex) : base(engine, iterator, 0) { _instance = instance; _index = startIndex - 1; }
public ArrayProtocol( Engine engine, JsValue thisArg, ObjectInstance instance, IteratorInstance iterator, ICallable callable) : base(engine, iterator, 2) { _thisArg = thisArg; _instance = ArrayOperations.For(instance); _callable = callable; }
internal bool TryGetIterator(Realm realm, out IteratorInstance iterator, GeneratorKind hint = GeneratorKind.Sync, ICallable method = null) { var obj = TypeConverter.ToObject(realm, this); if (method is null) { if (hint == GeneratorKind.Async) { method = obj.GetMethod(GlobalSymbolRegistry.AsyncIterator); if (method is null) { var syncMethod = obj.GetMethod(GlobalSymbolRegistry.Iterator); var syncIteratorRecord = obj.GetIterator(realm, GeneratorKind.Sync, syncMethod); // TODO async CreateAsyncFromSyncIterator(syncIteratorRecord); ExceptionHelper.ThrowNotImplementedException("async"); } } else { method = obj.GetMethod(GlobalSymbolRegistry.Iterator); } } if (method is null) { iterator = null; return(false); } var iteratorResult = method.Call(obj, Arguments.Empty) as ObjectInstance; if (iteratorResult is null) { ExceptionHelper.ThrowTypeError(realm, "Result of the Symbol.iterator method is not an object"); } if (iteratorResult is IteratorInstance i) { iterator = i; } else { iterator = new IteratorInstance.ObjectIterator(iteratorResult); } return(true); }
/// <summary> /// https://tc39.es/ecma262/#sec-runtime-semantics-forin-div-ofheadevaluation-tdznames-expr-iterationkind /// </summary> private bool HeadEvaluation(EvaluationContext context, out IteratorInstance result) { var engine = context.Engine; var oldEnv = engine.ExecutionContext.LexicalEnvironment; var tdz = JintEnvironment.NewDeclarativeEnvironment(engine, oldEnv); if (_tdzNames != null) { var TDZEnvRec = tdz; foreach (var name in _tdzNames) { TDZEnvRec.CreateMutableBinding(name); } } engine.UpdateLexicalEnvironment(tdz); var exprValue = _right.GetValue(context).Value; engine.UpdateLexicalEnvironment(oldEnv); if (_iterationKind == IterationKind.Enumerate) { if (exprValue.IsNullOrUndefined()) { result = null; return(false); } var obj = TypeConverter.ToObject(engine.Realm, exprValue); result = new ObjectKeyVisitor(engine, obj); } else { result = exprValue as IteratorInstance ?? exprValue.GetIterator(engine.Realm); } return(true); }
/// <summary> /// https://tc39.es/ecma262/#sec-runtime-semantics-forin-div-ofbodyevaluation-lhs-stmt-iterator-lhskind-labelset /// </summary> private Completion BodyEvaluation( EvaluationContext context, JintExpression lhs, JintStatement stmt, IteratorInstance iteratorRecord, IterationKind iterationKind, LhsKind lhsKind, IteratorKind iteratorKind = IteratorKind.Sync) { var engine = context.Engine; var oldEnv = engine.ExecutionContext.LexicalEnvironment; var v = Undefined.Instance; var destructuring = _destructuring; string lhsName = null; var completionType = CompletionType.Normal; var close = false; try { while (true) { EnvironmentRecord iterationEnv = null; if (!iteratorRecord.TryIteratorStep(out var nextResult)) { close = true; return(new Completion(CompletionType.Normal, v, null, Location)); } if (iteratorKind == IteratorKind.Async) { // nextResult = await nextResult; ExceptionHelper.ThrowNotImplementedException("await"); } var nextValue = nextResult.Get(CommonProperties.Value); close = true; var lhsRef = new ExpressionResult(); if (lhsKind != LhsKind.LexicalBinding) { if (!destructuring) { lhsRef = lhs.Evaluate(context); } } else { iterationEnv = JintEnvironment.NewDeclarativeEnvironment(engine, oldEnv); if (_tdzNames != null) { BindingInstantiation(iterationEnv); } engine.UpdateLexicalEnvironment(iterationEnv); if (!destructuring) { var identifier = (Identifier)((VariableDeclaration)_leftNode).Declarations[0].Id; lhsName ??= identifier.Name; lhsRef = new ExpressionResult(ExpressionCompletionType.Normal, engine.ResolveBinding(lhsName), identifier.Location); } } if (context.DebugMode) { context.Engine.DebugHandler.OnStep(_leftNode); } var status = new Completion(); if (!destructuring) { if (lhsRef.IsAbrupt()) { close = true; status = new Completion(lhsRef); } else if (lhsKind == LhsKind.LexicalBinding) { ((Reference)lhsRef.Value).InitializeReferencedBinding(nextValue); } else { engine.PutValue((Reference)lhsRef.Value, nextValue); } } else { status = BindingPatternAssignmentExpression.ProcessPatterns( context, _assignmentPattern, nextValue, iterationEnv, checkObjectPatternPropertyReference: _lhsKind != LhsKind.VarBinding); if (lhsKind == LhsKind.Assignment) { // DestructuringAssignmentEvaluation of assignmentPattern using nextValue as the argument. } else if (lhsKind == LhsKind.VarBinding) { // BindingInitialization for lhs passing nextValue and undefined as the arguments. } else { // BindingInitialization for lhs passing nextValue and iterationEnv as arguments } } if (status.IsAbrupt()) { engine.UpdateLexicalEnvironment(oldEnv); if (_iterationKind == IterationKind.AsyncIterate) { iteratorRecord.Close(status.Type); return(status); } if (iterationKind == IterationKind.Enumerate) { return(status); } iteratorRecord.Close(status.Type); return(status); } var result = stmt.Execute(context); engine.UpdateLexicalEnvironment(oldEnv); if (!ReferenceEquals(result.Value, null)) { v = result.Value; } if (result.Type == CompletionType.Break && (result.Target == null || result.Target == _statement?.LabelSet?.Name)) { completionType = CompletionType.Normal; return(new Completion(CompletionType.Normal, v, null, Location)); } if (result.Type != CompletionType.Continue || (result.Target != null && result.Target != _statement?.LabelSet?.Name)) { completionType = result.Type; if (result.IsAbrupt()) { close = true; return(result); } } } } catch { completionType = CompletionType.Throw; throw; } finally { if (close) { try { iteratorRecord.Close(completionType); } catch { // if we already have and exception, use it if (completionType != CompletionType.Throw) { throw; } } } engine.UpdateLexicalEnvironment(oldEnv); } }
internal void GetValueAndCheckIterator(EvaluationContext context, out JsValue instance, out IteratorInstance iterator) { instance = _argument.GetValue(context).Value; if (instance is null || !instance.TryGetIterator(context.Engine.Realm, out iterator)) { iterator = null; ExceptionHelper.ThrowTypeError(context.Engine.Realm, _argumentName + " is not iterable"); } }