Пример #1
0
        protected override Completion ExecuteInternal(EvaluationContext context)
        {
            EnvironmentRecord oldEnv  = null;
            EnvironmentRecord loopEnv = null;
            var engine = context.Engine;

            if (_boundNames != null)
            {
                oldEnv  = engine.ExecutionContext.LexicalEnvironment;
                loopEnv = JintEnvironment.NewDeclarativeEnvironment(engine, oldEnv);
                var loopEnvRec = loopEnv;
                var kind       = _initStatement._statement.Kind;
                for (var i = 0; i < _boundNames.Count; i++)
                {
                    var name = _boundNames[i];
                    if (kind == VariableDeclarationKind.Const)
                    {
                        loopEnvRec.CreateImmutableBinding(name, true);
                    }
                    else
                    {
                        loopEnvRec.CreateMutableBinding(name, false);
                    }
                }

                engine.UpdateLexicalEnvironment(loopEnv);
            }

            try
            {
                if (_initExpression != null)
                {
                    _initExpression?.GetValue(context);
                }
                else
                {
                    _initStatement?.Execute(context);
                }

                return(ForBodyEvaluation(context));
            }
            finally
            {
                if (oldEnv is not null)
                {
                    engine.UpdateLexicalEnvironment(oldEnv);
                }
            }
        }
Пример #2
0
        public override Completion GetValue(EvaluationContext context)
        {
            var engine  = context.Engine;
            var funcEnv = JintEnvironment.NewDeclarativeEnvironment(engine, engine.ExecutionContext.LexicalEnvironment);

            var closure = new ScriptFunctionInstance(
                engine,
                _function,
                funcEnv,
                _function.ThisMode);

            closure.MakeConstructor();

            if (_function.Name != null)
            {
                funcEnv.CreateMutableBindingAndInitialize(_function.Name, canBeDeleted: false, closure);
            }

            return(Completion.Normal(closure, _expression.Location));
        }
Пример #3
0
        protected override Completion ExecuteInternal(EvaluationContext context)
        {
            EnvironmentRecord oldEnv = null;
            var engine = context.Engine;

            if (_lexicalDeclarations != null)
            {
                oldEnv = engine.ExecutionContext.LexicalEnvironment;
                var blockEnv = JintEnvironment.NewDeclarativeEnvironment(engine, engine.ExecutionContext.LexicalEnvironment);
                JintStatementList.BlockDeclarationInstantiation(engine, blockEnv, _lexicalDeclarations);
                engine.UpdateLexicalEnvironment(blockEnv);
            }

            var blockValue = _statementList.Execute(context);

            if (oldEnv is not null)
            {
                engine.UpdateLexicalEnvironment(oldEnv);
            }

            return(blockValue);
        }
Пример #4
0
        private void CreatePerIterationEnvironment(EvaluationContext context)
        {
            if (_boundNames == null || _boundNames.Count == 0)
            {
                return;
            }

            var engine              = context.Engine;
            var lastIterationEnv    = engine.ExecutionContext.LexicalEnvironment;
            var lastIterationEnvRec = lastIterationEnv;
            var outer            = lastIterationEnv._outerEnv;
            var thisIterationEnv = JintEnvironment.NewDeclarativeEnvironment(engine, outer);

            for (var j = 0; j < _boundNames.Count; j++)
            {
                var bn        = _boundNames[j];
                var lastValue = lastIterationEnvRec.GetBindingValue(bn, true);
                thisIterationEnv.CreateMutableBindingAndInitialize(bn, false, lastValue);
            }

            engine.UpdateLexicalEnvironment(thisIterationEnv);
        }
Пример #5
0
        /// <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);
        }
