Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        protected override ExpressionResult EvaluateInternal(EvaluationContext context)
        {
            var engine = context.Engine;
            var env    = engine.ExecutionContext.LexicalEnvironment;
            var strict = StrictModeScope.IsStrictModeCode;
            var identifierEnvironment = JintEnvironment.TryGetIdentifierEnvironmentWithBinding(env, _expressionName, out var temp)
                ? temp
                : JsValue.Undefined;

            return(NormalCompletion(engine._referencePool.Rent(identifierEnvironment, _expressionName.StringValue, strict, thisValue: null)));
        }
Ejemplo n.º 3
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);
                }
            }
        }
Ejemplo n.º 4
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));
        }
Ejemplo n.º 5
0
        public override Completion GetValue(EvaluationContext context)
        {
            // need to notify correct node when taking shortcut
            context.LastSyntaxNode = _expression;

            if (_calculatedValue is not null)
            {
                return(Completion.Normal(_calculatedValue, _expression.Location));
            }

            var strict = StrictModeScope.IsStrictModeCode;
            var engine = context.Engine;
            var env    = engine.ExecutionContext.LexicalEnvironment;

            if (JintEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
                    env,
                    _expressionName,
                    strict,
                    out _,
                    out var value))
            {
                if (value is null)
                {
                    ExceptionHelper.ThrowReferenceError(engine.Realm, _expressionName.Key.Name + " has not been initialized");
                }
            }
            else
            {
                var reference = engine._referencePool.Rent(JsValue.Undefined, _expressionName.StringValue, strict, thisValue: null);
                value = engine.GetValue(reference, true);
            }

            // make sure arguments access freezes state
            if (value is ArgumentsInstance argumentsInstance)
            {
                argumentsInstance.Materialize();
            }

            return(Completion.Normal(value, _expression.Location));
        }
Ejemplo n.º 6
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);
        }
Ejemplo n.º 7
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);
        }
Ejemplo n.º 8
0
            internal static ExpressionResult?AssignToIdentifier(
                EvaluationContext context,
                JintIdentifierExpression left,
                JintExpression right,
                bool hasEvalOrArguments)
            {
                var engine = context.Engine;
                var env    = engine.ExecutionContext.LexicalEnvironment;
                var strict = StrictModeScope.IsStrictModeCode;

                if (JintEnvironment.TryGetIdentifierEnvironmentWithBinding(
                        env,
                        left._expressionName,
                        out var environmentRecord))
                {
                    if (strict && hasEvalOrArguments)
                    {
                        ExceptionHelper.ThrowSyntaxError(engine.Realm);
                    }

                    var completion = right.GetValue(context);
                    if (completion.IsAbrupt())
                    {
                        return(completion);
                    }

                    var rval = completion.Value.Clone();

                    if (right._expression.IsFunctionDefinition())
                    {
                        ((FunctionInstance)rval).SetFunctionName(left._expressionName.StringValue);
                    }

                    environmentRecord.SetMutableBinding(left._expressionName, rval, strict);
                    return(new Completion(CompletionType.Normal, rval, default));
                }

                return(null);
            }
Ejemplo n.º 9
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);
        }
Ejemplo n.º 10
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));
        }
Ejemplo n.º 11
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);
            }
        }
Ejemplo n.º 12
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();
                }
            }
        }
