Пример #1
0
            RuntimeObj BitwiseShift(RuntimeObj val, RuntimeObj shift, bool right)
            {
                if (val == JSEvalNumber.Zero)
                {
                    return(val);
                }
                double dR = shift.ToDouble();
                int    iShift;

                if (Double.IsNaN(dR) || (iShift = (dR < 0 ? (int)Math.Ceiling(dR) : (int)Math.Floor(dR)) % 64) == 0)
                {
                    return(Global.CreateNumber(val));
                }
                if (right && iShift < 0)
                {
                    return(JSEvalNumber.Zero);
                }
                Int32 lN = JSSupport.ToInt32(val.ToDouble());

                if (lN == 0)
                {
                    return(JSEvalNumber.Zero);
                }
                return(Global.CreateNumber(right ? lN >> iShift : lN << iShift));
            }
Пример #2
0
            RuntimeObj BitwiseShiftRightUnsigned(RuntimeObj left, RuntimeObj right)
            {
                if (left == JSEvalNumber.Zero)
                {
                    return(left);
                }

                double dR = right.ToDouble();

                if (Double.IsNaN(dR))
                {
                    return(Global.CreateNumber(left));
                }
                int iShift = (dR < 0 ? (int)Math.Ceiling(dR) : (int)Math.Floor(dR)) % 64;

                if (iShift < 0)
                {
                    return(JSEvalNumber.Zero);
                }

                UInt32 lN = (UInt32)JSSupport.ToInt64(left.ToDouble());

                if (lN == 0)
                {
                    return(JSEvalNumber.Zero);
                }

                return(Global.CreateNumber(lN >> iShift));
            }
Пример #3
0
            RuntimeObj BitwiseShiftRightUnsigned(RuntimeObj left, RuntimeObj right)
            {
                if (left == DoubleObj.Zero)
                {
                    return(left);
                }

                double dR = right.ToDouble();

                if (double.IsNaN(dR))
                {
                    return(left is DoubleObj ? left : DoubleObj.Create(left.ToDouble()));
                }
                int iShift = (dR < 0 ? (int)Math.Ceiling(dR) : (int)Math.Floor(dR)) % 64;

                if (iShift < 0)
                {
                    return(DoubleObj.Zero);
                }

                uint lN = (uint)JSSupport.ToInt64(left.ToDouble());

                if (lN == 0)
                {
                    return(DoubleObj.Zero);
                }

                return(DoubleObj.Create(lN >> iShift));
            }
Пример #4
0
            RuntimeObj BitwiseShift(RuntimeObj val, RuntimeObj shift, bool right)
            {
                if (val == DoubleObj.Zero)
                {
                    return(val);
                }
                double dR = shift.ToDouble();
                int    iShift;

                if (double.IsNaN(dR) || (iShift = (dR < 0 ? (int)Math.Ceiling(dR) : (int)Math.Floor(dR)) % 64) == 0)
                {
                    return(val.ToValue() as DoubleObj ?? DoubleObj.Create(val.ToDouble()));
                }
                if (right && iShift < 0)
                {
                    return(DoubleObj.Zero);
                }
                int lN = JSSupport.ToInt32(val.ToDouble());

                if (lN == 0)
                {
                    return(DoubleObj.Zero);
                }
                return(DoubleObj.Create(right ? lN >> iShift : lN << iShift));
            }
