Example #1
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);
        }
Example #2
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);
        }
Example #3
0
        public JsValue EvaluateUnaryExpression(UnaryExpression unaryExpression)
        {
            var       value = _engine.EvaluateExpression(unaryExpression.Argument);
            Reference r;

            switch (unaryExpression.Operator)
            {
            case UnaryOperator.Plus:
                return(TypeConverter.ToNumber(_engine.GetValue(value)));

            case UnaryOperator.Minus:
                var n = TypeConverter.ToNumber(_engine.GetValue(value));
                return(double.IsNaN(n) ? double.NaN : n *-1);

            case UnaryOperator.BitwiseNot:
                return(~TypeConverter.ToInt32(_engine.GetValue(value)));

            case UnaryOperator.LogicalNot:
                return(!TypeConverter.ToBoolean(_engine.GetValue(value)));

            case UnaryOperator.Delete:
                r = value as Reference;
                if (r == null)
                {
                    return(true);
                }
                if (r.IsUnresolvableReference())
                {
                    if (r.IsStrict())
                    {
                        throw new JavaScriptException(_engine.SyntaxError);
                    }

                    return(true);
                }
                if (r.IsPropertyReference())
                {
                    var o = TypeConverter.ToObject(_engine, r.GetBase());
                    return(o.Delete(r.GetReferencedName(), r.IsStrict()));
                }
                if (r.IsStrict())
                {
                    throw new JavaScriptException(_engine.SyntaxError);
                }
                var bindings = r.GetBase().TryCast <EnvironmentRecord>();
                return(bindings.DeleteBinding(r.GetReferencedName()));

            case UnaryOperator.Void:
                _engine.GetValue(value);
                return(Undefined.Instance);

            case UnaryOperator.TypeOf:
                r = value as Reference;
                if (r != null)
                {
                    if (r.IsUnresolvableReference())
                    {
                        return("undefined");
                    }
                }
                var v = _engine.GetValue(value);
                if (v == Undefined.Instance)
                {
                    return("undefined");
                }
                if (v == Null.Instance)
                {
                    return("object");
                }
                switch (v.Type)
                {
                case Types.Boolean: return("boolean");

                case Types.Number: return("number");

                case Types.String: return("string");
                }
                if (v.TryCast <ICallable>() != null)
                {
                    return("function");
                }
                return("object");

            default:
                throw new ArgumentException();
            }
        }