diff --git a/boa/src/builtins/value/mod.rs b/boa/src/builtins/value/mod.rs index 8998f6937d1..5647c5b38ee 100644 --- a/boa/src/builtins/value/mod.rs +++ b/boa/src/builtins/value/mod.rs @@ -710,7 +710,7 @@ impl ValueData { Self::String(_) => "string", Self::Boolean(_) => "boolean", Self::Symbol(_) => "symbol", - Self::Null => "null", + Self::Null => "object", Self::Undefined => "undefined", Self::Object(ref o) => { if o.deref().borrow().is_callable() { diff --git a/boa/src/builtins/value/operations.rs b/boa/src/builtins/value/operations.rs index c42e3831bc4..927cadf359e 100644 --- a/boa/src/builtins/value/operations.rs +++ b/boa/src/builtins/value/operations.rs @@ -18,6 +18,10 @@ impl Value { return number::equals(f64::from(self), f64::from(other)); } + if self.is_null() { + return true; + } + same_value_non_number(self, other) } diff --git a/boa/src/exec/mod.rs b/boa/src/exec/mod.rs index 524b693771a..9af6e44f36c 100644 --- a/boa/src/exec/mod.rs +++ b/boa/src/exec/mod.rs @@ -420,11 +420,10 @@ impl Executor for Interpreter { | Node::FunctionExpr(_, _, _) | Node::New(_) | Node::Object(_) - | Node::TypeOf(_) | Node::UnaryOp(_, _) => Value::boolean(true), _ => panic!("SyntaxError: wrong delete argument {}", node), }, - _ => unimplemented!(), + UnaryOp::TypeOf => Value::from(v_a.get_type()), }) } Node::BinOp(BinOp::Bit(ref op), ref a, ref b) => { @@ -607,24 +606,6 @@ impl Executor for Interpreter { } Ok(Value::undefined()) } - Node::TypeOf(ref val_e) => { - let val = self.run(val_e)?; - Ok(Value::from(match *val { - ValueData::Undefined => "undefined", - ValueData::Symbol(_) => "symbol", - ValueData::Null => "object", - ValueData::Boolean(_) => "boolean", - ValueData::Rational(_) | ValueData::Integer(_) => "number", - ValueData::String(_) => "string", - ValueData::Object(ref o) => { - if o.deref().borrow().is_callable() { - "function" - } else { - "object" - } - } - })) - } Node::StatementList(ref list) => { { let env = &mut self.realm.environment; diff --git a/boa/src/exec/tests.rs b/boa/src/exec/tests.rs index 7f3b6f78125..27815b577ac 100644 --- a/boa/src/exec/tests.rs +++ b/boa/src/exec/tests.rs @@ -385,6 +385,63 @@ fn unary_pre() { assert_eq!(&exec(execs_before_dec), "true"); } +#[test] +fn unary_typeof() { + let typeof_string = r#" + const a = String(); + typeof a; + "#; + assert_eq!(&exec(typeof_string), "string"); + + let typeof_int = r#" + let a = 5; + typeof a; + "#; + assert_eq!(&exec(typeof_int), "number"); + + let typeof_rational = r#" + let a = 0.5; + typeof a; + "#; + assert_eq!(&exec(typeof_rational), "number"); + + let typeof_undefined = r#" + let a = undefined; + typeof a; + "#; + assert_eq!(&exec(typeof_undefined), "undefined"); + + let typeof_boolean = r#" + let a = true; + typeof a; + "#; + assert_eq!(&exec(typeof_boolean), "boolean"); + + let typeof_null = r#" + let a = null; + typeof a; + "#; + assert_eq!(&exec(typeof_null), "object"); + + let typeof_object = r#" + let a = {}; + typeof a; + "#; + assert_eq!(&exec(typeof_object), "object"); + + let typeof_symbol = r#" + let a = Symbol(); + typeof a; + "#; + assert_eq!(&exec(typeof_symbol), "symbol"); + + let typeof_function = r#" + let a = function(){}; + typeof a; + "#; + assert_eq!(&exec(typeof_function), "function"); +} + #[test] fn unary_post() { let unary_inc = r#" diff --git a/boa/src/syntax/ast/node.rs b/boa/src/syntax/ast/node.rs index b2288af8ea3..dc27bde520d 100644 --- a/boa/src/syntax/ast/node.rs +++ b/boa/src/syntax/ast/node.rs @@ -469,20 +469,6 @@ pub enum Node { /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw Throw(Box), - /// The `typeof` operator returns a string indicating the type of the unevaluated operand. - /// - /// Syntax: `typeof operand` - /// - /// Returns a string indicating the type of the unevaluated operand. - /// - /// More information: - /// - [ECMAScript reference][spec] - /// - [MDN documentation][mdn] - /// - /// [spec]: https://tc39.es/ecma262/#sec-typeof-operator - /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof - TypeOf(Box), - /// The `try...catch` statement marks a block of statements to try and specifies a response /// should an exception be thrown. /// @@ -564,7 +550,7 @@ pub enum Node { impl Operator for Node { fn get_assoc(&self) -> bool { match *self { - Self::UnaryOp(_, _) | Self::TypeOf(_) | Self::If(_, _, _) | Self::Assign(_, _) => false, + Self::UnaryOp(_, _) | Self::If(_, _, _) | Self::Assign(_, _) => false, _ => true, } } @@ -580,7 +566,7 @@ impl Operator for Node { Self::UnaryOp(UnaryOp::Not, _) | Self::UnaryOp(UnaryOp::Tilde, _) | Self::UnaryOp(UnaryOp::Minus, _) - | Self::TypeOf(_) => 4, + | Self::UnaryOp(UnaryOp::TypeOf, _) => 4, Self::BinOp(op, _, _) => op.get_precedence(), Self::If(_, _, _) => 15, // 16 should be yield @@ -848,14 +834,6 @@ impl Node { Self::Throw(val.into()) } - /// Creates a `TypeOf` AST node. - pub fn type_of(expr: E) -> Self - where - E: Into>, - { - Self::TypeOf(expr.into()) - } - /// Creates a `Try` AST node. pub fn try_node(try_node: T, catch: OC, param: OP, finally: OF) -> Self where @@ -1116,7 +1094,6 @@ impl Node { } Ok(()) } - Self::TypeOf(ref e) => write!(f, "typeof {}", e), } } }