[parser] Push variables of non-arrow parenthesized expression to parent
Parenthesized variable names are valid references for assignment. To make sure we can properly mark the variable as assigned, we should push parenthesized variables to the outer expression scope after the parenthesized expression is guaranteed to not be an arrow head; so that the variable list of the parent is complete. Technically we could probably get by with simply pushing a single variable, since more complex expressions aren't valid parenthesized assignment targets: (a) = ... and [(a),(b)] = ... are valid, but ([a,b]) = ... isn't. It doesn't really seem worth it though. Bug: chromium:1015372 Change-Id: I095c35126742a14d0171537b9795f7258c33ab4d Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1872389 Commit-Queue: Toon Verwaest <verwaest@chromium.org> Reviewed-by: Dan Elphick <delphick@chromium.org> Cr-Commit-Position: refs/heads/master@{#64455}
This commit is contained in:
parent
1deefe5edd
commit
7ff8299231
@ -66,6 +66,24 @@ class ExpressionScope {
|
||||
return result;
|
||||
}
|
||||
|
||||
void MergeVariableList(
|
||||
ScopedList<std::pair<VariableProxy*, int>>* variable_list) {
|
||||
if (!CanBeExpression()) return;
|
||||
// Merged variables come from a CanBeDeclaration expression scope, and
|
||||
// weren't added as unresolved references to the variable scope yet. Add
|
||||
// them to the variable scope on the boundary where it becomes clear they
|
||||
// aren't declarations. We explicitly delay declaring the variables up to
|
||||
// that point to avoid trying to add them to the unresolved list multiple
|
||||
// times, e.g., for (((a))).
|
||||
if (!CanBeDeclaration()) {
|
||||
for (auto& proxy_initializer_pair : *variable_list) {
|
||||
VariableProxy* proxy = proxy_initializer_pair.first;
|
||||
this->parser()->scope()->AddUnresolved(proxy);
|
||||
}
|
||||
}
|
||||
variable_list->MergeInto(AsExpressionParsingScope()->variable_list());
|
||||
}
|
||||
|
||||
Variable* Declare(const AstRawString* name, int pos = kNoSourcePosition) {
|
||||
if (type_ == kParameterDeclaration) {
|
||||
return AsParameterDeclarationParsingScope()->Declare(name, pos);
|
||||
@ -724,10 +742,7 @@ class ArrowHeadParsingScope : public ExpressionParsingScope<Types> {
|
||||
// references.
|
||||
this->parser()->next_arrow_function_info_.ClearStrictParameterError();
|
||||
ExpressionParsingScope<Types>::ValidateExpression();
|
||||
for (auto& proxy_initializer_pair : *this->variable_list()) {
|
||||
VariableProxy* proxy = proxy_initializer_pair.first;
|
||||
this->parser()->scope()->AddUnresolved(proxy);
|
||||
}
|
||||
this->parent()->MergeVariableList(this->variable_list());
|
||||
}
|
||||
|
||||
DeclarationScope* ValidateAndCreateScope() {
|
||||
|
45
test/mjsunit/regress/regress-crbug-1015372.js
Normal file
45
test/mjsunit/regress/regress-crbug-1015372.js
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright 2019 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
|
||||
(function() {
|
||||
function opt(flag) {
|
||||
function inline() {
|
||||
(function () {
|
||||
flag()
|
||||
})();
|
||||
(flag) = 1;
|
||||
}
|
||||
inline();
|
||||
}
|
||||
assertThrows(opt, TypeError);
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function opt(flag){
|
||||
function inline() {
|
||||
var f = (function() {
|
||||
return flag;
|
||||
});
|
||||
function g(x) {
|
||||
(flag) = x;
|
||||
}
|
||||
|
||||
return [f,g];
|
||||
}
|
||||
return inline();
|
||||
}
|
||||
[f, g] = opt(1);
|
||||
|
||||
%PrepareFunctionForOptimization(f);
|
||||
assertEquals(1, f());
|
||||
assertEquals(1, f());
|
||||
%OptimizeFunctionOnNextCall(f);
|
||||
assertEquals(1, f());
|
||||
|
||||
g(2);
|
||||
|
||||
assertEquals(2, f());
|
||||
})();
|
Loading…
Reference in New Issue
Block a user