classifier->RecordExpressionError(scanner()->location(),
"strong_arguments");
}
+ if (this->IsArguments(name)) scope_->RecordArgumentsUsage();
return name;
} else if (is_sloppy(language_mode()) &&
(next == Token::FUTURE_STRICT_RESERVED_WORD ||
}
IdentifierT name = this->GetSymbol(scanner());
+ if (this->IsArguments(name)) scope_->RecordArgumentsUsage();
return name;
}
}
IdentifierT name = this->GetSymbol(scanner());
+ if (this->IsArguments(name)) scope_->RecordArgumentsUsage();
return name;
}
scope_inside_with_ = false;
scope_contains_with_ = false;
scope_calls_eval_ = false;
+ scope_uses_arguments_ = false;
scope_uses_super_property_ = false;
asm_module_ = false;
asm_function_ = outer_scope != NULL && outer_scope->asm_module_;
language_mode_ = outer_scope != NULL ? outer_scope->language_mode_ : SLOPPY;
outer_scope_calls_sloppy_eval_ = false;
inner_scope_calls_eval_ = false;
+ inner_scope_uses_arguments_ = false;
inner_scope_uses_super_property_ = false;
force_eager_compilation_ = false;
force_context_allocation_ = (outer_scope != NULL && !is_function_scope())
}
// Propagate usage flags to outer scope.
+ if (uses_arguments()) outer_scope_->RecordArgumentsUsage();
if (uses_super_property()) outer_scope_->RecordSuperPropertyUsage();
if (scope_calls_eval_) outer_scope_->RecordEvalCall();
if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");
if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n");
if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
+ if (scope_uses_arguments_) Indent(n1, "// scope uses 'arguments'\n");
if (scope_uses_super_property_)
Indent(n1, "// scope uses 'super' property\n");
+ if (inner_scope_uses_arguments_) {
+ Indent(n1, "// inner scope uses 'arguments'\n");
+ }
if (inner_scope_uses_super_property_)
Indent(n1, "// inner scope uses 'super' property\n");
if (outer_scope_calls_sloppy_eval_) {
// usage of arguments/super/this, but do not propagate them out from normal
// functions.
if (!inner->is_function_scope() || inner->is_arrow_scope()) {
+ if (inner->scope_uses_arguments_ || inner->inner_scope_uses_arguments_) {
+ inner_scope_uses_arguments_ = true;
+ }
if (inner->scope_uses_super_property_ ||
inner->inner_scope_uses_super_property_) {
inner_scope_uses_super_property_ = true;
// Inform the scope that the corresponding code contains an eval call.
void RecordEvalCall() { if (!is_script_scope()) scope_calls_eval_ = true; }
+ // Inform the scope that the corresponding code uses "arguments".
+ void RecordArgumentsUsage() { scope_uses_arguments_ = true; }
+
// Inform the scope that the corresponding code uses "super".
void RecordSuperPropertyUsage() { scope_uses_super_property_ = true; }
// Does this scope contain a with statement.
bool contains_with() const { return scope_contains_with_; }
+ // Does this scope access "arguments".
+ bool uses_arguments() const { return scope_uses_arguments_; }
+ // Does any inner scope access "arguments".
+ bool inner_uses_arguments() const { return inner_scope_uses_arguments_; }
// Does this scope access "super" property (super.foo).
bool uses_super_property() const { return scope_uses_super_property_; }
// Does any inner scope access "super" property.
// This scope or a nested catch scope or with scope contain an 'eval' call. At
// the 'eval' call site this scope is the declaration scope.
bool scope_calls_eval_;
+ // This scope uses "arguments".
+ bool scope_uses_arguments_;
// This scope uses "super" property ('super.foo').
bool scope_uses_super_property_;
// This scope contains an "use asm" annotation.
// Computed via PropagateScopeInfo.
bool outer_scope_calls_sloppy_eval_;
bool inner_scope_calls_eval_;
+ bool inner_scope_uses_arguments_;
bool inner_scope_uses_super_property_;
bool force_eager_compilation_;
bool force_context_allocation_;
ARGUMENTS = 1,
SUPER_PROPERTY = 1 << 1,
THIS = 1 << 2,
+ INNER_ARGUMENTS = 1 << 3,
INNER_SUPER_PROPERTY = 1 << 4,
};
{"return { m(x) { return () => super.m() } }", NONE},
// Flags must be correctly set when using block scoping.
{"\"use strict\"; while (true) { let x; this, arguments; }",
- ARGUMENTS | THIS},
+ INNER_ARGUMENTS | THIS},
{"\"use strict\"; while (true) { let x; this, super.f(), arguments; }",
- ARGUMENTS | INNER_SUPER_PROPERTY | THIS},
+ INNER_ARGUMENTS | INNER_SUPER_PROPERTY | THIS},
{"\"use strict\"; if (foo()) { let x; this.f() }", THIS},
{"\"use strict\"; if (foo()) { let x; super.f() }",
INNER_SUPER_PROPERTY},
CHECK_EQ(1, scope->inner_scopes()->length());
scope = scope->inner_scopes()->at(0);
}
- // Arguments usage in an arrow function doesn't cause local allocation of
- // an arguments object.
- CHECK_EQ((source_data[i].expected & ARGUMENTS) != 0 && j != 1,
- scope->arguments() != nullptr);
+ CHECK_EQ((source_data[i].expected & ARGUMENTS) != 0,
+ scope->uses_arguments());
CHECK_EQ((source_data[i].expected & SUPER_PROPERTY) != 0,
scope->uses_super_property());
if ((source_data[i].expected & THIS) != 0) {
// script scope are marked as used.
CHECK(scope->LookupThis()->is_used());
}
+ CHECK_EQ((source_data[i].expected & INNER_ARGUMENTS) != 0,
+ scope->inner_uses_arguments());
CHECK_EQ((source_data[i].expected & INNER_SUPER_PROPERTY) != 0,
scope->inner_uses_super_property());
}