Index: src/parsing/parser-base.h |
diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h |
index 9375bb0df5bb2f04a65e3dd336829e9c573029be..e1e3d3412281a274f2a3d03079735cc7c113a2de 100644 |
--- a/src/parsing/parser-base.h |
+++ b/src/parsing/parser-base.h |
@@ -1346,6 +1346,24 @@ |
bool IsValidPattern(ExpressionT expression) { |
return expression->IsObjectLiteral() || expression->IsArrayLiteral(); |
} |
+ |
+ // Due to hoisting, the value of a 'var'-declared variable may actually change |
+ // even if the code contains only the "initial" assignment, namely when that |
+ // assignment occurs inside a loop. For example: |
+ // |
+ // let i = 10; |
+ // do { var x = i } while (i--): |
+ // |
+ // As a simple and very conservative approximation of this, we explicitly mark |
+ // as maybe-assigned any non-lexical variable whose initializing "declaration" |
+ // does not syntactically occur in the function scope. (In the example above, |
+ // it occurs in a block scope.) |
+ // |
+ // Note that non-lexical variables include temporaries, which may also get |
+ // assigned inside a loop due to the various rewritings that the parser |
+ // performs. |
+ // |
+ static void MarkLoopVariableAsAssigned(Scope* scope, Variable* var); |
// Keep track of eval() calls since they disable all local variable |
// optimizations. This checks if expression is an eval call, and if yes, |
@@ -5698,8 +5716,12 @@ |
return loop; |
} |
-#undef CHECK_OK |
-#undef CHECK_OK_CUSTOM |
+template <typename Impl> |
+void ParserBase<Impl>::MarkLoopVariableAsAssigned(Scope* scope, Variable* var) { |
+ if (!IsLexicalVariableMode(var->mode()) && !scope->is_function_scope()) { |
+ var->set_maybe_assigned(); |
+ } |
+} |
template <typename Impl> |
void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( |
@@ -5751,6 +5773,8 @@ |
} |
} |
+#undef CHECK_OK |
+#undef CHECK_OK_CUSTOM |
#undef CHECK_OK_VOID |
} // namespace internal |