Пример #5
0
            protected override PExpr DoVisit()
            {
                if (IsPendingOrSignal(ref _expression, Expr.Expression))
                {
                    return(PendingOrSignal(_expression));
                }

                RuntimeObj result = _expression.Result;

                // Minus and Plus are classified as a binary operator.
                // Handle those special cases here.
                if (Expr.TokenType == JSTokenizerToken.Minus)
                {
                    result = Global.CreateNumber(-result.ToDouble());
                }
                else if (Expr.TokenType == JSTokenizerToken.Plus)
                {
                    result = Global.CreateNumber(result.ToDouble());
                }
                else
                {
                    switch ((int)Expr.TokenType & 15)
                    {
                    case (int)JSTokenizerToken.Not & 15:
                    {
                        result = Global.CreateBoolean(!result.ToBoolean());
                        break;
                    }

                    case (int)JSTokenizerToken.BitwiseNot & 15:
                    {
                        result = Global.CreateNumber(~JSSupport.ToInt64(result.ToDouble()));
                        break;
                    }

                    case (int)JSTokenizerToken.TypeOf & 15:
                    {
                        // Well known Javascript bug: typeof null === "object".
                        if (result == RuntimeObj.Null)
                        {
                            result = Global.CreateString(RuntimeObj.TypeObject);
                        }
                        else
                        {
                            result = Global.CreateString(result.Type);
                        }
                        break;
                    }

                    case (int)JSTokenizerToken.Void & 15:
                    {
                        result = RuntimeObj.Undefined;
                        break;
                    }

                    default: throw UnsupportedOperatorException();
                    }
                }
                return(SetResult(result));
            }
Пример #6
0
        public override PExpr Visit(IAccessorFrame frame)
        {
            var s = frame.GetState(c =>
                                   c.On("toString").OnCall((f, args) =>
            {
                return(f.SetResult(f.Global.CreateString(JSSupport.ToString(_value))));
            }
                                                           ));

            return(s != null?s.Visit() : frame.SetError());
        }
Пример #7
0
        public override PExpr Visit(IAccessorFrame frame)
        {
            var s = frame.GetState(c =>
                                   c.On("toString").OnCall((f, args) =>
            {
                int radix = 10;
                if (args.Count == 1)
                {
                    radix = JSSupport.ToInt32(args[0].ToDouble());
                }
                if (radix < 2 || radix > 36)
                {
                    return(f.SetError("Radix must be between 2 and 36."));
                }
                return(f.SetResult(f.Global.CreateString(JSSupport.ToString(_value, radix))));
            }
                                                           ));

            return(s != null?s.Visit() : frame.SetError());
        }
Пример #8
0
        public override PExpr Visit(IAccessorFrame frame)
        {
            var s = frame.GetState(c =>
                                   c.On("charAt").OnCall((f, args) =>
            {
                int idx = args.Count > 0 ? JSSupport.ToInt32(args[0].ToDouble()) : 0;
                if (idx < 0 || idx >= _value.Length)
                {
                    return(f.SetResult(JSEvalString.EmptyString));
                }
                return(f.SetResult(f.Global.CreateString(new String(_value[idx], 1))));
            })
                                   .On("toString").OnCall((f, args) =>
            {
                return(f.SetResult(this));
            }
                                                          ));

            return(s != null?s.Visit() : frame.SetError());
        }
Пример #9
0
        public override PExpr Visit(IAccessorFrame frame)
        {
            var s = frame.GetImplementationState(c =>
                                                 c.OnIndex((f, arg) =>
            {
                int idx = JSSupport.ToInt32(arg.ToDouble());
                if (idx < 0 || idx >= _value.Length)
                {
                    return(f.SetResult(EmptyString));
                }
                return(f.SetResult(Create(new string( _value[idx], 1 ))));
            })
                                                 .On("ToString").OnCall((f, args) =>
            {
                return(f.SetResult(this));
            }
                                                                        ));

            return(s != null?s.Visit() : frame.SetError());
        }
