Commit a450d3ae authored by neis's avatar neis Committed by Commit bot

[parsing] Fix maybe-assigned for top-level class declarations.

Move the logic into Scope::DeclareVariable to be more robust.

BUG=v8:5636

Review-Url: https://codereview.chromium.org/2685293003
Cr-Commit-Position: refs/heads/master@{#43098}
parent fc1af41d
......@@ -1009,6 +1009,17 @@ Variable* Scope::DeclareVariable(
const AstRawString* name = proxy->raw_name();
bool is_function_declaration = declaration->IsFunctionDeclaration();
// Pessimistically assume that top-level variables will be assigned.
//
// Top-level variables in a script can be accessed by other scripts or even
// become global properties. While this does not apply to top-level variables
// in a module (assuming they are not exported), we must still mark these as
// assigned because they might be accessed by a lazily parsed top-level
// function, which, for efficiency, we preparse without variable tracking.
if (is_script_scope() || is_module_scope()) {
if (mode != CONST) proxy->set_is_assigned();
}
Variable* var = nullptr;
if (is_eval_scope() && is_sloppy(language_mode()) && mode == VAR) {
// In a var binding in a sloppy direct eval, pollute the enclosing scope
......@@ -1152,6 +1163,7 @@ Variable* DeclarationScope::DeclareDynamicGlobal(const AstRawString* name,
VariableKind kind) {
DCHECK(is_script_scope());
return variables_.Declare(zone(), this, name, DYNAMIC_GLOBAL, kind);
// TODO(neis): Mark variable as maybe-assigned?
}
......
......@@ -1487,8 +1487,6 @@ Statement* Parser::DeclareFunction(const AstRawString* variable_name,
VariableProxy* proxy =
factory()->NewVariableProxy(variable_name, NORMAL_VARIABLE);
MarkTopLevelVariableAsAssigned(scope(), proxy);
Declaration* declaration =
factory()->NewFunctionDeclaration(proxy, function, scope(), pos);
Declare(declaration, DeclarationDescriptor::NORMAL, mode, kCreatedInitialized,
......
......@@ -824,20 +824,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
}
}
// Pessimistically assume that top-level variables will be assigned.
//
// Top-level variables in a script can be accessed by other scripts or even
// become global properties. While this does not apply to top-level variables
// in a module (assuming they are not exported), we must still mark these as
// assigned because they might be accessed by a lazily parsed top-level
// function, which, for efficiency, we preparse without variable tracking.
V8_INLINE static void MarkTopLevelVariableAsAssigned(Scope* scope,
VariableProxy* proxy) {
if (scope->is_script_scope() || scope->is_module_scope()) {
proxy->set_is_assigned();
}
}
// Returns true if we have a binary expression between two numeric
// literals. In that case, *x will be changed to an expression which is the
// computed value.
......
......@@ -171,12 +171,10 @@ void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
names_->Add(name, zone());
}
Scope* var_init_scope = descriptor_->scope;
MarkTopLevelVariableAsAssigned(var_init_scope, proxy);
// If there's no initializer, we're done.
if (value == nullptr) return;
Scope* var_init_scope = descriptor_->scope;
MarkLoopVariableAsAssigned(var_init_scope, proxy->var());
// A declaration of the form:
......
......@@ -3853,12 +3853,21 @@ TEST(MaybeAssignedTopLevel) {
i::Factory* factory = isolate->factory();
const char* prefixes[] = {
"let foo; ", "let foo = 0; ",
"let [foo] = [1]; ", "let {foo} = {foo: 2}; ",
"let {foo=3} = {}; ", "function foo() {}; ",
"var foo; ", "var foo = 0; ",
"var [foo] = [1]; ", "var {foo} = {foo: 2}; ",
"var {foo=3} = {}; ", "function* foo() {}; ",
"let foo; ",
"let foo = 0; ",
"let [foo] = [1]; ",
"let {foo} = {foo: 2}; ",
"let {foo=3} = {}; ",
"var foo; ",
"var foo = 0; ",
"var [foo] = [1]; ",
"var {foo} = {foo: 2}; ",
"var {foo=3} = {}; ",
"function foo() {}; ",
"function* foo() {}; ",
"async function foo() {}; ",
"class foo {}; ",
"class foo extends null {}; ",
};
const char* sources[] = {
"function bar() {foo = 42}; ext(bar); ext(foo)",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment