@@ -31,19 +31,18 @@ class ScopePusher {
31
31
enum Type {
32
32
Var = 1 ,
33
33
Let = 2 ,
34
- Function = 3 ,
35
34
};
36
35
37
- ScopePusher (Parser& parser, unsigned mask)
36
+ ScopePusher (Parser& parser, unsigned mask, Parser::Scope::Type scope_type )
38
37
: m_parser(parser)
39
38
, m_mask(mask)
40
39
{
41
40
if (m_mask & Var)
42
41
m_parser.m_state .var_scopes .append (NonnullRefPtrVector<VariableDeclaration>());
43
42
if (m_mask & Let)
44
43
m_parser.m_state .let_scopes .append (NonnullRefPtrVector<VariableDeclaration>());
45
- if (m_mask & Function)
46
- m_parser.m_state .function_scopes . append (NonnullRefPtrVector<FunctionDeclaration>() );
44
+
45
+ m_parser.m_state .current_scope = create<Parser::Scope>(scope_type, m_parser. m_state . current_scope );
47
46
}
48
47
49
48
~ScopePusher ()
@@ -52,8 +51,20 @@ class ScopePusher {
52
51
m_parser.m_state .var_scopes .take_last ();
53
52
if (m_mask & Let)
54
53
m_parser.m_state .let_scopes .take_last ();
55
- if (m_mask & Function)
56
- m_parser.m_state .function_scopes .take_last ();
54
+
55
+ auto & popped = m_parser.m_state .current_scope ;
56
+ m_parser.m_state .current_scope = popped->parent ;
57
+ }
58
+
59
+ void add_to_scope_node (NonnullRefPtr<ScopeNode> scope_node)
60
+ {
61
+ if (m_mask & Var)
62
+ scope_node->add_variables (m_parser.m_state .var_scopes .last ());
63
+ if (m_mask & Let)
64
+ scope_node->add_variables (m_parser.m_state .let_scopes .last ());
65
+
66
+ scope_node->add_functions (m_parser.m_state .current_scope ->function_declarations );
67
+ scope_node->add_hoisted_functions (m_parser.m_state .current_scope ->hoisted_function_declarations );
57
68
}
58
69
59
70
Parser& m_parser;
@@ -180,6 +191,24 @@ Parser::ParserState::ParserState(Lexer l)
180
191
{
181
192
}
182
193
194
+ Parser::Scope::Scope (Parser::Scope::Type type, RefPtr<Parser::Scope> parent_scope)
195
+ : type(type)
196
+ , parent(move(parent_scope))
197
+ {
198
+ }
199
+
200
+ RefPtr<Parser::Scope> Parser::Scope::get_current_function_scope ()
201
+ {
202
+ if (this ->type == Parser::Scope::Function) {
203
+ return *this ;
204
+ }
205
+ auto result = this ->parent ;
206
+ while (result->type != Parser::Scope::Function) {
207
+ result = result->parent ;
208
+ }
209
+ return result;
210
+ }
211
+
183
212
Parser::Parser (Lexer lexer)
184
213
: m_state(move(lexer))
185
214
{
@@ -229,7 +258,7 @@ Associativity Parser::operator_associativity(TokenType type) const
229
258
NonnullRefPtr<Program> Parser::parse_program (bool starts_in_strict_mode)
230
259
{
231
260
auto rule_start = push_start ();
232
- ScopePusher scope (*this , ScopePusher::Var | ScopePusher::Let | ScopePusher ::Function);
261
+ ScopePusher scope (*this , ScopePusher::Var | ScopePusher::Let, Scope ::Function);
233
262
auto program = adopt_ref (*new Program ({ m_filename, rule_start.position (), position () }));
234
263
if (starts_in_strict_mode) {
235
264
program->set_strict_mode ();
@@ -258,9 +287,7 @@ NonnullRefPtr<Program> Parser::parse_program(bool starts_in_strict_mode)
258
287
first = false ;
259
288
}
260
289
if (m_state.var_scopes .size () == 1 ) {
261
- program->add_variables (m_state.var_scopes .last ());
262
- program->add_variables (m_state.let_scopes .last ());
263
- program->add_functions (m_state.function_scopes .last ());
290
+ scope.add_to_scope_node (program);
264
291
} else {
265
292
syntax_error (" Unclosed lexical_environment" );
266
293
}
@@ -276,7 +303,8 @@ NonnullRefPtr<Declaration> Parser::parse_declaration()
276
303
return parse_class_declaration ();
277
304
case TokenType::Function: {
278
305
auto declaration = parse_function_node<FunctionDeclaration>();
279
- m_state.function_scopes .last ().append (declaration);
306
+ m_state.current_scope ->function_declarations .append (declaration);
307
+ m_state.current_scope ->get_current_function_scope ()->hoisted_function_declarations .append (declaration);
280
308
return declaration;
281
309
}
282
310
case TokenType::Let:
@@ -399,7 +427,10 @@ RefPtr<FunctionExpression> Parser::try_parse_arrow_function_expression(bool expe
399
427
TemporaryChange change (m_state.in_arrow_function_context , true );
400
428
if (match (TokenType::CurlyOpen)) {
401
429
// Parse a function body with statements
402
- return parse_block_statement (is_strict);
430
+ ScopePusher scope (*this , ScopePusher::Var, Scope::Function);
431
+ auto body = parse_block_statement (is_strict);
432
+ scope.add_to_scope_node (body);
433
+ return body;
403
434
}
404
435
if (match_expression ()) {
405
436
// Parse a function body which returns a single expression
@@ -1372,7 +1403,7 @@ NonnullRefPtr<BlockStatement> Parser::parse_block_statement()
1372
1403
NonnullRefPtr<BlockStatement> Parser::parse_block_statement (bool & is_strict)
1373
1404
{
1374
1405
auto rule_start = push_start ();
1375
- ScopePusher scope (*this , ScopePusher::Let);
1406
+ ScopePusher scope (*this , ScopePusher::Let, Parser::Scope::Block );
1376
1407
auto block = create_ast_node<BlockStatement>({ m_state.current_token .filename (), rule_start.position (), position () });
1377
1408
consume (TokenType::CurlyOpen);
1378
1409
@@ -1404,8 +1435,7 @@ NonnullRefPtr<BlockStatement> Parser::parse_block_statement(bool& is_strict)
1404
1435
m_state.strict_mode = initial_strict_mode_state;
1405
1436
m_state.string_legacy_octal_escape_sequence_in_scope = false ;
1406
1437
consume (TokenType::CurlyClose);
1407
- block->add_variables (m_state.let_scopes .last ());
1408
- block->add_functions (m_state.function_scopes .last ());
1438
+ scope.add_to_scope_node (block);
1409
1439
return block;
1410
1440
}
1411
1441
@@ -1418,7 +1448,7 @@ NonnullRefPtr<FunctionNodeType> Parser::parse_function_node(u8 parse_options)
1418
1448
TemporaryChange super_property_access_rollback (m_state.allow_super_property_lookup , !!(parse_options & FunctionNodeParseOptions::AllowSuperPropertyLookup));
1419
1449
TemporaryChange super_constructor_call_rollback (m_state.allow_super_constructor_call , !!(parse_options & FunctionNodeParseOptions::AllowSuperConstructorCall));
1420
1450
1421
- ScopePusher scope (*this , ScopePusher::Var | ScopePusher ::Function);
1451
+ ScopePusher scope (*this , ScopePusher::Var, Parser::Scope ::Function);
1422
1452
1423
1453
constexpr auto is_function_expression = IsSame<FunctionNodeType, FunctionExpression>;
1424
1454
auto is_generator = (parse_options & FunctionNodeParseOptions::IsGeneratorFunction) != 0 ;
@@ -1460,8 +1490,8 @@ NonnullRefPtr<FunctionNodeType> Parser::parse_function_node(u8 parse_options)
1460
1490
1461
1491
m_state.function_parameters .take_last ();
1462
1492
1463
- body-> add_variables (m_state. var_scopes . last () );
1464
- body-> add_functions (m_state. function_scopes . last ());
1493
+ scope. add_to_scope_node (body );
1494
+
1465
1495
return create_ast_node<FunctionNodeType>(
1466
1496
{ m_state.current_token .filename (), rule_start.position (), position () },
1467
1497
name, move (body), move (parameters), function_length,
@@ -1962,10 +1992,10 @@ NonnullRefPtr<IfStatement> Parser::parse_if_statement()
1962
1992
// Code matching this production is processed as if each matching occurrence of
1963
1993
// FunctionDeclaration[?Yield, ?Await, ~Default] was the sole StatementListItem
1964
1994
// of a BlockStatement occupying that position in the source code.
1965
- ScopePusher scope (*this , ScopePusher::Let);
1995
+ ScopePusher scope (*this , ScopePusher::Let, Parser::Scope::Block );
1966
1996
auto block = create_ast_node<BlockStatement>({ m_state.current_token .filename (), rule_start.position (), position () });
1967
1997
block->append (parse_declaration ());
1968
- block-> add_functions (m_state. function_scopes . last () );
1998
+ scope. add_to_scope_node (block );
1969
1999
return block;
1970
2000
};
1971
2001
0 commit comments