Пример #10
0
            protected override PExpr DoVisit()
            {
                if (IsPendingOrSignal(ref _left, Expr.Left))
                {
                    return(PendingOrSignal(_left));
                }

                // Do not evaluate right expression if it is useless: short-circuit boolean evaluation.
                if ((Expr.BinaryOperatorToken == JSTokenizerToken.And && !_left.Result.ToBoolean()) ||
                    (Expr.BinaryOperatorToken == JSTokenizerToken.Or && _left.Result.ToBoolean()))
                {
                    return(SetResult(_left.Result));
                }

                if (IsPendingOrSignal(ref _right, Expr.Right))
                {
                    return(PendingOrSignal(_right));
                }

                RuntimeObj left  = _left.Result;
                RuntimeObj right = _right.Result;

                // Right value is the result for And and Or.
                RuntimeObj result = right;

                if (Expr.BinaryOperatorToken != JSTokenizerToken.And && Expr.BinaryOperatorToken != JSTokenizerToken.Or)
                {
                    if ((Expr.BinaryOperatorToken & JSTokenizerToken.IsCompareOperator) != 0)
                    {
                        #region ==, <, >, <=, >=, !=, === and !==
                        int compareValue;
                        switch ((int)Expr.BinaryOperatorToken & 15)
                        {
                        case (int)JSTokenizerToken.StrictEqual & 15:
                        {
                            result = Global.CreateBoolean(new RuntimeObjComparer(left, right).AreEqualStrict(Global));
                            break;
                        }

                        case (int)JSTokenizerToken.StrictDifferent & 15:
                        {
                            result = Global.CreateBoolean(!new RuntimeObjComparer(left, right).AreEqualStrict(Global));
                            break;
                        }

                        case (int)JSTokenizerToken.Greater & 15:
                        {
                            result = Global.CreateBoolean(new RuntimeObjComparer(left, right).Compare(Global, out compareValue) && compareValue > 0);
                            break;
                        }

                        case (int)JSTokenizerToken.GreaterOrEqual & 15:
                        {
                            result = Global.CreateBoolean(new RuntimeObjComparer(left, right).Compare(Global, out compareValue) && compareValue >= 0);
                            break;
                        }

                        case (int)JSTokenizerToken.Less & 15:
                        {
                            result = Global.CreateBoolean(new RuntimeObjComparer(left, right).Compare(Global, out compareValue) && compareValue < 0);
                            break;
                        }

                        case (int)JSTokenizerToken.LessOrEqual & 15:
                        {
                            result = Global.CreateBoolean(new RuntimeObjComparer(left, right).Compare(Global, out compareValue) && compareValue <= 0);
                            break;
                        }

                        case (int)JSTokenizerToken.Equal & 15:
                        {
                            result = Global.CreateBoolean(new RuntimeObjComparer(left, right).AreEqual(Global));
                            break;
                        }

                        case (int)JSTokenizerToken.Different & 15:
                        {
                            result = Global.CreateBoolean(!new RuntimeObjComparer(left, right).AreEqual(Global));
                            break;
                        }

                        default: throw UnsupportedOperatorException();
                        }
                        #endregion
                    }
                    else if ((Expr.BinaryOperatorToken & JSTokenizerToken.IsBinaryOperator) != 0)
                    {
                        #region |, ^, &, >>, <<, >>>, +, -, /, * and %.
                        switch ((int)Expr.BinaryOperatorToken & 15)
                        {
                        case (int)JSTokenizerToken.Plus & 15:
                        {
                            if (ReferenceEquals(left.Type, RuntimeObj.TypeNumber) && ReferenceEquals(right.Type, RuntimeObj.TypeNumber))
                            {
                                result = Global.CreateNumber(left.ToDouble() + right.ToDouble());
                            }
                            else
                            {
                                result = Global.CreateString(String.Concat(left.ToString(), right.ToString()));
                            }
                            break;
                        }

                        case (int)JSTokenizerToken.Minus & 15:
                        {
                            result = Global.CreateNumber(left.ToDouble() - right.ToDouble());
                            break;
                        }

                        case (int)JSTokenizerToken.Mult & 15:
                        {
                            result = Global.CreateNumber(left.ToDouble() * right.ToDouble());
                            break;
                        }

                        case (int)JSTokenizerToken.Divide & 15:
                        {
                            result = Global.CreateNumber(left.ToDouble() / right.ToDouble());
                            break;
                        }

                        case (int)JSTokenizerToken.Modulo & 15:
                        {
                            if (right == JSEvalNumber.Zero || left == JSEvalNumber.NegativeInfinity || left == JSEvalNumber.Infinity)
                            {
                                result = JSEvalNumber.NaN;
                            }
                            else if (left == JSEvalNumber.NegativeInfinity || left == JSEvalNumber.Infinity)
                            {
                                result = right;
                            }
                            else
                            {
                                result = Global.CreateNumber(left.ToDouble() % right.ToDouble());
                            }
                            break;
                        }

                        case (int)JSTokenizerToken.BitwiseAnd & 15:
                        {
                            Int64 l  = JSSupport.ToInt64(left.ToDouble());
                            Int64 rO = JSSupport.ToInt64(right.ToDouble());
                            result = Global.CreateNumber(l & rO);
                            break;
                        }

                        case (int)JSTokenizerToken.BitwiseOr & 15:
                        {
                            Int64 l  = JSSupport.ToInt64(left.ToDouble());
                            Int64 rO = JSSupport.ToInt64(right.ToDouble());
                            result = Global.CreateNumber(l | rO);
                            break;
                        }

                        case (int)JSTokenizerToken.BitwiseXOr & 15:
                        {
                            Int64 l  = JSSupport.ToInt64(left.ToDouble());
                            Int64 rO = JSSupport.ToInt64(right.ToDouble());
                            result = Global.CreateNumber(l ^ rO);
                            break;
                        }

                        case (int)JSTokenizerToken.BitwiseShiftLeft & 15:
                        {
                            result = BitwiseShift(left, right, false);
                            break;
                        }

                        case (int)JSTokenizerToken.BitwiseShiftRight & 15:
                        {
                            result = BitwiseShift(left, right, true);
                            break;
                        }

                        case (int)JSTokenizerToken.BitwiseShiftRightNoSignBit & 15:
                        {
                            result = BitwiseShiftRightUnsigned(left, right);
                            break;
                        }

                        default: throw UnsupportedOperatorException();
                        }
                        #endregion
                    }
                    else
                    {
                        throw UnsupportedOperatorException();
                    }
                }
                return(SetResult(result));
            }
