diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index 5f1eab55e5..0f5753d6a3 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -130,21 +130,21 @@ CallExpression::ThisAndCallee CallExpression::compute_this_and_callee(Interprete { auto& vm = interpreter.vm(); - if (is_new_expression()) { + if (is(*this)) { // Computing |this| is irrelevant for "new" expression. return { js_undefined(), m_callee->execute(interpreter, global_object) }; } - if (m_callee->is_super_expression()) { + if (is(*m_callee)) { // If we are calling super, |this| has not been initialized yet, and would not be meaningful to provide. auto new_target = vm.get_new_target(); ASSERT(new_target.is_function()); return { js_undefined(), new_target }; } - if (m_callee->is_member_expression()) { + if (is(*m_callee)) { auto& member_expression = static_cast(*m_callee); - bool is_super_property_lookup = member_expression.object().is_super_expression(); + bool is_super_property_lookup = is(member_expression.object()); auto lookup_target = is_super_property_lookup ? interpreter.current_environment()->get_super_base() : member_expression.object().execute(interpreter, global_object); if (vm.exception()) return {}; @@ -178,12 +178,12 @@ Value CallExpression::execute(Interpreter& interpreter, GlobalObject& global_obj ASSERT(!callee.is_empty()); if (!callee.is_function() - || (is_new_expression() && (is(callee.as_object()) && !static_cast(callee.as_object()).has_constructor()))) { + || (is(*this) && (is(callee.as_object()) && !static_cast(callee.as_object()).has_constructor()))) { String error_message; - auto call_type = is_new_expression() ? "constructor" : "function"; - if (m_callee->is_identifier() || m_callee->is_member_expression()) { + auto call_type = is(*this) ? "constructor" : "function"; + if (is(*m_callee) || is(*m_callee)) { String expression_string; - if (m_callee->is_identifier()) { + if (is(*m_callee)) { expression_string = static_cast(*m_callee).string(); } else { expression_string = static_cast(*m_callee).to_string_approximation(); @@ -220,11 +220,11 @@ Value CallExpression::execute(Interpreter& interpreter, GlobalObject& global_obj Object* new_object = nullptr; Value result; - if (is_new_expression()) { + if (is(*this)) { result = vm.construct(function, function, move(arguments), global_object); if (result.is_object()) new_object = &result.as_object(); - } else if (m_callee->is_super_expression()) { + } else if (is(*m_callee)) { auto* super_constructor = interpreter.current_environment()->current_function()->prototype(); // FIXME: Functions should track their constructor kind. if (!super_constructor || !super_constructor->is_function()) { @@ -243,7 +243,7 @@ Value CallExpression::execute(Interpreter& interpreter, GlobalObject& global_obj if (vm.exception()) return {}; - if (is_new_expression()) { + if (is(*this)) { if (result.is_object()) return result; return new_object; @@ -371,7 +371,7 @@ Value ForStatement::execute(Interpreter& interpreter, GlobalObject& global_objec RefPtr wrapper; - if (m_init && m_init->is_variable_declaration() && static_cast(m_init.ptr())->declaration_kind() != DeclarationKind::Var) { + if (m_init && is(*m_init) && static_cast(*m_init).declaration_kind() != DeclarationKind::Var) { wrapper = create_ast_node(source_range()); NonnullRefPtrVector decls; decls.append(*static_cast(m_init.ptr())); @@ -444,20 +444,20 @@ Value ForStatement::execute(Interpreter& interpreter, GlobalObject& global_objec return last_value; } -static FlyString variable_from_for_declaration(Interpreter& interpreter, GlobalObject& global_object, NonnullRefPtr node, RefPtr wrapper) +static FlyString variable_from_for_declaration(Interpreter& interpreter, GlobalObject& global_object, const ASTNode& node, RefPtr wrapper) { FlyString variable_name; - if (node->is_variable_declaration()) { - auto* variable_declaration = static_cast(node.ptr()); - ASSERT(!variable_declaration->declarations().is_empty()); - if (variable_declaration->declaration_kind() != DeclarationKind::Var) { - wrapper = create_ast_node(node->source_range()); + if (is(node)) { + auto& variable_declaration = static_cast(node); + ASSERT(!variable_declaration.declarations().is_empty()); + if (variable_declaration.declaration_kind() != DeclarationKind::Var) { + wrapper = create_ast_node(node.source_range()); interpreter.enter_scope(*wrapper, ScopeType::Block, global_object); } - variable_declaration->execute(interpreter, global_object); - variable_name = variable_declaration->declarations().first().id().string(); - } else if (node->is_identifier()) { - variable_name = static_cast(*node).string(); + variable_declaration.execute(interpreter, global_object); + variable_name = variable_declaration.declarations().first().id().string(); + } else if (is(node)) { + variable_name = static_cast(node).string(); } else { ASSERT_NOT_REACHED(); } @@ -469,7 +469,7 @@ Value ForInStatement::execute(Interpreter& interpreter, GlobalObject& global_obj interpreter.enter_node(*this); ScopeGuard exit_node { [&] { interpreter.exit_node(*this); } }; - if (!m_lhs->is_variable_declaration() && !m_lhs->is_identifier()) { + if (!is(*m_lhs) && !is(*m_lhs)) { // FIXME: Implement "for (foo.bar in baz)", "for (foo[0] in bar)" ASSERT_NOT_REACHED(); } @@ -516,7 +516,7 @@ Value ForOfStatement::execute(Interpreter& interpreter, GlobalObject& global_obj interpreter.enter_node(*this); ScopeGuard exit_node { [&] { interpreter.exit_node(*this); } }; - if (!m_lhs->is_variable_declaration() && !m_lhs->is_identifier()) { + if (!is(*m_lhs) && !is(*m_lhs)) { // FIXME: Implement "for (foo.bar of baz)", "for (foo[0] of bar)" ASSERT_NOT_REACHED(); } @@ -700,7 +700,7 @@ Value UnaryExpression::execute(Interpreter& interpreter, GlobalObject& global_ob } Value lhs_result; - if (m_op == UnaryOp::Typeof && m_lhs->is_identifier()) { + if (m_op == UnaryOp::Typeof && is(*m_lhs)) { auto reference = m_lhs->to_reference(interpreter, global_object); if (interpreter.exception()) { return {}; @@ -1052,7 +1052,7 @@ void UnaryExpression::dump(int indent) const void CallExpression::dump(int indent) const { print_indent(indent); - if (is_new_expression()) + if (is(*this)) outln("CallExpression [new]"); else outln("CallExpression"); @@ -1744,7 +1744,7 @@ void MemberExpression::dump(int indent) const PropertyName MemberExpression::computed_property_name(Interpreter& interpreter, GlobalObject& global_object) const { if (!is_computed()) { - ASSERT(m_property->is_identifier()); + ASSERT(is(*m_property)); return static_cast(*m_property).string(); } auto value = m_property->execute(interpreter, global_object); @@ -1757,11 +1757,11 @@ PropertyName MemberExpression::computed_property_name(Interpreter& interpreter, String MemberExpression::to_string_approximation() const { String object_string = ""; - if (m_object->is_identifier()) + if (is(*m_object)) object_string = static_cast(*m_object).string(); if (is_computed()) return String::formatted("{}[]", object_string); - ASSERT(m_property->is_identifier()); + ASSERT(is(*m_property)); return String::formatted("{}.{}", object_string, static_cast(*m_property).string()); } @@ -1887,7 +1887,7 @@ Value ArrayExpression::execute(Interpreter& interpreter, GlobalObject& global_ob if (interpreter.exception()) return {}; - if (element->is_spread_expression()) { + if (is(*element)) { get_iterator_values(global_object, value, [&](Value iterator_value) { array->indexed_properties().append(iterator_value); return IterationDecision::Continue; diff --git a/Libraries/LibJS/AST.h b/Libraries/LibJS/AST.h index 4924f79ac9..fcc12d0460 100644 --- a/Libraries/LibJS/AST.h +++ b/Libraries/LibJS/AST.h @@ -56,17 +56,6 @@ public: virtual const char* class_name() const = 0; virtual Value execute(Interpreter&, GlobalObject&) const = 0; virtual void dump(int indent) const; - virtual bool is_identifier() const { return false; } - virtual bool is_spread_expression() const { return false; } - virtual bool is_member_expression() const { return false; } - virtual bool is_scope_node() const { return false; } - virtual bool is_program() const { return false; } - virtual bool is_variable_declaration() const { return false; } - virtual bool is_call_expression() const { return false; } - virtual bool is_new_expression() const { return false; } - virtual bool is_super_expression() const { return false; } - virtual bool is_expression_statement() const { return false; }; - virtual bool is_string_literal() const { return false; }; const SourceRange& source_range() const { return m_source_range; } SourceRange& source_range() { return m_source_range; } @@ -125,7 +114,6 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual bool is_expression_statement() const override { return true; } const Expression& expression() const { return m_expression; }; @@ -165,7 +153,6 @@ protected: } private: - virtual bool is_scope_node() const final { return true; } NonnullRefPtrVector m_children; NonnullRefPtrVector m_variables; NonnullRefPtrVector m_functions; @@ -186,7 +173,6 @@ public: private: bool m_is_strict_mode { false }; - virtual bool is_program() const override { return true; } virtual const char* class_name() const override { return "Program"; } }; @@ -695,7 +681,6 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual bool is_string_literal() const override { return true; }; StringView value() const { return m_value; } bool is_use_strict_directive() const { return m_is_use_strict_directive; }; @@ -755,7 +740,6 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual bool is_identifier() const override { return true; } virtual Reference to_reference(Interpreter&, GlobalObject&) const override; private: @@ -808,7 +792,6 @@ public: virtual void dump(int indent) const override; private: - virtual bool is_super_expression() const override { return true; } virtual const char* class_name() const override { return "SuperExpression"; } }; @@ -863,7 +846,6 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual bool is_spread_expression() const override { return true; } private: virtual const char* class_name() const override { return "SpreadExpression"; } @@ -903,7 +885,6 @@ public: private: virtual const char* class_name() const override { return "CallExpression"; } - virtual bool is_call_expression() const override { return true; } struct ThisAndCallee { Value this_value; @@ -924,8 +905,6 @@ public: private: virtual const char* class_name() const override { return "NewExpression"; } - virtual bool is_call_expression() const override { return false; } - virtual bool is_new_expression() const override { return true; } }; enum class AssignmentOp { @@ -1037,7 +1016,6 @@ public: { } - virtual bool is_variable_declaration() const override { return true; } DeclarationKind declaration_kind() const { return m_declaration_kind; } virtual Value execute(Interpreter&, GlobalObject&) const override; @@ -1198,7 +1176,6 @@ public: String to_string_approximation() const; private: - virtual bool is_member_expression() const override { return true; } virtual const char* class_name() const override { return "MemberExpression"; } NonnullRefPtr m_object; diff --git a/Libraries/LibJS/Interpreter.cpp b/Libraries/LibJS/Interpreter.cpp index b62c5482a0..72e4a9587a 100644 --- a/Libraries/LibJS/Interpreter.cpp +++ b/Libraries/LibJS/Interpreter.cpp @@ -107,7 +107,7 @@ void Interpreter::enter_scope(const ScopeNode& scope_node, ScopeType scope_type, for (auto& declaration : scope_node.variables()) { for (auto& declarator : declaration.declarations()) { - if (scope_node.is_program()) { + if (is(scope_node)) { global_object.put(declarator.id().string(), js_undefined()); if (exception()) return; @@ -160,7 +160,7 @@ void Interpreter::push_scope(ScopeFrame frame) Value Interpreter::execute_statement(GlobalObject& global_object, const Statement& statement, ScopeType scope_type) { - if (!statement.is_scope_node()) + if (!is(statement)) return statement.execute(*this, global_object); auto& block = static_cast(statement); diff --git a/Libraries/LibJS/Parser.cpp b/Libraries/LibJS/Parser.cpp index e0d0e33b3e..ac8fbeb2e9 100644 --- a/Libraries/LibJS/Parser.cpp +++ b/Libraries/LibJS/Parser.cpp @@ -35,11 +35,11 @@ namespace JS { static bool statement_is_use_strict_directive(NonnullRefPtr statement) { - if (!statement->is_expression_statement()) + if (!is(*statement)) return false; auto& expression_statement = static_cast(*statement); auto& expression = expression_statement.expression(); - if (!expression.is_string_literal()) + if (!is(expression)) return false; return static_cast(expression).is_use_strict_directive(); } @@ -711,7 +711,7 @@ NonnullRefPtr Parser::parse_unary_prefixed_expression() auto rhs = parse_expression(precedence, associativity); // FIXME: Apparently for functions this should also not be enforced on a parser level, // other engines throw ReferenceError for ++foo() - if (!rhs->is_identifier() && !rhs->is_member_expression()) + if (!is(*rhs) && !is(*rhs)) syntax_error(String::formatted("Right-hand side of prefix increment operator must be identifier or member expression, got {}", rhs->class_name()), rhs_start); return create_ast_node({ rule_start.position(), position() }, UpdateOp::Increment, move(rhs), true); } @@ -721,7 +721,7 @@ NonnullRefPtr Parser::parse_unary_prefixed_expression() auto rhs = parse_expression(precedence, associativity); // FIXME: Apparently for functions this should also not be enforced on a parser level, // other engines throw ReferenceError for --foo() - if (!rhs->is_identifier() && !rhs->is_member_expression()) + if (!is(*rhs) && !is(*rhs)) syntax_error(String::formatted("Right-hand side of prefix decrement operator must be identifier or member expression, got {}", rhs->class_name()), rhs_start); return create_ast_node({ rule_start.position(), position() }, UpdateOp::Decrement, move(rhs), true); } @@ -1120,14 +1120,14 @@ NonnullRefPtr Parser::parse_secondary_expression(NonnullRefPtris_identifier() && !lhs->is_member_expression()) + if (!is(*lhs) && !is(*lhs)) syntax_error(String::formatted("Left-hand side of postfix increment operator must be identifier or member expression, got {}", lhs->class_name())); consume(); return create_ast_node({ rule_start.position(), position() }, UpdateOp::Increment, move(lhs)); case TokenType::MinusMinus: // FIXME: Apparently for functions this should also not be enforced on a parser level, // other engines throw ReferenceError for foo()-- - if (!lhs->is_identifier() && !lhs->is_member_expression()) + if (!is(*lhs) && !is(*lhs)) syntax_error(String::formatted("Left-hand side of postfix increment operator must be identifier or member expression, got {}", lhs->class_name())); consume(); return create_ast_node({ rule_start.position(), position() }, UpdateOp::Decrement, move(lhs)); @@ -1175,13 +1175,13 @@ NonnullRefPtr Parser::parse_assignment_expression(Assignme || match(TokenType::DoublePipeEquals) || match(TokenType::DoubleQuestionMarkEquals)); consume(); - if (!lhs->is_identifier() && !lhs->is_member_expression() && !lhs->is_call_expression()) { + if (!is(*lhs) && !is(*lhs) && !is(*lhs)) { syntax_error("Invalid left-hand side in assignment"); - } else if (m_parser_state.m_strict_mode && lhs->is_identifier()) { + } else if (m_parser_state.m_strict_mode && is(*lhs)) { auto name = static_cast(*lhs).string(); if (name == "eval" || name == "arguments") syntax_error(String::formatted("'{}' cannot be assigned to in strict mode code", name)); - } else if (m_parser_state.m_strict_mode && lhs->is_call_expression()) { + } else if (m_parser_state.m_strict_mode && is(*lhs)) { syntax_error("Cannot assign to function call"); } return create_ast_node({ rule_start.position(), position() }, assignment_op, move(lhs), parse_expression(min_precedence, associativity)); @@ -1190,7 +1190,7 @@ NonnullRefPtr Parser::parse_assignment_expression(Assignme NonnullRefPtr Parser::parse_call_expression(NonnullRefPtr lhs) { auto rule_start = push_start(); - if (!m_parser_state.m_allow_super_constructor_call && lhs->is_super_expression()) + if (!m_parser_state.m_allow_super_constructor_call && is(*lhs)) syntax_error("'super' keyword unexpected here"); consume(TokenType::ParenOpen); @@ -1777,7 +1777,7 @@ NonnullRefPtr Parser::parse_for_statement() NonnullRefPtr Parser::parse_for_in_of_statement(NonnullRefPtr lhs) { auto rule_start = push_start(); - if (lhs->is_variable_declaration()) { + if (is(*lhs)) { auto declarations = static_cast(*lhs).declarations(); if (declarations.size() > 1) syntax_error("multiple declarations not allowed in for..in/of"); diff --git a/Libraries/LibJS/Runtime/ScriptFunction.cpp b/Libraries/LibJS/Runtime/ScriptFunction.cpp index 581b73edba..c5fef18602 100644 --- a/Libraries/LibJS/Runtime/ScriptFunction.cpp +++ b/Libraries/LibJS/Runtime/ScriptFunction.cpp @@ -94,7 +94,7 @@ LexicalEnvironment* ScriptFunction::create_environment() variables.set(parameter.name, { js_undefined(), DeclarationKind::Var }); } - if (body().is_scope_node()) { + if (is(body())) { for (auto& declaration : static_cast(body()).variables()) { for (auto& declarator : declaration.declarations()) { variables.set(declarator.id().string(), { js_undefined(), DeclarationKind::Var });