public static JsValue Compare(JsValue x, JsValue y, bool leftFirst = true) { JsValue px, py; if (leftFirst) { px = TypeConverter.ToPrimitive(x, Types.Number); py = TypeConverter.ToPrimitive(y, Types.Number); } else { py = TypeConverter.ToPrimitive(y, Types.Number); px = TypeConverter.ToPrimitive(x, Types.Number); } var typea = px.Type; var typeb = py.Type; if (typea != Types.String || typeb != Types.String) { var nx = TypeConverter.ToNumber(px); var ny = TypeConverter.ToNumber(py); if (double.IsNaN(nx) || double.IsNaN(ny)) { return(Undefined.Instance); } if (nx.Equals(ny)) { return(false); } if (double.IsPositiveInfinity(nx)) { return(false); } if (double.IsPositiveInfinity(ny)) { return(true); } if (double.IsNegativeInfinity(ny)) { return(false); } if (double.IsNegativeInfinity(nx)) { return(true); } return(nx < ny); } else { return(String.CompareOrdinal(TypeConverter.ToString(x), TypeConverter.ToString(y)) < 0); } }
public static bool Equal(JsValue x, JsValue y) { var typex = x.Type; var typey = y.Type; if (typex == typey) { return(StrictlyEqual(x, y)); } if (x == Null.Instance && y == Undefined.Instance) { return(true); } if (x == Undefined.Instance && y == Null.Instance) { return(true); } if (typex == Types.Number && typey == Types.String) { return(Equal(x, TypeConverter.ToNumber(y))); } if (typex == Types.String && typey == Types.Number) { return(Equal(TypeConverter.ToNumber(x), y)); } if (typex == Types.Boolean) { return(Equal(TypeConverter.ToNumber(x), y)); } if (typey == Types.Boolean) { return(Equal(x, TypeConverter.ToNumber(y))); } if (typey == Types.Object && (typex == Types.String || typex == Types.Number)) { return(Equal(x, TypeConverter.ToPrimitive(y))); } if (typex == Types.Object && (typey == Types.String || typey == Types.Number)) { return(Equal(TypeConverter.ToPrimitive(x), y)); } return(false); }
public JsValue EvaluateAssignmentExpression(AssignmentExpression assignmentExpression) { var lref = EvaluateExpression(assignmentExpression.Left) as Reference; JsValue rval = _engine.GetValue(EvaluateExpression(assignmentExpression.Right)); if (lref == null) { throw new JavaScriptException(_engine.ReferenceError); } if (assignmentExpression.Operator == AssignmentOperator.Assign) // "=" { if (lref.IsStrict() && lref.GetBase().TryCast <EnvironmentRecord>() != null && (lref.GetReferencedName() == "eval" || lref.GetReferencedName() == "arguments")) { throw new JavaScriptException(_engine.SyntaxError); } _engine.PutValue(lref, rval); return(rval); } JsValue lval = _engine.GetValue(lref); switch (assignmentExpression.Operator) { case AssignmentOperator.PlusAssign: var lprim = TypeConverter.ToPrimitive(lval); var rprim = TypeConverter.ToPrimitive(rval); if (lprim.IsString() || rprim.IsString()) { lval = TypeConverter.ToString(lprim) + TypeConverter.ToString(rprim); } else { lval = TypeConverter.ToNumber(lprim) + TypeConverter.ToNumber(rprim); } break; case AssignmentOperator.MinusAssign: lval = TypeConverter.ToNumber(lval) - TypeConverter.ToNumber(rval); break; case AssignmentOperator.TimesAssign: if (lval == Undefined.Instance || rval == Undefined.Instance) { lval = Undefined.Instance; } else { lval = TypeConverter.ToNumber(lval) * TypeConverter.ToNumber(rval); } break; case AssignmentOperator.DivideAssign: lval = Divide(lval, rval); break; case AssignmentOperator.ModuloAssign: if (lval == Undefined.Instance || rval == Undefined.Instance) { lval = Undefined.Instance; } else { lval = TypeConverter.ToNumber(lval) % TypeConverter.ToNumber(rval); } break; case AssignmentOperator.BitwiseAndAssign: lval = TypeConverter.ToInt32(lval) & TypeConverter.ToInt32(rval); break; case AssignmentOperator.BitwiseOrAssign: lval = TypeConverter.ToInt32(lval) | TypeConverter.ToInt32(rval); break; case AssignmentOperator.BitwiseXOrAssign: lval = TypeConverter.ToInt32(lval) ^ TypeConverter.ToInt32(rval); break; case AssignmentOperator.LeftShiftAssign: lval = TypeConverter.ToInt32(lval) << (int)(TypeConverter.ToUint32(rval) & 0x1F); break; case AssignmentOperator.RightShiftAssign: lval = TypeConverter.ToInt32(lval) >> (int)(TypeConverter.ToUint32(rval) & 0x1F); break; case AssignmentOperator.UnsignedRightShiftAssign: lval = (uint)TypeConverter.ToInt32(lval) >> (int)(TypeConverter.ToUint32(rval) & 0x1F); break; default: throw new NotImplementedException(); } _engine.PutValue(lref, lval); return(lval); }
public static bool Equal(JsValue x, JsValue y) { var typex = x.Type; var typey = y.Type; if (typex == typey) { if (typex == Types.Undefined || typex == Types.Null) { return(true); } if (typex == Types.Number) { var nx = TypeConverter.ToNumber(x); var ny = TypeConverter.ToNumber(y); if (double.IsNaN(nx) || double.IsNaN(ny)) { return(false); } if (nx.Equals(ny)) { return(true); } return(false); } if (typex == Types.String) { return(TypeConverter.ToString(x) == TypeConverter.ToString(y)); } if (typex == Types.Boolean) { return(x.AsBoolean() == y.AsBoolean()); } return(x == y); } if (x == Null.Instance && y == Undefined.Instance) { return(true); } if (x == Undefined.Instance && y == Null.Instance) { return(true); } if (typex == Types.Number && typey == Types.String) { return(Equal(x, TypeConverter.ToNumber(y))); } if (typex == Types.String && typey == Types.Number) { return(Equal(TypeConverter.ToNumber(x), y)); } if (typex == Types.Boolean) { return(Equal(TypeConverter.ToNumber(x), y)); } if (typey == Types.Boolean) { return(Equal(x, TypeConverter.ToNumber(y))); } if (typey == Types.Object && (typex == Types.String || typex == Types.Number)) { return(Equal(x, TypeConverter.ToPrimitive(y))); } if (typex == Types.Object && (typey == Types.String || typey == Types.Number)) { return(Equal(TypeConverter.ToPrimitive(x), y)); } return(false); }
public JsValue EvaluateBinaryExpression(BinaryExpression expression) { var leftExpression = EvaluateExpression(expression.Left); JsValue left = _engine.GetValue(leftExpression); var rightExpression = EvaluateExpression(expression.Right); JsValue right = _engine.GetValue(rightExpression); JsValue value; switch (expression.Operator) { case BinaryOperator.Plus: var lprim = TypeConverter.ToPrimitive(left); var rprim = TypeConverter.ToPrimitive(right); if (lprim.IsString() || rprim.IsString()) { value = TypeConverter.ToString(lprim) + TypeConverter.ToString(rprim); } else { value = TypeConverter.ToNumber(lprim) + TypeConverter.ToNumber(rprim); } break; case BinaryOperator.Minus: value = TypeConverter.ToNumber(left) - TypeConverter.ToNumber(right); break; case BinaryOperator.Times: if (left == Undefined.Instance || right == Undefined.Instance) { value = Undefined.Instance; } else { value = TypeConverter.ToNumber(left) * TypeConverter.ToNumber(right); } break; case BinaryOperator.Divide: value = Divide(left, right); break; case BinaryOperator.Modulo: if (left == Undefined.Instance || right == Undefined.Instance) { value = Undefined.Instance; } else { value = TypeConverter.ToNumber(left) % TypeConverter.ToNumber(right); } break; case BinaryOperator.Equal: value = Equal(left, right); break; case BinaryOperator.NotEqual: value = !Equal(left, right); break; case BinaryOperator.Greater: value = Compare(right, left, false); if (value == Undefined.Instance) { value = false; } break; case BinaryOperator.GreaterOrEqual: value = Compare(left, right); if (value == Undefined.Instance || value.AsBoolean()) { value = false; } else { value = true; } break; case BinaryOperator.Less: value = Compare(left, right); if (value == Undefined.Instance) { value = false; } break; case BinaryOperator.LessOrEqual: value = Compare(right, left, false); if (value == Undefined.Instance || value.AsBoolean()) { value = false; } else { value = true; } break; case BinaryOperator.StrictlyEqual: return(StrictlyEqual(left, right)); case BinaryOperator.StricltyNotEqual: return(!StrictlyEqual(left, right)); case BinaryOperator.BitwiseAnd: return(TypeConverter.ToInt32(left) & TypeConverter.ToInt32(right)); case BinaryOperator.BitwiseOr: return(TypeConverter.ToInt32(left) | TypeConverter.ToInt32(right)); case BinaryOperator.BitwiseXOr: return(TypeConverter.ToInt32(left) ^ TypeConverter.ToInt32(right)); case BinaryOperator.LeftShift: return(TypeConverter.ToInt32(left) << (int)(TypeConverter.ToUint32(right) & 0x1F)); case BinaryOperator.RightShift: return(TypeConverter.ToInt32(left) >> (int)(TypeConverter.ToUint32(right) & 0x1F)); case BinaryOperator.UnsignedRightShift: return((uint)TypeConverter.ToInt32(left) >> (int)(TypeConverter.ToUint32(right) & 0x1F)); case BinaryOperator.InstanceOf: var f = right.TryCast <FunctionInstance>(); if (f == null) { throw new JavaScriptException(_engine.TypeError, "instanceof can only be used with a function object"); } value = f.HasInstance(left); break; case BinaryOperator.In: if (!right.IsObject()) { throw new JavaScriptException(_engine.TypeError, "in can only be used with an object"); } value = right.AsObject().HasProperty(TypeConverter.ToString(left)); break; default: throw new NotImplementedException(); } return(value); }