protected override Completion ExecuteInternal() { var b = _block.Execute(); if (b.Type == CompletionType.Throw) { // execute catch if (_catch != null) { var c = b.Value; var oldEnv = _engine.ExecutionContext.LexicalEnvironment; var catchEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv); var catchEnvRecord = (DeclarativeEnvironmentRecord)catchEnv._record; catchEnvRecord.CreateMutableBindingAndInitialize(_catchParamName, canBeDeleted: false, c); _engine.UpdateLexicalEnvironment(catchEnv); b = _catch.Execute(); _engine.UpdateLexicalEnvironment(oldEnv); } } if (_finalizer != null) { var f = _finalizer.Execute(); if (f.Type == CompletionType.Normal) { return(b); } return(f); } return(b); }
protected override Completion ExecuteInternal(EvaluationContext context) { var jsValue = _object.GetValue(context).Value; var engine = context.Engine; var obj = TypeConverter.ToObject(engine.Realm, jsValue); var oldEnv = engine.ExecutionContext.LexicalEnvironment; var newEnv = JintEnvironment.NewObjectEnvironment(engine, obj, oldEnv, provideThis: true, withEnvironment: true); engine.UpdateLexicalEnvironment(newEnv); Completion c; try { c = _body.Execute(context); } catch (JavaScriptException e) { c = new Completion(CompletionType.Throw, e.Error, _statement.Location); } finally { engine.UpdateLexicalEnvironment(oldEnv); } return(c); }
protected override Completion ExecuteInternal() { JsValue v = Undefined.Instance; bool iterating; do { var completion = _body.Execute(); if (!ReferenceEquals(completion.Value, null)) { v = completion.Value; } if (completion.Type != CompletionType.Continue || completion.Identifier != _labelSetName) { if (completion.Type == CompletionType.Break && (completion.Identifier == null || completion.Identifier == _labelSetName)) { return(new Completion(CompletionType.Normal, v, null, Location)); } if (completion.Type != CompletionType.Normal) { return(completion); } } iterating = TypeConverter.ToBoolean(_test.GetValue()); } while (iterating); return(new Completion(CompletionType.Normal, v, null, Location)); }
/// <summary> /// https://tc39.es/ecma262/#sec-forbodyevaluation /// </summary> private Completion ForBodyEvaluation(EvaluationContext context) { var v = Undefined.Instance; if (_shouldCreatePerIterationEnvironment) { CreatePerIterationEnvironment(context); } while (true) { if (_test != null) { if (context.DebugMode) { context.Engine.DebugHandler.OnStep(_test._expression); } if (!TypeConverter.ToBoolean(_test.GetValue(context).Value)) { return(NormalCompletion(v)); } } var result = _body.Execute(context); if (!ReferenceEquals(result.Value, null)) { v = result.Value; } if (result.Type == CompletionType.Break && (result.Target == null || result.Target == _statement?.LabelSet?.Name)) { return(NormalCompletion(result.Value)); } if (result.Type != CompletionType.Continue || (result.Target != null && result.Target != _statement?.LabelSet?.Name)) { if (result.Type != CompletionType.Normal) { return(result); } } if (_shouldCreatePerIterationEnvironment) { CreatePerIterationEnvironment(context); } if (_increment != null) { if (context.DebugMode) { context.Engine.DebugHandler.OnStep(_increment._expression); } _increment.GetValue(context); } } }
protected override Completion ExecuteInternal() { // TODO: Esprima added Statement.Label, maybe not necessary as this line is finding the // containing label and could keep a table per program with all the labels // labeledStatement.Body.LabelSet = labeledStatement.Label; var result = _body.Execute(); if (result.Type == CompletionType.Break && result.Identifier == _labelName) { var value = result.Value; return(new Completion(CompletionType.Normal, value, null, Location)); } return(result); }
/// <summary> /// https://tc39.es/ecma262/#sec-forbodyevaluation /// </summary> private Completion ForBodyEvaluation() { var v = Undefined.Instance; if (_shouldCreatePerIterationEnvironment) { CreatePerIterationEnvironment(); } while (true) { if (_test != null) { if (!TypeConverter.ToBoolean(_test.GetValue())) { return(new Completion(CompletionType.Normal, v, null, Location)); } } var result = _body.Execute(); 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, result.Value, null, Location)); } if (result.Type != CompletionType.Continue || (result.Identifier != null && result.Identifier != _statement?.LabelSet?.Name)) { if (result.Type != CompletionType.Normal) { return(result); } } if (_shouldCreatePerIterationEnvironment) { CreatePerIterationEnvironment(); } _increment?.GetValue(); } }
protected override Completion ExecuteInternal(EvaluationContext context) { Completion result; if (TypeConverter.ToBoolean(_test.GetValue(context).Value)) { result = _statementConsequent.Execute(context); } else if (_alternate != null) { result = _alternate.Execute(context); } else { return(new Completion(CompletionType.Normal, null, Location)); } return(result); }
protected override Completion ExecuteInternal(EvaluationContext context) { var v = Undefined.Instance; while (true) { if (context.DebugMode) { context.Engine.DebugHandler.OnStep(_test._expression); } var jsValue = _test.GetValue(context).Value; if (!TypeConverter.ToBoolean(jsValue)) { return(new Completion(CompletionType.Normal, v, null, Location)); } var completion = _body.Execute(context); if (!ReferenceEquals(completion.Value, null)) { v = completion.Value; } if (completion.Type != CompletionType.Continue || completion.Target != _labelSetName) { if (completion.Type == CompletionType.Break && (completion.Target == null || completion.Target == _labelSetName)) { return(new Completion(CompletionType.Normal, v, null, Location)); } if (completion.Type != CompletionType.Normal) { return(completion); } } } }
/// <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); } }
/// <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); } }
protected override Completion ExecuteInternal(EvaluationContext context) { var engine = context.Engine; int callStackSizeBeforeExecution = engine.CallStack.Count; var b = _block.Execute(context); if (b.Type == CompletionType.Throw) { // initialize lazily if (_statement.Handler is not null && _catch is null) { _catch = Build(_statement.Handler.Body); } // execute catch if (_statement.Handler is not null) { // Quick-patch for call stack not being unwinded when an exception is caught. // Ideally, this should instead be solved by always popping the stack when returning // from a call, regardless of whether it throws (i.e. CallStack.Pop() in finally clause // in Engine.Call/Engine.Construct - however, that method currently breaks stack traces // in error messages. while (callStackSizeBeforeExecution < engine.CallStack.Count) { engine.CallStack.Pop(); } // https://tc39.es/ecma262/#sec-runtime-semantics-catchclauseevaluation var thrownValue = b.Value; var oldEnv = engine.ExecutionContext.LexicalEnvironment; var catchEnv = JintEnvironment.NewDeclarativeEnvironment(engine, oldEnv, catchEnvironment: true); var boundNames = new List <string>(); _statement.Handler.Param.GetBoundNames(boundNames); foreach (var argName in boundNames) { catchEnv.CreateMutableBinding(argName, false); } engine.UpdateLexicalEnvironment(catchEnv); var catchParam = _statement.Handler?.Param; catchParam.BindingInitialization(context, thrownValue, catchEnv); b = _catch.Execute(context); engine.UpdateLexicalEnvironment(oldEnv); } } if (_finalizer != null) { var f = _finalizer.Execute(context); if (f.Type == CompletionType.Normal) { return(b); } return(f.UpdateEmpty(Undefined.Instance)); } return(b.UpdateEmpty(Undefined.Instance)); }