Exemplo n.º 1
0
            protected override ExpressionResult EvaluateInternal(EvaluationContext context)
            {
                var left  = _left.GetValue(context).Value;
                var right = _right.GetValue(context).Value;

                JsValue result;

                if (context.OperatorOverloadingAllowed &&
                    TryOperatorOverloading(context, left, right, "op_Multiply", out var opResult))
                {
                    result = JsValue.FromObject(context.Engine, opResult);
                }
                else if (AreIntegerOperands(left, right))
                {
                    result = JsNumber.Create((long)left.AsInteger() * right.AsInteger());
                }
                else
                {
                    var leftNumeric  = TypeConverter.ToNumeric(left);
                    var rightNumeric = TypeConverter.ToNumeric(right);

                    if (leftNumeric.IsNumber() && rightNumeric.IsNumber())
                    {
                        result = JsNumber.Create(leftNumeric.AsNumber() * rightNumeric.AsNumber());
                    }
                    else
                    {
                        AssertValidBigIntArithmeticOperands(context, leftNumeric, rightNumeric);
                        result = JsBigInt.Create(leftNumeric.AsBigInt() * rightNumeric.AsBigInt());
                    }
                }

                return(NormalCompletion(result));
            }
Exemplo n.º 2
0
        internal static JsValue ConvertToJsValue(Literal literal)
        {
            if (literal.TokenType == TokenType.BooleanLiteral)
            {
                return(literal.NumericValue > 0.0 ? JsBoolean.True : JsBoolean.False);
            }

            if (literal.TokenType == TokenType.NullLiteral)
            {
                return(JsValue.Null);
            }

            if (literal.TokenType == TokenType.NumericLiteral)
            {
                var intValue = (int)literal.NumericValue;
                return(literal.NumericValue == intValue &&
                       (intValue != 0 || BitConverter.DoubleToInt64Bits(literal.NumericValue) != JsNumber.NegativeZeroBits)
                    ? JsNumber.Create(intValue)
                    : JsNumber.Create(literal.NumericValue));
            }

            if (literal.TokenType == TokenType.StringLiteral)
            {
                return(JsString.Create((string)literal.Value));
            }

            if (literal.TokenType == TokenType.BigIntLiteral)
            {
                return(JsBigInt.Create((BigInteger)literal.Value));
            }

            return(null);
        }
Exemplo n.º 3
0
            protected override ExpressionResult EvaluateInternal(EvaluationContext context)
            {
                var left  = _left.GetValue(context).Value;
                var right = _right.GetValue(context).Value;

                if (context.OperatorOverloadingAllowed &&
                    TryOperatorOverloading(context, left, right, "op_Subtraction", out var opResult))
                {
                    return(NormalCompletion(JsValue.FromObject(context.Engine, opResult)));
                }

                JsValue number;

                left  = TypeConverter.ToNumeric(left);
                right = TypeConverter.ToNumeric(right);

                if (AreIntegerOperands(left, right))
                {
                    number = JsNumber.Create((long)left.AsInteger() - right.AsInteger());
                }
                else if (AreNonBigIntOperands(left, right))
                {
                    number = JsNumber.Create(left.AsNumber() - right.AsNumber());
                }
                else
                {
                    number = JsBigInt.Create(TypeConverter.ToBigInt(left) - TypeConverter.ToBigInt(right));
                }

                return(NormalCompletion(number));
            }
Exemplo n.º 4
0
            protected override ExpressionResult EvaluateInternal(EvaluationContext context)
            {
                var left  = _left.GetValue(context).Value;
                var right = _right.GetValue(context).Value;

                if (context.OperatorOverloadingAllowed &&
                    TryOperatorOverloading(context, left, right, "op_Addition", out var opResult))
                {
                    return(NormalCompletion(JsValue.FromObject(context.Engine, opResult)));
                }

                if (AreIntegerOperands(left, right))
                {
                    return(NormalCompletion(JsNumber.Create((long)left.AsInteger() + right.AsInteger())));
                }

                var     lprim = TypeConverter.ToPrimitive(left);
                var     rprim = TypeConverter.ToPrimitive(right);
                JsValue result;

                if (lprim.IsString() || rprim.IsString())
                {
                    result = JsString.Create(TypeConverter.ToString(lprim) + TypeConverter.ToString(rprim));
                }
                else if (AreNonBigIntOperands(left, right))
                {
                    result = JsNumber.Create(TypeConverter.ToNumber(lprim) + TypeConverter.ToNumber(rprim));
                }
                else
                {
                    AssertValidBigIntArithmeticOperands(context, lprim, rprim);
                    result = JsBigInt.Create(TypeConverter.ToBigInt(lprim) + TypeConverter.ToBigInt(rprim));
                }

                return(NormalCompletion(result));
            }
