public JintForInForOfStatement(ForOfStatement statement) : base(statement) { _leftNode = statement.Left; _rightExpression = statement.Right; _forBody = statement.Body; _iterationKind = IterationKind.Iterate; }
public JintForInForOfStatement( Engine engine, ForOfStatement statement) : base(engine, statement) { _initialized = false; _leftNode = statement.Left; _rightExpression = statement.Right; _forBody = statement.Body; _iterationKind = IterationKind.Iterate; }
/// <summary> /// https://tc39.es/ecma262/#sec-runtime-semantics-forin-div-ofbodyevaluation-lhs-stmt-iterator-lhskind-labelset /// </summary> private Completion BodyEvaluation( JintExpression lhs, JintStatement stmt, IIterator iteratorRecord, IterationKind iterationKind, LhsKind lhsKind, IteratorKind iteratorKind = IteratorKind.Sync) { 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) { LexicalEnvironment 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; } var nextValue = nextResult.Get(CommonProperties.Value); close = true; Reference lhsRef = null; if (lhsKind != LhsKind.LexicalBinding) { if (!destructuring) { lhsRef = (Reference)lhs.Evaluate(); } } else { iterationEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv); if (_tdzNames != null) { BindingInstantiation(iterationEnv); } _engine.UpdateLexicalEnvironment(iterationEnv); if (!destructuring) { if (lhsName == null) { lhsName = ((Identifier)((VariableDeclaration)_leftNode).Declarations[0].Id).Name; } lhsRef = _engine.ResolveBinding(lhsName); } } if (!destructuring) { // If lhsRef is an abrupt completion, then // Let status be lhsRef. if (lhsKind == LhsKind.LexicalBinding) { lhsRef.InitializeReferencedBinding(nextValue); } else { _engine.PutValue(lhsRef, nextValue); } } else { BindingPatternAssignmentExpression.ProcessPatterns( _engine, _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 } } var result = stmt.Execute(); _engine.UpdateLexicalEnvironment(oldEnv); if (!ReferenceEquals(result.Value, null)) { v = result.Value; } if (result.Type == CompletionType.Break && (result.Identifier == null || result.Identifier == _statement?.LabelSet?.Name)) { return(new Completion(CompletionType.Normal, v, null, Location)); } if (result.Type != CompletionType.Continue || (result.Identifier != null && result.Identifier != _statement?.LabelSet?.Name)) { if (result.Type != CompletionType.Normal) { return(result); } } } } catch { completionType = CompletionType.Throw; throw; } finally { if (close) { iteratorRecord.Close(completionType); } _engine.UpdateLexicalEnvironment(oldEnv); } }
protected Completion ForInOfBodyEvaluation(IForInOfInitializer lhs, Statement stmt, IteratorRecord iteratorRecord, IterationKind iterationKind, LHSKind lhsKind, List <string> labelSet, IteratorKind?iteratorKindNullable = null) { var iteratorKind = iteratorKindNullable.GetValueOrDefault(IteratorKind.Sync); var oldEnv = Interpreter.Instance().RunningExecutionContext().LexicalEnvironment; IValue V = UndefinedValue.Instance; // TODO assuming destructuring is false bool destructuring = false; while (true) { var nextResultComp = iteratorRecord.NextMethod.Call(iteratorRecord.Iterator); if (nextResultComp.IsAbrupt()) { return(nextResultComp); } var nextResult = nextResultComp.value; if (iteratorKind == IteratorKind.Async) { throw new NotImplementedException("async"); } if (!(nextResult is Object nextResultObject)) { return(Completion.ThrowTypeError("iterator next did not return an object.")); } var doneComp = IteratorRecord.IteratorComplete(nextResultObject); if (doneComp.IsAbrupt()) { return(doneComp); } var done = (doneComp.value as BooleanValue) !.boolean; if (done) { return(Completion.NormalCompletion(V)); } var nextValueComp = IteratorRecord.IteratorValue(nextResultObject); if (nextValueComp.IsAbrupt()) { return(nextValueComp); } var nextValue = nextValueComp.value !; Completion lhsRef = Completion.NormalCompletion(); if (lhsKind == LHSKind.Assignment || lhsKind == LHSKind.VarBinding) { if (!destructuring) { lhsRef = lhs.Evaluate(Interpreter.Instance()); } } else { if (lhsKind != LHSKind.LexicalBinding) { throw new InvalidOperationException("Spec 13.7.5.13 step 6hi"); } if (!(lhs is ForDeclaration forDeclaration)) { throw new InvalidOperationException("Spec 13.7.5.13 step 6hii"); } var iterationEnv = oldEnv.NewDeclarativeEnvironment(); forDeclaration.BindingInstantiation(iterationEnv); Interpreter.Instance().RunningExecutionContext().LexicalEnvironment = iterationEnv; if (!destructuring) { lhsRef = Interpreter.Instance().ResolveBinding(forDeclaration.name, IsStrictMode); } } Completion status; if (!destructuring) { if (lhsRef.IsAbrupt()) { status = lhsRef; } else if (lhsKind == LHSKind.LexicalBinding) { status = (lhsRef.value as ReferenceValue) !.InitializeReferencedBinding(nextValue); } else { status = (lhsRef.value as ReferenceValue) !.PutValue(nextValue); } } else { throw new NotImplementedException("destructuring"); } if (status.IsAbrupt()) { Interpreter.Instance().RunningExecutionContext().LexicalEnvironment = oldEnv; if (iteratorKind == IteratorKind.Async) { throw new NotImplementedException("async"); } if (iterationKind == IterationKind.Enumerate) { return(status); } else { return(iteratorRecord.IteratorClose(status)); } } var result = stmt.Evaluate(Interpreter.Instance()); Interpreter.Instance().RunningExecutionContext().LexicalEnvironment = oldEnv; if (!LoopContinues(result, labelSet)) { if (iterationKind == IterationKind.Enumerate) { return(result.UpdateEmpty(V)); } else { status = result.UpdateEmpty(V); if (iteratorKind == IteratorKind.Async) { throw new NotImplementedException("async"); } return(iteratorRecord.IteratorClose(status)); } } if (result.value != null) { V = result.value; } } }
protected static CompletionOr <IteratorRecord?> ForInOfHeadEvaluation(IEnumerable <string> TDZNames, AbstractExpression expr, IterationKind iterationKind) { var oldEnv = Interpreter.Instance().RunningExecutionContext().LexicalEnvironment; if (TDZNames.Any()) { if (TDZNames.Distinct().Count() < TDZNames.Count()) { throw new InvalidOperationException("Spec 13.7.5.12 step 2a"); } var TDZ = oldEnv.NewDeclarativeEnvironment(); var TDZEnvRec = TDZ.EnvironmentRecord; foreach (var name in TDZNames) { TDZEnvRec.CreateMutableBinding(name, false); } Interpreter.Instance().RunningExecutionContext().LexicalEnvironment = TDZ; } var exprRef = expr.Evaluate(Interpreter.Instance()); Interpreter.Instance().RunningExecutionContext().LexicalEnvironment = oldEnv; var exprValue = exprRef.GetValue(); if (exprValue.IsAbrupt()) { return(exprValue.WithEmpty <IteratorRecord?>()); } if (iterationKind == IterationKind.Enumerate) { if (exprValue.value == UndefinedValue.Instance || exprValue.value == NullValue.Instance) { return(new Completion(CompletionType.Break, null, null).WithEmpty <IteratorRecord?>()); } var obj = exprValue.value !.ToObject().value as Object; return(obj !.EnumerateObjectProperties()); } else { return((exprValue.value !.ToObject().value as Object) !.GetIterator()); } }
/// <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); } }