Serenity Operating System
1/*
2 * Copyright (c) 2020, Stephan Unverwerth <s.unverwerth@serenityos.org>
3 * Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
4 * Copyright (c) 2021-2022, David Tuin <davidot@serenityos.org>
5 * Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
6 * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
7 * Copyright (c) 2023, Andreas Kling <kling@serenityos.org>
8 *
9 * SPDX-License-Identifier: BSD-2-Clause
10 */
11
12#include "Parser.h"
13#include <AK/Array.h>
14#include <AK/CharacterTypes.h>
15#include <AK/HashTable.h>
16#include <AK/ScopeGuard.h>
17#include <AK/StdLibExtras.h>
18#include <AK/TemporaryChange.h>
19#include <LibJS/Runtime/RegExpObject.h>
20#include <LibRegex/Regex.h>
21
22namespace JS {
23
24class ScopePusher {
25
26 // NOTE: We really only need ModuleTopLevel and NotModuleTopLevel as the only
27 // difference seems to be in https://tc39.es/ecma262/#sec-static-semantics-varscopeddeclarations
28 // where ModuleItemList only does the VarScopedDeclaration and not the
29 // TopLevelVarScopedDeclarations.
30 enum class ScopeLevel {
31 NotTopLevel,
32 ScriptTopLevel,
33 ModuleTopLevel,
34 FunctionTopLevel,
35 StaticInitTopLevel
36 };
37
38private:
39 ScopePusher(Parser& parser, ScopeNode* node, ScopeLevel scope_level)
40 : m_parser(parser)
41 , m_scope_level(scope_level)
42 {
43 m_parent_scope = exchange(m_parser.m_state.current_scope_pusher, this);
44 VERIFY(node || (m_parent_scope && scope_level == ScopeLevel::NotTopLevel));
45 if (!node)
46 m_node = m_parent_scope->m_node;
47 else
48 m_node = node;
49 VERIFY(m_node);
50
51 if (!is_top_level())
52 m_top_level_scope = m_parent_scope->m_top_level_scope;
53 else
54 m_top_level_scope = this;
55 }
56
57 bool is_top_level()
58 {
59 return m_scope_level != ScopeLevel::NotTopLevel;
60 }
61
62public:
63 static ScopePusher function_scope(Parser& parser, FunctionBody& function_body, Vector<FunctionParameter> const& parameters)
64 {
65 ScopePusher scope_pusher(parser, &function_body, ScopeLevel::FunctionTopLevel);
66 scope_pusher.m_function_parameters = parameters;
67 for (auto& parameter : parameters) {
68 parameter.binding.visit(
69 [&](DeprecatedFlyString const& name) {
70 scope_pusher.m_forbidden_lexical_names.set(name);
71 },
72 [&](NonnullRefPtr<BindingPattern const> const& binding_pattern) {
73 // NOTE: Nothing in the callback throws an exception.
74 MUST(binding_pattern->for_each_bound_name([&](auto const& name) {
75 scope_pusher.m_forbidden_lexical_names.set(name);
76 }));
77 });
78 }
79 return scope_pusher;
80 }
81
82 static ScopePusher program_scope(Parser& parser, Program& program)
83 {
84 return ScopePusher(parser, &program, program.type() == Program::Type::Script ? ScopeLevel::ScriptTopLevel : ScopeLevel::ModuleTopLevel);
85 }
86
87 static ScopePusher block_scope(Parser& parser, ScopeNode& node)
88 {
89 return ScopePusher(parser, &node, ScopeLevel::NotTopLevel);
90 }
91
92 static ScopePusher for_loop_scope(Parser& parser, RefPtr<ASTNode const> const& init)
93 {
94 ScopePusher scope_pusher(parser, nullptr, ScopeLevel::NotTopLevel);
95 if (init && is<VariableDeclaration>(*init)) {
96 auto& variable_declaration = static_cast<VariableDeclaration const&>(*init);
97 if (variable_declaration.declaration_kind() != DeclarationKind::Var) {
98 // NOTE: Nothing in the callback throws an exception.
99 MUST(variable_declaration.for_each_bound_name([&](auto const& name) {
100 scope_pusher.m_forbidden_var_names.set(name);
101 }));
102 }
103 }
104
105 return scope_pusher;
106 }
107
108 static ScopePusher catch_scope(Parser& parser, RefPtr<BindingPattern const> const& pattern, DeprecatedFlyString const& parameter)
109 {
110 ScopePusher scope_pusher(parser, nullptr, ScopeLevel::NotTopLevel);
111 if (pattern) {
112 // NOTE: Nothing in the callback throws an exception.
113 MUST(pattern->for_each_bound_name([&](auto const& name) {
114 scope_pusher.m_forbidden_var_names.set(name);
115 }));
116 } else if (!parameter.is_empty()) {
117 scope_pusher.m_var_names.set(parameter);
118 }
119 return scope_pusher;
120 }
121
122 static ScopePusher static_init_block_scope(Parser& parser, ScopeNode& node)
123 {
124 return ScopePusher(parser, &node, ScopeLevel::StaticInitTopLevel);
125 }
126
127 static ScopePusher class_field_scope(Parser& parser)
128 {
129 return ScopePusher(parser, nullptr, ScopeLevel::NotTopLevel);
130 }
131
132 void add_declaration(NonnullRefPtr<Declaration const> declaration)
133 {
134 if (declaration->is_lexical_declaration()) {
135 // NOTE: Nothing in the callback throws an exception.
136 MUST(declaration->for_each_bound_name([&](auto const& name) {
137 if (m_var_names.contains(name) || m_forbidden_lexical_names.contains(name) || m_function_names.contains(name))
138 throw_identifier_declared(name, declaration);
139
140 if (m_lexical_names.set(name) != AK::HashSetResult::InsertedNewEntry)
141 throw_identifier_declared(name, declaration);
142 }));
143
144 m_node->add_lexical_declaration(move(declaration));
145 } else if (!declaration->is_function_declaration()) {
146 // NOTE: Nothing in the callback throws an exception.
147 MUST(declaration->for_each_bound_name([&](auto const& name) {
148 ScopePusher* pusher = this;
149 while (true) {
150 if (pusher->m_lexical_names.contains(name)
151 || pusher->m_function_names.contains(name)
152 || pusher->m_forbidden_var_names.contains(name))
153 throw_identifier_declared(name, declaration);
154
155 pusher->m_var_names.set(name);
156 if (pusher->is_top_level())
157 break;
158
159 VERIFY(pusher->m_parent_scope != nullptr);
160 pusher = pusher->m_parent_scope;
161 }
162 VERIFY(pusher->is_top_level() && pusher->m_node);
163 pusher->m_node->add_var_scoped_declaration(declaration);
164 }));
165
166 VERIFY(m_top_level_scope);
167 m_top_level_scope->m_node->add_var_scoped_declaration(move(declaration));
168 } else {
169 if (m_scope_level != ScopeLevel::NotTopLevel && m_scope_level != ScopeLevel::ModuleTopLevel) {
170 // Only non-top levels and Module don't var declare the top functions
171 // NOTE: Nothing in the callback throws an exception.
172 MUST(declaration->for_each_bound_name([&](auto const& name) {
173 m_var_names.set(name);
174 }));
175 m_node->add_var_scoped_declaration(move(declaration));
176 } else {
177 VERIFY(is<FunctionDeclaration>(*declaration));
178 auto& function_declaration = static_cast<FunctionDeclaration const&>(*declaration);
179 auto& function_name = function_declaration.name();
180 if (m_var_names.contains(function_name) || m_lexical_names.contains(function_name))
181 throw_identifier_declared(function_name, declaration);
182
183 if (function_declaration.kind() != FunctionKind::Normal || m_parser.m_state.strict_mode) {
184 if (m_function_names.contains(function_name))
185 throw_identifier_declared(function_name, declaration);
186
187 m_lexical_names.set(function_name);
188 m_node->add_lexical_declaration(move(declaration));
189 return;
190 }
191
192 m_function_names.set(function_name);
193 if (!m_lexical_names.contains(function_name))
194 m_functions_to_hoist.append(static_ptr_cast<FunctionDeclaration const>(declaration));
195
196 m_node->add_lexical_declaration(move(declaration));
197 }
198 }
199 }
200
201 ScopePusher const* last_function_scope() const
202 {
203 for (auto scope_ptr = this; scope_ptr; scope_ptr = scope_ptr->m_parent_scope) {
204 if (scope_ptr->m_function_parameters.has_value())
205 return scope_ptr;
206 }
207 return nullptr;
208 }
209
210 Vector<FunctionParameter> const& function_parameters() const
211 {
212 return *m_function_parameters;
213 }
214
215 ScopePusher* parent_scope() { return m_parent_scope; }
216 ScopePusher const* parent_scope() const { return m_parent_scope; }
217
218 [[nodiscard]] bool has_declaration(DeprecatedFlyString const& name) const
219 {
220 return m_lexical_names.contains(name) || m_var_names.contains(name) || !m_functions_to_hoist.find_if([&name](auto& function) { return function->name() == name; }).is_end();
221 }
222
223 bool contains_direct_call_to_eval() const { return m_contains_direct_call_to_eval; }
224 bool contains_access_to_arguments_object() const { return m_contains_access_to_arguments_object; }
225 void set_contains_direct_call_to_eval() { m_contains_direct_call_to_eval = true; }
226 void set_contains_access_to_arguments_object() { m_contains_access_to_arguments_object = true; }
227
228 ~ScopePusher()
229 {
230 VERIFY(is_top_level() || m_parent_scope);
231
232 for (size_t i = 0; i < m_functions_to_hoist.size(); i++) {
233 auto const& function_declaration = m_functions_to_hoist[i];
234 if (m_lexical_names.contains(function_declaration->name()) || m_forbidden_var_names.contains(function_declaration->name()))
235 continue;
236 if (is_top_level()) {
237 m_node->add_hoisted_function(move(m_functions_to_hoist[i]));
238 } else {
239 if (!m_parent_scope->m_lexical_names.contains(function_declaration->name()) && !m_parent_scope->m_function_names.contains(function_declaration->name()))
240 m_parent_scope->m_functions_to_hoist.append(move(m_functions_to_hoist[i]));
241 }
242 }
243
244 if (m_parent_scope && !m_function_parameters.has_value()) {
245 m_parent_scope->m_contains_access_to_arguments_object |= m_contains_access_to_arguments_object;
246 m_parent_scope->m_contains_direct_call_to_eval |= m_contains_direct_call_to_eval;
247 }
248
249 VERIFY(m_parser.m_state.current_scope_pusher == this);
250 m_parser.m_state.current_scope_pusher = m_parent_scope;
251 }
252
253 void set_contains_await_expression()
254 {
255 m_contains_await_expression = true;
256 }
257
258 bool contains_await_expression() const
259 {
260 return m_contains_await_expression;
261 }
262
263 bool can_have_using_declaration() const
264 {
265 return m_scope_level != ScopeLevel::ScriptTopLevel;
266 }
267
268private:
269 void throw_identifier_declared(DeprecatedFlyString const& name, NonnullRefPtr<Declaration const> const& declaration)
270 {
271 m_parser.syntax_error(DeprecatedString::formatted("Identifier '{}' already declared", name), declaration->source_range().start);
272 }
273
274 Parser& m_parser;
275 ScopeNode* m_node { nullptr };
276 ScopeLevel m_scope_level { ScopeLevel::NotTopLevel };
277
278 ScopePusher* m_parent_scope { nullptr };
279 ScopePusher* m_top_level_scope { nullptr };
280
281 HashTable<DeprecatedFlyString> m_lexical_names;
282 HashTable<DeprecatedFlyString> m_var_names;
283 HashTable<DeprecatedFlyString> m_function_names;
284
285 HashTable<DeprecatedFlyString> m_forbidden_lexical_names;
286 HashTable<DeprecatedFlyString> m_forbidden_var_names;
287 Vector<NonnullRefPtr<FunctionDeclaration const>> m_functions_to_hoist;
288
289 Optional<Vector<FunctionParameter>> m_function_parameters;
290
291 bool m_contains_access_to_arguments_object { false };
292 bool m_contains_direct_call_to_eval { false };
293 bool m_contains_await_expression { false };
294};
295
296class OperatorPrecedenceTable {
297public:
298 constexpr OperatorPrecedenceTable()
299 : m_token_precedence()
300 {
301 for (size_t i = 0; i < array_size(m_operator_precedence); ++i) {
302 auto& op = m_operator_precedence[i];
303 m_token_precedence[static_cast<size_t>(op.token)] = op.precedence;
304 }
305 }
306
307 constexpr int get(TokenType token) const
308 {
309 int p = m_token_precedence[static_cast<size_t>(token)];
310 if (p == 0) {
311 warnln("Internal Error: No precedence for operator {}", Token::name(token));
312 VERIFY_NOT_REACHED();
313 return -1;
314 }
315
316 return p;
317 }
318
319private:
320 int m_token_precedence[cs_num_of_js_tokens];
321
322 struct OperatorPrecedence {
323 TokenType token;
324 int precedence;
325 };
326
327 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
328 static constexpr const OperatorPrecedence m_operator_precedence[] = {
329 { TokenType::Period, 20 },
330 { TokenType::BracketOpen, 20 },
331 { TokenType::ParenOpen, 20 },
332 { TokenType::QuestionMarkPeriod, 20 },
333
334 { TokenType::New, 19 },
335
336 { TokenType::PlusPlus, 18 },
337 { TokenType::MinusMinus, 18 },
338
339 { TokenType::ExclamationMark, 17 },
340 { TokenType::Tilde, 17 },
341 { TokenType::Typeof, 17 },
342 { TokenType::Void, 17 },
343 { TokenType::Delete, 17 },
344 { TokenType::Await, 17 },
345
346 { TokenType::DoubleAsterisk, 16 },
347
348 { TokenType::Asterisk, 15 },
349 { TokenType::Slash, 15 },
350 { TokenType::Percent, 15 },
351
352 { TokenType::Plus, 14 },
353 { TokenType::Minus, 14 },
354
355 { TokenType::ShiftLeft, 13 },
356 { TokenType::ShiftRight, 13 },
357 { TokenType::UnsignedShiftRight, 13 },
358
359 { TokenType::LessThan, 12 },
360 { TokenType::LessThanEquals, 12 },
361 { TokenType::GreaterThan, 12 },
362 { TokenType::GreaterThanEquals, 12 },
363 { TokenType::In, 12 },
364 { TokenType::Instanceof, 12 },
365
366 { TokenType::EqualsEquals, 11 },
367 { TokenType::ExclamationMarkEquals, 11 },
368 { TokenType::EqualsEqualsEquals, 11 },
369 { TokenType::ExclamationMarkEqualsEquals, 11 },
370
371 { TokenType::Ampersand, 10 },
372
373 { TokenType::Caret, 9 },
374
375 { TokenType::Pipe, 8 },
376
377 { TokenType::DoubleQuestionMark, 7 },
378
379 { TokenType::DoubleAmpersand, 6 },
380
381 { TokenType::DoublePipe, 5 },
382
383 { TokenType::QuestionMark, 4 },
384
385 { TokenType::Equals, 3 },
386 { TokenType::PlusEquals, 3 },
387 { TokenType::MinusEquals, 3 },
388 { TokenType::DoubleAsteriskEquals, 3 },
389 { TokenType::AsteriskEquals, 3 },
390 { TokenType::SlashEquals, 3 },
391 { TokenType::PercentEquals, 3 },
392 { TokenType::ShiftLeftEquals, 3 },
393 { TokenType::ShiftRightEquals, 3 },
394 { TokenType::UnsignedShiftRightEquals, 3 },
395 { TokenType::AmpersandEquals, 3 },
396 { TokenType::CaretEquals, 3 },
397 { TokenType::PipeEquals, 3 },
398 { TokenType::DoubleAmpersandEquals, 3 },
399 { TokenType::DoublePipeEquals, 3 },
400 { TokenType::DoubleQuestionMarkEquals, 3 },
401
402 { TokenType::Yield, 2 },
403
404 { TokenType::Comma, 1 },
405 };
406};
407
408constexpr OperatorPrecedenceTable g_operator_precedence;
409
410Parser::ParserState::ParserState(Lexer l, Program::Type program_type)
411 : lexer(move(l))
412{
413 if (program_type == Program::Type::Module)
414 lexer.disallow_html_comments();
415 current_token = lexer.next();
416}
417
418Parser::Parser(Lexer lexer, Program::Type program_type, Optional<EvalInitialState> initial_state_for_eval)
419 : m_source_code(SourceCode::create(lexer.filename(), String::from_deprecated_string(lexer.source()).release_value_but_fixme_should_propagate_errors()))
420 , m_state(move(lexer), program_type)
421 , m_program_type(program_type)
422{
423 if (initial_state_for_eval.has_value()) {
424 m_state.in_eval_function_context = initial_state_for_eval->in_eval_function_context;
425 m_state.allow_super_property_lookup = initial_state_for_eval->allow_super_property_lookup;
426 m_state.allow_super_constructor_call = initial_state_for_eval->allow_super_constructor_call;
427 m_state.in_class_field_initializer = initial_state_for_eval->in_class_field_initializer;
428 }
429}
430
431Associativity Parser::operator_associativity(TokenType type) const
432{
433 switch (type) {
434 case TokenType::Period:
435 case TokenType::BracketOpen:
436 case TokenType::ParenOpen:
437 case TokenType::QuestionMarkPeriod:
438 case TokenType::Asterisk:
439 case TokenType::Slash:
440 case TokenType::Percent:
441 case TokenType::Plus:
442 case TokenType::Minus:
443 case TokenType::ShiftLeft:
444 case TokenType::ShiftRight:
445 case TokenType::UnsignedShiftRight:
446 case TokenType::LessThan:
447 case TokenType::LessThanEquals:
448 case TokenType::GreaterThan:
449 case TokenType::GreaterThanEquals:
450 case TokenType::In:
451 case TokenType::Instanceof:
452 case TokenType::EqualsEquals:
453 case TokenType::ExclamationMarkEquals:
454 case TokenType::EqualsEqualsEquals:
455 case TokenType::ExclamationMarkEqualsEquals:
456 case TokenType::Typeof:
457 case TokenType::Void:
458 case TokenType::Delete:
459 case TokenType::Await:
460 case TokenType::Ampersand:
461 case TokenType::Caret:
462 case TokenType::Pipe:
463 case TokenType::DoubleQuestionMark:
464 case TokenType::DoubleAmpersand:
465 case TokenType::DoublePipe:
466 case TokenType::Comma:
467 return Associativity::Left;
468 default:
469 return Associativity::Right;
470 }
471}
472
473bool Parser::parse_directive(ScopeNode& body)
474{
475 bool found_use_strict = false;
476 while (!done() && match(TokenType::StringLiteral)) {
477 auto raw_value = m_state.current_token.original_value();
478 // It cannot be a labelled function since we hit a string literal.
479 auto statement = parse_statement(AllowLabelledFunction::No);
480 body.append(statement);
481
482 VERIFY(is<ExpressionStatement>(*statement));
483 auto& expression = static_cast<ExpressionStatement const&>(*statement).expression();
484
485 if (!is<StringLiteral>(expression))
486 break;
487
488 if (raw_value.is_one_of("'use strict'"sv, "\"use strict\"")) {
489 found_use_strict = true;
490
491 if (m_state.string_legacy_octal_escape_sequence_in_scope)
492 syntax_error("Octal escape sequence in string literal not allowed in strict mode");
493 break;
494 }
495 }
496
497 m_state.string_legacy_octal_escape_sequence_in_scope = false;
498 return found_use_strict;
499}
500
501NonnullRefPtr<Program> Parser::parse_program(bool starts_in_strict_mode)
502{
503 auto rule_start = push_start();
504 auto program = adopt_ref(*new Program({ m_source_code, rule_start.position(), position() }, m_program_type));
505 ScopePusher program_scope = ScopePusher::program_scope(*this, *program);
506
507 if (m_program_type == Program::Type::Script)
508 parse_script(program, starts_in_strict_mode);
509 else
510 parse_module(program);
511
512 program->set_end_offset({}, position().offset);
513 return program;
514}
515
516void Parser::parse_script(Program& program, bool starts_in_strict_mode)
517{
518 bool strict_before = m_state.strict_mode;
519 if (starts_in_strict_mode)
520 m_state.strict_mode = true;
521
522 bool has_use_strict = parse_directive(program);
523
524 if (m_state.strict_mode || has_use_strict) {
525 program.set_strict_mode();
526 m_state.strict_mode = true;
527 }
528
529 parse_statement_list(program, AllowLabelledFunction::Yes);
530 if (!done()) {
531 expected("statement or declaration");
532 consume();
533 }
534
535 m_state.strict_mode = strict_before;
536}
537
538void Parser::parse_module(Program& program)
539{
540 TemporaryChange strict_mode_rollback(m_state.strict_mode, true);
541 TemporaryChange await_expression_valid_rollback(m_state.await_expression_is_valid, true);
542
543 // Since strict mode is already enabled we skip any directive parsing.
544 while (!done()) {
545 parse_statement_list(program, AllowLabelledFunction::Yes);
546
547 if (done())
548 break;
549
550 if (match_export_or_import()) {
551 VERIFY(m_state.current_token.type() == TokenType::Export || m_state.current_token.type() == TokenType::Import);
552 if (m_state.current_token.type() == TokenType::Export)
553 program.append_export(parse_export_statement(program));
554 else
555 program.append_import(parse_import_statement(program));
556
557 } else {
558 expected("statement or declaration");
559 consume();
560 }
561 }
562
563 VERIFY(m_state.current_scope_pusher);
564 if (m_state.current_scope_pusher->contains_await_expression())
565 program.set_has_top_level_await();
566
567 for (auto& export_statement : program.exports()) {
568 if (export_statement->has_statement())
569 continue;
570 for (auto& entry : export_statement->entries()) {
571 if (entry.is_module_request() || entry.kind == ExportEntry::Kind::EmptyNamedExport)
572 return;
573
574 auto const& exported_name = entry.local_or_import_name;
575 bool found = false;
576 // NOTE: Nothing in the callback throws an exception.
577 MUST(program.for_each_lexically_declared_name([&](auto const& name) {
578 if (name == exported_name)
579 found = true;
580 }));
581 if (found)
582 continue;
583 // NOTE: Nothing in the callback throws an exception.
584 MUST(program.for_each_var_declared_name([&](auto const& name) {
585 if (name == exported_name)
586 found = true;
587 }));
588 for (auto& import : program.imports()) {
589 if (import->has_bound_name(exported_name)) {
590 found = true;
591 break;
592 }
593 }
594
595 if (!found)
596 syntax_error(DeprecatedString::formatted("'{}' in export is not declared", exported_name), export_statement->source_range().start);
597 }
598 }
599}
600
601NonnullRefPtr<Declaration const> Parser::parse_declaration()
602{
603 auto rule_start = push_start();
604 if (m_state.current_token.type() == TokenType::Async && next_token().type() == TokenType::Function)
605 return parse_function_node<FunctionDeclaration>();
606 switch (m_state.current_token.type()) {
607 case TokenType::Class:
608 return parse_class_declaration();
609 case TokenType::Function:
610 return parse_function_node<FunctionDeclaration>();
611 case TokenType::Let:
612 case TokenType::Const:
613 return parse_variable_declaration();
614 case TokenType::Identifier:
615 if (m_state.current_token.original_value() == "using"sv) {
616 if (!m_state.current_scope_pusher->can_have_using_declaration())
617 syntax_error("'using' not allowed outside of block, for loop or function");
618
619 return parse_using_declaration();
620 }
621 [[fallthrough]];
622 default:
623 expected("declaration");
624 consume();
625 return create_ast_node<ErrorDeclaration>({ m_source_code, rule_start.position(), position() });
626 }
627}
628
629NonnullRefPtr<Statement const> Parser::parse_statement(AllowLabelledFunction allow_labelled_function)
630{
631 auto rule_start = push_start();
632 auto type = m_state.current_token.type();
633 switch (type) {
634 case TokenType::CurlyOpen:
635 return parse_block_statement();
636 case TokenType::Return:
637 return parse_return_statement();
638 case TokenType::Var: {
639 auto declaration = parse_variable_declaration();
640 m_state.current_scope_pusher->add_declaration(declaration);
641 return declaration;
642 }
643 case TokenType::For:
644 return parse_for_statement();
645 case TokenType::If:
646 return parse_if_statement();
647 case TokenType::Throw:
648 return parse_throw_statement();
649 case TokenType::Try:
650 return parse_try_statement();
651 case TokenType::Break:
652 return parse_break_statement();
653 case TokenType::Continue:
654 return parse_continue_statement();
655 case TokenType::Switch:
656 return parse_switch_statement();
657 case TokenType::Do:
658 return parse_do_while_statement();
659 case TokenType::While:
660 return parse_while_statement();
661 case TokenType::With:
662 if (m_state.strict_mode)
663 syntax_error("'with' statement not allowed in strict mode");
664 return parse_with_statement();
665 case TokenType::Debugger:
666 return parse_debugger_statement();
667 case TokenType::Semicolon:
668 consume();
669 return create_ast_node<EmptyStatement>({ m_source_code, rule_start.position(), position() });
670 case TokenType::Slash:
671 case TokenType::SlashEquals:
672 m_state.current_token = m_state.lexer.force_slash_as_regex();
673 [[fallthrough]];
674 default:
675 if (match_invalid_escaped_keyword())
676 syntax_error("Keyword must not contain escaped characters");
677
678 if (match_identifier_name()) {
679 auto result = try_parse_labelled_statement(allow_labelled_function);
680 if (!result.is_null())
681 return result.release_nonnull();
682 }
683 if (match_expression()) {
684 if (match(TokenType::Async)) {
685 auto lookahead_token = next_token();
686 if (lookahead_token.type() == TokenType::Function && !lookahead_token.trivia_contains_line_terminator())
687 syntax_error("Async function declaration not allowed in single-statement context");
688 } else if (match(TokenType::Function) || match(TokenType::Class)) {
689 syntax_error(DeprecatedString::formatted("{} declaration not allowed in single-statement context", m_state.current_token.name()));
690 } else if (match(TokenType::Let) && next_token().type() == TokenType::BracketOpen) {
691 syntax_error(DeprecatedString::formatted("let followed by [ is not allowed in single-statement context"));
692 }
693
694 auto expr = parse_expression(0);
695 consume_or_insert_semicolon();
696 return create_ast_node<ExpressionStatement>({ m_source_code, rule_start.position(), position() }, move(expr));
697 }
698 expected("statement");
699 consume();
700 return create_ast_node<ErrorStatement>({ m_source_code, rule_start.position(), position() });
701 }
702}
703
704bool Parser::match_invalid_escaped_keyword() const
705{
706 if (m_state.current_token.type() != TokenType::EscapedKeyword)
707 return false;
708 auto token_value = m_state.current_token.value();
709 if (token_value == "await"sv)
710 return m_program_type == Program::Type::Module || m_state.await_expression_is_valid;
711 if (token_value == "async"sv)
712 return false;
713 if (token_value == "yield"sv)
714 return m_state.in_generator_function_context;
715 if (m_state.strict_mode)
716 return true;
717 return token_value != "let"sv;
718}
719
720static constexpr AK::Array<StringView, 9> strict_reserved_words = { "implements"sv, "interface"sv, "let"sv, "package"sv, "private"sv, "protected"sv, "public"sv, "static"sv, "yield"sv };
721
722static bool is_strict_reserved_word(StringView str)
723{
724 return any_of(strict_reserved_words, [&str](StringView word) {
725 return word == str;
726 });
727}
728
729static bool is_simple_parameter_list(Vector<FunctionParameter> const& parameters)
730{
731 return all_of(parameters, [](FunctionParameter const& parameter) {
732 return !parameter.is_rest && parameter.default_value.is_null() && parameter.binding.has<DeprecatedFlyString>();
733 });
734}
735
736RefPtr<FunctionExpression const> Parser::try_parse_arrow_function_expression(bool expect_parens, bool is_async)
737{
738 if (is_async)
739 VERIFY(match(TokenType::Async));
740
741 if (!expect_parens && !is_async) {
742 // NOTE: This is a fast path where we try to fail early in case this can't possibly
743 // be a match. The idea is to avoid the expensive parser state save/load mechanism.
744 // The logic is duplicated below in the "real" !expect_parens branch.
745 if (!match_identifier() && !match(TokenType::Yield) && !match(TokenType::Await))
746 return nullptr;
747 auto token = next_token();
748 if (token.trivia_contains_line_terminator())
749 return nullptr;
750 if (token.type() != TokenType::Arrow)
751 return nullptr;
752 }
753
754 save_state();
755 auto rule_start = (expect_parens && !is_async)
756 // Someone has consumed the opening parenthesis for us! Start there.
757 ? RulePosition { *this, m_rule_starts.last() }
758 // We've not encountered one yet, so the rule start is actually here.
759 : push_start();
760
761 ArmedScopeGuard state_rollback_guard = [&] {
762 load_state();
763 };
764
765 auto function_kind = FunctionKind::Normal;
766
767 if (is_async) {
768 consume(TokenType::Async);
769 function_kind = FunctionKind::Async;
770 if (m_state.current_token.trivia_contains_line_terminator())
771 return nullptr;
772
773 // Since we have async it can be followed by paren open in the expect_parens case
774 // so we also consume that token.
775 if (expect_parens) {
776 VERIFY(match(TokenType::ParenOpen));
777 consume(TokenType::ParenOpen);
778 }
779 }
780
781 Vector<FunctionParameter> parameters;
782 i32 function_length = -1;
783 if (expect_parens) {
784 // We have parens around the function parameters and can re-use the same parsing
785 // logic used for regular functions: multiple parameters, default values, rest
786 // parameter, maybe a trailing comma. If we have a new syntax error afterwards we
787 // check if it's about a wrong token (something like duplicate parameter name must
788 // not abort), know parsing failed and rollback the parser state.
789 auto previous_syntax_errors = m_state.errors.size();
790 TemporaryChange in_async_context(m_state.await_expression_is_valid, is_async || m_state.await_expression_is_valid);
791
792 parameters = parse_formal_parameters(function_length, FunctionNodeParseOptions::IsArrowFunction | (is_async ? FunctionNodeParseOptions::IsAsyncFunction : 0));
793 if (m_state.errors.size() > previous_syntax_errors && m_state.errors[previous_syntax_errors].message.starts_with("Unexpected token"sv))
794 return nullptr;
795 if (!match(TokenType::ParenClose))
796 return nullptr;
797 consume();
798 } else {
799 // No parens - this must be an identifier followed by arrow. That's it.
800 if (!match_identifier() && !match(TokenType::Yield) && !match(TokenType::Await))
801 return nullptr;
802 auto token = consume_identifier_reference();
803 if (m_state.strict_mode && token.value().is_one_of("arguments"sv, "eval"sv))
804 syntax_error("BindingIdentifier may not be 'arguments' or 'eval' in strict mode");
805 if (is_async && token.value() == "await"sv)
806 syntax_error("'await' is a reserved identifier in async functions");
807 parameters.append({ DeprecatedFlyString { token.value() }, {} });
808 }
809 // If there's a newline between the closing paren and arrow it's not a valid arrow function,
810 // ASI should kick in instead (it'll then fail with "Unexpected token Arrow")
811 if (m_state.current_token.trivia_contains_line_terminator())
812 return nullptr;
813 if (!match(TokenType::Arrow))
814 return nullptr;
815 consume();
816
817 if (function_length == -1)
818 function_length = parameters.size();
819
820 auto old_labels_in_scope = move(m_state.labels_in_scope);
821 ScopeGuard guard([&]() {
822 m_state.labels_in_scope = move(old_labels_in_scope);
823 });
824
825 bool contains_direct_call_to_eval = false;
826
827 auto function_body_result = [&]() -> RefPtr<FunctionBody const> {
828 TemporaryChange change(m_state.in_arrow_function_context, true);
829 TemporaryChange async_context_change(m_state.await_expression_is_valid, is_async);
830 TemporaryChange in_class_static_init_block_change(m_state.in_class_static_init_block, false);
831
832 if (match(TokenType::CurlyOpen)) {
833 // Parse a function body with statements
834 consume(TokenType::CurlyOpen);
835 auto body = parse_function_body(parameters, function_kind, contains_direct_call_to_eval);
836 consume(TokenType::CurlyClose);
837 return body;
838 }
839 if (match_expression()) {
840 // Parse a function body which returns a single expression
841
842 // FIXME: We synthesize a block with a return statement
843 // for arrow function bodies which are a single expression.
844 // Esprima generates a single "ArrowFunctionExpression"
845 // with a "body" property.
846 auto return_block = create_ast_node<FunctionBody>({ m_source_code, rule_start.position(), position() });
847 ScopePusher function_scope = ScopePusher::function_scope(*this, return_block, parameters);
848 auto return_expression = parse_expression(2);
849 return_block->append<ReturnStatement const>({ m_source_code, rule_start.position(), position() }, move(return_expression));
850 if (m_state.strict_mode)
851 const_cast<FunctionBody&>(*return_block).set_strict_mode();
852 contains_direct_call_to_eval = function_scope.contains_direct_call_to_eval();
853 return return_block;
854 }
855 // Invalid arrow function body
856 return nullptr;
857 }();
858
859 if (function_body_result.is_null())
860 return nullptr;
861
862 state_rollback_guard.disarm();
863 discard_saved_state();
864 auto body = function_body_result.release_nonnull();
865
866 if (body->in_strict_mode()) {
867 for (auto& parameter : parameters) {
868 parameter.binding.visit(
869 [&](DeprecatedFlyString const& name) {
870 check_identifier_name_for_assignment_validity(name, true);
871 },
872 [&](auto const&) {});
873 }
874 }
875
876 auto function_start_offset = rule_start.position().offset;
877 auto function_end_offset = position().offset - m_state.current_token.trivia().length();
878 auto source_text = DeprecatedString { m_state.lexer.source().substring_view(function_start_offset, function_end_offset - function_start_offset) };
879 return create_ast_node<FunctionExpression>(
880 { m_source_code, rule_start.position(), position() }, "", move(source_text),
881 move(body), move(parameters), function_length, function_kind, body->in_strict_mode(),
882 /* might_need_arguments_object */ false, contains_direct_call_to_eval, /* is_arrow_function */ true);
883}
884
885RefPtr<LabelledStatement const> Parser::try_parse_labelled_statement(AllowLabelledFunction allow_function)
886{
887 {
888 // NOTE: This is a fast path where we try to fail early to avoid the expensive save_state+load_state.
889 if (next_token().type() != TokenType::Colon)
890 return {};
891 }
892
893 save_state();
894 auto rule_start = push_start();
895 ArmedScopeGuard state_rollback_guard = [&] {
896 load_state();
897 };
898
899 if (m_state.current_token.value() == "yield"sv && (m_state.strict_mode || m_state.in_generator_function_context)) {
900 return {};
901 }
902
903 if (m_state.current_token.value() == "await"sv && (m_program_type == Program::Type::Module || m_state.await_expression_is_valid || m_state.in_class_static_init_block)) {
904 return {};
905 }
906
907 auto identifier = [&] {
908 if (m_state.current_token.value() == "await"sv) {
909 return consume().value();
910 }
911 return consume_identifier_reference().value();
912 }();
913 if (!match(TokenType::Colon))
914 return {};
915 consume(TokenType::Colon);
916
917 if (!match_statement())
918 return {};
919
920 state_rollback_guard.disarm();
921 discard_saved_state();
922
923 if (m_state.strict_mode && identifier == "let"sv) {
924 syntax_error("Strict mode reserved word 'let' is not allowed in label", rule_start.position());
925 return {};
926 }
927
928 if (match(TokenType::Function) && (allow_function == AllowLabelledFunction::No || m_state.strict_mode)) {
929 syntax_error("Not allowed to declare a function here");
930 return {};
931 }
932
933 if (m_state.labels_in_scope.contains(identifier))
934 syntax_error(DeprecatedString::formatted("Label '{}' has already been declared", identifier));
935
936 RefPtr<Statement const> labelled_item;
937
938 auto is_iteration_statement = false;
939
940 if (match(TokenType::Function)) {
941 m_state.labels_in_scope.set(identifier, {});
942 auto function_declaration = parse_function_node<FunctionDeclaration>();
943 VERIFY(m_state.current_scope_pusher);
944 m_state.current_scope_pusher->add_declaration(function_declaration);
945 if (function_declaration->kind() == FunctionKind::Generator)
946 syntax_error("Generator functions cannot be defined in labelled statements");
947 if (function_declaration->kind() == FunctionKind::Async)
948 syntax_error("Async functions cannot be defined in labelled statements");
949
950 labelled_item = move(function_declaration);
951 } else {
952 m_state.labels_in_scope.set(identifier, {});
953 labelled_item = parse_statement(allow_function);
954 // Extract the innermost statement from a potentially nested chain of LabelledStatements.
955 auto statement = labelled_item;
956 while (is<LabelledStatement>(*statement))
957 statement = static_cast<LabelledStatement const&>(*statement).labelled_item();
958 if (is<IterationStatement>(*statement))
959 is_iteration_statement = true;
960 }
961
962 if (!is_iteration_statement) {
963 if (auto entry = m_state.labels_in_scope.find(identifier); entry != m_state.labels_in_scope.end() && entry->value.has_value())
964 syntax_error("labelled continue statement cannot use non iterating statement", m_state.labels_in_scope.get(identifier).value());
965 }
966
967 m_state.labels_in_scope.remove(identifier);
968
969 return create_ast_node<LabelledStatement>({ m_source_code, rule_start.position(), position() }, identifier, labelled_item.release_nonnull());
970}
971
972RefPtr<MetaProperty const> Parser::try_parse_new_target_expression()
973{
974 // Optimization which skips the save/load state.
975 if (next_token().type() != TokenType::Period)
976 return {};
977
978 save_state();
979 auto rule_start = push_start();
980 ArmedScopeGuard state_rollback_guard = [&] {
981 load_state();
982 };
983
984 consume(TokenType::New);
985 consume(TokenType::Period);
986 if (!match(TokenType::Identifier))
987 return {};
988 // The string 'target' cannot have escapes so we check original value.
989 if (consume().original_value() != "target"sv)
990 return {};
991
992 state_rollback_guard.disarm();
993 discard_saved_state();
994 return create_ast_node<MetaProperty>({ m_source_code, rule_start.position(), position() }, MetaProperty::Type::NewTarget);
995}
996
997RefPtr<MetaProperty const> Parser::try_parse_import_meta_expression()
998{
999 // Optimization which skips the save/load state.
1000 if (next_token().type() != TokenType::Period)
1001 return {};
1002
1003 save_state();
1004 auto rule_start = push_start();
1005 ArmedScopeGuard state_rollback_guard = [&] {
1006 load_state();
1007 };
1008
1009 consume(TokenType::Import);
1010 consume(TokenType::Period);
1011 if (!match(TokenType::Identifier))
1012 return {};
1013 // The string 'meta' cannot have escapes so we check original value.
1014 if (consume().original_value() != "meta"sv)
1015 return {};
1016
1017 state_rollback_guard.disarm();
1018 discard_saved_state();
1019 return create_ast_node<MetaProperty>({ m_source_code, rule_start.position(), position() }, MetaProperty::Type::ImportMeta);
1020}
1021
1022NonnullRefPtr<ImportCall const> Parser::parse_import_call()
1023{
1024 auto rule_start = push_start();
1025
1026 // We use the extended definition:
1027 // ImportCall[Yield, Await]:
1028 // import(AssignmentExpression[+In, ?Yield, ?Await] ,opt)
1029 // import(AssignmentExpression[+In, ?Yield, ?Await] ,AssignmentExpression[+In, ?Yield, ?Await] ,opt)
1030 // From https://tc39.es/proposal-import-assertions/#sec-evaluate-import-call
1031
1032 consume(TokenType::Import);
1033 consume(TokenType::ParenOpen);
1034 auto argument = parse_expression(2);
1035
1036 RefPtr<Expression const> options;
1037 if (match(TokenType::Comma)) {
1038 consume(TokenType::Comma);
1039
1040 if (!match(TokenType::ParenClose)) {
1041 options = parse_expression(2);
1042
1043 // Second optional comma
1044 if (match(TokenType::Comma))
1045 consume(TokenType::Comma);
1046 }
1047 }
1048
1049 consume(TokenType::ParenClose);
1050
1051 return create_ast_node<ImportCall>({ m_source_code, rule_start.position(), position() }, move(argument), move(options));
1052}
1053
1054NonnullRefPtr<ClassDeclaration const> Parser::parse_class_declaration()
1055{
1056 auto rule_start = push_start();
1057 return create_ast_node<ClassDeclaration>({ m_source_code, rule_start.position(), position() }, parse_class_expression(true));
1058}
1059
1060NonnullRefPtr<ClassExpression const> Parser::parse_class_expression(bool expect_class_name)
1061{
1062 auto rule_start = push_start();
1063 // Classes are always in strict mode.
1064 TemporaryChange strict_mode_rollback(m_state.strict_mode, true);
1065
1066 consume(TokenType::Class);
1067
1068 Vector<NonnullRefPtr<ClassElement const>> elements;
1069 RefPtr<Expression const> super_class;
1070 RefPtr<FunctionExpression const> constructor;
1071 HashTable<DeprecatedFlyString> found_private_names;
1072
1073 DeprecatedFlyString class_name = expect_class_name || match_identifier() || match(TokenType::Yield) || match(TokenType::Await)
1074 ? consume_identifier_reference().DeprecatedFlyString_value()
1075 : "";
1076
1077 check_identifier_name_for_assignment_validity(class_name, true);
1078 if (m_state.in_class_static_init_block && class_name == "await"sv)
1079 syntax_error("Identifier must not be a reserved word in modules ('await')");
1080
1081 if (match(TokenType::Extends)) {
1082 consume();
1083 auto [expression, should_continue_parsing] = parse_primary_expression();
1084
1085 // Basically a (much) simplified parse_secondary_expression().
1086 for (;;) {
1087 if (match(TokenType::TemplateLiteralStart)) {
1088 auto template_literal = parse_template_literal(true);
1089 expression = create_ast_node<TaggedTemplateLiteral>({ m_source_code, rule_start.position(), position() }, move(expression), move(template_literal));
1090 continue;
1091 }
1092 if (match(TokenType::BracketOpen) || match(TokenType::Period) || match(TokenType::ParenOpen)) {
1093 auto precedence = g_operator_precedence.get(m_state.current_token.type());
1094 expression = parse_secondary_expression(move(expression), precedence).expression;
1095 continue;
1096 }
1097 break;
1098 }
1099
1100 super_class = move(expression);
1101 (void)should_continue_parsing;
1102 }
1103
1104 consume(TokenType::CurlyOpen);
1105
1106 HashTable<StringView> referenced_private_names;
1107 HashTable<StringView>* outer_referenced_private_names = m_state.referenced_private_names;
1108 m_state.referenced_private_names = &referenced_private_names;
1109 ScopeGuard restore_private_name_table = [&] {
1110 m_state.referenced_private_names = outer_referenced_private_names;
1111 };
1112
1113 while (!done() && !match(TokenType::CurlyClose)) {
1114 RefPtr<Expression const> property_key;
1115 bool is_static = false;
1116 bool is_constructor = false;
1117 bool is_generator = false;
1118 bool is_async = false;
1119 auto method_kind = ClassMethod::Kind::Method;
1120
1121 if (match(TokenType::Semicolon)) {
1122 consume();
1123 continue;
1124 }
1125
1126 auto function_start = position();
1127
1128 if (match(TokenType::Async)) {
1129 auto lookahead_token = next_token();
1130 // If async is followed by a Semicolon or CurlyClose it is a field (CurlyClose indicates end of class)
1131 // Otherwise if it is followed by a ParenOpen it is a function named async
1132 if (lookahead_token.type() != TokenType::Semicolon && lookahead_token.type() != TokenType::CurlyClose && lookahead_token.type() != TokenType::ParenOpen
1133 && !lookahead_token.trivia_contains_line_terminator()) {
1134 consume();
1135 is_async = true;
1136 }
1137 }
1138
1139 if (match(TokenType::Asterisk)) {
1140 consume();
1141 is_generator = true;
1142 }
1143
1144 StringView name;
1145 if (match_property_key() || match(TokenType::PrivateIdentifier)) {
1146 if (!is_generator && !is_async && m_state.current_token.original_value() == "static"sv) {
1147 if (match(TokenType::Identifier)) {
1148 consume();
1149 is_static = true;
1150 function_start = position();
1151 if (match(TokenType::Async)) {
1152 consume();
1153 is_async = true;
1154 }
1155 if (match(TokenType::Asterisk)) {
1156 consume();
1157 is_generator = true;
1158 }
1159 }
1160 }
1161
1162 if (match(TokenType::Identifier)) {
1163 auto identifier_name = m_state.current_token.original_value();
1164
1165 if (identifier_name == "get"sv) {
1166 method_kind = ClassMethod::Kind::Getter;
1167 consume();
1168 } else if (identifier_name == "set"sv) {
1169 method_kind = ClassMethod::Kind::Setter;
1170 consume();
1171 }
1172 }
1173
1174 if (match_property_key() || match(TokenType::PrivateIdentifier)) {
1175 switch (m_state.current_token.type()) {
1176 case TokenType::Identifier:
1177 name = consume().value();
1178 property_key = create_ast_node<StringLiteral>({ m_source_code, rule_start.position(), position() }, name);
1179 break;
1180 case TokenType::PrivateIdentifier:
1181 name = consume().value();
1182 if (name == "#constructor")
1183 syntax_error("Private property with name '#constructor' is not allowed");
1184
1185 if (method_kind != ClassMethod::Kind::Method) {
1186 // It is a Syntax Error if PrivateBoundIdentifiers of ClassElementList contains any duplicate entries,
1187 // unless the name is used once for a getter and once for a setter and in no other entries,
1188 // and the getter and setter are either both static or both non-static.
1189
1190 for (auto& element : elements) {
1191 auto private_name = element->private_bound_identifier();
1192 if (!private_name.has_value() || private_name.value() != name)
1193 continue;
1194
1195 if (element->class_element_kind() != ClassElement::ElementKind::Method
1196 || element->is_static() != is_static) {
1197 syntax_error(DeprecatedString::formatted("Duplicate private field or method named '{}'", name));
1198 break;
1199 }
1200
1201 VERIFY(is<ClassMethod>(*element));
1202 auto& class_method_element = static_cast<ClassMethod const&>(*element);
1203
1204 if (class_method_element.kind() == ClassMethod::Kind::Method || class_method_element.kind() == method_kind) {
1205 syntax_error(DeprecatedString::formatted("Duplicate private field or method named '{}'", name));
1206 break;
1207 }
1208 }
1209
1210 found_private_names.set(name);
1211 } else if (found_private_names.set(name) != AK::HashSetResult::InsertedNewEntry) {
1212 syntax_error(DeprecatedString::formatted("Duplicate private field or method named '{}'", name));
1213 }
1214
1215 property_key = create_ast_node<PrivateIdentifier>({ m_source_code, rule_start.position(), position() }, name);
1216 break;
1217 case TokenType::StringLiteral: {
1218 auto string_literal = parse_string_literal(consume());
1219 name = string_literal->value();
1220 property_key = move(string_literal);
1221 break;
1222 }
1223 default:
1224 property_key = parse_property_key();
1225 break;
1226 }
1227
1228 // https://tc39.es/ecma262/#sec-class-definitions-static-semantics-early-errors
1229 // ClassElement : static MethodDefinition
1230 // It is a Syntax Error if PropName of MethodDefinition is "prototype".
1231 if (is_static && name == "prototype"sv)
1232 syntax_error("Classes may not have a static property named 'prototype'");
1233 } else if ((match(TokenType::ParenOpen) || match(TokenType::Equals) || match(TokenType::Semicolon) || match(TokenType::CurlyClose)) && (is_static || is_async || method_kind != ClassMethod::Kind::Method)) {
1234 switch (method_kind) {
1235 case ClassMethod::Kind::Method:
1236 if (is_async) {
1237 name = "async"sv;
1238 is_async = false;
1239 } else {
1240 VERIFY(is_static);
1241 name = "static"sv;
1242 is_static = false;
1243 }
1244 break;
1245 case ClassMethod::Kind::Getter:
1246 name = "get"sv;
1247 method_kind = ClassMethod::Kind::Method;
1248 break;
1249 case ClassMethod::Kind::Setter:
1250 name = "set"sv;
1251 method_kind = ClassMethod::Kind::Method;
1252 break;
1253 }
1254 property_key = create_ast_node<StringLiteral>({ m_source_code, rule_start.position(), position() }, name);
1255 } else if (match(TokenType::CurlyOpen) && is_static) {
1256 auto static_start = push_start();
1257 consume(TokenType::CurlyOpen);
1258
1259 auto static_init_block = create_ast_node<FunctionBody>({ m_source_code, rule_start.position(), position() });
1260
1261 TemporaryChange break_context_rollback(m_state.in_break_context, false);
1262 TemporaryChange continue_context_rollback(m_state.in_continue_context, false);
1263 TemporaryChange function_context_rollback(m_state.in_function_context, false);
1264 TemporaryChange generator_function_context_rollback(m_state.in_generator_function_context, false);
1265 TemporaryChange async_function_context_rollback(m_state.await_expression_is_valid, false);
1266 TemporaryChange class_field_initializer_rollback(m_state.in_class_field_initializer, true);
1267 TemporaryChange class_static_init_block_rollback(m_state.in_class_static_init_block, true);
1268 TemporaryChange super_property_access_rollback(m_state.allow_super_property_lookup, true);
1269
1270 ScopePusher static_init_scope = ScopePusher::static_init_block_scope(*this, *static_init_block);
1271 parse_statement_list(static_init_block);
1272
1273 consume(TokenType::CurlyClose);
1274 elements.append(create_ast_node<StaticInitializer>({ m_source_code, static_start.position(), position() }, move(static_init_block), static_init_scope.contains_direct_call_to_eval()));
1275 continue;
1276 } else {
1277 expected("property key");
1278 }
1279
1280 // Constructor may be a StringLiteral or an Identifier.
1281 if (!is_static && name == "constructor"sv) {
1282 if (method_kind != ClassMethod::Kind::Method)
1283 syntax_error("Class constructor may not be an accessor");
1284 if (!constructor.is_null())
1285 syntax_error("Classes may not have more than one constructor");
1286 if (is_generator)
1287 syntax_error("Class constructor may not be a generator");
1288 if (is_async)
1289 syntax_error("Class constructor may not be async");
1290
1291 is_constructor = true;
1292 }
1293 }
1294
1295 if (match(TokenType::ParenOpen)) {
1296 u8 parse_options = FunctionNodeParseOptions::AllowSuperPropertyLookup;
1297 if (!super_class.is_null() && !is_static && is_constructor)
1298 parse_options |= FunctionNodeParseOptions::AllowSuperConstructorCall;
1299 if (method_kind == ClassMethod::Kind::Getter)
1300 parse_options |= FunctionNodeParseOptions::IsGetterFunction;
1301 if (method_kind == ClassMethod::Kind::Setter)
1302 parse_options |= FunctionNodeParseOptions::IsSetterFunction;
1303 if (is_generator)
1304 parse_options |= FunctionNodeParseOptions::IsGeneratorFunction;
1305 if (is_async)
1306 parse_options |= FunctionNodeParseOptions::IsAsyncFunction;
1307 auto function = parse_function_node<FunctionExpression>(parse_options, function_start);
1308 if (is_constructor) {
1309 constructor = move(function);
1310 } else if (!property_key.is_null()) {
1311 elements.append(create_ast_node<ClassMethod>({ m_source_code, rule_start.position(), position() }, property_key.release_nonnull(), move(function), method_kind, is_static));
1312 } else {
1313 syntax_error("No key for class method");
1314 }
1315 } else if (is_generator || is_async) {
1316 expected("ParenOpen");
1317 consume();
1318 } else if (property_key.is_null()) {
1319 expected("property key");
1320 consume();
1321 } else {
1322 if (name == "constructor"sv)
1323 syntax_error("Class cannot have field named 'constructor'");
1324
1325 RefPtr<Expression const> initializer;
1326 bool contains_direct_call_to_eval = false;
1327
1328 if (match(TokenType::Equals)) {
1329 consume();
1330
1331 TemporaryChange super_property_access_rollback(m_state.allow_super_property_lookup, true);
1332 TemporaryChange field_initializer_rollback(m_state.in_class_field_initializer, true);
1333
1334 auto class_field_scope = ScopePusher::class_field_scope(*this);
1335 initializer = parse_expression(2);
1336 contains_direct_call_to_eval = class_field_scope.contains_direct_call_to_eval();
1337 }
1338
1339 elements.append(create_ast_node<ClassField>({ m_source_code, rule_start.position(), position() }, property_key.release_nonnull(), move(initializer), contains_direct_call_to_eval, is_static));
1340 consume_or_insert_semicolon();
1341 }
1342 }
1343
1344 consume(TokenType::CurlyClose);
1345
1346 if (constructor.is_null()) {
1347 auto constructor_body = create_ast_node<BlockStatement>({ m_source_code, rule_start.position(), position() });
1348 if (!super_class.is_null()) {
1349 // Set constructor to the result of parsing the source text
1350 // constructor(... args){ super (...args);}
1351 // However: The most notable distinction is that while the aforementioned ECMAScript
1352 // source text observably calls the @@iterator method on %Array.prototype%,
1353 // this function does not.
1354 // So we use a custom version of SuperCall which doesn't use the @@iterator
1355 // method on %Array.prototype% visibly.
1356 DeprecatedFlyString argument_name = "args";
1357 auto super_call = create_ast_node<SuperCall>(
1358 { m_source_code, rule_start.position(), position() },
1359 SuperCall::IsPartOfSyntheticConstructor::Yes,
1360 CallExpression::Argument { create_ast_node<Identifier>({ m_source_code, rule_start.position(), position() }, "args"), true });
1361 // NOTE: While the JS approximation above doesn't do `return super(...args)`, the
1362 // abstract closure is expected to capture and return the result, so we do need a
1363 // return statement here to create the correct completion.
1364 constructor_body->append(create_ast_node<ReturnStatement>({ m_source_code, rule_start.position(), position() }, move(super_call)));
1365
1366 constructor = create_ast_node<FunctionExpression>(
1367 { m_source_code, rule_start.position(), position() }, class_name, "",
1368 move(constructor_body), Vector { FunctionParameter { move(argument_name), nullptr, true } }, 0, FunctionKind::Normal,
1369 /* is_strict_mode */ true, /* might_need_arguments_object */ false, /* contains_direct_call_to_eval */ false);
1370 } else {
1371 constructor = create_ast_node<FunctionExpression>(
1372 { m_source_code, rule_start.position(), position() }, class_name, "",
1373 move(constructor_body), Vector<FunctionParameter> {}, 0, FunctionKind::Normal,
1374 /* is_strict_mode */ true, /* might_need_arguments_object */ false, /* contains_direct_call_to_eval */ false);
1375 }
1376 }
1377
1378 // We could be in a subclass defined within the main class so must move all non declared private names to outer.
1379 for (auto& private_name : referenced_private_names) {
1380 if (found_private_names.contains(private_name))
1381 continue;
1382 if (outer_referenced_private_names)
1383 outer_referenced_private_names->set(private_name);
1384 else // FIXME: Make these error appear in the appropriate places.
1385 syntax_error(DeprecatedString::formatted("Reference to undeclared private field or method '{}'", private_name));
1386 }
1387
1388 auto function_start_offset = rule_start.position().offset;
1389 auto function_end_offset = position().offset - m_state.current_token.trivia().length();
1390 auto source_text = DeprecatedString { m_state.lexer.source().substring_view(function_start_offset, function_end_offset - function_start_offset) };
1391
1392 return create_ast_node<ClassExpression>({ m_source_code, rule_start.position(), position() }, move(class_name), move(source_text), move(constructor), move(super_class), move(elements));
1393}
1394
1395Parser::PrimaryExpressionParseResult Parser::parse_primary_expression()
1396{
1397 auto rule_start = push_start();
1398 if (match_unary_prefixed_expression())
1399 return { parse_unary_prefixed_expression() };
1400
1401 auto try_arrow_function_parse_or_fail = [this](Position const& position, bool expect_paren, bool is_async = false) -> RefPtr<FunctionExpression const> {
1402 if (try_parse_arrow_function_expression_failed_at_position(position))
1403 return nullptr;
1404 auto arrow_function = try_parse_arrow_function_expression(expect_paren, is_async);
1405 if (arrow_function)
1406 return arrow_function;
1407
1408 set_try_parse_arrow_function_expression_failed_at_position(position, true);
1409 return nullptr;
1410 };
1411
1412 switch (m_state.current_token.type()) {
1413 case TokenType::ParenOpen: {
1414 auto paren_position = position();
1415 consume(TokenType::ParenOpen);
1416 if ((match(TokenType::ParenClose) || match_identifier() || match(TokenType::TripleDot) || match(TokenType::CurlyOpen) || match(TokenType::BracketOpen))) {
1417 if (auto arrow_function_result = try_arrow_function_parse_or_fail(paren_position, true))
1418 return { arrow_function_result.release_nonnull(), false };
1419 }
1420 auto expression = parse_expression(0);
1421 consume(TokenType::ParenClose);
1422 if (is<FunctionExpression>(*expression)) {
1423 auto& function = static_cast<FunctionExpression const&>(*expression);
1424 if (function.kind() == FunctionKind::Generator && function.name() == "yield"sv)
1425 syntax_error("function is not allowed to be called 'yield' in this context", function.source_range().start);
1426 if (function.kind() == FunctionKind::Async && function.name() == "await"sv)
1427 syntax_error("function is not allowed to be called 'await' in this context", function.source_range().start);
1428 }
1429 return { move(expression) };
1430 }
1431 case TokenType::This:
1432 consume();
1433 return { create_ast_node<ThisExpression>({ m_source_code, rule_start.position(), position() }) };
1434 case TokenType::Class:
1435 return { parse_class_expression(false) };
1436 case TokenType::Super:
1437 consume();
1438 if (!m_state.allow_super_property_lookup)
1439 syntax_error("'super' keyword unexpected here");
1440 return { create_ast_node<SuperExpression>({ m_source_code, rule_start.position(), position() }) };
1441 case TokenType::EscapedKeyword:
1442 if (match_invalid_escaped_keyword())
1443 syntax_error("Keyword must not contain escaped characters");
1444 [[fallthrough]];
1445 case TokenType::Identifier: {
1446 read_as_identifier:;
1447 if (auto arrow_function_result = try_arrow_function_parse_or_fail(position(), false))
1448 return { arrow_function_result.release_nonnull(), false };
1449
1450 auto string = m_state.current_token.value();
1451 // This could be 'eval' or 'arguments' and thus needs a custom check (`eval[1] = true`)
1452 if (m_state.strict_mode && (string == "let" || is_strict_reserved_word(string)))
1453 syntax_error(DeprecatedString::formatted("Identifier must not be a reserved word in strict mode ('{}')", string));
1454 return { parse_identifier() };
1455 }
1456 case TokenType::NumericLiteral:
1457 return { create_ast_node<NumericLiteral>({ m_source_code, rule_start.position(), position() }, consume_and_validate_numeric_literal().double_value()) };
1458 case TokenType::BigIntLiteral:
1459 return { create_ast_node<BigIntLiteral>({ m_source_code, rule_start.position(), position() }, consume().value()) };
1460 case TokenType::BoolLiteral:
1461 return { create_ast_node<BooleanLiteral>({ m_source_code, rule_start.position(), position() }, consume().bool_value()) };
1462 case TokenType::StringLiteral:
1463 return { parse_string_literal(consume()) };
1464 case TokenType::NullLiteral:
1465 consume();
1466 return { create_ast_node<NullLiteral>({ m_source_code, rule_start.position(), position() }) };
1467 case TokenType::CurlyOpen:
1468 return { parse_object_expression() };
1469 case TokenType::Async: {
1470 auto lookahead_token = next_token();
1471 // No valid async function (arrow or not) can have a line terminator after the async since asi would kick in.
1472 if (lookahead_token.trivia_contains_line_terminator())
1473 goto read_as_identifier;
1474
1475 if (lookahead_token.type() == TokenType::Function)
1476 return { parse_function_node<FunctionExpression>() };
1477
1478 if (lookahead_token.type() == TokenType::ParenOpen) {
1479 if (auto arrow_function_result = try_arrow_function_parse_or_fail(position(), true, true))
1480 return { arrow_function_result.release_nonnull(), false };
1481 } else if (lookahead_token.is_identifier_name()) {
1482 if (auto arrow_function_result = try_arrow_function_parse_or_fail(position(), false, true))
1483 return { arrow_function_result.release_nonnull(), false };
1484 }
1485 goto read_as_identifier;
1486 }
1487 case TokenType::Function:
1488 return { parse_function_node<FunctionExpression>() };
1489 case TokenType::BracketOpen:
1490 return { parse_array_expression() };
1491 case TokenType::RegexLiteral:
1492 return { parse_regexp_literal() };
1493 case TokenType::TemplateLiteralStart:
1494 return { parse_template_literal(false) };
1495 case TokenType::New: {
1496 auto new_start = position();
1497 auto new_target_result = try_parse_new_target_expression();
1498 if (!new_target_result.is_null()) {
1499 if (!m_state.in_function_context && !m_state.in_eval_function_context && !m_state.in_class_static_init_block)
1500 syntax_error("'new.target' not allowed outside of a function", new_start);
1501 return { new_target_result.release_nonnull() };
1502 }
1503 return { parse_new_expression() };
1504 }
1505 case TokenType::Import: {
1506 auto lookahead_token = next_token();
1507 if (lookahead_token.type() == TokenType::ParenOpen)
1508 return { parse_import_call() };
1509
1510 if (lookahead_token.type() == TokenType::Period) {
1511 if (auto import_meta = try_parse_import_meta_expression()) {
1512 if (m_program_type != Program::Type::Module)
1513 syntax_error("import.meta is only allowed in modules");
1514 return { import_meta.release_nonnull() };
1515 }
1516 } else {
1517 consume();
1518 expected("import.meta or import call");
1519 }
1520 break;
1521 }
1522 case TokenType::Yield:
1523 if (!m_state.in_generator_function_context)
1524 goto read_as_identifier;
1525 return { parse_yield_expression(), false };
1526 case TokenType::Await:
1527 if (!m_state.await_expression_is_valid)
1528 goto read_as_identifier;
1529 return { parse_await_expression() };
1530 case TokenType::PrivateIdentifier:
1531 if (!is_private_identifier_valid())
1532 syntax_error(DeprecatedString::formatted("Reference to undeclared private field or method '{}'", m_state.current_token.value()));
1533 if (next_token().type() != TokenType::In)
1534 syntax_error("Cannot have a private identifier in expression if not followed by 'in'");
1535 return { create_ast_node<PrivateIdentifier>({ m_source_code, rule_start.position(), position() }, consume().value()) };
1536 default:
1537 if (match_identifier_name())
1538 goto read_as_identifier;
1539 break;
1540 }
1541 expected("primary expression");
1542 consume();
1543 return { create_ast_node<ErrorExpression>({ m_source_code, rule_start.position(), position() }) };
1544}
1545
1546NonnullRefPtr<RegExpLiteral const> Parser::parse_regexp_literal()
1547{
1548 auto rule_start = push_start();
1549 auto pattern = consume().value();
1550 // Remove leading and trailing slash.
1551 pattern = pattern.substring_view(1, pattern.length() - 2);
1552
1553 auto flags = DeprecatedString::empty();
1554 auto parsed_flags = RegExpObject::default_flags;
1555
1556 if (match(TokenType::RegexFlags)) {
1557 auto flags_start = position();
1558 flags = consume().value();
1559
1560 auto parsed_flags_or_error = regex_flags_from_string(flags);
1561 if (parsed_flags_or_error.is_error())
1562 syntax_error(parsed_flags_or_error.release_error(), flags_start);
1563 else
1564 parsed_flags = parsed_flags_or_error.release_value();
1565 }
1566
1567 DeprecatedString parsed_pattern;
1568 auto parsed_pattern_result = parse_regex_pattern(pattern, parsed_flags.has_flag_set(ECMAScriptFlags::Unicode), parsed_flags.has_flag_set(ECMAScriptFlags::UnicodeSets));
1569 if (parsed_pattern_result.is_error()) {
1570 syntax_error(parsed_pattern_result.release_error().error, rule_start.position());
1571 parsed_pattern = DeprecatedString::empty();
1572 } else {
1573 parsed_pattern = parsed_pattern_result.release_value();
1574 }
1575 auto parsed_regex = Regex<ECMA262>::parse_pattern(parsed_pattern, parsed_flags);
1576
1577 if (parsed_regex.error != regex::Error::NoError)
1578 syntax_error(DeprecatedString::formatted("RegExp compile error: {}", Regex<ECMA262>(parsed_regex, parsed_pattern, parsed_flags).error_string()), rule_start.position());
1579
1580 SourceRange range { m_source_code, rule_start.position(), position() };
1581 return create_ast_node<RegExpLiteral>(move(range), move(parsed_regex), move(parsed_pattern), move(parsed_flags), pattern.to_deprecated_string(), move(flags));
1582}
1583
1584static bool is_simple_assignment_target(Expression const& expression, bool allow_web_reality_call_expression = true)
1585{
1586 return is<Identifier>(expression) || is<MemberExpression>(expression) || (allow_web_reality_call_expression && is<CallExpression>(expression));
1587}
1588
1589NonnullRefPtr<Expression const> Parser::parse_unary_prefixed_expression()
1590{
1591 auto rule_start = push_start();
1592 auto precedence = g_operator_precedence.get(m_state.current_token.type());
1593 auto associativity = operator_associativity(m_state.current_token.type());
1594 switch (m_state.current_token.type()) {
1595 case TokenType::PlusPlus: {
1596 consume();
1597 auto rhs_start = position();
1598 auto rhs = parse_expression(precedence, associativity);
1599 if (!is_simple_assignment_target(*rhs))
1600 syntax_error(DeprecatedString::formatted("Right-hand side of prefix increment operator must be identifier or member expression, got {}", rhs->class_name()), rhs_start);
1601
1602 if (m_state.strict_mode && is<Identifier>(*rhs)) {
1603 auto& identifier = static_cast<Identifier const&>(*rhs);
1604 auto& name = identifier.string();
1605 check_identifier_name_for_assignment_validity(name);
1606 }
1607
1608 return create_ast_node<UpdateExpression>({ m_source_code, rule_start.position(), position() }, UpdateOp::Increment, move(rhs), true);
1609 }
1610 case TokenType::MinusMinus: {
1611 consume();
1612 auto rhs_start = position();
1613 auto rhs = parse_expression(precedence, associativity);
1614 if (!is_simple_assignment_target(*rhs))
1615 syntax_error(DeprecatedString::formatted("Right-hand side of prefix decrement operator must be identifier or member expression, got {}", rhs->class_name()), rhs_start);
1616
1617 if (m_state.strict_mode && is<Identifier>(*rhs)) {
1618 auto& identifier = static_cast<Identifier const&>(*rhs);
1619 auto& name = identifier.string();
1620 check_identifier_name_for_assignment_validity(name);
1621 }
1622
1623 return create_ast_node<UpdateExpression>({ m_source_code, rule_start.position(), position() }, UpdateOp::Decrement, move(rhs), true);
1624 }
1625 case TokenType::ExclamationMark:
1626 consume();
1627 return create_ast_node<UnaryExpression>({ m_source_code, rule_start.position(), position() }, UnaryOp::Not, parse_expression(precedence, associativity));
1628 case TokenType::Tilde:
1629 consume();
1630 return create_ast_node<UnaryExpression>({ m_source_code, rule_start.position(), position() }, UnaryOp::BitwiseNot, parse_expression(precedence, associativity));
1631 case TokenType::Plus:
1632 consume();
1633 return create_ast_node<UnaryExpression>({ m_source_code, rule_start.position(), position() }, UnaryOp::Plus, parse_expression(precedence, associativity));
1634 case TokenType::Minus:
1635 consume();
1636 return create_ast_node<UnaryExpression>({ m_source_code, rule_start.position(), position() }, UnaryOp::Minus, parse_expression(precedence, associativity));
1637 case TokenType::Typeof:
1638 consume();
1639 return create_ast_node<UnaryExpression>({ m_source_code, rule_start.position(), position() }, UnaryOp::Typeof, parse_expression(precedence, associativity));
1640 case TokenType::Void:
1641 consume();
1642 // FIXME: This check is really hiding the fact that we don't deal with different expressions correctly.
1643 if (match(TokenType::Yield) && m_state.in_generator_function_context)
1644 syntax_error("'yield' is not an identifier in generator function context");
1645 return create_ast_node<UnaryExpression>({ m_source_code, rule_start.position(), position() }, UnaryOp::Void, parse_expression(precedence, associativity));
1646 case TokenType::Delete: {
1647 consume();
1648 auto rhs_start = position();
1649 auto rhs = parse_expression(precedence, associativity);
1650 if (is<Identifier>(*rhs) && m_state.strict_mode) {
1651 syntax_error("Delete of an unqualified identifier in strict mode.", rhs_start);
1652 }
1653 if (is<MemberExpression>(*rhs)) {
1654 auto& member_expression = static_cast<MemberExpression const&>(*rhs);
1655 if (member_expression.ends_in_private_name())
1656 syntax_error("Private fields cannot be deleted");
1657 }
1658 return create_ast_node<UnaryExpression>({ m_source_code, rule_start.position(), position() }, UnaryOp::Delete, move(rhs));
1659 }
1660 default:
1661 expected("primary expression");
1662 consume();
1663 return create_ast_node<ErrorExpression>({ m_source_code, rule_start.position(), position() });
1664 }
1665}
1666
1667NonnullRefPtr<Expression const> Parser::parse_property_key()
1668{
1669 auto rule_start = push_start();
1670 if (match(TokenType::StringLiteral)) {
1671 return parse_string_literal(consume());
1672 } else if (match(TokenType::NumericLiteral)) {
1673 return create_ast_node<NumericLiteral>({ m_source_code, rule_start.position(), position() }, consume().double_value());
1674 } else if (match(TokenType::BigIntLiteral)) {
1675 return create_ast_node<BigIntLiteral>({ m_source_code, rule_start.position(), position() }, consume().value());
1676 } else if (match(TokenType::BracketOpen)) {
1677 consume(TokenType::BracketOpen);
1678 auto result = parse_expression(2);
1679 consume(TokenType::BracketClose);
1680 return result;
1681 } else {
1682 if (!match_identifier_name())
1683 expected("IdentifierName");
1684 return create_ast_node<StringLiteral>({ m_source_code, rule_start.position(), position() }, consume().value());
1685 }
1686}
1687
1688NonnullRefPtr<ObjectExpression const> Parser::parse_object_expression()
1689{
1690 auto rule_start = push_start();
1691 consume(TokenType::CurlyOpen);
1692
1693 Vector<NonnullRefPtr<ObjectProperty>> properties;
1694 ObjectProperty::Type property_type;
1695 Optional<SourceRange> invalid_object_literal_property_range;
1696
1697 auto skip_to_next_property = [&] {
1698 while (!done() && !match(TokenType::Comma) && !match(TokenType::CurlyOpen))
1699 consume();
1700 };
1701
1702 // It is a Syntax Error if PropertyNameList of PropertyDefinitionList contains any duplicate
1703 // entries for "__proto__" and at least two of those entries were obtained from productions of
1704 // the form PropertyDefinition : PropertyKey : AssignmentExpression .
1705 bool has_direct_proto_property = false;
1706
1707 while (!done() && !match(TokenType::CurlyClose)) {
1708 property_type = ObjectProperty::Type::KeyValue;
1709 RefPtr<Expression const> property_key;
1710 RefPtr<Expression const> property_value;
1711 FunctionKind function_kind { FunctionKind::Normal };
1712
1713 if (match(TokenType::TripleDot)) {
1714 consume();
1715 property_key = parse_expression(4);
1716 properties.append(create_ast_node<ObjectProperty>({ m_source_code, rule_start.position(), position() }, *property_key, nullptr, ObjectProperty::Type::Spread, false));
1717 if (!match(TokenType::Comma))
1718 break;
1719 consume(TokenType::Comma);
1720 continue;
1721 }
1722
1723 auto type = m_state.current_token.type();
1724 auto function_start = position();
1725
1726 if (match(TokenType::Async)) {
1727 auto lookahead_token = next_token();
1728
1729 if (lookahead_token.type() != TokenType::ParenOpen && lookahead_token.type() != TokenType::Colon
1730 && lookahead_token.type() != TokenType::Comma && lookahead_token.type() != TokenType::CurlyClose
1731 && lookahead_token.type() != TokenType::Async
1732 && !lookahead_token.trivia_contains_line_terminator()) {
1733 consume(TokenType::Async);
1734 function_kind = FunctionKind::Async;
1735 }
1736 }
1737 if (match(TokenType::Asterisk)) {
1738 consume();
1739 property_type = ObjectProperty::Type::KeyValue;
1740 property_key = parse_property_key();
1741 VERIFY(function_kind == FunctionKind::Normal || function_kind == FunctionKind::Async);
1742 function_kind = function_kind == FunctionKind::Normal ? FunctionKind::Generator : FunctionKind::AsyncGenerator;
1743 } else if (match_identifier()) {
1744 auto identifier = consume();
1745 if (identifier.original_value() == "get"sv && match_property_key()) {
1746 property_type = ObjectProperty::Type::Getter;
1747 property_key = parse_property_key();
1748 } else if (identifier.original_value() == "set"sv && match_property_key()) {
1749 property_type = ObjectProperty::Type::Setter;
1750 property_key = parse_property_key();
1751 } else {
1752 property_key = create_ast_node<StringLiteral>({ m_source_code, rule_start.position(), position() }, identifier.value());
1753 property_value = create_ast_node<Identifier>({ m_source_code, rule_start.position(), position() }, identifier.DeprecatedFlyString_value());
1754 }
1755 } else {
1756 property_key = parse_property_key();
1757 }
1758
1759 // 4. Else if propKey is the String value "__proto__" and if IsComputedPropertyKey of PropertyName is false, then
1760 // a. Let isProtoSetter be true.
1761 bool is_proto = (type == TokenType::StringLiteral || type == TokenType::Identifier) && is<StringLiteral>(*property_key) && static_cast<StringLiteral const&>(*property_key).value() == "__proto__";
1762
1763 if (property_type == ObjectProperty::Type::Getter || property_type == ObjectProperty::Type::Setter) {
1764 if (!match(TokenType::ParenOpen)) {
1765 expected("'(' for object getter or setter property");
1766 skip_to_next_property();
1767 continue;
1768 }
1769 }
1770 if (match(TokenType::Equals)) {
1771 // Not a valid object literal, but a valid assignment target
1772 consume();
1773 // Parse the expression and throw it away
1774 auto expression = parse_expression(2);
1775 if (!invalid_object_literal_property_range.has_value())
1776 invalid_object_literal_property_range = expression->source_range();
1777 } else if (match(TokenType::ParenOpen)) {
1778 VERIFY(property_key);
1779 u8 parse_options = FunctionNodeParseOptions::AllowSuperPropertyLookup;
1780 if (property_type == ObjectProperty::Type::Getter)
1781 parse_options |= FunctionNodeParseOptions::IsGetterFunction;
1782 if (property_type == ObjectProperty::Type::Setter)
1783 parse_options |= FunctionNodeParseOptions::IsSetterFunction;
1784 if (function_kind == FunctionKind::Generator || function_kind == FunctionKind::AsyncGenerator)
1785 parse_options |= FunctionNodeParseOptions::IsGeneratorFunction;
1786 if (function_kind == FunctionKind::Async || function_kind == FunctionKind::AsyncGenerator)
1787 parse_options |= FunctionNodeParseOptions::IsAsyncFunction;
1788 auto function = parse_function_node<FunctionExpression>(parse_options, function_start);
1789 properties.append(create_ast_node<ObjectProperty>({ m_source_code, rule_start.position(), position() }, *property_key, function, property_type, true));
1790 } else if (match(TokenType::Colon)) {
1791 if (!property_key) {
1792 expected("a property name");
1793 skip_to_next_property();
1794 continue;
1795 }
1796 consume();
1797 if (is_proto) {
1798 if (has_direct_proto_property)
1799 syntax_error("Property name '__proto__' must not appear more than once in object literal");
1800 has_direct_proto_property = true;
1801 }
1802 if (is_proto && property_type == ObjectProperty::Type::KeyValue)
1803 property_type = ObjectProperty::Type::ProtoSetter;
1804
1805 auto rhs_expression = parse_expression(2);
1806 bool is_method = is<FunctionExpression>(*rhs_expression);
1807 properties.append(create_ast_node<ObjectProperty>({ m_source_code, rule_start.position(), position() }, *property_key, move(rhs_expression), property_type, is_method));
1808 } else if (property_key && property_value) {
1809 if (m_state.strict_mode && is<StringLiteral>(*property_key)) {
1810 auto& string_literal = static_cast<StringLiteral const&>(*property_key);
1811 if (is_strict_reserved_word(string_literal.value()))
1812 syntax_error(DeprecatedString::formatted("'{}' is a reserved keyword", string_literal.value()));
1813 }
1814
1815 properties.append(create_ast_node<ObjectProperty>({ m_source_code, rule_start.position(), position() }, *property_key, *property_value, property_type, false));
1816 } else {
1817 expected("a property");
1818 skip_to_next_property();
1819 continue;
1820 }
1821
1822 if (!match(TokenType::Comma))
1823 break;
1824 consume(TokenType::Comma);
1825 }
1826
1827 consume(TokenType::CurlyClose);
1828
1829 if (invalid_object_literal_property_range.has_value()) {
1830 size_t object_expression_offset = rule_start.position().offset;
1831 VERIFY(!m_state.invalid_property_range_in_object_expression.contains(object_expression_offset));
1832 m_state.invalid_property_range_in_object_expression.set(object_expression_offset, invalid_object_literal_property_range->start);
1833 }
1834
1835 properties.shrink_to_fit();
1836 return create_ast_node<ObjectExpression>(
1837 { m_source_code, rule_start.position(), position() },
1838 move(properties));
1839}
1840
1841NonnullRefPtr<ArrayExpression const> Parser::parse_array_expression()
1842{
1843 auto rule_start = push_start();
1844 consume(TokenType::BracketOpen);
1845
1846 Vector<RefPtr<Expression const>> elements;
1847 while (match_expression() || match(TokenType::TripleDot) || match(TokenType::Comma)) {
1848 RefPtr<Expression const> expression;
1849
1850 if (match(TokenType::TripleDot)) {
1851 consume(TokenType::TripleDot);
1852 expression = create_ast_node<SpreadExpression>({ m_source_code, rule_start.position(), position() }, parse_expression(2));
1853 } else if (match_expression()) {
1854 expression = parse_expression(2);
1855 }
1856
1857 elements.append(expression);
1858 if (!match(TokenType::Comma))
1859 break;
1860 consume(TokenType::Comma);
1861 }
1862
1863 consume(TokenType::BracketClose);
1864
1865 elements.shrink_to_fit();
1866 return create_ast_node<ArrayExpression>({ m_source_code, rule_start.position(), position() }, move(elements));
1867}
1868
1869NonnullRefPtr<StringLiteral const> Parser::parse_string_literal(Token const& token, StringLiteralType string_literal_type, bool* contains_invalid_escape)
1870{
1871 auto rule_start = push_start();
1872 auto status = Token::StringValueStatus::Ok;
1873 auto string = token.string_value(status);
1874 // NOTE: Tagged templates should not fail on invalid strings as their raw contents can still be accessed.
1875 if (status != Token::StringValueStatus::Ok) {
1876 DeprecatedString message;
1877 if (status == Token::StringValueStatus::LegacyOctalEscapeSequence) {
1878 m_state.string_legacy_octal_escape_sequence_in_scope = true;
1879 // It is a Syntax Error if the [Tagged] parameter was not set and Template{Head, Middle, Tail} Contains NotEscapeSequence.
1880 if (string_literal_type != StringLiteralType::Normal)
1881 message = "Octal escape sequence not allowed in template literal";
1882 else if (m_state.strict_mode)
1883 message = "Octal escape sequence in string literal not allowed in strict mode";
1884 } else if (status == Token::StringValueStatus::MalformedHexEscape || status == Token::StringValueStatus::MalformedUnicodeEscape) {
1885 auto type = status == Token::StringValueStatus::MalformedUnicodeEscape ? "unicode" : "hexadecimal";
1886 message = DeprecatedString::formatted("Malformed {} escape sequence", type);
1887 } else if (status == Token::StringValueStatus::UnicodeEscapeOverflow) {
1888 message = "Unicode code_point must not be greater than 0x10ffff in escape sequence";
1889 } else {
1890 VERIFY_NOT_REACHED();
1891 }
1892
1893 if (!message.is_empty()) {
1894 if (contains_invalid_escape != nullptr) {
1895 VERIFY(string_literal_type == StringLiteralType::TaggedTemplate);
1896 *contains_invalid_escape = true;
1897 } else {
1898 syntax_error(message, Position { token.line_number(), token.line_column() });
1899 }
1900 }
1901 }
1902
1903 return create_ast_node<StringLiteral>({ m_source_code, rule_start.position(), position() }, string);
1904}
1905
1906NonnullRefPtr<TemplateLiteral const> Parser::parse_template_literal(bool is_tagged)
1907{
1908 auto rule_start = push_start();
1909 consume(TokenType::TemplateLiteralStart);
1910
1911 Vector<NonnullRefPtr<Expression const>> expressions;
1912 Vector<NonnullRefPtr<Expression const>> raw_strings;
1913
1914 auto append_empty_string = [this, &rule_start, &expressions, &raw_strings, is_tagged]() {
1915 auto string_literal = create_ast_node<StringLiteral>({ m_source_code, rule_start.position(), position() }, "");
1916 expressions.append(string_literal);
1917 if (is_tagged)
1918 raw_strings.append(string_literal);
1919 };
1920
1921 if (!match(TokenType::TemplateLiteralString))
1922 append_empty_string();
1923
1924 while (!done() && !match(TokenType::TemplateLiteralEnd) && !match(TokenType::UnterminatedTemplateLiteral)) {
1925 if (match(TokenType::TemplateLiteralString)) {
1926 auto token = consume();
1927 bool contains_invalid_escape = false;
1928 auto parsed_string_value = parse_string_literal(token,
1929 is_tagged ? StringLiteralType::TaggedTemplate : StringLiteralType::NonTaggedTemplate,
1930 is_tagged ? &contains_invalid_escape : nullptr);
1931 // An invalid string leads to a cooked value of `undefined` but still gives the raw string.
1932 if (contains_invalid_escape)
1933 expressions.append(create_ast_node<NullLiteral>({ m_source_code, rule_start.position(), position() }));
1934 else
1935 expressions.append(move(parsed_string_value));
1936 if (is_tagged)
1937 raw_strings.append(create_ast_node<StringLiteral>({ m_source_code, rule_start.position(), position() }, token.raw_template_value()));
1938 } else if (match(TokenType::TemplateLiteralExprStart)) {
1939 consume(TokenType::TemplateLiteralExprStart);
1940 if (match(TokenType::TemplateLiteralExprEnd)) {
1941 syntax_error("Empty template literal expression block");
1942 return create_ast_node<TemplateLiteral>({ m_source_code, rule_start.position(), position() }, expressions);
1943 }
1944
1945 expressions.append(parse_expression(0));
1946 if (match(TokenType::UnterminatedTemplateLiteral)) {
1947 syntax_error("Unterminated template literal");
1948 return create_ast_node<TemplateLiteral>({ m_source_code, rule_start.position(), position() }, expressions);
1949 }
1950 consume(TokenType::TemplateLiteralExprEnd);
1951
1952 if (!match(TokenType::TemplateLiteralString))
1953 append_empty_string();
1954 } else {
1955 expected("Template literal string or expression");
1956 break;
1957 }
1958 }
1959
1960 if (match(TokenType::UnterminatedTemplateLiteral)) {
1961 syntax_error("Unterminated template literal");
1962 } else {
1963 consume(TokenType::TemplateLiteralEnd);
1964 }
1965
1966 if (is_tagged)
1967 return create_ast_node<TemplateLiteral>({ m_source_code, rule_start.position(), position() }, expressions, raw_strings);
1968 return create_ast_node<TemplateLiteral>({ m_source_code, rule_start.position(), position() }, expressions);
1969}
1970
1971NonnullRefPtr<Expression const> Parser::parse_expression(int min_precedence, Associativity associativity, ForbiddenTokens forbidden)
1972{
1973 auto rule_start = push_start();
1974 auto [expression, should_continue_parsing] = parse_primary_expression();
1975 auto check_for_invalid_object_property = [&](auto& expression) {
1976 if (is<ObjectExpression>(*expression)) {
1977 if (auto start_offset = m_state.invalid_property_range_in_object_expression.get(expression->start_offset()); start_offset.has_value())
1978 syntax_error("Invalid property in object literal", start_offset.value());
1979 }
1980 };
1981 if (is<Identifier>(*expression) && m_state.current_scope_pusher) {
1982 auto identifier_instance = static_ptr_cast<Identifier const>(expression);
1983 auto function_scope = m_state.current_scope_pusher->last_function_scope();
1984 auto function_parent_scope = function_scope ? function_scope->parent_scope() : nullptr;
1985 bool has_not_been_declared_as_variable = true;
1986 for (auto scope = m_state.current_scope_pusher; scope != function_parent_scope; scope = scope->parent_scope()) {
1987 if (scope->has_declaration(identifier_instance->string())) {
1988 has_not_been_declared_as_variable = false;
1989 break;
1990 }
1991 }
1992
1993 if (has_not_been_declared_as_variable) {
1994 if (identifier_instance->string() == "arguments"sv)
1995 m_state.current_scope_pusher->set_contains_access_to_arguments_object();
1996 }
1997 }
1998
1999 while (match(TokenType::TemplateLiteralStart)) {
2000 auto template_literal = parse_template_literal(true);
2001 expression = create_ast_node<TaggedTemplateLiteral>({ m_source_code, rule_start.position(), position() }, move(expression), move(template_literal));
2002 }
2003 if (should_continue_parsing) {
2004 while (match_secondary_expression(forbidden)) {
2005 int new_precedence = g_operator_precedence.get(m_state.current_token.type());
2006 if (new_precedence < min_precedence)
2007 break;
2008 if (new_precedence == min_precedence && associativity == Associativity::Left)
2009 break;
2010 check_for_invalid_object_property(expression);
2011
2012 Associativity new_associativity = operator_associativity(m_state.current_token.type());
2013 auto result = parse_secondary_expression(move(expression), new_precedence, new_associativity, forbidden);
2014 expression = result.expression;
2015 forbidden = forbidden.merge(result.forbidden);
2016 while (match(TokenType::TemplateLiteralStart) && !is<UpdateExpression>(*expression)) {
2017 auto template_literal = parse_template_literal(true);
2018 expression = create_ast_node<TaggedTemplateLiteral>({ m_source_code, rule_start.position(), position() }, move(expression), move(template_literal));
2019 }
2020 }
2021 }
2022
2023 if (is<SuperExpression>(*expression))
2024 syntax_error("'super' keyword unexpected here");
2025
2026 check_for_invalid_object_property(expression);
2027
2028 if (is<CallExpression>(*expression) && m_state.current_scope_pusher) {
2029 auto& callee = static_ptr_cast<CallExpression const>(expression)->callee();
2030 if (is<Identifier>(callee)) {
2031 auto& identifier_instance = static_cast<Identifier const&>(callee);
2032 if (identifier_instance.string() == "eval"sv) {
2033 bool has_not_been_declared_as_variable = true;
2034 for (auto scope = m_state.current_scope_pusher; scope; scope = scope->parent_scope()) {
2035 if (scope->has_declaration(identifier_instance.string())) {
2036 has_not_been_declared_as_variable = false;
2037 break;
2038 }
2039 }
2040 if (has_not_been_declared_as_variable)
2041 m_state.current_scope_pusher->set_contains_direct_call_to_eval();
2042 }
2043 }
2044 }
2045
2046 if (match(TokenType::Comma) && min_precedence <= 1) {
2047 Vector<NonnullRefPtr<Expression const>> expressions;
2048 expressions.append(expression);
2049 while (match(TokenType::Comma)) {
2050 consume();
2051 expressions.append(parse_expression(2));
2052 }
2053 expressions.shrink_to_fit();
2054 expression = create_ast_node<SequenceExpression>({ m_source_code, rule_start.position(), position() }, move(expressions));
2055 }
2056 return expression;
2057}
2058
2059Parser::ExpressionResult Parser::parse_secondary_expression(NonnullRefPtr<Expression const> lhs, int min_precedence, Associativity associativity, ForbiddenTokens forbidden)
2060{
2061 auto rule_start = push_start();
2062 switch (m_state.current_token.type()) {
2063 case TokenType::Plus:
2064 consume();
2065 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::Addition, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2066 case TokenType::PlusEquals:
2067 return parse_assignment_expression(AssignmentOp::AdditionAssignment, move(lhs), min_precedence, associativity, forbidden);
2068 case TokenType::Minus:
2069 consume();
2070 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::Subtraction, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2071 case TokenType::MinusEquals:
2072 return parse_assignment_expression(AssignmentOp::SubtractionAssignment, move(lhs), min_precedence, associativity, forbidden);
2073 case TokenType::Asterisk:
2074 consume();
2075 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::Multiplication, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2076 case TokenType::AsteriskEquals:
2077 return parse_assignment_expression(AssignmentOp::MultiplicationAssignment, move(lhs), min_precedence, associativity, forbidden);
2078 case TokenType::Slash:
2079 consume();
2080 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::Division, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2081 case TokenType::SlashEquals:
2082 return parse_assignment_expression(AssignmentOp::DivisionAssignment, move(lhs), min_precedence, associativity, forbidden);
2083 case TokenType::Percent:
2084 consume();
2085 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::Modulo, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2086 case TokenType::PercentEquals:
2087 return parse_assignment_expression(AssignmentOp::ModuloAssignment, move(lhs), min_precedence, associativity, forbidden);
2088 case TokenType::DoubleAsterisk:
2089 consume();
2090 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::Exponentiation, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2091 case TokenType::DoubleAsteriskEquals:
2092 return parse_assignment_expression(AssignmentOp::ExponentiationAssignment, move(lhs), min_precedence, associativity, forbidden);
2093 case TokenType::GreaterThan:
2094 consume();
2095 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::GreaterThan, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2096 case TokenType::GreaterThanEquals:
2097 consume();
2098 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::GreaterThanEquals, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2099 case TokenType::LessThan:
2100 consume();
2101 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::LessThan, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2102 case TokenType::LessThanEquals:
2103 consume();
2104 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::LessThanEquals, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2105 case TokenType::EqualsEqualsEquals:
2106 consume();
2107 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::StrictlyEquals, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2108 case TokenType::ExclamationMarkEqualsEquals:
2109 consume();
2110 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::StrictlyInequals, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2111 case TokenType::EqualsEquals:
2112 consume();
2113 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::LooselyEquals, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2114 case TokenType::ExclamationMarkEquals:
2115 consume();
2116 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::LooselyInequals, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2117 case TokenType::In:
2118 consume();
2119 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::In, move(lhs), parse_expression(min_precedence, associativity));
2120 case TokenType::Instanceof:
2121 consume();
2122 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::InstanceOf, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2123 case TokenType::Ampersand:
2124 consume();
2125 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::BitwiseAnd, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2126 case TokenType::AmpersandEquals:
2127 return parse_assignment_expression(AssignmentOp::BitwiseAndAssignment, move(lhs), min_precedence, associativity, forbidden);
2128 case TokenType::Pipe:
2129 consume();
2130 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::BitwiseOr, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2131 case TokenType::PipeEquals:
2132 return parse_assignment_expression(AssignmentOp::BitwiseOrAssignment, move(lhs), min_precedence, associativity, forbidden);
2133 case TokenType::Caret:
2134 consume();
2135 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::BitwiseXor, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2136 case TokenType::CaretEquals:
2137 return parse_assignment_expression(AssignmentOp::BitwiseXorAssignment, move(lhs), min_precedence, associativity, forbidden);
2138 case TokenType::ShiftLeft:
2139 consume();
2140 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::LeftShift, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2141 case TokenType::ShiftLeftEquals:
2142 return parse_assignment_expression(AssignmentOp::LeftShiftAssignment, move(lhs), min_precedence, associativity, forbidden);
2143 case TokenType::ShiftRight:
2144 consume();
2145 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::RightShift, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2146 case TokenType::ShiftRightEquals:
2147 return parse_assignment_expression(AssignmentOp::RightShiftAssignment, move(lhs), min_precedence, associativity, forbidden);
2148 case TokenType::UnsignedShiftRight:
2149 consume();
2150 return create_ast_node<BinaryExpression>({ m_source_code, rule_start.position(), position() }, BinaryOp::UnsignedRightShift, move(lhs), parse_expression(min_precedence, associativity, forbidden));
2151 case TokenType::UnsignedShiftRightEquals:
2152 return parse_assignment_expression(AssignmentOp::UnsignedRightShiftAssignment, move(lhs), min_precedence, associativity, forbidden);
2153 case TokenType::ParenOpen:
2154 return parse_call_expression(move(lhs));
2155 case TokenType::Equals:
2156 return parse_assignment_expression(AssignmentOp::Assignment, move(lhs), min_precedence, associativity, forbidden);
2157 case TokenType::Period:
2158 consume();
2159 if (match(TokenType::PrivateIdentifier)) {
2160 if (!is_private_identifier_valid())
2161 syntax_error(DeprecatedString::formatted("Reference to undeclared private field or method '{}'", m_state.current_token.value()));
2162 else if (is<SuperExpression>(*lhs))
2163 syntax_error(DeprecatedString::formatted("Cannot access private field or method '{}' on super", m_state.current_token.value()));
2164
2165 return create_ast_node<MemberExpression>({ m_source_code, rule_start.position(), position() }, move(lhs), create_ast_node<PrivateIdentifier>({ m_source_code, rule_start.position(), position() }, consume().value()));
2166 } else if (!match_identifier_name()) {
2167 expected("IdentifierName");
2168 }
2169
2170 return create_ast_node<MemberExpression>({ m_source_code, rule_start.position(), position() }, move(lhs), create_ast_node<Identifier>({ m_source_code, rule_start.position(), position() }, consume().DeprecatedFlyString_value()));
2171 case TokenType::BracketOpen: {
2172 consume(TokenType::BracketOpen);
2173 auto expression = create_ast_node<MemberExpression>({ m_source_code, rule_start.position(), position() }, move(lhs), parse_expression(0), true);
2174 consume(TokenType::BracketClose);
2175 return expression;
2176 }
2177 case TokenType::PlusPlus:
2178 if (!is_simple_assignment_target(*lhs))
2179 syntax_error(DeprecatedString::formatted("Left-hand side of postfix increment operator must be identifier or member expression, got {}", lhs->class_name()));
2180
2181 if (m_state.strict_mode && is<Identifier>(*lhs)) {
2182 auto& identifier = static_cast<Identifier const&>(*lhs);
2183 auto& name = identifier.string();
2184 check_identifier_name_for_assignment_validity(name);
2185 }
2186
2187 consume();
2188 return create_ast_node<UpdateExpression>({ m_source_code, rule_start.position(), position() }, UpdateOp::Increment, move(lhs));
2189 case TokenType::MinusMinus:
2190 if (!is_simple_assignment_target(*lhs))
2191 syntax_error(DeprecatedString::formatted("Left-hand side of postfix increment operator must be identifier or member expression, got {}", lhs->class_name()));
2192
2193 if (m_state.strict_mode && is<Identifier>(*lhs)) {
2194 auto& identifier = static_cast<Identifier const&>(*lhs);
2195 auto& name = identifier.string();
2196 check_identifier_name_for_assignment_validity(name);
2197 }
2198 consume();
2199 return create_ast_node<UpdateExpression>({ m_source_code, rule_start.position(), position() }, UpdateOp::Decrement, move(lhs));
2200 case TokenType::DoubleAmpersand: {
2201 consume();
2202 auto expression = create_ast_node<LogicalExpression>({ m_source_code, rule_start.position(), position() }, LogicalOp::And, move(lhs), parse_expression(min_precedence, associativity, forbidden.forbid({ TokenType::DoubleQuestionMark })));
2203 return { expression, { TokenType::DoubleQuestionMark } };
2204 }
2205 case TokenType::DoubleAmpersandEquals:
2206 return parse_assignment_expression(AssignmentOp::AndAssignment, move(lhs), min_precedence, associativity, forbidden);
2207 case TokenType::DoublePipe: {
2208 consume();
2209 auto expression = create_ast_node<LogicalExpression>({ m_source_code, rule_start.position(), position() }, LogicalOp::Or, move(lhs), parse_expression(min_precedence, associativity, forbidden.forbid({ TokenType::DoubleQuestionMark })));
2210 return { expression, { TokenType::DoubleQuestionMark } };
2211 }
2212 case TokenType::DoublePipeEquals:
2213 return parse_assignment_expression(AssignmentOp::OrAssignment, move(lhs), min_precedence, associativity, forbidden);
2214 case TokenType::DoubleQuestionMark: {
2215 consume();
2216 auto expression = create_ast_node<LogicalExpression>({ m_source_code, rule_start.position(), position() }, LogicalOp::NullishCoalescing, move(lhs), parse_expression(min_precedence, associativity, forbidden.forbid({ TokenType::DoubleAmpersand, TokenType::DoublePipe })));
2217 return { expression, { TokenType::DoubleAmpersand, TokenType::DoublePipe } };
2218 }
2219 case TokenType::DoubleQuestionMarkEquals:
2220 return parse_assignment_expression(AssignmentOp::NullishAssignment, move(lhs), min_precedence, associativity, forbidden);
2221 case TokenType::QuestionMark:
2222 return parse_conditional_expression(move(lhs), forbidden);
2223 case TokenType::QuestionMarkPeriod:
2224 // FIXME: This should allow `(new Foo)?.bar', but as our parser strips parenthesis,
2225 // we can't really tell if `lhs' was parenthesized at this point.
2226 if (is<NewExpression>(lhs.ptr())) {
2227 syntax_error("'new' cannot be used with optional chaining", position());
2228 consume();
2229 return lhs;
2230 }
2231 return parse_optional_chain(move(lhs));
2232 default:
2233 expected("secondary expression");
2234 consume();
2235 return create_ast_node<ErrorExpression>({ m_source_code, rule_start.position(), position() });
2236 }
2237}
2238
2239bool Parser::is_private_identifier_valid() const
2240{
2241 VERIFY(match(TokenType::PrivateIdentifier));
2242 if (!m_state.referenced_private_names)
2243 return false;
2244
2245 // We might not have hit the declaration yet so class will check this in the end
2246 m_state.referenced_private_names->set(m_state.current_token.value());
2247 return true;
2248}
2249
2250RefPtr<BindingPattern const> Parser::synthesize_binding_pattern(Expression const& expression)
2251{
2252 VERIFY(is<ArrayExpression>(expression) || is<ObjectExpression>(expression));
2253 // Clear any syntax error that has occurred in the range that 'expression' spans.
2254 m_state.errors.remove_all_matching([range = expression.source_range()](auto const& error) {
2255 return error.position.has_value() && range.contains(*error.position);
2256 });
2257 // Make a parser and parse the source for this expression as a binding pattern.
2258 // NOTE: There's currently a fundamental problem that we pass the *next* (a.k.a. `current_token`)
2259 // token's position to most nodes' SourceRange when using `rule_start.position(), position()`.
2260 // This means that `source` will contain the subsequent token's trivia, if any (which is fine).
2261 auto source_start_offset = expression.source_range().start.offset;
2262 auto source_end_offset = expression.source_range().end.offset;
2263 auto source = m_state.lexer.source().substring_view(source_start_offset, source_end_offset - source_start_offset);
2264 Lexer lexer { source, m_state.lexer.filename(), expression.source_range().start.line, expression.source_range().start.column };
2265 Parser parser { lexer };
2266
2267 parser.m_state.strict_mode = m_state.strict_mode;
2268 parser.m_state.allow_super_property_lookup = m_state.allow_super_property_lookup;
2269 parser.m_state.allow_super_constructor_call = m_state.allow_super_constructor_call;
2270 parser.m_state.in_function_context = m_state.in_function_context;
2271 parser.m_state.in_formal_parameter_context = m_state.in_formal_parameter_context;
2272 parser.m_state.in_generator_function_context = m_state.in_generator_function_context;
2273 parser.m_state.await_expression_is_valid = m_state.await_expression_is_valid;
2274 parser.m_state.in_arrow_function_context = m_state.in_arrow_function_context;
2275 parser.m_state.in_break_context = m_state.in_break_context;
2276 parser.m_state.in_continue_context = m_state.in_continue_context;
2277 parser.m_state.string_legacy_octal_escape_sequence_in_scope = m_state.string_legacy_octal_escape_sequence_in_scope;
2278 parser.m_state.in_class_field_initializer = m_state.in_class_field_initializer;
2279 parser.m_state.in_class_static_init_block = m_state.in_class_static_init_block;
2280 parser.m_state.referenced_private_names = m_state.referenced_private_names;
2281
2282 auto result = parser.parse_binding_pattern(AllowDuplicates::Yes, AllowMemberExpressions::Yes);
2283 if (parser.has_errors())
2284 m_state.errors.extend(parser.errors());
2285 return result;
2286}
2287
2288NonnullRefPtr<AssignmentExpression const> Parser::parse_assignment_expression(AssignmentOp assignment_op, NonnullRefPtr<Expression const> lhs, int min_precedence, Associativity associativity, ForbiddenTokens forbidden)
2289{
2290 auto rule_start = push_start();
2291 VERIFY(match(TokenType::Equals)
2292 || match(TokenType::PlusEquals)
2293 || match(TokenType::MinusEquals)
2294 || match(TokenType::AsteriskEquals)
2295 || match(TokenType::SlashEquals)
2296 || match(TokenType::PercentEquals)
2297 || match(TokenType::DoubleAsteriskEquals)
2298 || match(TokenType::AmpersandEquals)
2299 || match(TokenType::PipeEquals)
2300 || match(TokenType::CaretEquals)
2301 || match(TokenType::ShiftLeftEquals)
2302 || match(TokenType::ShiftRightEquals)
2303 || match(TokenType::UnsignedShiftRightEquals)
2304 || match(TokenType::DoubleAmpersandEquals)
2305 || match(TokenType::DoublePipeEquals)
2306 || match(TokenType::DoubleQuestionMarkEquals));
2307 consume();
2308
2309 if (assignment_op == AssignmentOp::Assignment) {
2310 if (is<ArrayExpression>(*lhs) || is<ObjectExpression>(*lhs)) {
2311 auto binding_pattern = synthesize_binding_pattern(*lhs);
2312 if (binding_pattern) {
2313 auto rhs = parse_expression(min_precedence, associativity);
2314 return create_ast_node<AssignmentExpression>(
2315 { m_source_code, rule_start.position(), position() },
2316 assignment_op,
2317 binding_pattern.release_nonnull(),
2318 move(rhs));
2319 }
2320 }
2321 }
2322
2323 // Note: The web reality is that all but &&=, ||= and ??= do allow left hand side CallExpresions.
2324 // These are the exception as they are newer.
2325 auto has_web_reality_assignment_target_exceptions = assignment_op != AssignmentOp::AndAssignment
2326 && assignment_op != AssignmentOp::OrAssignment
2327 && assignment_op != AssignmentOp::NullishAssignment;
2328
2329 if (!is_simple_assignment_target(*lhs, has_web_reality_assignment_target_exceptions)) {
2330 syntax_error("Invalid left-hand side in assignment");
2331 } else if (m_state.strict_mode && is<Identifier>(*lhs)) {
2332 auto const& name = static_cast<Identifier const&>(*lhs).string();
2333 check_identifier_name_for_assignment_validity(name);
2334 }
2335 auto rhs = parse_expression(min_precedence, associativity, forbidden);
2336 return create_ast_node<AssignmentExpression>({ m_source_code, rule_start.position(), position() }, assignment_op, move(lhs), move(rhs));
2337}
2338
2339NonnullRefPtr<Identifier const> Parser::parse_identifier()
2340{
2341 auto identifier_start = position();
2342 auto token = consume_identifier();
2343 if (m_state.in_class_field_initializer && token.value() == "arguments"sv)
2344 syntax_error("'arguments' is not allowed in class field initializer");
2345 return create_ast_node<Identifier>(
2346 { m_source_code, identifier_start, position() },
2347 token.DeprecatedFlyString_value());
2348}
2349
2350Vector<CallExpression::Argument> Parser::parse_arguments()
2351{
2352 Vector<CallExpression::Argument> arguments;
2353
2354 consume(TokenType::ParenOpen);
2355 while (match_expression() || match(TokenType::TripleDot)) {
2356 if (match(TokenType::TripleDot)) {
2357 consume();
2358 arguments.append({ parse_expression(2), true });
2359 } else {
2360 arguments.append({ parse_expression(2), false });
2361 }
2362 if (!match(TokenType::Comma))
2363 break;
2364 consume();
2365 }
2366
2367 consume(TokenType::ParenClose);
2368 return arguments;
2369}
2370
2371NonnullRefPtr<Expression const> Parser::parse_call_expression(NonnullRefPtr<Expression const> lhs)
2372{
2373 auto rule_start = push_start();
2374 if (!m_state.allow_super_constructor_call && is<SuperExpression>(*lhs))
2375 syntax_error("'super' keyword unexpected here");
2376
2377 auto arguments = parse_arguments();
2378
2379 if (is<SuperExpression>(*lhs))
2380 return create_ast_node<SuperCall>({ m_source_code, rule_start.position(), position() }, move(arguments));
2381
2382 return CallExpression::create({ m_source_code, rule_start.position(), position() }, move(lhs), arguments.span());
2383}
2384
2385NonnullRefPtr<NewExpression const> Parser::parse_new_expression()
2386{
2387 auto rule_start = push_start();
2388 consume(TokenType::New);
2389
2390 auto callee = parse_expression(g_operator_precedence.get(TokenType::New), Associativity::Right, { TokenType::ParenOpen, TokenType::QuestionMarkPeriod });
2391 if (is<ImportCall>(*callee))
2392 syntax_error("Cannot call new on dynamic import", callee->source_range().start);
2393
2394 Vector<CallExpression::Argument> arguments;
2395
2396 if (match(TokenType::ParenOpen)) {
2397 consume(TokenType::ParenOpen);
2398 while (match_expression() || match(TokenType::TripleDot)) {
2399 if (match(TokenType::TripleDot)) {
2400 consume();
2401 arguments.append({ parse_expression(2), true });
2402 } else {
2403 arguments.append({ parse_expression(2), false });
2404 }
2405 if (!match(TokenType::Comma))
2406 break;
2407 consume();
2408 }
2409 consume(TokenType::ParenClose);
2410 }
2411
2412 return NewExpression::create({ m_source_code, rule_start.position(), position() }, move(callee), move(arguments));
2413}
2414
2415NonnullRefPtr<YieldExpression const> Parser::parse_yield_expression()
2416{
2417 auto rule_start = push_start();
2418
2419 if (m_state.in_formal_parameter_context)
2420 syntax_error("'Yield' expression is not allowed in formal parameters of generator function");
2421
2422 consume(TokenType::Yield);
2423 RefPtr<Expression const> argument;
2424 bool yield_from = false;
2425
2426 if (!m_state.current_token.trivia_contains_line_terminator()) {
2427 if (match(TokenType::Asterisk)) {
2428 consume();
2429 yield_from = true;
2430 }
2431
2432 if (yield_from || match_expression() || match(TokenType::Class))
2433 argument = parse_expression(2);
2434 }
2435
2436 return create_ast_node<YieldExpression>({ m_source_code, rule_start.position(), position() }, move(argument), yield_from);
2437}
2438
2439NonnullRefPtr<AwaitExpression const> Parser::parse_await_expression()
2440{
2441 auto rule_start = push_start();
2442
2443 if (m_state.in_formal_parameter_context)
2444 syntax_error("'Await' expression is not allowed in formal parameters of an async function");
2445
2446 consume(TokenType::Await);
2447
2448 auto precedence = g_operator_precedence.get(TokenType::Await);
2449 auto associativity = operator_associativity(TokenType::Await);
2450 auto argument = parse_expression(precedence, associativity);
2451
2452 m_state.current_scope_pusher->set_contains_await_expression();
2453
2454 return create_ast_node<AwaitExpression>({ m_source_code, rule_start.position(), position() }, move(argument));
2455}
2456
2457NonnullRefPtr<ReturnStatement const> Parser::parse_return_statement()
2458{
2459 auto rule_start = push_start();
2460 if (!m_state.in_function_context && !m_state.in_arrow_function_context)
2461 syntax_error("'return' not allowed outside of a function");
2462
2463 consume(TokenType::Return);
2464
2465 // Automatic semicolon insertion: terminate statement when return is followed by newline
2466 if (m_state.current_token.trivia_contains_line_terminator())
2467 return create_ast_node<ReturnStatement>({ m_source_code, rule_start.position(), position() }, nullptr);
2468
2469 if (match_expression()) {
2470 auto expression = parse_expression(0);
2471 consume_or_insert_semicolon();
2472 return create_ast_node<ReturnStatement>({ m_source_code, rule_start.position(), position() }, move(expression));
2473 }
2474
2475 consume_or_insert_semicolon();
2476 return create_ast_node<ReturnStatement>({ m_source_code, rule_start.position(), position() }, nullptr);
2477}
2478
2479void Parser::parse_statement_list(ScopeNode& output_node, AllowLabelledFunction allow_labelled_functions)
2480{
2481 while (!done()) {
2482 if (match_declaration(AllowUsingDeclaration::Yes)) {
2483 auto declaration = parse_declaration();
2484 VERIFY(m_state.current_scope_pusher);
2485 m_state.current_scope_pusher->add_declaration(declaration);
2486 output_node.append(move(declaration));
2487 } else if (match_statement()) {
2488 output_node.append(parse_statement(allow_labelled_functions));
2489 } else {
2490 break;
2491 }
2492 }
2493
2494 output_node.shrink_to_fit();
2495}
2496
2497// FunctionBody, https://tc39.es/ecma262/#prod-FunctionBody
2498NonnullRefPtr<FunctionBody const> Parser::parse_function_body(Vector<FunctionParameter> const& parameters, FunctionKind function_kind, bool& contains_direct_call_to_eval)
2499{
2500 auto rule_start = push_start();
2501 auto function_body = create_ast_node<FunctionBody>({ m_source_code, rule_start.position(), position() });
2502 ScopePusher function_scope = ScopePusher::function_scope(*this, function_body, parameters); // FIXME <-
2503 auto has_use_strict = parse_directive(function_body);
2504 bool previous_strict_mode = m_state.strict_mode;
2505 if (has_use_strict) {
2506 m_state.strict_mode = true;
2507 function_body->set_strict_mode();
2508 if (!is_simple_parameter_list(parameters))
2509 syntax_error("Illegal 'use strict' directive in function with non-simple parameter list");
2510 } else if (previous_strict_mode) {
2511 function_body->set_strict_mode();
2512 }
2513
2514 parse_statement_list(function_body);
2515
2516 // If we're parsing the function body standalone, e.g. via CreateDynamicFunction, we must have reached EOF here.
2517 // Otherwise, we need a closing curly bracket (which is consumed elsewhere). If we get neither, it's an error.
2518 if (!match(TokenType::Eof) && !match(TokenType::CurlyClose))
2519 expected(Token::name(TokenType::CurlyClose));
2520
2521 // If the function contains 'use strict' we need to check the parameters (again).
2522 if (function_body->in_strict_mode() || function_kind != FunctionKind::Normal) {
2523 Vector<StringView> parameter_names;
2524 for (auto& parameter : parameters) {
2525 parameter.binding.visit(
2526 [&](DeprecatedFlyString const& parameter_name) {
2527 check_identifier_name_for_assignment_validity(parameter_name, function_body->in_strict_mode());
2528 if (function_kind == FunctionKind::Generator && parameter_name == "yield"sv)
2529 syntax_error("Parameter name 'yield' not allowed in this context");
2530
2531 if (function_kind == FunctionKind::Async && parameter_name == "await"sv)
2532 syntax_error("Parameter name 'await' not allowed in this context");
2533
2534 for (auto& previous_name : parameter_names) {
2535 if (previous_name == parameter_name) {
2536 syntax_error(DeprecatedString::formatted("Duplicate parameter '{}' not allowed in strict mode", parameter_name));
2537 }
2538 }
2539
2540 parameter_names.append(parameter_name);
2541 },
2542 [&](NonnullRefPtr<BindingPattern const> const& binding) {
2543 // NOTE: Nothing in the callback throws an exception.
2544 MUST(binding->for_each_bound_name([&](auto& bound_name) {
2545 if (function_kind == FunctionKind::Generator && bound_name == "yield"sv)
2546 syntax_error("Parameter name 'yield' not allowed in this context");
2547
2548 if (function_kind == FunctionKind::Async && bound_name == "await"sv)
2549 syntax_error("Parameter name 'await' not allowed in this context");
2550
2551 for (auto& previous_name : parameter_names) {
2552 if (previous_name == bound_name) {
2553 syntax_error(DeprecatedString::formatted("Duplicate parameter '{}' not allowed in strict mode", bound_name));
2554 break;
2555 }
2556 }
2557 parameter_names.append(bound_name);
2558 }));
2559 });
2560 }
2561 }
2562
2563 m_state.strict_mode = previous_strict_mode;
2564 contains_direct_call_to_eval = function_scope.contains_direct_call_to_eval();
2565 return function_body;
2566}
2567
2568NonnullRefPtr<BlockStatement const> Parser::parse_block_statement()
2569{
2570 auto rule_start = push_start();
2571 auto block = create_ast_node<BlockStatement>({ m_source_code, rule_start.position(), position() });
2572 ScopePusher block_scope = ScopePusher::block_scope(*this, block);
2573 consume(TokenType::CurlyOpen);
2574 parse_statement_list(block);
2575 consume(TokenType::CurlyClose);
2576
2577 return block;
2578}
2579
2580template<typename FunctionNodeType>
2581NonnullRefPtr<FunctionNodeType> Parser::parse_function_node(u16 parse_options, Optional<Position> const& function_start)
2582{
2583 auto rule_start = function_start.has_value()
2584 ? RulePosition { *this, *function_start }
2585 : push_start();
2586 VERIFY(!(parse_options & FunctionNodeParseOptions::IsGetterFunction && parse_options & FunctionNodeParseOptions::IsSetterFunction));
2587
2588 TemporaryChange super_property_access_rollback(m_state.allow_super_property_lookup, !!(parse_options & FunctionNodeParseOptions::AllowSuperPropertyLookup));
2589 TemporaryChange super_constructor_call_rollback(m_state.allow_super_constructor_call, !!(parse_options & FunctionNodeParseOptions::AllowSuperConstructorCall));
2590 TemporaryChange break_context_rollback(m_state.in_break_context, false);
2591 TemporaryChange continue_context_rollback(m_state.in_continue_context, false);
2592 TemporaryChange class_field_initializer_rollback(m_state.in_class_field_initializer, false);
2593 TemporaryChange might_need_arguments_object_rollback(m_state.function_might_need_arguments_object, false);
2594
2595 constexpr auto is_function_expression = IsSame<FunctionNodeType, FunctionExpression>;
2596 FunctionKind function_kind;
2597 if ((parse_options & FunctionNodeParseOptions::IsGeneratorFunction) != 0 && (parse_options & FunctionNodeParseOptions::IsAsyncFunction) != 0)
2598 function_kind = FunctionKind::AsyncGenerator;
2599 else if ((parse_options & FunctionNodeParseOptions::IsGeneratorFunction) != 0)
2600 function_kind = FunctionKind::Generator;
2601 else if ((parse_options & FunctionNodeParseOptions::IsAsyncFunction) != 0)
2602 function_kind = FunctionKind::Async;
2603 else
2604 function_kind = FunctionKind::Normal;
2605 DeprecatedFlyString name;
2606 if (parse_options & FunctionNodeParseOptions::CheckForFunctionAndName) {
2607 if (function_kind == FunctionKind::Normal && match(TokenType::Async) && !next_token().trivia_contains_line_terminator()) {
2608 function_kind = FunctionKind::Async;
2609 consume(TokenType::Async);
2610 parse_options |= FunctionNodeParseOptions::IsAsyncFunction;
2611 }
2612 consume(TokenType::Function);
2613 if (match(TokenType::Asterisk)) {
2614 function_kind = function_kind == FunctionKind::Normal ? FunctionKind::Generator : FunctionKind::AsyncGenerator;
2615 consume(TokenType::Asterisk);
2616 parse_options |= FunctionNodeParseOptions::IsGeneratorFunction;
2617 }
2618
2619 if (parse_options & FunctionNodeParseOptions::HasDefaultExportName)
2620 name = ExportStatement::local_name_for_default;
2621 else if (FunctionNodeType::must_have_name() || match_identifier())
2622 name = consume_identifier().DeprecatedFlyString_value();
2623 else if (is_function_expression && (match(TokenType::Yield) || match(TokenType::Await)))
2624 name = consume().DeprecatedFlyString_value();
2625
2626 check_identifier_name_for_assignment_validity(name);
2627
2628 if (function_kind == FunctionKind::AsyncGenerator && (name == "await"sv || name == "yield"sv))
2629 syntax_error(DeprecatedString::formatted("async generator function is not allowed to be called '{}'", name));
2630
2631 if (m_state.in_class_static_init_block && name == "await"sv)
2632 syntax_error("'await' is a reserved word");
2633 }
2634 TemporaryChange class_static_initializer_rollback(m_state.in_class_static_init_block, false);
2635 TemporaryChange generator_change(m_state.in_generator_function_context, function_kind == FunctionKind::Generator || function_kind == FunctionKind::AsyncGenerator);
2636 TemporaryChange async_change(m_state.await_expression_is_valid, function_kind == FunctionKind::Async || function_kind == FunctionKind::AsyncGenerator);
2637
2638 consume(TokenType::ParenOpen);
2639 i32 function_length = -1;
2640 auto parameters = parse_formal_parameters(function_length, parse_options);
2641 consume(TokenType::ParenClose);
2642
2643 if (function_length == -1)
2644 function_length = parameters.size();
2645
2646 TemporaryChange function_context_rollback(m_state.in_function_context, true);
2647
2648 auto old_labels_in_scope = move(m_state.labels_in_scope);
2649 ScopeGuard guard([&]() {
2650 m_state.labels_in_scope = move(old_labels_in_scope);
2651 });
2652
2653 consume(TokenType::CurlyOpen);
2654 bool contains_direct_call_to_eval = false;
2655 auto body = parse_function_body(parameters, function_kind, contains_direct_call_to_eval);
2656 consume(TokenType::CurlyClose);
2657
2658 auto has_strict_directive = body->in_strict_mode();
2659
2660 if (has_strict_directive)
2661 check_identifier_name_for_assignment_validity(name, true);
2662
2663 auto function_start_offset = rule_start.position().offset;
2664 auto function_end_offset = position().offset - m_state.current_token.trivia().length();
2665 auto source_text = DeprecatedString { m_state.lexer.source().substring_view(function_start_offset, function_end_offset - function_start_offset) };
2666 return create_ast_node<FunctionNodeType>(
2667 { m_source_code, rule_start.position(), position() },
2668 name, move(source_text), move(body), move(parameters), function_length,
2669 function_kind, has_strict_directive, m_state.function_might_need_arguments_object,
2670 contains_direct_call_to_eval);
2671}
2672
2673Vector<FunctionParameter> Parser::parse_formal_parameters(int& function_length, u16 parse_options)
2674{
2675 auto rule_start = push_start();
2676 bool has_default_parameter = false;
2677 bool has_rest_parameter = false;
2678 TemporaryChange formal_parameter_context_change { m_state.in_formal_parameter_context, true };
2679
2680 Vector<FunctionParameter> parameters;
2681
2682 auto consume_identifier_or_binding_pattern = [&]() -> Variant<DeprecatedFlyString, NonnullRefPtr<BindingPattern const>> {
2683 if (auto pattern = parse_binding_pattern(AllowDuplicates::No, AllowMemberExpressions::No))
2684 return pattern.release_nonnull();
2685
2686 auto token = consume_identifier();
2687 auto parameter_name = token.DeprecatedFlyString_value();
2688
2689 check_identifier_name_for_assignment_validity(parameter_name);
2690
2691 for (auto& parameter : parameters) {
2692 bool has_same_name = parameter.binding.visit(
2693 [&](DeprecatedFlyString const& name) {
2694 return name == parameter_name;
2695 },
2696 [&](NonnullRefPtr<BindingPattern const> const& bindings) {
2697 bool found_duplicate = false;
2698 // NOTE: Nothing in the callback throws an exception.
2699 MUST(bindings->for_each_bound_name([&](auto& bound_name) {
2700 if (bound_name == parameter_name)
2701 found_duplicate = true;
2702 }));
2703 return found_duplicate;
2704 });
2705
2706 if (!has_same_name)
2707 continue;
2708
2709 DeprecatedString message;
2710 if (parse_options & FunctionNodeParseOptions::IsArrowFunction)
2711 message = DeprecatedString::formatted("Duplicate parameter '{}' not allowed in arrow function", parameter_name);
2712 else if (m_state.strict_mode)
2713 message = DeprecatedString::formatted("Duplicate parameter '{}' not allowed in strict mode", parameter_name);
2714 else if (has_default_parameter || match(TokenType::Equals))
2715 message = DeprecatedString::formatted("Duplicate parameter '{}' not allowed in function with default parameter", parameter_name);
2716 else if (has_rest_parameter)
2717 message = DeprecatedString::formatted("Duplicate parameter '{}' not allowed in function with rest parameter", parameter_name);
2718 if (!message.is_empty())
2719 syntax_error(message, Position { token.line_number(), token.line_column() });
2720 break;
2721 }
2722 return DeprecatedFlyString { token.value() };
2723 };
2724
2725 while (match(TokenType::CurlyOpen) || match(TokenType::BracketOpen) || match_identifier() || match(TokenType::TripleDot)) {
2726 if (parse_options & FunctionNodeParseOptions::IsGetterFunction)
2727 syntax_error("Getter function must have no arguments");
2728 if (parse_options & FunctionNodeParseOptions::IsSetterFunction && (parameters.size() >= 1 || match(TokenType::TripleDot)))
2729 syntax_error("Setter function must have one argument");
2730 auto is_rest = false;
2731 if (match(TokenType::TripleDot)) {
2732 consume();
2733 has_rest_parameter = true;
2734 function_length = parameters.size();
2735 is_rest = true;
2736 }
2737 auto parameter = consume_identifier_or_binding_pattern();
2738 RefPtr<Expression const> default_value;
2739 if (match(TokenType::Equals)) {
2740 consume();
2741
2742 if (is_rest)
2743 syntax_error("Rest parameter may not have a default initializer");
2744
2745 TemporaryChange change(m_state.in_function_context, true);
2746 has_default_parameter = true;
2747 function_length = parameters.size();
2748 default_value = parse_expression(2);
2749
2750 bool is_generator = parse_options & FunctionNodeParseOptions::IsGeneratorFunction;
2751 if ((is_generator || m_state.strict_mode) && default_value && default_value->fast_is<Identifier>() && static_cast<Identifier const&>(*default_value).string() == "yield"sv)
2752 syntax_error("Generator function parameter initializer cannot contain a reference to an identifier named \"yield\"");
2753 }
2754 parameters.append({ move(parameter), default_value, is_rest });
2755 if (!match(TokenType::Comma) || is_rest)
2756 break;
2757 consume(TokenType::Comma);
2758 }
2759 if (parse_options & FunctionNodeParseOptions::IsSetterFunction && parameters.is_empty())
2760 syntax_error("Setter function must have one argument");
2761 // If we're parsing the parameters standalone, e.g. via CreateDynamicFunction, we must have reached EOF here.
2762 // Otherwise, we need a closing parenthesis (which is consumed elsewhere). If we get neither, it's an error.
2763 if (!match(TokenType::Eof) && !match(TokenType::ParenClose))
2764 expected(Token::name(TokenType::ParenClose));
2765
2766 parameters.shrink_to_fit();
2767 return parameters;
2768}
2769
2770static AK::Array<DeprecatedFlyString, 36> s_reserved_words = { "break", "case", "catch", "class", "const", "continue", "debugger", "default", "delete", "do", "else", "enum", "export", "extends", "false", "finally", "for", "function", "if", "import", "in", "instanceof", "new", "null", "return", "super", "switch", "this", "throw", "true", "try", "typeof", "var", "void", "while", "with" };
2771
2772RefPtr<BindingPattern const> Parser::parse_binding_pattern(Parser::AllowDuplicates allow_duplicates, Parser::AllowMemberExpressions allow_member_expressions)
2773{
2774 auto rule_start = push_start();
2775
2776 TokenType closing_token;
2777 bool is_object = true;
2778
2779 if (match(TokenType::BracketOpen)) {
2780 consume();
2781 closing_token = TokenType::BracketClose;
2782 is_object = false;
2783 } else if (match(TokenType::CurlyOpen)) {
2784 consume();
2785 closing_token = TokenType::CurlyClose;
2786 } else {
2787 return {};
2788 }
2789
2790 Vector<BindingPattern::BindingEntry> entries;
2791
2792 while (!match(closing_token)) {
2793 if (!is_object && match(TokenType::Comma)) {
2794 consume();
2795 entries.append(BindingPattern::BindingEntry {});
2796 continue;
2797 }
2798
2799 auto is_rest = false;
2800
2801 if (match(TokenType::TripleDot)) {
2802 consume();
2803 is_rest = true;
2804 }
2805
2806 decltype(BindingPattern::BindingEntry::name) name = Empty {};
2807 decltype(BindingPattern::BindingEntry::alias) alias = Empty {};
2808 RefPtr<Expression const> initializer = {};
2809
2810 if (is_object) {
2811 bool needs_alias = false;
2812 if (allow_member_expressions == AllowMemberExpressions::Yes && is_rest) {
2813 auto expression_position = position();
2814 auto expression = parse_expression(2, Associativity::Right, { TokenType::Equals });
2815 if (is<MemberExpression>(*expression))
2816 alias = static_ptr_cast<MemberExpression const>(expression);
2817 else if (is<Identifier>(*expression))
2818 name = static_ptr_cast<Identifier const>(expression);
2819 else
2820 syntax_error("Invalid destructuring assignment target", expression_position);
2821 } else if (match_identifier_name() || match(TokenType::StringLiteral) || match(TokenType::NumericLiteral) || match(TokenType::BigIntLiteral)) {
2822 if (match(TokenType::StringLiteral) || match(TokenType::NumericLiteral))
2823 needs_alias = true;
2824
2825 if (match(TokenType::StringLiteral)) {
2826 auto token = consume(TokenType::StringLiteral);
2827 auto string_literal = parse_string_literal(token);
2828
2829 name = create_ast_node<Identifier const>(
2830 { m_source_code, rule_start.position(), position() },
2831 string_literal->value());
2832 } else if (match(TokenType::BigIntLiteral)) {
2833 auto string_value = consume().DeprecatedFlyString_value();
2834 VERIFY(string_value.ends_with("n"sv));
2835 name = create_ast_node<Identifier const>(
2836 { m_source_code, rule_start.position(), position() },
2837 DeprecatedFlyString(string_value.view().substring_view(0, string_value.length() - 1)));
2838 } else {
2839 name = create_ast_node<Identifier const>(
2840 { m_source_code, rule_start.position(), position() },
2841 consume().DeprecatedFlyString_value());
2842 }
2843 } else if (match(TokenType::BracketOpen)) {
2844 consume();
2845 auto expression = parse_expression(0);
2846
2847 name = move(expression);
2848 consume(TokenType::BracketClose);
2849 } else {
2850 expected("identifier or computed property name");
2851 return {};
2852 }
2853
2854 if (!is_rest && match(TokenType::Colon)) {
2855 consume();
2856 if (allow_member_expressions == AllowMemberExpressions::Yes) {
2857 auto expression_position = position();
2858 auto expression = parse_expression(2, Associativity::Right, { TokenType::Equals });
2859 if (is<ArrayExpression>(*expression) || is<ObjectExpression>(*expression)) {
2860 if (auto synthesized_binding_pattern = synthesize_binding_pattern(*expression))
2861 alias = synthesized_binding_pattern.release_nonnull();
2862 else
2863 syntax_error("Invalid destructuring assignment target", expression_position);
2864 } else if (is<MemberExpression>(*expression)) {
2865 alias = static_ptr_cast<MemberExpression const>(expression);
2866 } else if (is<Identifier>(*expression)) {
2867 alias = static_ptr_cast<Identifier const>(expression);
2868 } else {
2869 syntax_error("Invalid destructuring assignment target", expression_position);
2870 }
2871 } else if (match(TokenType::CurlyOpen) || match(TokenType::BracketOpen)) {
2872 auto binding_pattern = parse_binding_pattern(allow_duplicates, allow_member_expressions);
2873 if (!binding_pattern)
2874 return {};
2875 alias = binding_pattern.release_nonnull();
2876 } else if (match_identifier_name()) {
2877 alias = create_ast_node<Identifier const>(
2878 { m_source_code, rule_start.position(), position() },
2879 consume().DeprecatedFlyString_value());
2880
2881 } else {
2882 expected("identifier or binding pattern");
2883 return {};
2884 }
2885 } else if (needs_alias) {
2886 expected("alias for string or numeric literal name");
2887 return {};
2888 }
2889 } else {
2890 if (allow_member_expressions == AllowMemberExpressions::Yes) {
2891 auto expression_position = position();
2892 auto expression = parse_expression(2, Associativity::Right, { TokenType::Equals });
2893
2894 if (is<ArrayExpression>(*expression) || is<ObjectExpression>(*expression)) {
2895 if (auto synthesized_binding_pattern = synthesize_binding_pattern(*expression))
2896 alias = synthesized_binding_pattern.release_nonnull();
2897 else
2898 syntax_error("Invalid destructuring assignment target", expression_position);
2899 } else if (is<MemberExpression>(*expression)) {
2900 alias = static_ptr_cast<MemberExpression const>(expression);
2901 } else if (is<Identifier>(*expression)) {
2902 alias = static_ptr_cast<Identifier const>(expression);
2903 } else {
2904 syntax_error("Invalid destructuring assignment target", expression_position);
2905 }
2906 } else if (match(TokenType::BracketOpen) || match(TokenType::CurlyOpen)) {
2907 auto pattern = parse_binding_pattern(allow_duplicates, allow_member_expressions);
2908 if (!pattern) {
2909 expected("binding pattern");
2910 return {};
2911 }
2912 alias = pattern.release_nonnull();
2913 } else if (match_identifier_name()) {
2914 // BindingElement must always have an Empty name field
2915 auto identifier_name = consume_identifier().DeprecatedFlyString_value();
2916 alias = create_ast_node<Identifier const>(
2917 { m_source_code, rule_start.position(), position() },
2918 identifier_name);
2919 } else {
2920 expected("identifier or binding pattern");
2921 return {};
2922 }
2923 }
2924
2925 if (match(TokenType::Equals)) {
2926 if (is_rest) {
2927 syntax_error("Unexpected initializer after rest element");
2928 return {};
2929 }
2930
2931 consume();
2932
2933 initializer = parse_expression(2);
2934 if (!initializer) {
2935 expected("initialization expression");
2936 return {};
2937 }
2938 }
2939
2940 entries.append(BindingPattern::BindingEntry { move(name), move(alias), move(initializer), is_rest });
2941
2942 if (match(TokenType::Comma)) {
2943 if (is_rest) {
2944 syntax_error("Rest element may not be followed by a comma");
2945 return {};
2946 }
2947 consume();
2948 } else if (is_object && !match(TokenType::CurlyClose)) {
2949 consume(TokenType::Comma);
2950 }
2951 }
2952
2953 while (!is_object && match(TokenType::Comma))
2954 consume();
2955
2956 consume(closing_token);
2957
2958 auto kind = is_object ? BindingPattern::Kind::Object : BindingPattern::Kind::Array;
2959 auto pattern = adopt_ref(*new BindingPattern);
2960 pattern->entries = move(entries);
2961 pattern->kind = kind;
2962
2963 Vector<StringView> bound_names;
2964 // NOTE: Nothing in the callback throws an exception.
2965 MUST(pattern->for_each_bound_name([&](auto& name) {
2966 if (allow_duplicates == AllowDuplicates::No) {
2967 if (bound_names.contains_slow(name))
2968 syntax_error("Duplicate parameter names in bindings");
2969 bound_names.append(name);
2970 }
2971 check_identifier_name_for_assignment_validity(name);
2972 }));
2973
2974 return pattern;
2975}
2976
2977RefPtr<Identifier const> Parser::parse_lexical_binding()
2978{
2979 auto binding_start = push_start();
2980
2981 if (match_identifier()) {
2982 auto name = consume_identifier().DeprecatedFlyString_value();
2983 return create_ast_node<Identifier>(
2984 { m_source_code, binding_start.position(), position() },
2985 name);
2986 }
2987 if (!m_state.in_generator_function_context && match(TokenType::Yield)) {
2988 if (m_state.strict_mode)
2989 syntax_error("Identifier must not be a reserved word in strict mode ('yield')");
2990
2991 return create_ast_node<Identifier>(
2992 { m_source_code, binding_start.position(), position() },
2993 consume().DeprecatedFlyString_value());
2994 }
2995 if (!m_state.await_expression_is_valid && match(TokenType::Async)) {
2996 if (m_program_type == Program::Type::Module)
2997 syntax_error("Identifier must not be a reserved word in modules ('async')");
2998
2999 return create_ast_node<Identifier>(
3000 { m_source_code, binding_start.position(), position() },
3001 consume().DeprecatedFlyString_value());
3002 }
3003
3004 return {};
3005}
3006
3007NonnullRefPtr<VariableDeclaration const> Parser::parse_variable_declaration(IsForLoopVariableDeclaration is_for_loop_variable_declaration)
3008{
3009 auto rule_start = push_start();
3010 DeclarationKind declaration_kind;
3011
3012 switch (m_state.current_token.type()) {
3013 case TokenType::Var:
3014 declaration_kind = DeclarationKind::Var;
3015 break;
3016 case TokenType::Let:
3017 declaration_kind = DeclarationKind::Let;
3018 break;
3019 case TokenType::Const:
3020 declaration_kind = DeclarationKind::Const;
3021 break;
3022 default:
3023 VERIFY_NOT_REACHED();
3024 }
3025 consume();
3026
3027 Vector<NonnullRefPtr<VariableDeclarator const>> declarations;
3028 for (;;) {
3029 Variant<NonnullRefPtr<Identifier const>, NonnullRefPtr<BindingPattern const>, Empty> target {};
3030 if (auto pattern = parse_binding_pattern(declaration_kind != DeclarationKind::Var ? AllowDuplicates::No : AllowDuplicates::Yes, AllowMemberExpressions::No)) {
3031 if ((declaration_kind == DeclarationKind::Let || declaration_kind == DeclarationKind::Const)) {
3032 // NOTE: Nothing in the callback throws an exception.
3033 MUST(pattern->for_each_bound_name([this](auto& name) {
3034 if (name == "let"sv)
3035 syntax_error("Lexical binding may not be called 'let'");
3036 }));
3037 }
3038
3039 target = pattern.release_nonnull();
3040 } else if (auto lexical_binding = parse_lexical_binding()) {
3041 check_identifier_name_for_assignment_validity(lexical_binding->string());
3042 if ((declaration_kind == DeclarationKind::Let || declaration_kind == DeclarationKind::Const) && lexical_binding->string() == "let"sv)
3043 syntax_error("Lexical binding may not be called 'let'");
3044
3045 target = lexical_binding.release_nonnull();
3046 }
3047
3048 if (target.has<Empty>()) {
3049 expected("identifier or a binding pattern");
3050 if (match(TokenType::Comma)) {
3051 consume();
3052 continue;
3053 }
3054 break;
3055 }
3056
3057 RefPtr<Expression const> init;
3058 if (match(TokenType::Equals)) {
3059 consume();
3060 // In a for loop 'in' can be ambiguous so we do not allow it
3061 // 14.7.4 The for Statement, https://tc39.es/ecma262/#prod-ForStatement and 14.7.5 The for-in, for-of, and for-await-of Statements, https://tc39.es/ecma262/#prod-ForInOfStatement
3062 if (is_for_loop_variable_declaration == IsForLoopVariableDeclaration::Yes)
3063 init = parse_expression(2, Associativity::Right, { TokenType::In });
3064 else
3065 init = parse_expression(2);
3066 } else if (is_for_loop_variable_declaration == IsForLoopVariableDeclaration::No && declaration_kind == DeclarationKind::Const) {
3067 syntax_error("Missing initializer in 'const' variable declaration");
3068 } else if (is_for_loop_variable_declaration == IsForLoopVariableDeclaration::No && target.has<NonnullRefPtr<BindingPattern const>>()) {
3069 syntax_error("Missing initializer in destructuring assignment");
3070 }
3071
3072 declarations.append(create_ast_node<VariableDeclarator>(
3073 { m_source_code, rule_start.position(), position() },
3074 move(target).downcast<NonnullRefPtr<Identifier const>, NonnullRefPtr<BindingPattern const>>(),
3075 move(init)));
3076
3077 if (match(TokenType::Comma)) {
3078 consume();
3079 continue;
3080 }
3081 break;
3082 }
3083 if (is_for_loop_variable_declaration == IsForLoopVariableDeclaration::No)
3084 consume_or_insert_semicolon();
3085
3086 declarations.shrink_to_fit();
3087
3088 auto declaration = create_ast_node<VariableDeclaration>({ m_source_code, rule_start.position(), position() }, declaration_kind, move(declarations));
3089 return declaration;
3090}
3091
3092NonnullRefPtr<UsingDeclaration const> Parser::parse_using_declaration(IsForLoopVariableDeclaration is_for_loop_variable_declaration)
3093{
3094 // using [no LineTerminator here] BindingList[?In, ?Yield, ?Await, +Using] ;
3095 auto rule_start = push_start();
3096 VERIFY(m_state.current_token.original_value() == "using"sv);
3097 consume(TokenType::Identifier);
3098 VERIFY(!m_state.current_token.trivia_contains_line_terminator());
3099 Vector<NonnullRefPtr<VariableDeclarator const>> declarations;
3100
3101 for (;;) {
3102 auto lexical_binding = parse_lexical_binding();
3103 if (!lexical_binding) {
3104 expected("lexical binding");
3105 break;
3106 }
3107
3108 check_identifier_name_for_assignment_validity(lexical_binding->string());
3109 if (lexical_binding->string() == "let"sv)
3110 syntax_error("Lexical binding may not be called 'let'");
3111
3112 RefPtr<Expression const> initializer;
3113 if (match(TokenType::Equals)) {
3114 consume();
3115
3116 if (is_for_loop_variable_declaration == IsForLoopVariableDeclaration::Yes)
3117 initializer = parse_expression(2, Associativity::Right, { TokenType::In });
3118 else
3119 initializer = parse_expression(2);
3120 } else if (is_for_loop_variable_declaration == IsForLoopVariableDeclaration::No) {
3121 consume(TokenType::Equals);
3122 }
3123
3124 declarations.append(create_ast_node<VariableDeclarator>(
3125 { m_source_code, rule_start.position(), position() },
3126 lexical_binding.release_nonnull(),
3127 move(initializer)));
3128
3129 if (match(TokenType::Comma)) {
3130 consume();
3131 continue;
3132 }
3133 break;
3134 }
3135 if (is_for_loop_variable_declaration == IsForLoopVariableDeclaration::No)
3136 consume_or_insert_semicolon();
3137
3138 return create_ast_node<UsingDeclaration>({ m_source_code, rule_start.position(), position() }, move(declarations));
3139}
3140
3141NonnullRefPtr<ThrowStatement const> Parser::parse_throw_statement()
3142{
3143 auto rule_start = push_start();
3144 consume(TokenType::Throw);
3145
3146 // Automatic semicolon insertion: terminate statement when throw is followed by newline
3147 if (m_state.current_token.trivia_contains_line_terminator()) {
3148 syntax_error("No line break is allowed between 'throw' and its expression");
3149 return create_ast_node<ThrowStatement>({ m_source_code, rule_start.position(), position() }, create_ast_node<ErrorExpression>({ m_source_code, rule_start.position(), position() }));
3150 }
3151
3152 auto expression = parse_expression(0);
3153 consume_or_insert_semicolon();
3154 return create_ast_node<ThrowStatement>({ m_source_code, rule_start.position(), position() }, move(expression));
3155}
3156
3157NonnullRefPtr<BreakStatement const> Parser::parse_break_statement()
3158{
3159 auto rule_start = push_start();
3160 consume(TokenType::Break);
3161 DeprecatedFlyString target_label;
3162 if (match(TokenType::Semicolon)) {
3163 consume();
3164 } else {
3165 if (!m_state.current_token.trivia_contains_line_terminator() && match_identifier()) {
3166 target_label = consume().value();
3167
3168 auto label = m_state.labels_in_scope.find(target_label);
3169 if (label == m_state.labels_in_scope.end())
3170 syntax_error(DeprecatedString::formatted("Label '{}' not found", target_label));
3171 }
3172 consume_or_insert_semicolon();
3173 }
3174
3175 if (target_label.is_null() && !m_state.in_break_context)
3176 syntax_error("Unlabeled 'break' not allowed outside of a loop or switch statement");
3177
3178 return create_ast_node<BreakStatement>({ m_source_code, rule_start.position(), position() }, target_label);
3179}
3180
3181NonnullRefPtr<ContinueStatement const> Parser::parse_continue_statement()
3182{
3183 auto rule_start = push_start();
3184 if (!m_state.in_continue_context)
3185 syntax_error("'continue' not allow outside of a loop");
3186
3187 consume(TokenType::Continue);
3188 DeprecatedFlyString target_label;
3189 if (match(TokenType::Semicolon)) {
3190 consume();
3191 return create_ast_node<ContinueStatement>({ m_source_code, rule_start.position(), position() }, target_label);
3192 }
3193 if (!m_state.current_token.trivia_contains_line_terminator() && match_identifier()) {
3194 auto label_position = position();
3195 target_label = consume().value();
3196
3197 auto label = m_state.labels_in_scope.find(target_label);
3198 if (label == m_state.labels_in_scope.end())
3199 syntax_error(DeprecatedString::formatted("Label '{}' not found or invalid", target_label));
3200 else
3201 label->value = label_position;
3202 }
3203 consume_or_insert_semicolon();
3204 return create_ast_node<ContinueStatement>({ m_source_code, rule_start.position(), position() }, target_label);
3205}
3206
3207NonnullRefPtr<ConditionalExpression const> Parser::parse_conditional_expression(NonnullRefPtr<Expression const> test, ForbiddenTokens forbidden)
3208{
3209 auto rule_start = push_start();
3210 consume(TokenType::QuestionMark);
3211 auto consequent = parse_expression(2);
3212 consume(TokenType::Colon);
3213 auto alternate = parse_expression(2, Associativity::Right, forbidden);
3214 return create_ast_node<ConditionalExpression>({ m_source_code, rule_start.position(), position() }, move(test), move(consequent), move(alternate));
3215}
3216
3217NonnullRefPtr<OptionalChain const> Parser::parse_optional_chain(NonnullRefPtr<Expression const> base)
3218{
3219 auto rule_start = push_start();
3220 Vector<OptionalChain::Reference> chain;
3221 do {
3222 if (match(TokenType::QuestionMarkPeriod)) {
3223 consume(TokenType::QuestionMarkPeriod);
3224 switch (m_state.current_token.type()) {
3225 case TokenType::ParenOpen:
3226 chain.append(OptionalChain::Call { parse_arguments(), OptionalChain::Mode::Optional });
3227 break;
3228 case TokenType::BracketOpen:
3229 consume();
3230 chain.append(OptionalChain::ComputedReference { parse_expression(0), OptionalChain::Mode::Optional });
3231 consume(TokenType::BracketClose);
3232 break;
3233 case TokenType::PrivateIdentifier: {
3234 if (!is_private_identifier_valid())
3235 syntax_error(DeprecatedString::formatted("Reference to undeclared private field or method '{}'", m_state.current_token.value()));
3236
3237 auto start = position();
3238 auto private_identifier = consume();
3239 chain.append(OptionalChain::PrivateMemberReference {
3240 create_ast_node<PrivateIdentifier>({ m_source_code, start, position() }, private_identifier.value()),
3241 OptionalChain::Mode::Optional });
3242 break;
3243 }
3244 case TokenType::TemplateLiteralStart:
3245 // 13.3.1.1 - Static Semantics: Early Errors
3246 // OptionalChain :
3247 // ?. TemplateLiteral
3248 // OptionalChain TemplateLiteral
3249 // This is a hard error.
3250 syntax_error("Invalid tagged template literal after ?.", position());
3251 break;
3252 default:
3253 if (match_identifier_name()) {
3254 auto start = position();
3255 auto identifier = consume();
3256 chain.append(OptionalChain::MemberReference {
3257 create_ast_node<Identifier>({ m_source_code, start, position() }, identifier.DeprecatedFlyString_value()),
3258 OptionalChain::Mode::Optional,
3259 });
3260 } else {
3261 syntax_error("Invalid optional chain reference after ?.", position());
3262 }
3263 break;
3264 }
3265 } else if (match(TokenType::ParenOpen)) {
3266 chain.append(OptionalChain::Call { parse_arguments(), OptionalChain::Mode::NotOptional });
3267 } else if (match(TokenType::Period)) {
3268 consume();
3269 if (match(TokenType::PrivateIdentifier)) {
3270 if (!is_private_identifier_valid())
3271 syntax_error(DeprecatedString::formatted("Reference to undeclared private field or method '{}'", m_state.current_token.value()));
3272
3273 auto start = position();
3274 auto private_identifier = consume();
3275 chain.append(OptionalChain::PrivateMemberReference {
3276 create_ast_node<PrivateIdentifier>({ m_source_code, start, position() }, private_identifier.value()),
3277 OptionalChain::Mode::NotOptional,
3278 });
3279 } else if (match_identifier_name()) {
3280 auto start = position();
3281 auto identifier = consume();
3282 chain.append(OptionalChain::MemberReference {
3283 create_ast_node<Identifier>({ m_source_code, start, position() }, identifier.DeprecatedFlyString_value()),
3284 OptionalChain::Mode::NotOptional,
3285 });
3286 } else {
3287 expected("an identifier");
3288 break;
3289 }
3290 } else if (match(TokenType::TemplateLiteralStart)) {
3291 // 13.3.1.1 - Static Semantics: Early Errors
3292 // OptionalChain :
3293 // ?. TemplateLiteral
3294 // OptionalChain TemplateLiteral
3295 syntax_error("Invalid tagged template literal after optional chain", position());
3296 break;
3297 } else if (match(TokenType::BracketOpen)) {
3298 consume();
3299 chain.append(OptionalChain::ComputedReference { parse_expression(2), OptionalChain::Mode::NotOptional });
3300 consume(TokenType::BracketClose);
3301 } else {
3302 break;
3303 }
3304 } while (!done());
3305
3306 return create_ast_node<OptionalChain>(
3307 { m_source_code, rule_start.position(), position() },
3308 move(base),
3309 move(chain));
3310}
3311
3312NonnullRefPtr<TryStatement const> Parser::parse_try_statement()
3313{
3314 auto rule_start = push_start();
3315 consume(TokenType::Try);
3316
3317 auto block = parse_block_statement();
3318
3319 RefPtr<CatchClause const> handler;
3320 if (match(TokenType::Catch))
3321 handler = parse_catch_clause();
3322
3323 RefPtr<BlockStatement const> finalizer;
3324 if (match(TokenType::Finally)) {
3325 consume();
3326 finalizer = parse_block_statement();
3327 }
3328
3329 if (!handler && !finalizer)
3330 syntax_error("try statement must have a 'catch' or 'finally' clause");
3331
3332 return create_ast_node<TryStatement>({ m_source_code, rule_start.position(), position() }, move(block), move(handler), move(finalizer));
3333}
3334
3335NonnullRefPtr<DoWhileStatement const> Parser::parse_do_while_statement()
3336{
3337 auto rule_start = push_start();
3338 consume(TokenType::Do);
3339
3340 auto body = [&]() -> NonnullRefPtr<Statement const> {
3341 TemporaryChange break_change(m_state.in_break_context, true);
3342 TemporaryChange continue_change(m_state.in_continue_context, true);
3343 return parse_statement();
3344 }();
3345
3346 consume(TokenType::While);
3347 consume(TokenType::ParenOpen);
3348
3349 auto test = parse_expression(0);
3350
3351 consume(TokenType::ParenClose);
3352
3353 // Since ES 2015 a missing semicolon is inserted here, despite the regular ASI rules not applying
3354 if (match(TokenType::Semicolon))
3355 consume();
3356
3357 return create_ast_node<DoWhileStatement>({ m_source_code, rule_start.position(), position() }, move(test), move(body));
3358}
3359
3360NonnullRefPtr<WhileStatement const> Parser::parse_while_statement()
3361{
3362 auto rule_start = push_start();
3363 consume(TokenType::While);
3364 consume(TokenType::ParenOpen);
3365
3366 auto test = parse_expression(0);
3367
3368 consume(TokenType::ParenClose);
3369
3370 TemporaryChange break_change(m_state.in_break_context, true);
3371 TemporaryChange continue_change(m_state.in_continue_context, true);
3372 auto body = parse_statement();
3373
3374 return create_ast_node<WhileStatement>({ m_source_code, rule_start.position(), position() }, move(test), move(body));
3375}
3376
3377NonnullRefPtr<SwitchStatement const> Parser::parse_switch_statement()
3378{
3379 auto rule_start = push_start();
3380 consume(TokenType::Switch);
3381
3382 consume(TokenType::ParenOpen);
3383 auto determinant = parse_expression(0);
3384 consume(TokenType::ParenClose);
3385
3386 consume(TokenType::CurlyOpen);
3387
3388 Vector<NonnullRefPtr<SwitchCase>> cases;
3389
3390 auto switch_statement = create_ast_node<SwitchStatement>({ m_source_code, rule_start.position(), position() }, move(determinant));
3391
3392 ScopePusher switch_scope = ScopePusher::block_scope(*this, switch_statement);
3393
3394 auto has_default = false;
3395 while (match(TokenType::Case) || match(TokenType::Default)) {
3396 if (match(TokenType::Default)) {
3397 if (has_default)
3398 syntax_error("Multiple 'default' clauses in switch statement");
3399 has_default = true;
3400 }
3401 switch_statement->add_case(parse_switch_case());
3402 }
3403
3404 consume(TokenType::CurlyClose);
3405
3406 return switch_statement;
3407}
3408
3409NonnullRefPtr<WithStatement const> Parser::parse_with_statement()
3410{
3411 auto rule_start = push_start();
3412 consume(TokenType::With);
3413 consume(TokenType::ParenOpen);
3414
3415 auto object = parse_expression(0);
3416
3417 consume(TokenType::ParenClose);
3418
3419 auto body = parse_statement();
3420 return create_ast_node<WithStatement>({ m_source_code, rule_start.position(), position() }, move(object), move(body));
3421}
3422
3423NonnullRefPtr<SwitchCase const> Parser::parse_switch_case()
3424{
3425 auto rule_start = push_start();
3426 RefPtr<Expression const> test;
3427
3428 if (consume().type() == TokenType::Case) {
3429 test = parse_expression(0);
3430 }
3431
3432 consume(TokenType::Colon);
3433
3434 Vector<NonnullRefPtr<Statement>> consequent;
3435 TemporaryChange break_change(m_state.in_break_context, true);
3436 auto switch_case = create_ast_node<SwitchCase>({ m_source_code, rule_start.position(), position() }, move(test));
3437 parse_statement_list(switch_case);
3438
3439 return switch_case;
3440}
3441
3442NonnullRefPtr<CatchClause const> Parser::parse_catch_clause()
3443{
3444 auto rule_start = push_start();
3445 consume(TokenType::Catch);
3446
3447 DeprecatedFlyString parameter;
3448 RefPtr<BindingPattern const> pattern_parameter;
3449 auto should_expect_parameter = false;
3450 if (match(TokenType::ParenOpen)) {
3451 should_expect_parameter = true;
3452 consume();
3453 if (match_identifier_name()
3454 && (!match(TokenType::Yield) || !m_state.in_generator_function_context)
3455 && (!match(TokenType::Async) || !m_state.await_expression_is_valid)
3456 && (!match(TokenType::Await) || !m_state.in_class_static_init_block))
3457 parameter = consume().value();
3458 else
3459 pattern_parameter = parse_binding_pattern(AllowDuplicates::No, AllowMemberExpressions::No);
3460 consume(TokenType::ParenClose);
3461 }
3462
3463 if (should_expect_parameter && parameter.is_empty() && !pattern_parameter)
3464 expected("an identifier or a binding pattern");
3465
3466 HashTable<DeprecatedFlyString> bound_names;
3467
3468 if (pattern_parameter) {
3469 // NOTE: Nothing in the callback throws an exception.
3470 MUST(pattern_parameter->for_each_bound_name(
3471 [&](auto& name) {
3472 check_identifier_name_for_assignment_validity(name);
3473 bound_names.set(name);
3474 }));
3475 }
3476
3477 if (!parameter.is_empty()) {
3478 check_identifier_name_for_assignment_validity(parameter);
3479 bound_names.set(parameter);
3480 }
3481
3482 ScopePusher catch_scope = ScopePusher::catch_scope(*this, pattern_parameter, parameter);
3483 auto body = parse_block_statement();
3484
3485 // NOTE: Nothing in the callback throws an exception.
3486 MUST(body->for_each_lexically_declared_name([&](auto const& name) {
3487 if (bound_names.contains(name))
3488 syntax_error(DeprecatedString::formatted("Identifier '{}' already declared as catch parameter", name));
3489 }));
3490
3491 if (pattern_parameter) {
3492 return create_ast_node<CatchClause>(
3493 { m_source_code, rule_start.position(), position() },
3494 pattern_parameter.release_nonnull(),
3495 move(body));
3496 }
3497
3498 return create_ast_node<CatchClause>(
3499 { m_source_code, rule_start.position(), position() },
3500 move(parameter),
3501 move(body));
3502}
3503
3504NonnullRefPtr<IfStatement const> Parser::parse_if_statement()
3505{
3506 auto rule_start = push_start();
3507 auto parse_function_declaration_as_block_statement = [&] {
3508 // https://tc39.es/ecma262/#sec-functiondeclarations-in-ifstatement-statement-clauses
3509 // This production only applies when parsing non-strict code. Source text matched
3510 // by this production is processed as if each matching occurrence of
3511 // FunctionDeclaration[?Yield, ?Await, ~Default] was the sole StatementListItem
3512 // of a BlockStatement occupying that position in the source text.
3513 // The semantics of such a synthetic BlockStatement includes the web legacy
3514 // compatibility semantics specified in B.3.2.
3515 VERIFY(match(TokenType::Function));
3516 auto block = create_ast_node<BlockStatement>({ m_source_code, rule_start.position(), position() });
3517 ScopePusher block_scope = ScopePusher::block_scope(*this, *block);
3518 auto declaration = parse_declaration();
3519 VERIFY(m_state.current_scope_pusher);
3520 block_scope.add_declaration(declaration);
3521
3522 VERIFY(is<FunctionDeclaration>(*declaration));
3523 auto& function_declaration = static_cast<FunctionDeclaration const&>(*declaration);
3524 if (function_declaration.kind() == FunctionKind::Generator)
3525 syntax_error("Generator functions can only be declared in top-level or within a block");
3526 if (function_declaration.kind() == FunctionKind::Async)
3527 syntax_error("Async functions can only be declared in top-level or within a block");
3528 block->append(move(declaration));
3529 return block;
3530 };
3531
3532 consume(TokenType::If);
3533 consume(TokenType::ParenOpen);
3534 auto predicate = parse_expression(0);
3535 consume(TokenType::ParenClose);
3536
3537 RefPtr<Statement const> consequent;
3538 if (!m_state.strict_mode && match(TokenType::Function))
3539 consequent = parse_function_declaration_as_block_statement();
3540 else
3541 consequent = parse_statement();
3542
3543 RefPtr<Statement const> alternate;
3544 if (match(TokenType::Else)) {
3545 consume();
3546 if (!m_state.strict_mode && match(TokenType::Function))
3547 alternate = parse_function_declaration_as_block_statement();
3548 else
3549 alternate = parse_statement();
3550 }
3551 return create_ast_node<IfStatement>({ m_source_code, rule_start.position(), position() }, move(predicate), move(*consequent), move(alternate));
3552}
3553
3554NonnullRefPtr<Statement const> Parser::parse_for_statement()
3555{
3556 auto rule_start = push_start();
3557 auto is_await_loop = IsForAwaitLoop::No;
3558
3559 auto match_of = [&](Token const& token) {
3560 return token.type() == TokenType::Identifier && token.original_value() == "of"sv;
3561 };
3562
3563 auto match_for_in_of = [&]() {
3564 bool is_of = match_of(m_state.current_token);
3565 if (is_await_loop == IsForAwaitLoop::Yes) {
3566 if (!is_of)
3567 syntax_error("for await loop is only valid with 'of'");
3568 else if (!m_state.await_expression_is_valid)
3569 syntax_error("for await loop is only valid in async function or generator");
3570 return true;
3571 }
3572
3573 return match(TokenType::In) || is_of;
3574 };
3575
3576 consume(TokenType::For);
3577
3578 if (match(TokenType::Await)) {
3579 consume();
3580 if (!m_state.await_expression_is_valid)
3581 syntax_error("for-await-of is only allowed in async function context");
3582 is_await_loop = IsForAwaitLoop::Yes;
3583 }
3584
3585 consume(TokenType::ParenOpen);
3586
3587 Optional<ScopePusher> scope_pusher;
3588
3589 RefPtr<ASTNode const> init;
3590 if (!match(TokenType::Semicolon)) {
3591
3592 auto match_for_using_declaration = [&] {
3593 if (!match(TokenType::Identifier) || m_state.current_token.original_value() != "using"sv)
3594 return false;
3595
3596 auto lookahead = next_token();
3597 if (lookahead.trivia_contains_line_terminator())
3598 return false;
3599
3600 if (lookahead.original_value() == "of"sv)
3601 return false;
3602
3603 return token_is_identifier(lookahead);
3604 };
3605
3606 if (match_for_using_declaration()) {
3607 auto declaration = parse_using_declaration(IsForLoopVariableDeclaration::Yes);
3608
3609 if (match_of(m_state.current_token)) {
3610 if (declaration->declarations().size() != 1)
3611 syntax_error("Must have exactly one declaration in for using of");
3612 else if (declaration->declarations().first()->init())
3613 syntax_error("Using declaration cannot have initializer");
3614
3615 return parse_for_in_of_statement(move(declaration), is_await_loop);
3616 }
3617
3618 if (match(TokenType::In))
3619 syntax_error("Using declaration not allowed in for-in loop");
3620
3621 init = move(declaration);
3622 } else if (match_variable_declaration()) {
3623 auto declaration = parse_variable_declaration(IsForLoopVariableDeclaration::Yes);
3624 if (declaration->declaration_kind() == DeclarationKind::Var) {
3625 m_state.current_scope_pusher->add_declaration(declaration);
3626 } else {
3627 // This does not follow the normal declaration structure so we need additional checks.
3628 HashTable<DeprecatedFlyString> bound_names;
3629 // NOTE: Nothing in the callback throws an exception.
3630 MUST(declaration->for_each_bound_name([&](auto const& name) {
3631 if (bound_names.set(name) != AK::HashSetResult::InsertedNewEntry)
3632 syntax_error(DeprecatedString::formatted("Identifier '{}' already declared in for loop initializer", name), declaration->source_range().start);
3633 }));
3634 }
3635
3636 if (match_for_in_of()) {
3637 if (declaration->declarations().size() > 1)
3638 syntax_error("Multiple declarations not allowed in for..in/of");
3639 else if (declaration->declarations().size() < 1)
3640 syntax_error("Need exactly one variable declaration in for..in/of");
3641
3642 return parse_for_in_of_statement(move(declaration), is_await_loop);
3643 }
3644 if (declaration->declaration_kind() == DeclarationKind::Const) {
3645 for (auto const& variable : declaration->declarations()) {
3646 if (!variable->init())
3647 syntax_error("Missing initializer in 'const' variable declaration");
3648 }
3649 }
3650
3651 init = move(declaration);
3652 } else if (match_expression()) {
3653 auto lookahead_token = next_token();
3654 bool starts_with_async_of = match(TokenType::Async) && match_of(lookahead_token);
3655
3656 init = parse_expression(0, Associativity::Right, { TokenType::In });
3657 if (match_for_in_of()) {
3658 if (is_await_loop != IsForAwaitLoop::Yes
3659 && starts_with_async_of && match_of(m_state.current_token))
3660 syntax_error("for-of loop may not start with async of");
3661 return parse_for_in_of_statement(*init, is_await_loop);
3662 }
3663 } else {
3664 syntax_error("Unexpected token in for loop");
3665 }
3666 }
3667 consume(TokenType::Semicolon);
3668
3669 RefPtr<Expression const> test;
3670 if (!match(TokenType::Semicolon))
3671 test = parse_expression(0);
3672
3673 consume(TokenType::Semicolon);
3674
3675 RefPtr<Expression const> update;
3676 if (!match(TokenType::ParenClose))
3677 update = parse_expression(0);
3678
3679 consume(TokenType::ParenClose);
3680
3681 TemporaryChange break_change(m_state.in_break_context, true);
3682 TemporaryChange continue_change(m_state.in_continue_context, true);
3683 ScopePusher for_loop_scope = ScopePusher::for_loop_scope(*this, init);
3684 auto body = parse_statement();
3685
3686 return create_ast_node<ForStatement>({ m_source_code, rule_start.position(), position() }, move(init), move(test), move(update), move(body));
3687}
3688
3689NonnullRefPtr<Statement const> Parser::parse_for_in_of_statement(NonnullRefPtr<ASTNode const> lhs, IsForAwaitLoop is_for_await_loop)
3690{
3691 Variant<NonnullRefPtr<ASTNode const>, NonnullRefPtr<BindingPattern const>> for_declaration = lhs;
3692 auto rule_start = push_start();
3693
3694 auto has_annexB_for_in_init_extension = false;
3695
3696 if (is<VariableDeclaration>(*lhs)) {
3697 auto& declaration = static_cast<VariableDeclaration const&>(*lhs);
3698 // Syntax errors for wrong amounts of declaration should have already been hit.
3699 if (!declaration.declarations().is_empty()) {
3700 // AnnexB extension B.3.5 Initializers in ForIn Statement Heads, https://tc39.es/ecma262/#sec-initializers-in-forin-statement-heads
3701 auto& variable = declaration.declarations().first();
3702 if (variable->init()) {
3703 if (m_state.strict_mode || declaration.declaration_kind() != DeclarationKind::Var || !variable->target().has<NonnullRefPtr<Identifier const>>())
3704 syntax_error("Variable initializer not allowed in for..in/of");
3705 else
3706 has_annexB_for_in_init_extension = true;
3707 }
3708 }
3709 } else if (!lhs->is_identifier() && !is<MemberExpression>(*lhs) && !is<CallExpression>(*lhs) && !is<UsingDeclaration>(*lhs)) {
3710 bool valid = false;
3711 if (is<ObjectExpression>(*lhs) || is<ArrayExpression>(*lhs)) {
3712 auto synthesized_binding_pattern = synthesize_binding_pattern(static_cast<Expression const&>(*lhs));
3713 if (synthesized_binding_pattern) {
3714 for_declaration = synthesized_binding_pattern.release_nonnull();
3715 valid = true;
3716 }
3717 }
3718 if (!valid)
3719 syntax_error(DeprecatedString::formatted("Invalid left-hand side in for-loop ('{}')", lhs->class_name()));
3720 }
3721 auto in_or_of = consume();
3722 auto is_in = in_or_of.type() == TokenType::In;
3723
3724 if (!is_in) {
3725 if (is<MemberExpression>(*lhs)) {
3726 auto& member = static_cast<MemberExpression const&>(*lhs);
3727 if (member.object().is_identifier() && static_cast<Identifier const&>(member.object()).string() == "let"sv)
3728 syntax_error("For of statement may not start with let.");
3729 }
3730 if (has_annexB_for_in_init_extension)
3731 syntax_error("Variable initializer not allowed in for..of", rule_start.position());
3732 }
3733
3734 auto rhs = parse_expression(is_in ? 0 : 2);
3735 consume(TokenType::ParenClose);
3736
3737 TemporaryChange break_change(m_state.in_break_context, true);
3738 TemporaryChange continue_change(m_state.in_continue_context, true);
3739 ScopePusher for_loop_scope = ScopePusher::for_loop_scope(*this, lhs);
3740 auto body = parse_statement();
3741 if (is_in)
3742 return create_ast_node<ForInStatement>({ m_source_code, rule_start.position(), position() }, move(for_declaration), move(rhs), move(body));
3743 if (is_for_await_loop == IsForAwaitLoop::Yes)
3744 return create_ast_node<ForAwaitOfStatement>({ m_source_code, rule_start.position(), position() }, move(for_declaration), move(rhs), move(body));
3745 return create_ast_node<ForOfStatement>({ m_source_code, rule_start.position(), position() }, move(for_declaration), move(rhs), move(body));
3746}
3747
3748NonnullRefPtr<DebuggerStatement const> Parser::parse_debugger_statement()
3749{
3750 auto rule_start = push_start();
3751 consume(TokenType::Debugger);
3752 consume_or_insert_semicolon();
3753 return create_ast_node<DebuggerStatement>({ m_source_code, rule_start.position(), position() });
3754}
3755
3756bool Parser::match(TokenType type) const
3757{
3758 return m_state.current_token.type() == type;
3759}
3760
3761bool Parser::match_expression() const
3762{
3763 auto type = m_state.current_token.type();
3764 if (type == TokenType::Import) {
3765 auto lookahead_token = next_token();
3766 return lookahead_token.type() == TokenType::Period || lookahead_token.type() == TokenType::ParenOpen;
3767 }
3768
3769 return type == TokenType::BoolLiteral
3770 || type == TokenType::NumericLiteral
3771 || type == TokenType::BigIntLiteral
3772 || type == TokenType::StringLiteral
3773 || type == TokenType::TemplateLiteralStart
3774 || type == TokenType::NullLiteral
3775 || match_identifier()
3776 || type == TokenType::PrivateIdentifier
3777 || type == TokenType::Await
3778 || type == TokenType::New
3779 || type == TokenType::Class
3780 || type == TokenType::CurlyOpen
3781 || type == TokenType::BracketOpen
3782 || type == TokenType::ParenOpen
3783 || type == TokenType::Function
3784 || type == TokenType::Async
3785 || type == TokenType::This
3786 || type == TokenType::Super
3787 || type == TokenType::RegexLiteral
3788 || type == TokenType::Slash // Wrongly recognized regex by lexer
3789 || type == TokenType::SlashEquals // Wrongly recognized regex by lexer (/=a/ is a valid regex)
3790 || type == TokenType::Yield
3791 || match_unary_prefixed_expression();
3792}
3793
3794bool Parser::match_unary_prefixed_expression() const
3795{
3796 auto type = m_state.current_token.type();
3797 return type == TokenType::PlusPlus
3798 || type == TokenType::MinusMinus
3799 || type == TokenType::ExclamationMark
3800 || type == TokenType::Tilde
3801 || type == TokenType::Plus
3802 || type == TokenType::Minus
3803 || type == TokenType::Typeof
3804 || type == TokenType::Void
3805 || type == TokenType::Delete;
3806}
3807
3808bool Parser::match_secondary_expression(ForbiddenTokens forbidden) const
3809{
3810 auto type = m_state.current_token.type();
3811 if (!forbidden.allows(type))
3812 return false;
3813 return type == TokenType::Plus
3814 || type == TokenType::PlusEquals
3815 || type == TokenType::Minus
3816 || type == TokenType::MinusEquals
3817 || type == TokenType::Asterisk
3818 || type == TokenType::AsteriskEquals
3819 || type == TokenType::Slash
3820 || type == TokenType::SlashEquals
3821 || type == TokenType::Percent
3822 || type == TokenType::PercentEquals
3823 || type == TokenType::DoubleAsterisk
3824 || type == TokenType::DoubleAsteriskEquals
3825 || type == TokenType::Equals
3826 || type == TokenType::EqualsEqualsEquals
3827 || type == TokenType::ExclamationMarkEqualsEquals
3828 || type == TokenType::EqualsEquals
3829 || type == TokenType::ExclamationMarkEquals
3830 || type == TokenType::GreaterThan
3831 || type == TokenType::GreaterThanEquals
3832 || type == TokenType::LessThan
3833 || type == TokenType::LessThanEquals
3834 || type == TokenType::ParenOpen
3835 || type == TokenType::Period
3836 || type == TokenType::BracketOpen
3837 || (type == TokenType::PlusPlus && !m_state.current_token.trivia_contains_line_terminator())
3838 || (type == TokenType::MinusMinus && !m_state.current_token.trivia_contains_line_terminator())
3839 || type == TokenType::In
3840 || type == TokenType::Instanceof
3841 || type == TokenType::QuestionMark
3842 || type == TokenType::Ampersand
3843 || type == TokenType::AmpersandEquals
3844 || type == TokenType::Pipe
3845 || type == TokenType::PipeEquals
3846 || type == TokenType::Caret
3847 || type == TokenType::CaretEquals
3848 || type == TokenType::ShiftLeft
3849 || type == TokenType::ShiftLeftEquals
3850 || type == TokenType::ShiftRight
3851 || type == TokenType::ShiftRightEquals
3852 || type == TokenType::UnsignedShiftRight
3853 || type == TokenType::UnsignedShiftRightEquals
3854 || type == TokenType::DoubleAmpersand
3855 || type == TokenType::DoubleAmpersandEquals
3856 || type == TokenType::DoublePipe
3857 || type == TokenType::DoublePipeEquals
3858 || type == TokenType::DoubleQuestionMark
3859 || type == TokenType::DoubleQuestionMarkEquals
3860 || type == TokenType::QuestionMarkPeriod;
3861}
3862
3863bool Parser::match_statement() const
3864{
3865 auto type = m_state.current_token.type();
3866 return match_expression()
3867 || type == TokenType::Return
3868 || type == TokenType::Yield
3869 || type == TokenType::Do
3870 || type == TokenType::If
3871 || type == TokenType::Throw
3872 || type == TokenType::Try
3873 || type == TokenType::While
3874 || type == TokenType::With
3875 || type == TokenType::For
3876 || type == TokenType::CurlyOpen
3877 || type == TokenType::Switch
3878 || type == TokenType::Break
3879 || type == TokenType::Continue
3880 || type == TokenType::Var
3881 || type == TokenType::Debugger
3882 || type == TokenType::Semicolon;
3883}
3884
3885bool Parser::match_export_or_import() const
3886{
3887 auto type = m_state.current_token.type();
3888 return type == TokenType::Export
3889 || type == TokenType::Import;
3890}
3891
3892bool Parser::match_declaration(AllowUsingDeclaration allow_using) const
3893{
3894 auto type = m_state.current_token.type();
3895
3896 if (type == TokenType::Let && !m_state.strict_mode) {
3897 return try_match_let_declaration();
3898 }
3899
3900 if (type == TokenType::Async) {
3901 auto lookahead_token = next_token();
3902 return lookahead_token.type() == TokenType::Function && !lookahead_token.trivia_contains_line_terminator();
3903 }
3904
3905 if (allow_using == AllowUsingDeclaration::Yes && type == TokenType::Identifier && m_state.current_token.original_value() == "using"sv)
3906 return try_match_using_declaration();
3907
3908 return type == TokenType::Function
3909 || type == TokenType::Class
3910 || type == TokenType::Const
3911 || type == TokenType::Let;
3912}
3913
3914Token Parser::next_token(size_t steps) const
3915{
3916 Lexer lookahead_lexer = m_state.lexer;
3917
3918 Token lookahead_token;
3919
3920 while (steps > 0) {
3921 lookahead_token = lookahead_lexer.next();
3922 steps--;
3923 }
3924
3925 return lookahead_token;
3926}
3927
3928bool Parser::try_match_let_declaration() const
3929{
3930 VERIFY(m_state.current_token.type() == TokenType::Let);
3931 auto token_after = next_token();
3932
3933 if (token_after.is_identifier_name() && token_after.value() != "in"sv)
3934 return true;
3935
3936 if (token_after.type() == TokenType::CurlyOpen || token_after.type() == TokenType::BracketOpen)
3937 return true;
3938
3939 return false;
3940}
3941
3942bool Parser::try_match_using_declaration() const
3943{
3944 VERIFY(m_state.current_token.type() == TokenType::Identifier);
3945 VERIFY(m_state.current_token.original_value() == "using"sv);
3946
3947 auto token_after = next_token();
3948 if (token_after.trivia_contains_line_terminator())
3949 return false;
3950
3951 return token_after.is_identifier_name();
3952}
3953
3954bool Parser::match_variable_declaration() const
3955{
3956 auto type = m_state.current_token.type();
3957
3958 if (type == TokenType::Let && !m_state.strict_mode) {
3959 return try_match_let_declaration();
3960 }
3961
3962 return type == TokenType::Var
3963 || type == TokenType::Let
3964 || type == TokenType::Const;
3965}
3966
3967bool Parser::match_identifier() const
3968{
3969 return token_is_identifier(m_state.current_token);
3970}
3971
3972bool Parser::token_is_identifier(Token const& token) const
3973{
3974 if (token.type() == TokenType::EscapedKeyword) {
3975 if (token.value() == "let"sv)
3976 return !m_state.strict_mode;
3977 if (token.value() == "yield"sv)
3978 return !m_state.strict_mode && !m_state.in_generator_function_context;
3979 if (token.value() == "await"sv)
3980 return m_program_type != Program::Type::Module && !m_state.await_expression_is_valid && !m_state.in_class_static_init_block;
3981 return true;
3982 }
3983
3984 return token.type() == TokenType::Identifier
3985 || token.type() == TokenType::Async
3986 || (token.type() == TokenType::Let && !m_state.strict_mode)
3987 || (token.type() == TokenType::Await && m_program_type != Program::Type::Module && !m_state.await_expression_is_valid && !m_state.in_class_static_init_block)
3988 || (token.type() == TokenType::Yield && !m_state.in_generator_function_context && !m_state.strict_mode); // See note in Parser::parse_identifier().
3989}
3990
3991bool Parser::match_identifier_name() const
3992{
3993 return m_state.current_token.is_identifier_name();
3994}
3995
3996bool Parser::match_property_key() const
3997{
3998 auto type = m_state.current_token.type();
3999 return match_identifier_name()
4000 || type == TokenType::BracketOpen
4001 || type == TokenType::StringLiteral
4002 || type == TokenType::NumericLiteral
4003 || type == TokenType::BigIntLiteral;
4004}
4005
4006bool Parser::done() const
4007{
4008 return match(TokenType::Eof);
4009}
4010
4011Token Parser::consume()
4012{
4013 auto old_token = m_state.current_token;
4014 m_state.current_token = m_state.lexer.next();
4015 // NOTE: This is the bare minimum needed to decide whether we might need an arguments object
4016 // in a function expression or declaration. ("might" because the AST implements some further
4017 // conditions from the spec that rule out the need for allocating one)
4018 if (old_token.type() == TokenType::Identifier && old_token.value().is_one_of("arguments"sv, "eval"sv))
4019 m_state.function_might_need_arguments_object = true;
4020 return old_token;
4021}
4022
4023void Parser::consume_or_insert_semicolon()
4024{
4025 // Semicolon was found and will be consumed
4026 if (match(TokenType::Semicolon)) {
4027 consume();
4028 return;
4029 }
4030 // Insert semicolon if...
4031 // ...token is preceded by one or more newlines
4032 if (m_state.current_token.trivia_contains_line_terminator())
4033 return;
4034 // ...token is a closing curly brace
4035 if (match(TokenType::CurlyClose))
4036 return;
4037 // ...token is eof
4038 if (match(TokenType::Eof))
4039 return;
4040
4041 // No rule for semicolon insertion applies -> syntax error
4042 expected("Semicolon");
4043}
4044
4045Token Parser::consume_identifier()
4046{
4047 if (match(TokenType::Identifier))
4048 return consume(TokenType::Identifier);
4049
4050 if (match(TokenType::EscapedKeyword))
4051 return consume(TokenType::EscapedKeyword);
4052
4053 // Note that 'let' is not a reserved keyword, but our lexer considers it such
4054 // As it's pretty nice to have that (for syntax highlighting and such), we'll
4055 // special-case it here instead.
4056 if (match(TokenType::Let)) {
4057 if (m_state.strict_mode)
4058 syntax_error("'let' is not allowed as an identifier in strict mode");
4059 return consume();
4060 }
4061
4062 if (match(TokenType::Yield)) {
4063 if (m_state.strict_mode || m_state.in_generator_function_context)
4064 syntax_error("Identifier must not be a reserved word in strict mode ('yield')");
4065 return consume();
4066 }
4067
4068 if (match(TokenType::Await)) {
4069 if (m_program_type == Program::Type::Module || m_state.await_expression_is_valid || m_state.in_class_static_init_block)
4070 syntax_error("Identifier must not be a reserved word in modules ('await')");
4071 return consume();
4072 }
4073
4074 if (match(TokenType::Async))
4075 return consume();
4076
4077 expected("Identifier");
4078 return consume();
4079}
4080
4081// https://tc39.es/ecma262/#prod-IdentifierReference
4082Token Parser::consume_identifier_reference()
4083{
4084 if (match(TokenType::Identifier))
4085 return consume(TokenType::Identifier);
4086
4087 if (match(TokenType::EscapedKeyword)) {
4088 auto name = m_state.current_token.value();
4089 if (m_state.strict_mode && (name == "let"sv || name == "yield"sv))
4090 syntax_error(DeprecatedString::formatted("'{}' is not allowed as an identifier in strict mode", name));
4091 if (m_program_type == Program::Type::Module && name == "await"sv)
4092 syntax_error("'await' is not allowed as an identifier in module");
4093
4094 return consume();
4095 }
4096
4097 // See note in Parser::parse_identifier().
4098 if (match(TokenType::Let)) {
4099 if (m_state.strict_mode)
4100 syntax_error("'let' is not allowed as an identifier in strict mode");
4101 return consume();
4102 }
4103
4104 if (match(TokenType::Yield)) {
4105 if (m_state.strict_mode)
4106 syntax_error("Identifier reference may not be 'yield' in strict mode");
4107 return consume();
4108 }
4109
4110 if (match(TokenType::Await)) {
4111 if (m_program_type == Program::Type::Module)
4112 syntax_error("'await' is not allowed as an identifier in module");
4113 return consume();
4114 }
4115
4116 if (match(TokenType::Async))
4117 return consume();
4118
4119 expected(Token::name(TokenType::Identifier));
4120 return consume();
4121}
4122
4123Token Parser::consume(TokenType expected_type)
4124{
4125 if (!match(expected_type)) {
4126 expected(Token::name(expected_type));
4127 }
4128 auto token = consume();
4129 if (expected_type == TokenType::Identifier) {
4130 if (m_state.strict_mode && is_strict_reserved_word(token.value()))
4131 syntax_error(DeprecatedString::formatted("Identifier must not be a reserved word in strict mode ('{}')", token.value()));
4132 }
4133 return token;
4134}
4135
4136Token Parser::consume_and_validate_numeric_literal()
4137{
4138 auto is_unprefixed_octal_number = [](StringView value) {
4139 return value.length() > 1 && value[0] == '0' && is_ascii_digit(value[1]);
4140 };
4141 auto literal_start = position();
4142 auto token = consume(TokenType::NumericLiteral);
4143 if (m_state.strict_mode && is_unprefixed_octal_number(token.value()))
4144 syntax_error("Unprefixed octal number not allowed in strict mode", literal_start);
4145 if (match_identifier_name() && m_state.current_token.trivia().is_empty())
4146 syntax_error("Numeric literal must not be immediately followed by identifier");
4147 return token;
4148}
4149
4150void Parser::expected(char const* what)
4151{
4152 auto message = m_state.current_token.message().to_deprecated_string();
4153 if (message.is_empty())
4154 message = DeprecatedString::formatted("Unexpected token {}. Expected {}", m_state.current_token.name(), what);
4155 syntax_error(message);
4156}
4157
4158Position Parser::position() const
4159{
4160 return {
4161 m_state.current_token.line_number(),
4162 m_state.current_token.line_column(),
4163 m_state.current_token.offset(),
4164 };
4165}
4166
4167bool Parser::try_parse_arrow_function_expression_failed_at_position(Position const& position) const
4168{
4169 auto it = m_token_memoizations.find(position);
4170 if (it == m_token_memoizations.end())
4171 return false;
4172
4173 return (*it).value.try_parse_arrow_function_expression_failed;
4174}
4175
4176void Parser::set_try_parse_arrow_function_expression_failed_at_position(Position const& position, bool failed)
4177{
4178 m_token_memoizations.set(position, { failed });
4179}
4180
4181void Parser::syntax_error(DeprecatedString const& message, Optional<Position> position)
4182{
4183 if (!position.has_value())
4184 position = this->position();
4185 m_state.errors.append({ message, position });
4186}
4187
4188void Parser::save_state()
4189{
4190 m_saved_state.append(m_state);
4191}
4192
4193void Parser::load_state()
4194{
4195 VERIFY(!m_saved_state.is_empty());
4196 m_state = m_saved_state.take_last();
4197}
4198
4199void Parser::discard_saved_state()
4200{
4201 m_saved_state.take_last();
4202}
4203
4204void Parser::check_identifier_name_for_assignment_validity(DeprecatedFlyString const& name, bool force_strict)
4205{
4206 // FIXME: this is now called from multiple places maybe the error message should be dynamic?
4207 if (any_of(s_reserved_words, [&](auto& value) { return name == value; })) {
4208 syntax_error("Binding pattern target may not be a reserved word");
4209 } else if (m_state.strict_mode || force_strict) {
4210 if (name.is_one_of("arguments"sv, "eval"sv))
4211 syntax_error("Binding pattern target may not be called 'arguments' or 'eval' in strict mode");
4212 else if (is_strict_reserved_word(name))
4213 syntax_error(DeprecatedString::formatted("Binding pattern target may not be called '{}' in strict mode", name));
4214 }
4215}
4216
4217bool Parser::match_assert_clause() const
4218{
4219 return !m_state.current_token.trivia_contains_line_terminator() && m_state.current_token.original_value() == "assert"sv;
4220}
4221
4222DeprecatedFlyString Parser::consume_string_value()
4223{
4224 VERIFY(match(TokenType::StringLiteral));
4225 auto string_token = consume();
4226 DeprecatedFlyString value = parse_string_literal(string_token)->value();
4227
4228 // This also checks IsStringWellFormedUnicode which makes sure there is no unpaired surrogate
4229 // Surrogates are at least 3 bytes
4230 if (value.length() < 3)
4231 return value;
4232
4233 Utf8View view { value.view().substring_view(value.length() - 3) };
4234 VERIFY(view.length() <= 3);
4235 auto codepoint = *view.begin();
4236 if (Utf16View::is_high_surrogate(codepoint)) {
4237 syntax_error("StringValue ending with unpaired high surrogate");
4238 VERIFY(view.length() == 1);
4239 }
4240
4241 return value;
4242}
4243
4244// AssertClause, https://tc39.es/proposal-import-assertions/#prod-AssertClause
4245ModuleRequest Parser::parse_module_request()
4246{
4247 // Does not include the 'from' since that is not always required.
4248
4249 if (!match(TokenType::StringLiteral)) {
4250 expected("ModuleSpecifier (string)");
4251 return ModuleRequest { "!!invalid!!" };
4252 }
4253
4254 ModuleRequest request { consume_string_value() };
4255
4256 if (!match_assert_clause())
4257 return request;
4258
4259 VERIFY(m_state.current_token.original_value() == "assert"sv);
4260 consume(TokenType::Identifier);
4261 consume(TokenType::CurlyOpen);
4262
4263 while (!done() && !match(TokenType::CurlyClose)) {
4264 DeprecatedString key;
4265 if (match(TokenType::StringLiteral)) {
4266 key = parse_string_literal(m_state.current_token)->value().to_deprecated_string();
4267 consume();
4268 } else if (match_identifier_name()) {
4269 key = consume().value();
4270 } else {
4271 expected("IdentifierName or StringValue as AssertionKey");
4272 consume();
4273 }
4274
4275 consume(TokenType::Colon);
4276
4277 if (match(TokenType::StringLiteral)) {
4278 for (auto& entries : request.assertions) {
4279 if (entries.key == key)
4280 syntax_error(DeprecatedString::formatted("Duplicate assertion clauses with name: {}", key));
4281 }
4282 request.add_assertion(move(key), parse_string_literal(m_state.current_token)->value().to_deprecated_string());
4283 }
4284 consume(TokenType::StringLiteral);
4285
4286 if (match(TokenType::Comma))
4287 consume(TokenType::Comma);
4288 else
4289 break;
4290 }
4291
4292 consume(TokenType::CurlyClose);
4293
4294 return request;
4295}
4296
4297static DeprecatedFlyString default_string_value = "default";
4298
4299NonnullRefPtr<ImportStatement const> Parser::parse_import_statement(Program& program)
4300{
4301 // We use the extended syntax which adds:
4302 // ImportDeclaration:
4303 // import ImportClause FromClause [no LineTerminator here] AssertClause;
4304 // import ModuleSpecifier [no LineTerminator here] AssertClause;
4305 // From: https://tc39.es/proposal-import-assertions/#prod-ImportDeclaration
4306
4307 auto rule_start = push_start();
4308 if (program.type() != Program::Type::Module)
4309 syntax_error("Cannot use import statement outside a module");
4310
4311 consume(TokenType::Import);
4312
4313 if (match(TokenType::StringLiteral)) {
4314 // import ModuleSpecifier ;
4315 auto module_request = parse_module_request();
4316 return create_ast_node<ImportStatement>({ m_source_code, rule_start.position(), position() }, move(module_request));
4317 }
4318
4319 auto match_imported_binding = [&] {
4320 return match_identifier() || match(TokenType::Yield) || match(TokenType::Await);
4321 };
4322
4323 auto match_as = [&] {
4324 return match(TokenType::Identifier) && m_state.current_token.original_value() == "as"sv;
4325 };
4326
4327 bool continue_parsing = true;
4328
4329 struct ImportWithLocation {
4330 ImportEntry entry;
4331 Position position;
4332 };
4333
4334 Vector<ImportWithLocation> entries_with_location;
4335
4336 // import ImportClause FromClause ;
4337 // ImportClause :
4338 // ImportedDefaultBinding
4339 // NameSpaceImport
4340 // NamedImports
4341 // ImportedDefaultBinding , NameSpaceImport
4342 // ImportedDefaultBinding , NamedImports
4343
4344 if (match_imported_binding()) {
4345 // ImportedDefaultBinding : ImportedBinding
4346 auto id_position = position();
4347 auto bound_name = consume().value();
4348 entries_with_location.append({ { default_string_value, bound_name }, id_position });
4349
4350 if (match(TokenType::Comma)) {
4351 consume(TokenType::Comma);
4352 } else {
4353 continue_parsing = false;
4354 }
4355 }
4356
4357 if (!continue_parsing) {
4358 // skip the rest
4359 } else if (match(TokenType::Asterisk)) {
4360 // NameSpaceImport : * as ImportedBinding
4361 consume(TokenType::Asterisk);
4362
4363 if (!match_as())
4364 syntax_error(DeprecatedString::formatted("Unexpected token: {}", m_state.current_token.name()));
4365
4366 consume(TokenType::Identifier);
4367
4368 if (match_imported_binding()) {
4369 auto namespace_position = position();
4370 auto namespace_name = consume().value();
4371 entries_with_location.append({ ImportEntry({}, namespace_name, true), namespace_position });
4372 } else {
4373 syntax_error(DeprecatedString::formatted("Unexpected token: {}", m_state.current_token.name()));
4374 }
4375
4376 } else if (match(TokenType::CurlyOpen)) {
4377 // NamedImports :
4378 // { ImportSpecifier ,_opt } (repeated any amount of times)
4379
4380 consume(TokenType::CurlyOpen);
4381 while (!done() && !match(TokenType::CurlyClose)) {
4382 if (match_identifier_name()) {
4383 // ImportSpecifier : ImportedBinding
4384 auto require_as = !match_imported_binding();
4385 auto name_position = position();
4386 auto name = consume().DeprecatedFlyString_value();
4387
4388 if (match_as()) {
4389 consume(TokenType::Identifier);
4390
4391 auto alias_position = position();
4392 auto alias = consume_identifier().DeprecatedFlyString_value();
4393 check_identifier_name_for_assignment_validity(alias);
4394
4395 entries_with_location.append({ { name, alias }, alias_position });
4396 } else if (require_as) {
4397 syntax_error(DeprecatedString::formatted("Unexpected reserved word '{}'", name));
4398 } else {
4399 check_identifier_name_for_assignment_validity(name);
4400
4401 entries_with_location.append({ { name, name }, name_position });
4402 }
4403 } else if (match(TokenType::StringLiteral)) {
4404 // ImportSpecifier : ModuleExportName as ImportedBinding
4405 auto name = consume_string_value();
4406
4407 if (!match_as())
4408 expected("as");
4409
4410 consume(TokenType::Identifier);
4411
4412 auto alias_position = position();
4413 auto alias = consume_identifier().DeprecatedFlyString_value();
4414 check_identifier_name_for_assignment_validity(alias);
4415
4416 entries_with_location.append({ { move(name), alias }, alias_position });
4417 } else {
4418 expected("identifier");
4419 break;
4420 }
4421
4422 if (!match(TokenType::Comma))
4423 break;
4424
4425 consume(TokenType::Comma);
4426 }
4427
4428 consume(TokenType::CurlyClose);
4429 } else {
4430 expected("import clauses");
4431 }
4432
4433 auto from_statement = consume(TokenType::Identifier).original_value();
4434 if (from_statement != "from"sv)
4435 syntax_error(DeprecatedString::formatted("Expected 'from' got {}", from_statement));
4436
4437 auto module_request = parse_module_request();
4438
4439 Vector<ImportEntry> entries;
4440 entries.ensure_capacity(entries_with_location.size());
4441
4442 for (auto& entry : entries_with_location) {
4443 for (auto& import_statement : program.imports()) {
4444 if (import_statement->has_bound_name(entry.entry.local_name))
4445 syntax_error(DeprecatedString::formatted("Identifier '{}' already declared", entry.entry.local_name), entry.position);
4446 }
4447
4448 for (auto& new_entry : entries) {
4449 if (new_entry.local_name == entry.entry.local_name)
4450 syntax_error(DeprecatedString::formatted("Identifier '{}' already declared", entry.entry.local_name), entry.position);
4451 }
4452
4453 entries.append(move(entry.entry));
4454 }
4455
4456 return create_ast_node<ImportStatement>({ m_source_code, rule_start.position(), position() }, move(module_request), move(entries));
4457}
4458
4459NonnullRefPtr<ExportStatement const> Parser::parse_export_statement(Program& program)
4460{
4461 // We use the extended syntax which adds:
4462 // ExportDeclaration:
4463 // export ExportFromClause FromClause [no LineTerminator here] AssertClause ;
4464 // From: https://tc39.es/proposal-import-assertions/#prod-ExportDeclaration
4465
4466 auto rule_start = push_start();
4467 if (program.type() != Program::Type::Module)
4468 syntax_error("Cannot use export statement outside a module");
4469
4470 auto match_as = [&] {
4471 return match(TokenType::Identifier) && m_state.current_token.original_value() == "as"sv;
4472 };
4473
4474 auto match_from = [&] {
4475 return match(TokenType::Identifier) && m_state.current_token.original_value() == "from"sv;
4476 };
4477
4478 auto match_default = [&] {
4479 return match(TokenType::Default) && m_state.current_token.original_value() == "default"sv;
4480 };
4481
4482 consume(TokenType::Export);
4483
4484 struct EntryAndLocation {
4485 ExportEntry entry;
4486 Position position;
4487 };
4488
4489 Vector<EntryAndLocation> entries_with_location;
4490
4491 RefPtr<ASTNode const> expression = {};
4492 bool is_default = false;
4493 ModuleRequest from_specifier;
4494
4495 if (match_default()) {
4496 is_default = true;
4497 auto default_position = position();
4498 consume(TokenType::Default);
4499
4500 DeprecatedFlyString local_name;
4501
4502 auto lookahead_token = next_token();
4503
4504 enum class MatchesFunctionDeclaration {
4505 Yes,
4506 No,
4507 WithoutName,
4508 };
4509
4510 // Note: For some reason the spec here has declaration which can have no name
4511 // and the rest of the parser is just not setup for that. With these
4512 // hacks below we get through most things but we should probably figure
4513 // out a better solution. I have attempted to explain why/what these "hacks" do below.
4514 // The summary is treat named declarations just as declarations and hack around unnamed
4515 // declarations with expression see also SourceTextModule::initialize_environment.
4516 // As far as I'm aware the only problem (which is a tricky one) is:
4517 // `export default function() {}()`
4518 // Since we parse this as an expression you are immediately allowed to call it
4519 // which is incorrect and this should give a SyntaxError.
4520
4521 auto has_name = [&](Token const& token) {
4522 if (token.type() != TokenType::ParenOpen)
4523 return MatchesFunctionDeclaration::Yes;
4524
4525 return MatchesFunctionDeclaration::WithoutName;
4526 };
4527
4528 auto match_function_declaration = [&] {
4529 // Hack part 1.
4530 // Match a function declaration with a name, since we have async and generator
4531 // and asyncgenerator variants this is quite complicated.
4532 auto current_type = m_state.current_token.type();
4533 Lexer lookahead_lexer = m_state.lexer;
4534 lookahead_lexer.next();
4535
4536 if (current_type == TokenType::Function) {
4537 if (lookahead_token.type() == TokenType::Asterisk)
4538 return has_name(lookahead_lexer.next()); // function * [name]
4539 else
4540 return has_name(lookahead_token); // function [name]
4541 }
4542
4543 if (current_type == TokenType::Async) {
4544 if (lookahead_token.type() != TokenType::Function)
4545 return MatchesFunctionDeclaration::No;
4546
4547 if (lookahead_token.trivia_contains_line_terminator())
4548 return MatchesFunctionDeclaration::No;
4549
4550 auto lookahead_two_token = lookahead_lexer.next();
4551 if (lookahead_two_token.type() == TokenType::Asterisk)
4552 return has_name(lookahead_lexer.next()); // async function * [name]
4553 else
4554 return has_name(lookahead_two_token); // async function [name]
4555 }
4556
4557 return MatchesFunctionDeclaration::No;
4558 };
4559
4560 if (auto matches_function = match_function_declaration(); matches_function != MatchesFunctionDeclaration::No) {
4561
4562 auto function_declaration = parse_function_node<FunctionDeclaration>(
4563 (matches_function == MatchesFunctionDeclaration::WithoutName ? FunctionNodeParseOptions::HasDefaultExportName : 0)
4564 | FunctionNodeParseOptions::CheckForFunctionAndName);
4565
4566 m_state.current_scope_pusher->add_declaration(function_declaration);
4567 if (matches_function == MatchesFunctionDeclaration::WithoutName)
4568 local_name = ExportStatement::local_name_for_default;
4569 else
4570 local_name = function_declaration->name();
4571
4572 expression = move(function_declaration);
4573 } else if (match(TokenType::Class) && lookahead_token.type() != TokenType::CurlyOpen && lookahead_token.type() != TokenType::Extends) {
4574 // Hack part 2.
4575 // Attempt to detect classes with names only as those are declarations,
4576 // this actually seems to cover all cases already.
4577 auto class_expression = parse_class_declaration();
4578 m_state.current_scope_pusher->add_declaration(class_expression);
4579 local_name = class_expression->name();
4580 expression = move(class_expression);
4581
4582 } else if (match_expression()) {
4583 // Hack part 3.
4584 // Even though the unnamed declarations look like expression we should
4585 // not treat them as such and thus not consume a semicolon after them.
4586
4587 bool special_case_declaration_without_name = match(TokenType::Class) || match(TokenType::Function) || (match(TokenType::Async) && lookahead_token.type() == TokenType::Function && !lookahead_token.trivia_contains_line_terminator());
4588 expression = parse_expression(2);
4589
4590 if (!special_case_declaration_without_name)
4591 consume_or_insert_semicolon();
4592
4593 if (is<ClassExpression>(*expression)) {
4594 auto const& class_expression = static_cast<ClassExpression const&>(*expression);
4595 if (class_expression.has_name())
4596 local_name = class_expression.name();
4597 }
4598 } else {
4599 expected("Declaration or assignment expression");
4600 local_name = "!!invalid!!";
4601 }
4602
4603 if (local_name.is_null()) {
4604 local_name = ExportStatement::local_name_for_default;
4605 }
4606
4607 entries_with_location.append({ ExportEntry::named_export(default_string_value, move(local_name)), default_position });
4608 } else {
4609 enum class FromSpecifier {
4610 NotAllowed,
4611 Optional,
4612 Required
4613 } check_for_from { FromSpecifier::NotAllowed };
4614
4615 auto parse_module_export_name = [&](bool lhs) -> DeprecatedFlyString {
4616 // https://tc39.es/ecma262/#prod-ModuleExportName
4617 // ModuleExportName :
4618 // IdentifierName
4619 // StringLiteral
4620 if (match_identifier_name()) {
4621 return consume().value();
4622 }
4623 if (match(TokenType::StringLiteral)) {
4624 // It is a Syntax Error if ReferencedBindings of NamedExports contains any StringLiterals.
4625 // Only for export { "a" as "b" }; // <-- no from
4626 if (lhs)
4627 check_for_from = FromSpecifier::Required;
4628 return consume_string_value();
4629 }
4630 expected("ExportSpecifier (string or identifier)");
4631 return {};
4632 };
4633
4634 if (match(TokenType::Asterisk)) {
4635 auto asterisk_position = position();
4636 consume(TokenType::Asterisk);
4637
4638 if (match_as()) {
4639 // * as ModuleExportName
4640 consume(TokenType::Identifier);
4641 auto namespace_position = position();
4642 auto exported_name = parse_module_export_name(false);
4643 entries_with_location.append({ ExportEntry::all_module_request(exported_name), namespace_position });
4644 } else {
4645 entries_with_location.append({ ExportEntry::all_but_default_entry(), asterisk_position });
4646 }
4647 check_for_from = FromSpecifier::Required;
4648 } else if (match_declaration()) {
4649 auto decl_position = position();
4650 auto declaration = parse_declaration();
4651 m_state.current_scope_pusher->add_declaration(declaration);
4652 if (is<FunctionDeclaration>(*declaration)) {
4653 auto& func = static_cast<FunctionDeclaration const&>(*declaration);
4654 entries_with_location.append({ ExportEntry::named_export(func.name(), func.name()), func.source_range().start });
4655 } else if (is<ClassDeclaration>(*declaration)) {
4656 auto& class_declaration = static_cast<ClassDeclaration const&>(*declaration);
4657 entries_with_location.append({ ExportEntry::named_export(class_declaration.name(), class_declaration.name()), class_declaration.source_range().start });
4658 } else {
4659 VERIFY(is<VariableDeclaration>(*declaration));
4660 auto& variables = static_cast<VariableDeclaration const&>(*declaration);
4661 VERIFY(variables.is_lexical_declaration());
4662 for (auto& decl : variables.declarations()) {
4663 decl->target().visit(
4664 [&](NonnullRefPtr<Identifier const> const& identifier) {
4665 entries_with_location.append({ ExportEntry::named_export(identifier->string(), identifier->string()), identifier->source_range().start });
4666 },
4667 [&](NonnullRefPtr<BindingPattern const> const& binding) {
4668 // NOTE: Nothing in the callback throws an exception.
4669 MUST(binding->for_each_bound_name([&](auto& name) {
4670 entries_with_location.append({ ExportEntry::named_export(name, name), decl_position });
4671 }));
4672 });
4673 }
4674 }
4675 expression = declaration;
4676 } else if (match(TokenType::Var)) {
4677 auto variable_position = position();
4678 auto variable_declaration = parse_variable_declaration();
4679 m_state.current_scope_pusher->add_declaration(variable_declaration);
4680 for (auto& decl : variable_declaration->declarations()) {
4681 decl->target().visit(
4682 [&](NonnullRefPtr<Identifier const> const& identifier) {
4683 entries_with_location.append({ ExportEntry::named_export(identifier->string(), identifier->string()), identifier->source_range().start });
4684 },
4685 [&](NonnullRefPtr<BindingPattern const> const& binding) {
4686 // NOTE: Nothing in the callback throws an exception.
4687 MUST(binding->for_each_bound_name([&](auto& name) {
4688 entries_with_location.append({ ExportEntry::named_export(name, name), variable_position });
4689 }));
4690 });
4691 }
4692 expression = variable_declaration;
4693 } else if (match(TokenType::CurlyOpen)) {
4694 consume(TokenType::CurlyOpen);
4695 check_for_from = FromSpecifier::Optional;
4696
4697 // FIXME: Even when empty should add module to requiredModules!
4698 while (!done() && !match(TokenType::CurlyClose)) {
4699 auto identifier_position = position();
4700 auto identifier = parse_module_export_name(true);
4701
4702 if (match_as()) {
4703 consume(TokenType::Identifier);
4704 auto export_name = parse_module_export_name(false);
4705
4706 entries_with_location.append({ ExportEntry::named_export(move(export_name), move(identifier)), identifier_position });
4707 } else {
4708 entries_with_location.append({ ExportEntry::named_export(identifier, identifier), identifier_position });
4709 }
4710
4711 if (!match(TokenType::Comma))
4712 break;
4713
4714 consume(TokenType::Comma);
4715 }
4716
4717 if (entries_with_location.is_empty()) {
4718 // export {} from "module"; Since this will never be a
4719 // duplicate we can give a slightly wrong location.
4720 entries_with_location.append({ ExportEntry::empty_named_export(), position() });
4721 }
4722
4723 consume(TokenType::CurlyClose);
4724
4725 } else {
4726 syntax_error("Unexpected token 'export'", rule_start.position());
4727 }
4728
4729 if (check_for_from != FromSpecifier::NotAllowed && match_from()) {
4730 consume(TokenType::Identifier);
4731 from_specifier = parse_module_request();
4732 } else if (check_for_from == FromSpecifier::Required) {
4733 expected("from");
4734 }
4735
4736 if (check_for_from != FromSpecifier::NotAllowed)
4737 consume_or_insert_semicolon();
4738 }
4739
4740 Vector<ExportEntry> entries;
4741 entries.ensure_capacity(entries_with_location.size());
4742
4743 for (auto& entry : entries_with_location) {
4744 for (auto& export_statement : program.exports()) {
4745 if (export_statement->has_export(entry.entry.export_name))
4746 syntax_error(DeprecatedString::formatted("Duplicate export with name: '{}'", entry.entry.export_name), entry.position);
4747 }
4748
4749 for (auto& new_entry : entries) {
4750 if (new_entry.kind != ExportEntry::Kind::EmptyNamedExport && new_entry.export_name == entry.entry.export_name)
4751 syntax_error(DeprecatedString::formatted("Duplicate export with name: '{}'", entry.entry.export_name), entry.position);
4752 }
4753
4754 entries.append(move(entry.entry));
4755 }
4756
4757 return create_ast_node<ExportStatement>({ m_source_code, rule_start.position(), position() }, move(expression), move(entries), is_default, move(from_specifier));
4758}
4759
4760Parser::ForbiddenTokens::ForbiddenTokens(std::initializer_list<TokenType> const& forbidden)
4761{
4762 forbid_tokens(forbidden);
4763}
4764
4765void Parser::ForbiddenTokens::forbid_tokens(std::initializer_list<TokenType> const& forbidden)
4766{
4767 for (auto token : forbidden) {
4768 switch (token) {
4769 case TokenType::In:
4770 m_forbid_in_token = true;
4771 break;
4772 case TokenType::DoubleAmpersand:
4773 case TokenType::DoublePipe:
4774 m_forbid_logical_tokens = true;
4775 break;
4776 case TokenType::DoubleQuestionMark:
4777 m_forbid_coalesce_token = true;
4778 break;
4779 case TokenType::QuestionMarkPeriod:
4780 m_forbid_question_mark_period = true;
4781 break;
4782 case TokenType::ParenOpen:
4783 m_forbid_paren_open = true;
4784 break;
4785 case TokenType::Equals:
4786 m_forbid_equals = true;
4787 break;
4788 default:
4789 VERIFY_NOT_REACHED();
4790 }
4791 }
4792}
4793
4794bool Parser::ForbiddenTokens::allows(TokenType token) const
4795{
4796 switch (token) {
4797 case TokenType::In:
4798 return !m_forbid_in_token;
4799 case TokenType::DoubleAmpersand:
4800 case TokenType::DoublePipe:
4801 return !m_forbid_logical_tokens;
4802 case TokenType::DoubleQuestionMark:
4803 return !m_forbid_coalesce_token;
4804 case TokenType::QuestionMarkPeriod:
4805 return !m_forbid_question_mark_period;
4806 case TokenType::ParenOpen:
4807 return !m_forbid_paren_open;
4808 case TokenType::Equals:
4809 return !m_forbid_equals;
4810 default:
4811 return true;
4812 }
4813}
4814
4815Parser::ForbiddenTokens Parser::ForbiddenTokens::merge(ForbiddenTokens other) const
4816{
4817 ForbiddenTokens result = *this;
4818 result.m_forbid_in_token |= other.m_forbid_in_token;
4819 result.m_forbid_logical_tokens |= other.m_forbid_logical_tokens;
4820 result.m_forbid_coalesce_token |= other.m_forbid_coalesce_token;
4821 result.m_forbid_paren_open |= other.m_forbid_paren_open;
4822 result.m_forbid_question_mark_period |= other.m_forbid_question_mark_period;
4823 result.m_forbid_equals |= other.m_forbid_equals;
4824 return result;
4825}
4826
4827Parser::ForbiddenTokens Parser::ForbiddenTokens::forbid(std::initializer_list<TokenType> const& forbidden) const
4828{
4829 ForbiddenTokens result = *this;
4830 result.forbid_tokens(forbidden);
4831 return result;
4832}
4833
4834template NonnullRefPtr<FunctionExpression> Parser::parse_function_node(u16, Optional<Position> const&);
4835template NonnullRefPtr<FunctionDeclaration> Parser::parse_function_node(u16, Optional<Position> const&);
4836
4837}