Пример #1
0
 public void ShouldHandleDictionaryObjects() {
     var dic = new JsObject();
     dic["prop1"] = new JsNumber(1, JsNull.Instance);
     Assert.IsTrue(dic.HasProperty(new JsString("prop1", JsNull.Instance)));
     Assert.IsTrue(dic.HasProperty("prop1"));
     Assert.AreEqual(1, dic["prop1"].ToNumber());
 }
Пример #2
0
        /// <summary>
        /// 15.7.4.6
        /// </summary>
        /// <param name="target"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public JsInstance ToExponentialImpl(JsNumber target, JsInstance[] parameters)
        {
            if (double.IsInfinity(target.ToNumber()) || double.IsNaN(target.ToNumber())) {
                return ToStringImpl(target, new JsInstance[0]);
            }

            int fractions = 16;
            if (parameters.Length > 0) {
                fractions = Convert.ToInt32(parameters[0].ToNumber());
            }

            if (fractions > 20 || fractions < 0) {
                throw new JsException(Global.SyntaxErrorClass.New("Fraction Digits must be greater than 0 and lesser than 20"));
            }

            string format = String.Concat("#.", new String('0', fractions), "e+0");
            return Global.StringClass.New(target.ToNumber().ToString(format, CultureInfo.InvariantCulture));
        }
Пример #3
0
 private static JsString GiveMeJavascript(JsNumber number, JsInstance instance) {
     return new JsString(number + instance.ToString(), JsNull.Instance);
 }
Пример #4
0
        public void Visit(BinaryExpression expression)
        {
            JsInstance old = Result;

            // Evaluates the left expression and saves the value
            expression.LeftExpression.Accept(this);
            JsInstance left = Result;

            //prevents execution of the right hand side if false
            if (expression.Type == BinaryExpressionType.And && !left.ToBoolean())
            {
                Result = left;
                return;
            }

            //prevents execution of the right hand side if true
            if (expression.Type == BinaryExpressionType.Or && left.ToBoolean())
            {
                Result = left;
                return;
            }

            Result = null;

            // Evaluates the right expression and saves the value
            expression.RightExpression.Accept(this);
            JsInstance right = Result;

            Result = old;

            switch (expression.Type)
            {
                case BinaryExpressionType.And:

                    if (left.ToBoolean())
                    {
                        Result = right;
                    }
                    else
                    {
                        Result = JsBoolean.False;
                    }

                    break;

                case BinaryExpressionType.Or:
                    if (left.ToBoolean())
                    {
                        Result = left;
                    }
                    else
                    {
                        Result = right;
                    }

                    break;

                case BinaryExpressionType.Div:
                    var rightNumber = right.ToNumber();
                    var leftNumber = left.ToNumber();

                    if (right == Global.NumberClass["NEGATIVE_INFINITY"] || right == Global.NumberClass["POSITIVE_INFINITY"])
                    {
                        Result = new JsNumber(0);
                    }
                    else if (rightNumber == 0)
                    {
                        Result = leftNumber > 0 ? Global.NumberClass["POSITIVE_INFINITY"] : Global.NumberClass["NEGATIVE_INFINITY"];
                    }
                    else
                    {
                        Result = Global.NumberClass.New(leftNumber / rightNumber);
                    }
                    break;

                case BinaryExpressionType.Equal:
                    if (left == JsUndefined.Instance && right == JsUndefined.Instance || left == JsNull.Instance && right == JsNull.Instance)
                    {
                        Result = JsBoolean.True;
                    }
                    else
                    {
                        if (left == JsUndefined.Instance && right != JsUndefined.Instance || left == JsNull.Instance && right != JsNull.Instance)
                        {
                            Result = JsBoolean.False;
                        }
                        else
                            if (left != JsUndefined.Instance && right == JsUndefined.Instance || left != JsNull.Instance && right == JsNull.Instance)
                            {
                                Result = JsBoolean.False;
                            }
                            else
                            {
                                if (left.Class == JsNumber.TYPEOF || left.Class == JsBoolean.TYPEOF ||
                                    right.Class == JsNumber.TYPEOF || right.Class == JsBoolean.TYPEOF)
                                {
                                    Result = Global.BooleanClass.New(left.ToNumber() == right.ToNumber());
                                }
                                else if (left.Class == JsString.TYPEOF || right.Class == JsString.TYPEOF)
                                {
                                    Result = Global.BooleanClass.New(left.ToString() == right.ToString());
                                }
                                else if (left.Value != null)
                                {
                                    Result = Global.BooleanClass.New(left.Value.Equals(right.Value));
                                }
                                else
                                {
                                    Result = Global.BooleanClass.New(left == right);
                                }
                            }

                    }
                    break;

                case BinaryExpressionType.Greater:
                    // Use the type of the left operand to make the comparison
                    Result = Global.BooleanClass.New(left.ToNumber() > right.ToNumber());
                    break;

                case BinaryExpressionType.GreaterOrEqual:
                    // Use the type of the left operand to make the comparison
                    Result = Global.BooleanClass.New(left.ToNumber() >= right.ToNumber());
                    break;

                case BinaryExpressionType.Lesser:
                    // Use the type of the left operand to make the comparison
                    Result = Global.BooleanClass.New(left.ToNumber() < right.ToNumber());
                    break;

                case BinaryExpressionType.LesserOrEqual:
                    // Use the type of the left operand to make the comparison
                    Result = Global.BooleanClass.New(left.ToNumber() <= right.ToNumber());
                    break;

                case BinaryExpressionType.Minus:
                    Result = Global.NumberClass.New(left.ToNumber() - right.ToNumber());
                    break;

                case BinaryExpressionType.Modulo:
                    if (right == Global.NumberClass["NEGATIVE_INFINITY"] || right == Global.NumberClass["POSITIVE_INFINITY"])
                    {
                        Result = Global.NumberClass["POSITIVE_INFINITY"];
                    }
                    else if (right.ToNumber() == 0)
                    {
                        Result = Global.NumberClass["NaN"];
                    }
                    else
                    {
                        Result = Global.NumberClass.New(left.ToNumber() % right.ToNumber());
                    }
                    break;

                case BinaryExpressionType.NotEqual:

                    if (left == JsUndefined.Instance && right == JsUndefined.Instance || left == JsNull.Instance && right == JsNull.Instance)
                    {
                        Result = JsBoolean.False;
                    }
                    else
                    {
                        if (left == JsUndefined.Instance && right != JsUndefined.Instance || left == JsNull.Instance && right != JsNull.Instance)
                        {
                            Result = JsBoolean.True;
                        }
                        else
                            if (left != JsUndefined.Instance && right == JsUndefined.Instance || left != JsNull.Instance && right == JsNull.Instance)
                            {
                                Result = JsBoolean.True;
                            }
                            else
                            {
                                Result = Global.BooleanClass.New(!left.Value.Equals(right.Value));
                            }
                    }
                    break;

                case BinaryExpressionType.Plus:
                    if (left.Class == JsString.TYPEOF || right.Class == JsString.TYPEOF)
                    {
                        Result = Global.StringClass.New(String.Concat(left.ToString(), right.ToString()));
                    }
                    else
                    {
                        Result = Global.NumberClass.New(left.ToNumber() + right.ToNumber());
                    }
                    break;

                case BinaryExpressionType.Times:
                    Result = Global.NumberClass.New(left.ToNumber() * right.ToNumber());
                    break;

                case BinaryExpressionType.Pow:
                    Result = Global.NumberClass.New(Math.Pow(left.ToNumber(), right.ToNumber()));
                    break;

                case BinaryExpressionType.BitwiseAnd:
                    Result = Global.NumberClass.New(Convert.ToUInt64(left.ToNumber()) & Convert.ToUInt64(right.ToNumber()));
                    break;

                case BinaryExpressionType.BitwiseOr:
                    Result = Global.NumberClass.New(Convert.ToUInt64(left.ToNumber()) | Convert.ToUInt64(right.ToNumber()));
                    break;

                case BinaryExpressionType.BitwiseXOr:
                    Result = Global.NumberClass.New(Convert.ToUInt64(left.ToNumber()) ^ Convert.ToUInt64(right.ToNumber()));
                    break;

                case BinaryExpressionType.Same:
                    // 11.9.6 The Strict Equality Comparison Algorithm
                    if (left.Class != right.Class)
                    {
                        Result = JsBoolean.False;
                    }
                    else if (left.Class == JsUndefined.TYPEOF)
                    {
                        Result = JsBoolean.True;
                    }
                    else if (left.Class == JsNull.TYPEOF)
                    {
                        Result = JsBoolean.True;
                    }
                    else if (left.Class == JsNumber.TYPEOF)
                    {
                        if (left == Global.NumberClass["NaN"] || right == Global.NumberClass["NaN"])
                        {
                            Result = JsBoolean.False;
                        }
                        else if (left.ToNumber() == right.ToNumber())
                        {
                            Result = JsBoolean.True;
                        }
                        else
                            Result = JsBoolean.False;
                    }
                    else if (left.Class == JsString.TYPEOF)
                    {
                        Result = new JsBoolean(left.ToString() == right.ToString());
                    }
                    else if (left.Class == JsBoolean.TYPEOF)
                    {
                        Result = new JsBoolean(left.ToBoolean() == right.ToBoolean());
                    }
                    else if (left == right)
                    {
                        Result = JsBoolean.True;
                    }
                    else
                    {
                        Result = JsBoolean.False;
                    }

                    break;

                case BinaryExpressionType.NotSame:
                    new BinaryExpression(BinaryExpressionType.Same, expression.LeftExpression, expression.RightExpression).Accept(this);
                    Result = new JsBoolean(!Result.ToBoolean());
                    break;

                case BinaryExpressionType.LeftShift:
                    Result = Global.NumberClass.New(Convert.ToUInt64(left.ToNumber()) << Convert.ToUInt16(right.ToNumber()));
                    break;

                case BinaryExpressionType.RightShift:
                    Result = Global.NumberClass.New(Convert.ToUInt64(left.ToNumber()) >> Convert.ToUInt16(right.ToNumber()));
                    break;

                case BinaryExpressionType.UnsignedRightShift:
                    Result = Global.NumberClass.New(Convert.ToUInt64(left.ToNumber()) >> Convert.ToUInt16(right.ToNumber()));
                    break;

                case BinaryExpressionType.InstanceOf:
                    Result = new JsBoolean(left.Class == right.ToString());
                    break;

                case BinaryExpressionType.In:
                    if (right is JsDictionaryObject)
                    {
                        ((JsDictionaryObject)right).HasProperty(left);
                    }
                    else
                    {
                        throw new JintException("Cannot apply 'in' operator to the specified member.");
                    }

                    break;

                default:
                    throw new NotSupportedException("Unkown binary operator");
            }
        }
Пример #5
0
 public JsInstance ToLocaleStringImpl(JsNumber target, JsInstance[] parameters)
 {
     // Remove parameters
     return ToStringImpl(target, new JsInstance[0]);
 }
Пример #6
0
        /// <summary>
        /// 15.7.4.7
        /// </summary>
        /// <param name="target"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public JsInstance ToPrecisionImpl(JsNumber target, JsInstance[] parameters)
        {
            if (double.IsInfinity(target.ToNumber()) || double.IsNaN(target.ToNumber()))
            {
                return ToStringImpl(target, new JsInstance[0]);
            }

            if (parameters.Length == 0)
            {
                throw new JsException(Global.SyntaxErrorClass.New("precision missing"));
            }

            if (parameters[0] == JsUndefined.Instance)
            {
                return ToStringImpl(target, new JsInstance[0]);
            }

            int precision = 0;
            if (parameters.Length > 0)
            {
                precision = Convert.ToInt32(parameters[0].ToNumber());
            }

            if (precision < 1 || precision > 21)
            {
                throw new JsException(Global.RangeErrorClass.New("precision must be between 1 and 21"));
            }

            // Get the number of decimals
            string str = target.ToNumber().ToString("e23", CultureInfo.InvariantCulture);
            int decimals = str.IndexOfAny(new char[] { '.', 'e' });
            decimals = decimals == -1 ? str.Length : decimals;

            precision -= decimals;
            precision = precision < 1 ? 1 : precision;

            return Global.StringClass.New(target.ToNumber().ToString("f" + precision, CultureInfo.InvariantCulture));
        }
Пример #7
0
        /// <summary>
        /// 15.7.4.5
        /// </summary>
        /// <param name="target"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public JsInstance ToFixedImpl(JsNumber target, JsInstance[] parameters)
        {
            int fractions = 0;
            if (parameters.Length > 0)
            {
                fractions = Convert.ToInt32(parameters[0].ToNumber());
            }

            if (fractions > 20 || fractions < 0)
            {
                throw new JsException(Global.SyntaxErrorClass.New("Fraction Digits must be greater than 0 and lesser than 20"));
            }

            if (target == Global.NaN)
            {
                return Global.StringClass.New(target.ToString());
            }

            return Global.StringClass.New(target.ToNumber().ToString("f" + fractions, CultureInfo.InvariantCulture));
        }