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()); }
/// <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)); }
private static JsString GiveMeJavascript(JsNumber number, JsInstance instance) { return new JsString(number + instance.ToString(), JsNull.Instance); }
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"); } }
public JsInstance ToLocaleStringImpl(JsNumber target, JsInstance[] parameters) { // Remove parameters return ToStringImpl(target, new JsInstance[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)); }
/// <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)); }