Пример #11
0
 public override string ToString()
 {
     return(JSSupport.ToString(_value));
 }
Пример #12
0
 public override double ToDouble()
 {
     return(JSSupport.ToNumber(_value));
 }
Пример #13
0
 public override bool ToBoolean()
 {
     return(JSSupport.ToBoolean(_value));
 }
Пример #14
0
            protected override PExpr DoVisit()
            {
                if (IsPendingOrSignal(ref _expression, Expr.Expression))
                {
                    RuntimeError e = _expression.AsErrorResult;
                    if (e != null &&
                        e.IsReferenceError &&
                        ((int)Expr.TokenType & 15) == ((int)TokenizerToken.TypeOf & 15))
                    {
                        return(SetResult(StringObj.Create(RuntimeObj.TypeUndefined)));
                    }
                    return(PendingOrSignal(_expression));
                }
                RuntimeObj result = _expression.Result;

                // Minus and Plus are classified as a binary operator.
                // Handle those special cases here.
                if (Expr.TokenType == TokenizerToken.Minus)
                {
                    result = DoubleObj.Create(-result.ToDouble());
                }
                else if (Expr.TokenType == TokenizerToken.Plus)
                {
                    result = DoubleObj.Create(result.ToDouble());
                }
                else
                {
                    switch ((int)Expr.TokenType & 15)
                    {
                    case (int)TokenizerToken.Not & 15:
                    {
                        result = result.ToBoolean() ? BooleanObj.False : BooleanObj.True;
                        break;
                    }

                    case (int)TokenizerToken.BitwiseNot & 15:
                    {
                        result = DoubleObj.Create(~JSSupport.ToInt64(result.ToDouble()));
                        break;
                    }

                    case (int)TokenizerToken.TypeOf & 15:
                    {
                        // Well known Javascript bug: typeof null === "object".
                        if (result == RuntimeObj.Null)
                        {
                            result = StringObj.Create(RuntimeObj.TypeObject);
                        }
                        else
                        {
                            result = StringObj.Create(result.Type);
                        }
                        break;
                    }

                    case (int)TokenizerToken.IndexOf & 15:
                    {
                        RefRuntimeIndexedObj iO = result as RefRuntimeIndexedObj;
                        if (iO == null)
                        {
                            result = new RuntimeError(Expr, "No associated index. indexof must be used on a foreach variable.");
                        }
                        else
                        {
                            result = iO.Index;
                        }
                        break;
                    }

                    case (int)TokenizerToken.Void & 15:
                    {
                        result = RuntimeObj.Undefined;
                        break;
                    }

                    default: throw UnsupportedOperatorException();
                    }
                }
                return(SetResult(result));
            }