diff --git a/Libraries/LibGUI/JSSyntaxHighlighter.cpp b/Libraries/LibGUI/JSSyntaxHighlighter.cpp index 3527f21866..1659fd4263 100644 --- a/Libraries/LibGUI/JSSyntaxHighlighter.cpp +++ b/Libraries/LibGUI/JSSyntaxHighlighter.cpp @@ -102,6 +102,7 @@ static TextStyle style_for_token_type(Gfx::Palette palette, JS::TokenType type) case JS::TokenType::Class: case JS::TokenType::Const: case JS::TokenType::Delete: + case JS::TokenType::Debugger: case JS::TokenType::Function: case JS::TokenType::In: case JS::TokenType::Instanceof: diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index 9b82013a0e..ab91564887 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -1396,6 +1396,12 @@ Value SequenceExpression::execute(Interpreter& interpreter) const return last_value; } +Value DebuggerStatement::execute(Interpreter&) const +{ + dbg() << "Sorry, no JavaScript debugger available (yet)!"; + return js_undefined(); +} + void ScopeNode::add_variables(NonnullRefPtrVector variables) { m_variables.append(move(variables)); diff --git a/Libraries/LibJS/AST.h b/Libraries/LibJS/AST.h index 27d660f99e..cfb74594d8 100644 --- a/Libraries/LibJS/AST.h +++ b/Libraries/LibJS/AST.h @@ -923,4 +923,14 @@ private: virtual const char* class_name() const override { return "ContinueStatement"; } }; +class DebuggerStatement final : public Statement { +public: + DebuggerStatement() {} + + virtual Value execute(Interpreter&) const override; + +private: + virtual const char* class_name() const override { return "DebuggerStatement"; } +}; + } diff --git a/Libraries/LibJS/Lexer.cpp b/Libraries/LibJS/Lexer.cpp index c59a8cd17e..cfcead6906 100644 --- a/Libraries/LibJS/Lexer.cpp +++ b/Libraries/LibJS/Lexer.cpp @@ -49,6 +49,7 @@ Lexer::Lexer(StringView source) s_keywords.set("class", TokenType::Class); s_keywords.set("const", TokenType::Const); s_keywords.set("continue", TokenType::Continue); + s_keywords.set("debugger", TokenType::Debugger); s_keywords.set("default", TokenType::Default); s_keywords.set("delete", TokenType::Delete); s_keywords.set("do", TokenType::Do); diff --git a/Libraries/LibJS/Parser.cpp b/Libraries/LibJS/Parser.cpp index 4982f0baea..05d2c81bb7 100644 --- a/Libraries/LibJS/Parser.cpp +++ b/Libraries/LibJS/Parser.cpp @@ -253,6 +253,8 @@ NonnullRefPtr Parser::parse_statement() return parse_do_while_statement(); case TokenType::While: return parse_while_statement(); + case TokenType::Debugger: + return parse_debugger_statement(); default: if (match_expression()) { auto expr = parse_expression(0); @@ -1044,6 +1046,13 @@ NonnullRefPtr Parser::parse_for_statement() return create_ast_node(move(init), move(test), move(update), move(body)); } +NonnullRefPtr Parser::parse_debugger_statement() +{ + consume(TokenType::Debugger); + consume_or_insert_semicolon(); + return create_ast_node(); +} + bool Parser::match(TokenType type) const { return m_parser_state.m_current_token.type() == type; @@ -1156,7 +1165,8 @@ bool Parser::match_statement() const || type == TokenType::Switch || type == TokenType::Break || type == TokenType::Continue - || type == TokenType::Var; + || type == TokenType::Var + || type == TokenType::Debugger; } bool Parser::match_identifier_name() const diff --git a/Libraries/LibJS/Parser.h b/Libraries/LibJS/Parser.h index 8d171c46a4..248005defa 100644 --- a/Libraries/LibJS/Parser.h +++ b/Libraries/LibJS/Parser.h @@ -61,6 +61,7 @@ public: NonnullRefPtr parse_continue_statement(); NonnullRefPtr parse_do_while_statement(); NonnullRefPtr parse_while_statement(); + NonnullRefPtr parse_debugger_statement(); NonnullRefPtr parse_conditional_expression(NonnullRefPtr test); NonnullRefPtr parse_expression(int min_precedence, Associativity associate = Associativity::Right); diff --git a/Libraries/LibJS/Tests/debugger-statement.js b/Libraries/LibJS/Tests/debugger-statement.js new file mode 100644 index 0000000000..cf94b79084 --- /dev/null +++ b/Libraries/LibJS/Tests/debugger-statement.js @@ -0,0 +1,9 @@ +load("test-common.js"); + +try { + debugger; + + console.log("PASS"); +} catch (e) { + console.log("FAIL: " + e); +} diff --git a/Libraries/LibJS/Token.h b/Libraries/LibJS/Token.h index f60a288ce1..e272eff804 100644 --- a/Libraries/LibJS/Token.h +++ b/Libraries/LibJS/Token.h @@ -53,6 +53,7 @@ namespace JS { __ENUMERATE_JS_TOKEN(Continue) \ __ENUMERATE_JS_TOKEN(CurlyClose) \ __ENUMERATE_JS_TOKEN(CurlyOpen) \ + __ENUMERATE_JS_TOKEN(Debugger) \ __ENUMERATE_JS_TOKEN(Default) \ __ENUMERATE_JS_TOKEN(Delete) \ __ENUMERATE_JS_TOKEN(Do) \ diff --git a/Userland/js.cpp b/Userland/js.cpp index c8957abbf7..c3e27d3d10 100644 --- a/Userland/js.cpp +++ b/Userland/js.cpp @@ -532,6 +532,7 @@ int main(int argc, char** argv) break; case JS::TokenType::Class: case JS::TokenType::Const: + case JS::TokenType::Debugger: case JS::TokenType::Delete: case JS::TokenType::Function: case JS::TokenType::In: