Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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);
        }