Exemplo n.º 5
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.º 6
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);
        }
Exemplo n.º 7
0
        protected override ExpressionResult EvaluateInternal(EvaluationContext context)
        {
            var lref = _left.Evaluate(context).Value as Reference;

            if (lref is null)
            {
                ExceptionHelper.ThrowReferenceError(context.Engine.Realm, "not a valid reference");
            }

            var engine            = context.Engine;
            var lval              = context.Engine.GetValue(lref, false);
            var handledByOverload = false;

            if (context.OperatorOverloadingAllowed)
            {
                string operatorClrName = null;
                switch (_operator)
                {
                case AssignmentOperator.PlusAssign:
                    operatorClrName = "op_Addition";
                    break;

                case AssignmentOperator.MinusAssign:
                    operatorClrName = "op_Subtraction";
                    break;

                case AssignmentOperator.TimesAssign:
                    operatorClrName = "op_Multiply";
                    break;

                case AssignmentOperator.DivideAssign:
                    operatorClrName = "op_Division";
                    break;

                case AssignmentOperator.ModuloAssign:
                    operatorClrName = "op_Modulus";
                    break;

                case AssignmentOperator.BitwiseAndAssign:
                    operatorClrName = "op_BitwiseAnd";
                    break;

                case AssignmentOperator.BitwiseOrAssign:
                    operatorClrName = "op_BitwiseOr";
                    break;

                case AssignmentOperator.BitwiseXOrAssign:
                    operatorClrName = "op_ExclusiveOr";
                    break;

                case AssignmentOperator.LeftShiftAssign:
                    operatorClrName = "op_LeftShift";
                    break;

                case AssignmentOperator.RightShiftAssign:
                    operatorClrName = "op_RightShift";
                    break;

                case AssignmentOperator.UnsignedRightShiftAssign:
                    operatorClrName = "op_UnsignedRightShift";
                    break;

                case AssignmentOperator.ExponentiationAssign:
                case AssignmentOperator.Assign:
                default:
                    break;
                }

                if (operatorClrName != null)
                {
                    var rval = _right.GetValue(context).Value;
                    if (JintBinaryExpression.TryOperatorOverloading(context, lval, rval, operatorClrName, out var result))
                    {
                        lval = JsValue.FromObject(context.Engine, result);
                        handledByOverload = true;
                    }
                }
            }

            if (!handledByOverload)
            {
                switch (_operator)
                {
                case AssignmentOperator.PlusAssign:
                {
                    var rval = _right.GetValue(context).Value;
                    if (AreIntegerOperands(lval, rval))
                    {
                        lval = (long)lval.AsInteger() + rval.AsInteger();
                    }
                    else
                    {
                        var lprim = TypeConverter.ToPrimitive(lval);
                        var rprim = TypeConverter.ToPrimitive(rval);

                        if (lprim.IsString() || rprim.IsString())
                        {
                            if (!(lprim is JsString jsString))
                            {
                                jsString = new JsString.ConcatenatedString(TypeConverter.ToString(lprim));
                            }

                            lval = jsString.Append(rprim);
                        }
                        else if (!AreIntegerOperands(lval, rval))
                        {
                            lval = TypeConverter.ToNumber(lprim) + TypeConverter.ToNumber(rprim);
                        }
                        else
                        {
                            lval = TypeConverter.ToBigInt(lprim) + TypeConverter.ToBigInt(rprim);
                        }
                    }

                    break;
                }

                case AssignmentOperator.MinusAssign:
                {
                    var rval = _right.GetValue(context).Value;
                    if (AreIntegerOperands(lval, rval))
                    {
                        lval = JsNumber.Create(lval.AsInteger() - rval.AsInteger());
                    }
                    else if (!AreIntegerOperands(lval, rval))
                    {
                        lval = JsNumber.Create(TypeConverter.ToNumber(lval) - TypeConverter.ToNumber(rval));
                    }
                    else
                    {
                        lval = JsNumber.Create(TypeConverter.ToBigInt(lval) - TypeConverter.ToBigInt(rval));
                    }

                    break;
                }

                case AssignmentOperator.TimesAssign:
                {
                    var rval = _right.GetValue(context).Value;
                    if (AreIntegerOperands(lval, rval))
                    {
                        lval = (long)lval.AsInteger() * rval.AsInteger();
                    }
                    else if (lval.IsUndefined() || rval.IsUndefined())
                    {
                        lval = Undefined.Instance;
                    }
                    else if (!AreIntegerOperands(lval, rval))
                    {
                        lval = TypeConverter.ToNumber(lval) * TypeConverter.ToNumber(rval);
                    }
                    else
                    {
                        lval = TypeConverter.ToBigInt(lval) * TypeConverter.ToBigInt(rval);
                    }

                    break;
                }

                case AssignmentOperator.DivideAssign:
                {
                    var rval = _right.GetValue(context).Value;
                    lval = Divide(context, lval, rval);
                    break;
                }

                case AssignmentOperator.ModuloAssign:
                {
                    var rval = _right.GetValue(context).Value;
                    if (lval.IsUndefined() || rval.IsUndefined())
                    {
                        lval = Undefined.Instance;
                    }
                    else if (!AreIntegerOperands(lval, rval))
                    {
                        lval = TypeConverter.ToNumber(lval) % TypeConverter.ToNumber(rval);
                    }
                    else
                    {
                        lval = TypeConverter.ToNumber(lval) % TypeConverter.ToNumber(rval);
                    }

                    break;
                }

                case AssignmentOperator.BitwiseAndAssign:
                {
                    var rval = _right.GetValue(context).Value;
                    lval = TypeConverter.ToInt32(lval) & TypeConverter.ToInt32(rval);
                    break;
                }

                case AssignmentOperator.BitwiseOrAssign:
                {
                    var rval = _right.GetValue(context).Value;
                    lval = TypeConverter.ToInt32(lval) | TypeConverter.ToInt32(rval);
                    break;
                }

                case AssignmentOperator.BitwiseXOrAssign:
                {
                    var rval = _right.GetValue(context).Value;
                    lval = TypeConverter.ToInt32(lval) ^ TypeConverter.ToInt32(rval);
                    break;
                }

                case AssignmentOperator.LeftShiftAssign:
                {
                    var rval = _right.GetValue(context).Value;
                    lval = TypeConverter.ToInt32(lval) << (int)(TypeConverter.ToUint32(rval) & 0x1F);
                    break;
                }

                case AssignmentOperator.RightShiftAssign:
                {
                    var rval = _right.GetValue(context).Value;
                    lval = TypeConverter.ToInt32(lval) >> (int)(TypeConverter.ToUint32(rval) & 0x1F);
                    break;
                }

                case AssignmentOperator.UnsignedRightShiftAssign:
                {
                    var rval = _right.GetValue(context).Value;
                    lval = (uint)TypeConverter.ToInt32(lval) >> (int)(TypeConverter.ToUint32(rval) & 0x1F);
                    break;
                }

                case AssignmentOperator.NullishAssign:
                {
                    if (!lval.IsNullOrUndefined())
                    {
                        return(NormalCompletion(lval));
                    }

                    var rval = NamedEvaluation(context, _right);
                    lval = rval;
                    break;
                }

                case AssignmentOperator.AndAssign:
                {
                    if (!TypeConverter.ToBoolean(lval))
                    {
                        return(NormalCompletion(lval));
                    }

                    var rval = NamedEvaluation(context, _right);
                    lval = rval;
                    break;
                }

                case AssignmentOperator.OrAssign:
                {
                    if (TypeConverter.ToBoolean(lval))
                    {
                        return(NormalCompletion(lval));
                    }

                    var rval = NamedEvaluation(context, _right);
                    lval = rval;
                    break;
                }

                case AssignmentOperator.ExponentiationAssign:
                {
                    var rval = _right.GetValue(context).Value;
                    if (!lval.IsBigInt() && !rval.IsBigInt())
                    {
                        lval = JsNumber.Create(System.Math.Pow(TypeConverter.ToNumber(lval), TypeConverter.ToNumber(rval)));
                    }
                    else
                    {
                        var exponent = TypeConverter.ToBigInt(rval);
                        if (exponent > int.MaxValue || exponent < int.MinValue)
                        {
                            ExceptionHelper.ThrowTypeError(context.Engine.Realm, "Cannot do exponentation with exponent not fitting int32");
                        }
                        lval = JsBigInt.Create(BigInteger.Pow(TypeConverter.ToBigInt(lval), (int)exponent));
                    }

                    break;
                }

                default:
                    ExceptionHelper.ThrowNotImplementedException();
                    return(default);
                }
            }

            engine.PutValue(lref, lval);

            engine._referencePool.Return(lref);
            return(NormalCompletion(lval));
        }