Browse Source

Resolved #359 (#396)

Removed Node::TypeOf, implemented UnaryOp::TypeOf, and added tests
pull/418/head
Javed Nissar 4 years ago committed by GitHub
parent
commit
29abfd6147
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      boa/src/builtins/value/mod.rs
  2. 8
      boa/src/builtins/value/operations.rs
  3. 22
      boa/src/exec/mod.rs
  4. 57
      boa/src/exec/tests.rs
  5. 27
      boa/src/syntax/ast/node.rs

2
boa/src/builtins/value/mod.rs

@ -755,7 +755,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() {

8
boa/src/builtins/value/operations.rs

@ -19,6 +19,14 @@ impl Value {
return number::equals(f64::from(self), f64::from(other));
}
//Null has to be handled specially because "typeof null" returns object and if we managed
//this without a special case we would compare self and other as if they were actually
//objects which unfortunately fails
//Specification Link: https://tc39.es/ecma262/#sec-typeof-operator
if self.is_null() {
return true;
}
same_value_non_number(self, other)
}

22
boa/src/exec/mod.rs

@ -362,11 +362,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) => {
@ -549,25 +548,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"
}
}
ValueData::BigInt(_) => "bigint",
}))
}
Node::StatementList(ref list) => {
let mut obj = Value::null();
for (i, item) in list.iter().enumerate() {

57
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#"

27
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<Node>),
/// 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<Node>),
/// 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<E>(expr: E) -> Self
where
E: Into<Box<Self>>,
{
Self::TypeOf(expr.into())
}
/// Creates a `Try` AST node.
pub fn try_node<T, OC, OP, OF, C, P, F>(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),
}
}
}

Loading…
Cancel
Save