PreParsing inner funcs: make scope analysis more complete.
This adds tracking the following: - Declarations created by catch (potentially destructuring) - Declarations created by for-each (potentially destructuring) - Class declarations BUG=v8:5501, v8:5516 Review-Url: https://codereview.chromium.org/2617923003 Cr-Commit-Position: refs/heads/master@{#42129}
This commit is contained in:
parent
9e65ecd957
commit
d17558bc49
@ -1032,11 +1032,14 @@ void Scope::DeclareVariableName(const AstRawString* name, VariableMode mode) {
|
||||
if (mode == VAR && !is_declaration_scope()) {
|
||||
return GetDeclarationScope()->DeclareVariableName(name, mode);
|
||||
}
|
||||
DCHECK(!is_catch_scope());
|
||||
DCHECK(!is_with_scope());
|
||||
DCHECK(!is_eval_scope());
|
||||
DCHECK(is_declaration_scope() ||
|
||||
(IsLexicalVariableMode(mode) && is_block_scope()));
|
||||
// Unlike DeclareVariable, DeclareVariableName allows declaring variables in
|
||||
// catch scopes: Parser::RewriteCatchPattern bypasses DeclareVariable by
|
||||
// calling DeclareLocal directly, and it doesn't make sense to add a similar
|
||||
// bypass mechanism for PreParser.
|
||||
DCHECK(is_declaration_scope() || (IsLexicalVariableMode(mode) &&
|
||||
(is_block_scope() || is_catch_scope())));
|
||||
DCHECK(scope_info_.is_null());
|
||||
|
||||
// Declare the variable in the declaration scope.
|
||||
|
@ -1892,6 +1892,7 @@ void Parser::DesugarBindingInForEachStatement(ForInfo* for_info,
|
||||
Block** body_block,
|
||||
Expression** each_variable,
|
||||
bool* ok) {
|
||||
DCHECK(for_info->parsing_result.declarations.length() == 1);
|
||||
DeclarationParsingResult::Declaration& decl =
|
||||
for_info->parsing_result.declarations[0];
|
||||
Variable* temp = NewTemporary(ast_value_factory()->dot_for_string());
|
||||
|
@ -1049,7 +1049,22 @@ class PreParser : public ParserBase<PreParser> {
|
||||
PreParserStatementList cases, Scope* scope) {
|
||||
return PreParserStatement::Default();
|
||||
}
|
||||
V8_INLINE void RewriteCatchPattern(CatchInfo* catch_info, bool* ok) {}
|
||||
|
||||
V8_INLINE void RewriteCatchPattern(CatchInfo* catch_info, bool* ok) {
|
||||
if (track_unresolved_variables_) {
|
||||
if (catch_info->name.string_ != nullptr) {
|
||||
// Unlike in the parser, we need to declare the catch variable as LET
|
||||
// variable, so that it won't get hoisted out of the scope.
|
||||
catch_info->scope->DeclareVariableName(catch_info->name.string_, LET);
|
||||
}
|
||||
if (catch_info->pattern.variables_ != nullptr) {
|
||||
for (auto variable : *catch_info->pattern.variables_) {
|
||||
scope()->DeclareVariableName(variable->raw_name(), LET);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
V8_INLINE void ValidateCatchBlock(const CatchInfo& catch_info, bool* ok) {}
|
||||
V8_INLINE PreParserStatement RewriteTryStatement(
|
||||
PreParserStatement try_block, PreParserStatement catch_block,
|
||||
@ -1084,6 +1099,12 @@ class PreParser : public ParserBase<PreParser> {
|
||||
DeclareClass(PreParserIdentifier variable_name, PreParserExpression value,
|
||||
ZoneList<const AstRawString*>* names, int class_token_pos,
|
||||
int end_pos, bool* ok) {
|
||||
// Preparser shouldn't be used in contexts where we need to track the names.
|
||||
DCHECK_NULL(names);
|
||||
if (variable_name.string_ != nullptr) {
|
||||
DCHECK(track_unresolved_variables_);
|
||||
scope()->DeclareVariableName(variable_name.string_, LET);
|
||||
}
|
||||
return PreParserStatement::Default();
|
||||
}
|
||||
V8_INLINE void DeclareClassVariable(PreParserIdentifier name,
|
||||
@ -1264,9 +1285,18 @@ class PreParser : public ParserBase<PreParser> {
|
||||
V8_INLINE PreParserStatement RewriteForVarInLegacy(const ForInfo& for_info) {
|
||||
return PreParserStatement::Null();
|
||||
}
|
||||
|
||||
V8_INLINE void DesugarBindingInForEachStatement(
|
||||
ForInfo* for_info, PreParserStatement* body_block,
|
||||
PreParserExpression* each_variable, bool* ok) {}
|
||||
PreParserExpression* each_variable, bool* ok) {
|
||||
if (track_unresolved_variables_) {
|
||||
DCHECK(for_info->parsing_result.declarations.length() == 1);
|
||||
DeclareAndInitializeVariables(
|
||||
PreParserStatement::Default(), &for_info->parsing_result.descriptor,
|
||||
&for_info->parsing_result.declarations[0], nullptr, ok);
|
||||
}
|
||||
}
|
||||
|
||||
V8_INLINE PreParserStatement CreateForEachStatementTDZ(
|
||||
PreParserStatement init_block, const ForInfo& for_info, bool* ok) {
|
||||
return init_block;
|
||||
|
@ -8805,62 +8805,76 @@ TEST(NoPessimisticContextAllocation) {
|
||||
{"function inner() { ({y, x: my_var}) => { }}", false},
|
||||
{"function inner() { ({y, x: my_var} = {y: 0, x: 0}) => my_var;}", false},
|
||||
{"function inner() { ({y, x: my_var} = {y: 0, x: 0}) => { }}", false},
|
||||
{"function inner() { try { } catch (my_var) { my_var; } }", false},
|
||||
{"function inner() { try { } catch ([a, my_var, b]) { my_var; } }",
|
||||
false},
|
||||
{"function inner() { try { } catch ({x: my_var}) { my_var; } }", false},
|
||||
{"function inner() { try { } catch ({y, x: my_var}) { my_var; } }",
|
||||
false},
|
||||
{"function inner() { try { } catch ({my_var}) { my_var; } }", false},
|
||||
{"function inner() { for (let my_var in {}) { my_var; } }", false},
|
||||
{"function inner() { for (let my_var in {}) { } }", false},
|
||||
{"function inner() { for (let my_var of []) { my_var; } }", false},
|
||||
{"function inner() { for (let my_var of []) { } }", false},
|
||||
{"function inner() { for (let [a, my_var, b] in {}) { my_var; } }",
|
||||
false},
|
||||
{"function inner() { for (let [a, my_var, b] of []) { my_var; } }",
|
||||
false},
|
||||
{"function inner() { for (let {x: my_var} in {}) { my_var; } }", false},
|
||||
{"function inner() { for (let {x: my_var} of []) { my_var; } }", false},
|
||||
{"function inner() { for (let {my_var} in {}) { my_var; } }", false},
|
||||
{"function inner() { for (let {my_var} of []) { my_var; } }", false},
|
||||
{"function inner() { for (let {y, x: my_var} in {}) { my_var; } }",
|
||||
false},
|
||||
{"function inner() { for (let {y, x: my_var} of []) { my_var; } }",
|
||||
false},
|
||||
{"function inner() { for (let {a, my_var} in {}) { my_var; } }", false},
|
||||
{"function inner() { for (let {a, my_var} of []) { my_var; } }", false},
|
||||
{"function inner() { for (var my_var in {}) { my_var; } }", false},
|
||||
{"function inner() { for (var my_var in {}) { } }", false},
|
||||
{"function inner() { for (var my_var of []) { my_var; } }", false},
|
||||
{"function inner() { for (var my_var of []) { } }", false},
|
||||
{"function inner() { for (var [a, my_var, b] in {}) { my_var; } }",
|
||||
false},
|
||||
{"function inner() { for (var [a, my_var, b] of []) { my_var; } }",
|
||||
false},
|
||||
{"function inner() { for (var {x: my_var} in {}) { my_var; } }", false},
|
||||
{"function inner() { for (var {x: my_var} of []) { my_var; } }", false},
|
||||
{"function inner() { for (var {my_var} in {}) { my_var; } }", false},
|
||||
{"function inner() { for (var {my_var} of []) { my_var; } }", false},
|
||||
{"function inner() { for (var {y, x: my_var} in {}) { my_var; } }",
|
||||
false},
|
||||
{"function inner() { for (var {y, x: my_var} of []) { my_var; } }",
|
||||
false},
|
||||
{"function inner() { for (var {a, my_var} in {}) { my_var; } }", false},
|
||||
{"function inner() { for (var {a, my_var} of []) { my_var; } }", false},
|
||||
{"function inner() { for (var my_var in {}) { } my_var; }", false},
|
||||
{"function inner() { for (var my_var of []) { } my_var; }", false},
|
||||
{"function inner() { for (var [a, my_var, b] in {}) { } my_var; }",
|
||||
false},
|
||||
{"function inner() { for (var [a, my_var, b] of []) { } my_var; }",
|
||||
false},
|
||||
{"function inner() { for (var {x: my_var} in {}) { } my_var; }", false},
|
||||
{"function inner() { for (var {x: my_var} of []) { } my_var; }", false},
|
||||
{"function inner() { for (var {my_var} in {}) { } my_var; }", false},
|
||||
{"function inner() { for (var {my_var} of []) { } my_var; }", false},
|
||||
{"function inner() { for (var {y, x: my_var} in {}) { } my_var; }",
|
||||
false},
|
||||
{"function inner() { for (var {y, x: my_var} of []) { } my_var; }",
|
||||
false},
|
||||
{"function inner() { for (var {a, my_var} in {}) { } my_var; }", false},
|
||||
{"function inner() { for (var {a, my_var} of []) { } my_var; }", false},
|
||||
{"function inner() { class my_var {}; my_var }", false},
|
||||
// In the following cases we still context allocate pessimistically:
|
||||
{"function inner() { function my_var() {} my_var; }", true},
|
||||
{"function inner() { if (true) { function my_var() {} } my_var; }",
|
||||
true},
|
||||
{"function inner() { try { } catch (my_var) { my_var; } }", true},
|
||||
{"function inner() { try { } catch ([a, my_var, b]) { my_var; } }", true},
|
||||
{"function inner() { try { } catch ({x: my_var}) { my_var; } }", true},
|
||||
{"function inner() { try { } catch ({y, x: my_var}) { my_var; } }", true},
|
||||
{"function inner() { try { } catch ({my_var}) { my_var; } }", true},
|
||||
{"function inner() { for (let my_var = 0; my_var < 1; ++my_var) { my_var "
|
||||
"} }",
|
||||
true},
|
||||
{"function inner() { for (let a = 0, my_var = 0; my_var < 1; ++my_var) { "
|
||||
"my_var } }",
|
||||
true},
|
||||
{"function inner() { for (let my_var in {}) { my_var; } }", true},
|
||||
{"function inner() { for (let my_var in {}) { } }", true},
|
||||
{"function inner() { for (let my_var of []) { my_var; } }", true},
|
||||
{"function inner() { for (let my_var of []) { } }", true},
|
||||
{"function inner() { for (let [a, my_var, b] in {}) { my_var; } }", true},
|
||||
{"function inner() { for (let [a, my_var, b] of []) { my_var; } }", true},
|
||||
{"function inner() { for (let {x: my_var} in {}) { my_var; } }", true},
|
||||
{"function inner() { for (let {x: my_var} of []) { my_var; } }", true},
|
||||
{"function inner() { for (let {my_var} in {}) { my_var; } }", true},
|
||||
{"function inner() { for (let {my_var} of []) { my_var; } }", true},
|
||||
{"function inner() { for (let {y, x: my_var} in {}) { my_var; } }", true},
|
||||
{"function inner() { for (let {y, x: my_var} of []) { my_var; } }", true},
|
||||
{"function inner() { for (let {a, my_var} in {}) { my_var; } }", true},
|
||||
{"function inner() { for (let {a, my_var} of []) { my_var; } }", true},
|
||||
{"function inner() { for (var my_var in {}) { my_var; } }", true},
|
||||
{"function inner() { for (var my_var in {}) { } }", true},
|
||||
{"function inner() { for (var my_var of []) { my_var; } }", true},
|
||||
{"function inner() { for (var my_var of []) { } }", true},
|
||||
{"function inner() { for (var [a, my_var, b] in {}) { my_var; } }", true},
|
||||
{"function inner() { for (var [a, my_var, b] of []) { my_var; } }", true},
|
||||
{"function inner() { for (var {x: my_var} in {}) { my_var; } }", true},
|
||||
{"function inner() { for (var {x: my_var} of []) { my_var; } }", true},
|
||||
{"function inner() { for (var {my_var} in {}) { my_var; } }", true},
|
||||
{"function inner() { for (var {my_var} of []) { my_var; } }", true},
|
||||
{"function inner() { for (var {y, x: my_var} in {}) { my_var; } }", true},
|
||||
{"function inner() { for (var {y, x: my_var} of []) { my_var; } }", true},
|
||||
{"function inner() { for (var {a, my_var} in {}) { my_var; } }", true},
|
||||
{"function inner() { for (var {a, my_var} of []) { my_var; } }", true},
|
||||
{"function inner() { for (var my_var in {}) { } my_var; }", true},
|
||||
{"function inner() { for (var my_var of []) { } my_var; }", true},
|
||||
{"function inner() { for (var [a, my_var, b] in {}) { } my_var; }", true},
|
||||
{"function inner() { for (var [a, my_var, b] of []) { } my_var; }", true},
|
||||
{"function inner() { for (var {x: my_var} in {}) { } my_var; }", true},
|
||||
{"function inner() { for (var {x: my_var} of []) { } my_var; }", true},
|
||||
{"function inner() { for (var {my_var} in {}) { } my_var; }", true},
|
||||
{"function inner() { for (var {my_var} of []) { } my_var; }", true},
|
||||
{"function inner() { for (var {y, x: my_var} in {}) { } my_var; }", true},
|
||||
{"function inner() { for (var {y, x: my_var} of []) { } my_var; }", true},
|
||||
{"function inner() { for (var {a, my_var} in {}) { } my_var; }", true},
|
||||
{"function inner() { for (var {a, my_var} of []) { } my_var; }", true},
|
||||
{"function inner() { class my_var {}; my_var }", true},
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < arraysize(inners); ++i) {
|
||||
|
Loading…
Reference in New Issue
Block a user