Exemplo n.º 1
0
        protected internal static JintExpression Build(Engine engine, Expression expression)
        {
            switch (expression.Type)
            {
            case Nodes.AssignmentExpression: return(JintAssignmentExpression.Build(engine, (AssignmentExpression)expression));

            case Nodes.ArrayExpression: return(new JintArrayExpression(engine, (ArrayExpression)expression));

            case Nodes.ArrowFunctionExpression: return(new JintArrowFunctionExpression(engine, (IFunction)expression));

            case Nodes.BinaryExpression: return(JintBinaryExpression.Build(engine, (BinaryExpression)expression));

            case Nodes.CallExpression: return(new JintCallExpression(engine, (CallExpression)expression));

            case Nodes.ConditionalExpression: return(new JintConditionalExpression(engine, (ConditionalExpression)expression));

            case Nodes.FunctionExpression: return(new JintFunctionExpression(engine, (IFunction)expression));

            case Nodes.Identifier: return(new JintIdentifierExpression(engine, (Identifier)expression));

            case Nodes.Literal: return(JintLiteralExpression.Build(engine, (Literal)expression));

            case Nodes.LogicalExpression:
                switch (((BinaryExpression)expression).Operator)
                {
                case BinaryOperator.LogicalAnd: return(new JintLogicalAndExpression(engine, (BinaryExpression)expression));

                case BinaryOperator.LogicalOr: return(new JintLogicalOrExpression(engine, (BinaryExpression)expression));

                default: return(ExceptionHelper.ThrowArgumentOutOfRangeException <JintExpression>());
                }

            case Nodes.MemberExpression: return(new JintMemberExpression(engine, (MemberExpression)expression));

            case Nodes.NewExpression: return(new JintNewExpression(engine, (NewExpression)expression));

            case Nodes.ObjectExpression: return(new JintObjectExpression(engine, (ObjectExpression)expression));

            case Nodes.SequenceExpression: return(new JintSequenceExpression(engine, (SequenceExpression)expression));

            case Nodes.ThisExpression: return(new JintThisExpression(engine, (ThisExpression)expression));

            case Nodes.UpdateExpression: return(new JintUpdateExpression(engine, (UpdateExpression)expression));

            case Nodes.UnaryExpression: return(JintUnaryExpression.Build(engine, (UnaryExpression)expression));

            case Nodes.SpreadElement: return(new JintSpreadExpression(engine, (SpreadElement)expression));

            case Nodes.TemplateLiteral: return(new JintTemplateLiteralExpression(engine, (TemplateLiteral)expression));

            case Nodes.TaggedTemplateExpression: return(new JintTaggedTemplateExpression(engine, (TaggedTemplateExpression)expression));

            default:
                return(ExceptionHelper.ThrowArgumentOutOfRangeException <JintExpression>(nameof(expression), $"unsupported expression type '{expression.Type}'"));
            }
        }
Exemplo n.º 2
0
        private JsValue UpdateNonIdentifier(EvaluationContext context)
        {
            var engine    = context.Engine;
            var reference = _argument.Evaluate(context).Value as Reference;

            if (reference is null)
            {
                ExceptionHelper.ThrowTypeError(engine.Realm, "Invalid left-hand side expression");
            }

            reference.AssertValid(engine.Realm);

            var value     = engine.GetValue(reference, false);
            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.IsBigInt())
                {
                    newValue = JsNumber.Create(TypeConverter.ToNumber(value) + _change);
                }
                else
                {
                    newValue = JsBigInt.Create(TypeConverter.ToBigInt(value) + _change);
                }
            }

            engine.PutValue(reference, newValue);
            engine._referencePool.Return(reference);

            if (_prefix)
            {
                return(newValue);
            }
            else
            {
                if (isInteger || operatorOverloaded)
                {
                    return(value);
                }

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

                return(JsBigInt.Create(value));
            }
        }
Exemplo n.º 3
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);
        }