Skip to content

Commit

Permalink
Resolved #359
Browse files Browse the repository at this point in the history
Removed Node::TypeOf, implemented UnaryOp::TypeOf, and added tests
  • Loading branch information
JavedNissar committed May 14, 2020
1 parent 402041d commit 08760f2
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 46 deletions.
34 changes: 15 additions & 19 deletions boa/src/exec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,10 +420,24 @@ impl Executor for Interpreter {
| Node::FunctionExpr(_, _, _)
| Node::New(_)
| Node::Object(_)
| Node::TypeOf(_)
| Node::UnaryOp(_, _) => Value::boolean(true),
_ => panic!("SyntaxError: wrong delete argument {}", node),
},
UnaryOp::TypeOf => Value::from(match v_a.data() {
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"
}
}
}),
_ => unimplemented!(),
})
}
Expand Down Expand Up @@ -607,24 +621,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;
Expand Down
56 changes: 56 additions & 0 deletions boa/src/exec/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,62 @@ fn unary_pre() {
assert_eq!(&exec(execs_before_dec), "true");
}

#[test]
fn unary_typeof() {
let string_type_result = String::from("string");
let number_type_result = String::from("number");
let undefined_type_result = String::from("undefined");
let boolean_type_result = String::from("boolean");
let object_type_result = String::from("object");
let function_type_result = String::from("function");
let symbol_type_result = String::from("symbol");
let typeof_string = r#"
const a = String();
typeof a;
"#;
assert_eq!(exec(typeof_string), string_type_result);
let typeof_int = r#"
let a = 5;
typeof a;
"#;
assert_eq!(exec(typeof_int), number_type_result);
let typeof_rational = r#"
let a = 0.5;
typeof a;
"#;
assert_eq!(exec(typeof_rational), number_type_result);
let typeof_undefined = r#"
let a = undefined;
typeof a;
"#;
assert_eq!(exec(typeof_undefined), undefined_type_result);
let typeof_boolean = r#"
let a = true;
typeof a;
"#;
assert_eq!(exec(typeof_boolean), boolean_type_result);
let typeof_null = r#"
let a = null;
typeof a;
"#;
assert_eq!(exec(typeof_null), object_type_result);
let typeof_object = r#"
let a = {};
typeof a;
"#;
assert_eq!(exec(typeof_object), object_type_result);
let typeof_symbol = r#"
let a = Symbol();
typeof a;
"#;
assert_eq!(exec(typeof_symbol), symbol_type_result);
let typeof_function = r#"
let a = function(){};
typeof a;
"#;
assert_eq!(exec(typeof_function), function_type_result);
}

#[test]
fn unary_post() {
let unary_inc = r#"
Expand Down
30 changes: 3 additions & 27 deletions boa/src/syntax/ast/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -469,22 +469,7 @@ 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.
/// The `try...catch` statement marks a block of statements to try and specifies a response should an exception be thrown.
///
/// The `try` statement consists of a `try`-block, which contains one or more statements. `{}`
/// must always be used, even for single statements. At least one `catch`-block, or a
Expand Down Expand Up @@ -564,7 +549,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,
}
}
Expand All @@ -580,7 +565,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
Expand Down Expand Up @@ -848,14 +833,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
Expand Down Expand Up @@ -1116,7 +1093,6 @@ impl Node {
}
Ok(())
}
Self::TypeOf(ref e) => write!(f, "typeof {}", e),
}
}
}
Expand Down

0 comments on commit 08760f2

Please sign in to comment.