Ejemplo n.º 13
0
    /// <summary>
    /// https://tc39.es/ecma262/#sec-source-text-module-record-initialize-environment
    /// </summary>
    protected override void InitializeEnvironment()
    {
        for (var i = 0; i < _indirectExportEntries.Count; i++)
        {
            var e          = _indirectExportEntries[i];
            var resolution = ResolveExport(e.ExportName);
            if (resolution is null || resolution == ResolvedBinding.Ambiguous)
            {
                ExceptionHelper.ThrowSyntaxError(_realm, "Ambiguous import statement for identifier: " + e.ExportName);
            }
        }

        var realm = _realm;
        var env   = JintEnvironment.NewModuleEnvironment(_engine, realm.GlobalEnv);

        _environment = env;

        if (_importEntries != null)
        {
            for (var i = 0; i < _importEntries.Count; i++)
            {
                var ie             = _importEntries[i];
                var importedModule = _engine._host.ResolveImportedModule(this, ie.ModuleRequest);
                if (ie.ImportName == "*")
                {
                    var ns = GetModuleNamespace(importedModule);
                    env.CreateImmutableBinding(ie.LocalName, true);
                    env.InitializeBinding(ie.LocalName, ns);
                }
                else
                {
                    var resolution = importedModule.ResolveExport(ie.ImportName);
                    if (resolution is null || resolution == ResolvedBinding.Ambiguous)
                    {
                        ExceptionHelper.ThrowSyntaxError(_realm, "Ambiguous import statement for identifier " + ie.ImportName);
                    }

                    if (resolution.BindingName == "*namespace*")
                    {
                        var ns = GetModuleNamespace(resolution.Module);
                        env.CreateImmutableBinding(ie.LocalName, true);
                        env.InitializeBinding(ie.LocalName, ns);
                    }
                    else
                    {
                        env.CreateImportBinding(ie.LocalName, resolution.Module, resolution.BindingName);
                    }
                }
            }
        }

        var moduleContext = new ExecutionContext(this, _environment, _environment, null, realm, null);

        _context = moduleContext;

        _engine.EnterExecutionContext(_context);

        var hoistingScope = HoistingScope.GetModuleLevelDeclarations(_source);

        var varDeclarations  = hoistingScope._variablesDeclarations;
        var declaredVarNames = new HashSet <string>();

        if (varDeclarations != null)
        {
            var boundNames = new List <string>();
            for (var i = 0; i < varDeclarations.Count; i++)
            {
                var d = varDeclarations[i];
                boundNames.Clear();
                d.GetBoundNames(boundNames);
                for (var j = 0; j < boundNames.Count; j++)
                {
                    var dn = boundNames[j];
                    if (declaredVarNames.Add(dn))
                    {
                        env.CreateMutableBinding(dn, false);
                        env.InitializeBinding(dn, Undefined);
                    }
                }
            }
        }

        var lexDeclarations = hoistingScope._lexicalDeclarations;

        if (lexDeclarations != null)
        {
            var boundNames = new List <string>();
            for (var i = 0; i < lexDeclarations.Count; i++)
            {
                var d = lexDeclarations[i];
                boundNames.Clear();
                d.GetBoundNames(boundNames);
                for (var j = 0; j < boundNames.Count; j++)
                {
                    var dn = boundNames[j];
                    if (d.IsConstantDeclaration())
                    {
                        env.CreateImmutableBinding(dn, true);
                    }
                    else
                    {
                        env.CreateMutableBinding(dn, false);
                    }
                }
            }
        }

        var functionDeclarations = hoistingScope._functionDeclarations;

        if (functionDeclarations != null)
        {
            for (var i = 0; i < functionDeclarations.Count; i++)
            {
                var d  = functionDeclarations[i];
                var fn = d.Id?.Name ?? "*default*";
                var fd = new JintFunctionDefinition(_engine, d);
                env.CreateMutableBinding(fn, true);
                var fo = realm.Intrinsics.Function.InstantiateFunctionObject(fd, env);
                if (fn == "*default*")
                {
                    fo.SetFunctionName("default");
                }
                env.InitializeBinding(fn, fo);
            }
        }

        _engine.LeaveExecutionContext();
    }
Ejemplo n.º 14
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));
        }
