Index: src/parsing/parser-base.h |
diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h |
index 56b40abf987917ad7df9b94180daacba8597ad24..58b6e3645ab6535b7c63e1d25f946e7b87507be5 100644 |
--- a/src/parsing/parser-base.h |
+++ b/src/parsing/parser-base.h |
@@ -1347,6 +1347,24 @@ class ParserBase { |
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 "declaration" does not |
marja
2017/02/06 21:08:43
Confused by this comment + the comment about prepa
|
+ // 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, |
// forwards the information to scope. |
@@ -5699,8 +5717,12 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStandardForLoop( |
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( |
@@ -5752,6 +5774,8 @@ void ParserBase<Impl>::ClassLiteralChecker::CheckClassMethodName( |
} |
} |
+#undef CHECK_OK |
+#undef CHECK_OK_CUSTOM |
#undef CHECK_OK_VOID |
} // namespace internal |