예제 #1
0
        /// <summary>
        /// https://tc39.es/ecma262/#sec-performeval
        /// </summary>
        public JsValue Call(JsValue thisObject, JsValue[] arguments, bool direct)
        {
            if (!(arguments.At(0) is JsString x))
            {
                return(arguments.At(0));
            }

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

            try
            {
                script = parser.ParseScript(StrictModeScope.IsStrictModeCode);
            }
            catch (ParserException e)
            {
                return(e.Description == Messages.InvalidLHSInAssignment
                    ? ExceptionHelper.ThrowReferenceError <JsValue>(_engine)
                    : ExceptionHelper.ThrowSyntaxError <JsValue>(_engine));
            }

            var body = script.Body;

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

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

            using (new StrictModeScope(strictEval))
            {
                LexicalEnvironment lexEnv;
                LexicalEnvironment varEnv;
                if (direct)
                {
                    lexEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, ctx.LexicalEnvironment);
                    varEnv = ctx.VariableEnvironment;
                }
                else
                {
                    lexEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, Engine.GlobalEnvironment);
                    varEnv = Engine.GlobalEnvironment;
                }

                if (strictEval)
                {
                    varEnv = lexEnv;
                }

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

                Engine.EnterExecutionContext(lexEnv, varEnv);

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

                    var statement = new JintScript(_engine, script);
                    var result    = statement.Execute();
                    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();
                }
            }
        }
예제 #2
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();
                }
            }
        }