Пример #6
0
        public Completion Execute(EvaluationContext context, JsValue input)
        {
            if (!_initialized)
            {
                Initialize(context);
                _initialized = true;
            }

            var            engine      = context.Engine;
            JsValue        v           = Undefined.Instance;
            Location       l           = context.LastSyntaxNode.Location;
            JintSwitchCase defaultCase = null;
            bool           hit         = false;

            for (var i = 0; i < (uint)_jintSwitchBlock.Length; i++)
            {
                var clause = _jintSwitchBlock[i];

                EnvironmentRecord oldEnv = null;
                if (clause.LexicalDeclarations != null)
                {
                    oldEnv = engine.ExecutionContext.LexicalEnvironment;
                    var blockEnv = JintEnvironment.NewDeclarativeEnvironment(engine, oldEnv);
                    JintStatementList.BlockDeclarationInstantiation(engine, blockEnv, clause.LexicalDeclarations);
                    engine.UpdateLexicalEnvironment(blockEnv);
                }

                if (clause.Test == null)
                {
                    defaultCase = clause;
                }
                else
                {
                    var clauseSelector = clause.Test.GetValue(context).Value;
                    if (clauseSelector == input)
                    {
                        hit = true;
                    }
                }

                if (hit && clause.Consequent != null)
                {
                    var r = clause.Consequent.Execute(context);

                    if (oldEnv is not null)
                    {
                        engine.UpdateLexicalEnvironment(oldEnv);
                    }

                    if (r.Type != CompletionType.Normal)
                    {
                        return(r);
                    }

                    l = r.Location;
                    v = r.Value ?? Undefined.Instance;
                }
            }

            // do we need to execute the default case ?
            if (hit == false && defaultCase != null)
            {
                EnvironmentRecord oldEnv = null;
                if (defaultCase.LexicalDeclarations != null)
                {
                    oldEnv = engine.ExecutionContext.LexicalEnvironment;
                    var blockEnv = JintEnvironment.NewDeclarativeEnvironment(engine, oldEnv);
                    JintStatementList.BlockDeclarationInstantiation(engine, blockEnv, defaultCase.LexicalDeclarations);
                    engine.UpdateLexicalEnvironment(blockEnv);
                }

                var r = defaultCase.Consequent.Execute(context);

                if (oldEnv is not null)
                {
                    engine.UpdateLexicalEnvironment(oldEnv);
                }
                if (r.Type != CompletionType.Normal)
                {
                    return(r);
                }

                l = r.Location;
                v = r.Value ?? Undefined.Instance;
            }

            return(new Completion(CompletionType.Normal, v, null, l));
        }
Пример #7
0
        /// <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);
            }
        }
Пример #8
0
        /// <summary>
        /// https://tc39.es/ecma262/#sec-performeval
        /// </summary>
        public JsValue PerformEval(JsValue x, Realm callerRealm, bool strictCaller, bool direct)
        {
            if (!x.IsString())
            {
                return(x);
            }

            var evalRealm = _realm;

            _engine._host.EnsureCanCompileStrings(callerRealm, evalRealm);

            var inFunction           = false;
            var inMethod             = false;
            var inDerivedConstructor = false;

            if (direct)
            {
                var thisEnvRec = _engine.ExecutionContext.GetThisEnvironment();
                if (thisEnvRec is FunctionEnvironmentRecord functionEnvironmentRecord)
                {
                    var F = functionEnvironmentRecord._functionObject;
                    inFunction = true;
                    inMethod   = thisEnvRec.HasSuperBinding();

                    if (F._constructorKind == ConstructorKind.Derived)
                    {
                        inDerivedConstructor = true;
                    }
                }
            }

            var    parser = new JavaScriptParser(x.ToString(), ParserOptions);
            Script script = null;

            try
            {
                script = parser.ParseScript(strictCaller);
            }
            catch (ParserException e)
            {
                if (e.Description == Messages.InvalidLHSInAssignment)
                {
                    ExceptionHelper.ThrowReferenceError(callerRealm, (string)null);
                }
                else
                {
                    ExceptionHelper.ThrowSyntaxError(callerRealm, e.Message);
                }
            }

            var body = script.Body;

            if (body.Count == 0)
            {
                return(Undefined);
            }

            if (!inFunction)
            {
                // if body Contains NewTarget, throw a SyntaxError exception.
            }
            if (!inMethod)
            {
                // if body Contains SuperProperty, throw a SyntaxError exception.
            }
            if (!inDerivedConstructor)
            {
                // if body Contains SuperCall, throw a SyntaxError exception.
            }

            var strictEval = script.Strict || _engine._isStrict;
            var ctx        = _engine.ExecutionContext;

            using (new StrictModeScope(strictEval))
            {
                EnvironmentRecord        lexEnv;
                EnvironmentRecord        varEnv;
                PrivateEnvironmentRecord privateEnv;
                if (direct)
                {
                    lexEnv     = JintEnvironment.NewDeclarativeEnvironment(_engine, ctx.LexicalEnvironment);
                    varEnv     = ctx.VariableEnvironment;
                    privateEnv = ctx.PrivateEnvironment;
                }
                else
                {
                    lexEnv     = JintEnvironment.NewDeclarativeEnvironment(_engine, evalRealm.GlobalEnv);
                    varEnv     = evalRealm.GlobalEnv;
                    privateEnv = null;
                }

                if (strictEval)
                {
                    varEnv = lexEnv;
                }

                // If ctx is not already suspended, suspend ctx.

                Engine.EnterExecutionContext(lexEnv, varEnv, evalRealm, privateEnv);

                try
                {
                    Engine.EvalDeclarationInstantiation(script, varEnv, lexEnv, privateEnv, strictEval);

                    var statement = new JintScript(script);
                    var result    = statement.Execute(_engine._activeEvaluationContext);
                    var value     = result.GetValueOrDefault();

                    if (result.Type == CompletionType.Throw)
                    {
                        var ex = new JavaScriptException(value).SetCallstack(_engine, result.Location);
                        throw ex;
                    }
                    else
                    {
                        return(value);
                    }
                }
                finally
                {
                    Engine.LeaveExecutionContext();
                }
            }
        }
Пример #9
0
        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));
        }