@@ -230,7 +230,8 @@ void linter::visit_enter_function_scope() { this->scopes_.push(); }
230
230
void linter::visit_enter_function_scope_body () {
231
231
this ->propagate_variable_uses_to_parent_scope (
232
232
/* allow_variable_use_before_declaration=*/ true ,
233
- /* consume_arguments=*/ true );
233
+ /* consume_arguments=*/ true ,
234
+ /* propagate_eval_use=*/ true );
234
235
}
235
236
236
237
void linter::visit_enter_named_function_scope (identifier function_name) {
@@ -244,7 +245,8 @@ void linter::visit_exit_block_scope() {
244
245
QLJS_ASSERT (!this ->scopes_ .empty ());
245
246
this ->propagate_variable_uses_to_parent_scope (
246
247
/* allow_variable_use_before_declaration=*/ false ,
247
- /* consume_arguments=*/ false );
248
+ /* consume_arguments=*/ false ,
249
+ /* propagate_eval_use=*/ true );
248
250
this ->propagate_variable_declarations_to_parent_scope ();
249
251
this ->scopes_ .pop ();
250
252
}
@@ -260,7 +262,8 @@ void linter::visit_exit_class_scope() {
260
262
QLJS_ASSERT (!this ->scopes_ .empty ());
261
263
this ->propagate_variable_uses_to_parent_scope (
262
264
/* allow_variable_use_before_declaration=*/ false ,
263
- /* consume_arguments=*/ false );
265
+ /* consume_arguments=*/ false ,
266
+ /* propagate_eval_use=*/ false );
264
267
265
268
// No variable declarations should be propagatable to the parent scope.
266
269
for (const declared_variable &var :
@@ -275,7 +278,8 @@ void linter::visit_exit_for_scope() {
275
278
QLJS_ASSERT (!this ->scopes_ .empty ());
276
279
this ->propagate_variable_uses_to_parent_scope (
277
280
/* allow_variable_use_before_declaration=*/ false ,
278
- /* consume_arguments=*/ false );
281
+ /* consume_arguments=*/ false ,
282
+ /* propagate_eval_use=*/ true );
279
283
this ->propagate_variable_declarations_to_parent_scope ();
280
284
this ->scopes_ .pop ();
281
285
}
@@ -284,7 +288,8 @@ void linter::visit_exit_function_scope() {
284
288
QLJS_ASSERT (!this ->scopes_ .empty ());
285
289
this ->propagate_variable_uses_to_parent_scope (
286
290
/* allow_variable_use_before_declaration=*/ true ,
287
- /* consume_arguments=*/ true );
291
+ /* consume_arguments=*/ true ,
292
+ /* propagate_eval_use=*/ false );
288
293
this ->scopes_ .pop ();
289
294
}
290
295
@@ -416,7 +421,8 @@ void linter::visit_end_of_module() {
416
421
this ->propagate_variable_uses_to_parent_scope (
417
422
/* parent_scope=*/ global_scope,
418
423
/* allow_variable_use_before_declaration=*/ false ,
419
- /* consume_arguments=*/ false );
424
+ /* consume_arguments=*/ false ,
425
+ /* propagate_eval_use=*/ false );
420
426
421
427
std::vector<identifier> typeof_variables;
422
428
for (const used_variable &used_var : global_scope.variables_used ) {
@@ -480,18 +486,21 @@ void linter::visit_end_of_module() {
480
486
}
481
487
482
488
void linter::propagate_variable_uses_to_parent_scope (
483
- bool allow_variable_use_before_declaration, bool consume_arguments) {
489
+ bool allow_variable_use_before_declaration, bool consume_arguments,
490
+ bool propagate_eval_use) {
484
491
this ->propagate_variable_uses_to_parent_scope (
485
492
/* parent_scope=*/ this ->parent_scope (),
486
493
/* allow_variable_use_before_declaration=*/
487
494
allow_variable_use_before_declaration,
488
- /* consume_arguments=*/ consume_arguments);
495
+ /* consume_arguments=*/
496
+ consume_arguments,
497
+ /* propagate_eval_use=*/ propagate_eval_use);
489
498
}
490
499
491
500
template <class Scope >
492
501
void linter::propagate_variable_uses_to_parent_scope (
493
502
Scope &parent_scope, bool allow_variable_use_before_declaration,
494
- bool consume_arguments) {
503
+ bool consume_arguments, bool propagate_eval_use ) {
495
504
scope ¤t_scope = this ->current_scope ();
496
505
497
506
auto is_current_scope_function_name = [&](const used_variable &var) {
@@ -500,44 +509,67 @@ void linter::propagate_variable_uses_to_parent_scope(
500
509
var.name .normalized_name ();
501
510
};
502
511
503
- for (const used_variable &used_var : current_scope.variables_used ) {
504
- QLJS_ASSERT (!current_scope.declared_variables .find (used_var.name ));
505
- const declared_variable *var =
506
- parent_scope.declared_variables .find (used_var.name );
507
- if (var) {
508
- // This variable was declared in the parent scope. Don't propagate.
509
- if (used_var.kind == used_variable_kind::assignment) {
510
- this ->report_error_if_assignment_is_illegal (
511
- var, used_var.name , /* is_assigned_before_declaration=*/ false );
512
+ auto has_eval = [&](const std::vector<used_variable> &variables_used) {
513
+ for (const used_variable &used_var : variables_used) {
514
+ if (used_var.name .normalized_name () == u8" eval" ) {
515
+ if (propagate_eval_use) {
516
+ (allow_variable_use_before_declaration
517
+ ? parent_scope.variables_used_in_descendant_scope
518
+ : parent_scope.variables_used )
519
+ .emplace_back (used_var);
520
+ }
521
+ return true ;
522
+ }
523
+ }
524
+ return false ;
525
+ };
526
+
527
+ bool has_eval_in_current_scope = has_eval (current_scope.variables_used );
528
+ if (!has_eval_in_current_scope) {
529
+ for (const used_variable &used_var : current_scope.variables_used ) {
530
+ QLJS_ASSERT (!current_scope.declared_variables .find (used_var.name ));
531
+ const declared_variable *var =
532
+ parent_scope.declared_variables .find (used_var.name );
533
+ if (var) {
534
+ // This variable was declared in the parent scope. Don't propagate.
535
+ if (used_var.kind == used_variable_kind::assignment) {
536
+ this ->report_error_if_assignment_is_illegal (
537
+ var, used_var.name , /* is_assigned_before_declaration=*/ false );
538
+ }
539
+ } else if (consume_arguments &&
540
+ used_var.name .normalized_name () == u8" arguments" ) {
541
+ // Treat this variable as declared in the current scope.
542
+ } else if (is_current_scope_function_name (used_var)) {
543
+ // Treat this variable as declared in the current scope.
544
+ } else {
545
+ (allow_variable_use_before_declaration
546
+ ? parent_scope.variables_used_in_descendant_scope
547
+ : parent_scope.variables_used )
548
+ .emplace_back (used_var);
512
549
}
513
- } else if (consume_arguments &&
514
- used_var.name .normalized_name () == u8" arguments" ) {
515
- // Treat this variable as declared in the current scope.
516
- } else if (is_current_scope_function_name (used_var)) {
517
- // Treat this variable as declared in the current scope.
518
- } else {
519
- (allow_variable_use_before_declaration
520
- ? parent_scope.variables_used_in_descendant_scope
521
- : parent_scope.variables_used )
522
- .emplace_back (used_var);
523
550
}
524
551
}
525
552
current_scope.variables_used .clear ();
526
553
527
- for (const used_variable &used_var :
528
- current_scope.variables_used_in_descendant_scope ) {
529
- const declared_variable *var =
530
- parent_scope.declared_variables .find (used_var.name );
531
- if (var) {
532
- // This variable was declared in the parent scope. Don't propagate.
533
- if (used_var.kind == used_variable_kind::assignment) {
534
- this ->report_error_if_assignment_is_illegal (
535
- var, used_var.name , /* is_assigned_before_declaration=*/ false );
554
+ bool has_eval_in_descendant_scope =
555
+ has_eval_in_current_scope ||
556
+ has_eval (current_scope.variables_used_in_descendant_scope );
557
+ if (!has_eval_in_descendant_scope) {
558
+ for (const used_variable &used_var :
559
+ current_scope.variables_used_in_descendant_scope ) {
560
+ const declared_variable *var =
561
+ parent_scope.declared_variables .find (used_var.name );
562
+ if (var) {
563
+ // This variable was declared in the parent scope. Don't propagate.
564
+ if (used_var.kind == used_variable_kind::assignment) {
565
+ this ->report_error_if_assignment_is_illegal (
566
+ var, used_var.name , /* is_assigned_before_declaration=*/ false );
567
+ }
568
+ } else if (is_current_scope_function_name (used_var)) {
569
+ // Treat this variable as declared in the current scope.
570
+ } else {
571
+ parent_scope.variables_used_in_descendant_scope .emplace_back (used_var);
536
572
}
537
- } else if (is_current_scope_function_name (used_var)) {
538
- // Treat this variable as declared in the current scope.
539
- } else {
540
- parent_scope.variables_used_in_descendant_scope .emplace_back (used_var);
541
573
}
542
574
}
543
575
current_scope.variables_used_in_descendant_scope .clear ();
0 commit comments