Ejemplo n.º 15
0
        protected override ExpressionResult EvaluateInternal(EvaluationContext context)
        {
            JsValue actualThis        = null;
            string  baseReferenceName = null;
            JsValue baseValue         = null;
            var     isStrictModeCode  = StrictModeScope.IsStrictModeCode;

            var engine = context.Engine;

            if (_objectExpression is JintIdentifierExpression identifierExpression)
            {
                baseReferenceName = identifierExpression._expressionName.Key.Name;
                var strict = isStrictModeCode;
                var env    = engine.ExecutionContext.LexicalEnvironment;
                JintEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
                    env,
                    identifierExpression._expressionName,
                    strict,
                    out _,
                    out baseValue);
            }
            else if (_objectExpression is JintThisExpression thisExpression)
            {
                baseValue = thisExpression.GetValue(context).Value;
            }
            else if (_objectExpression is JintSuperExpression)
            {
                var env = (FunctionEnvironmentRecord)engine.ExecutionContext.GetThisEnvironment();
                actualThis = env.GetThisBinding();
                baseValue  = env.GetSuperBase();
            }

            if (baseValue is null)
            {
                // fast checks failed
                var baseReference = _objectExpression.Evaluate(context).Value;
                if (ReferenceEquals(Undefined.Instance, baseReference))
                {
                    return(NormalCompletion(Undefined.Instance));
                }
                if (baseReference is Reference reference)
                {
                    baseReferenceName = reference.GetReferencedName().ToString();
                    baseValue         = engine.GetValue(reference, false);
                    engine._referencePool.Return(reference);
                }
                else
                {
                    baseValue = engine.GetValue(baseReference, false);
                }
            }

            if (baseValue.IsNullOrUndefined() && (_memberExpression.Optional || _objectExpression._expression.IsOptional()))
            {
                return(NormalCompletion(Undefined.Instance));
            }

            var property = _determinedProperty ?? _propertyExpression.GetValue(context).Value;

            if (baseValue.IsNullOrUndefined())
            {
                // we can use base data types securely, object evaluation can mess things up
                var referenceName = property.IsPrimitive()
                    ? TypeConverter.ToString(property)
                    : _determinedProperty?.ToString() ?? baseReferenceName;

                TypeConverter.CheckObjectCoercible(engine, baseValue, _memberExpression.Property, referenceName);
            }

            // only convert if necessary
            var propertyKey = property.IsInteger() && baseValue.IsIntegerIndexedArray
                ? property
                : TypeConverter.ToPropertyKey(property);

            var rent = context.Engine._referencePool.Rent(baseValue, propertyKey, isStrictModeCode, thisValue: actualThis);

            return(new ExpressionResult(
                       ExpressionCompletionType.Reference,
                       rent,
                       _expression.Location));
        }
Ejemplo n.º 16
0
        private JsValue UpdateIdentifier(EvaluationContext context)
        {
            var strict = StrictModeScope.IsStrictModeCode;
            var name   = _leftIdentifier._expressionName;
            var engine = context.Engine;
            var env    = engine.ExecutionContext.LexicalEnvironment;

            if (JintEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
                    env,
                    name,
                    strict,
                    out var environmentRecord,
                    out var value))
            {
                if (strict && _evalOrArguments)
                {
                    ExceptionHelper.ThrowSyntaxError(engine.Realm);
                }

                var isInteger = value._type == InternalTypes.Integer;

                JsValue newValue = null;

                var operatorOverloaded = false;
                if (context.OperatorOverloadingAllowed)
                {
                    if (JintUnaryExpression.TryOperatorOverloading(context, _argument.GetValue(context).Value, _change > 0 ? "op_Increment" : "op_Decrement", out var result))
                    {
                        operatorOverloaded = true;
                        newValue           = result;
                    }
                }

                if (!operatorOverloaded)
                {
                    if (isInteger)
                    {
                        newValue = JsNumber.Create(value.AsInteger() + _change);
                    }
                    else if (value._type != InternalTypes.BigInt)
                    {
                        newValue = JsNumber.Create(TypeConverter.ToNumber(value) + _change);
                    }
                    else
                    {
                        newValue = JsBigInt.Create(TypeConverter.ToBigInt(value) + _change);
                    }
                }

                environmentRecord.SetMutableBinding(name.Key.Name, newValue, strict);
                if (_prefix)
                {
                    return(newValue);
                }

                if (!value.IsBigInt() && !value.IsNumber() && !operatorOverloaded)
                {
                    return(JsNumber.Create(TypeConverter.ToNumber(value)));
                }

                return(value);
            }

            return(null);
        }