| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/parsing/parser.h" | 5 #include "src/parsing/parser.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "src/api.h" | 9 #include "src/api.h" |
| 10 #include "src/ast/ast-expression-rewriter.h" | 10 #include "src/ast/ast-expression-rewriter.h" |
| (...skipping 1977 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1988 zone()); | 1988 zone()); |
| 1989 block->statements()->Add(body, zone()); | 1989 block->statements()->Add(body, zone()); |
| 1990 body = block; | 1990 body = block; |
| 1991 each = factory()->NewVariableProxy(temp); | 1991 each = factory()->NewVariableProxy(temp); |
| 1992 } | 1992 } |
| 1993 stmt->AsForInStatement()->Initialize(each, subject, body); | 1993 stmt->AsForInStatement()->Initialize(each, subject, body); |
| 1994 } | 1994 } |
| 1995 return stmt; | 1995 return stmt; |
| 1996 } | 1996 } |
| 1997 | 1997 |
| 1998 // Special case for legacy for |
| 1999 // |
| 2000 // for (var x = initializer in enumerable) body |
| 2001 // |
| 2002 // An initialization block of the form |
| 2003 // |
| 2004 // { |
| 2005 // x = initializer; |
| 2006 // } |
| 2007 // |
| 2008 // is returned in this case. It has reserved space for two statements, |
| 2009 // so that (later on during parsing), the equivalent of |
| 2010 // |
| 2011 // for (x in enumerable) body |
| 2012 // |
| 2013 // is added as a second statement to it. |
| 2014 Block* Parser::RewriteForVarInLegacy(const ForInfo& for_info) { |
| 2015 const DeclarationParsingResult::Declaration& decl = |
| 2016 for_info.parsing_result.declarations[0]; |
| 2017 if (!IsLexicalVariableMode(for_info.parsing_result.descriptor.mode) && |
| 2018 decl.pattern->IsVariableProxy() && decl.initializer != nullptr) { |
| 2019 DCHECK(!allow_harmony_for_in()); |
| 2020 ++use_counts_[v8::Isolate::kForInInitializer]; |
| 2021 const AstRawString* name = decl.pattern->AsVariableProxy()->raw_name(); |
| 2022 VariableProxy* single_var = NewUnresolved(name); |
| 2023 Block* init_block = factory()->NewBlock( |
| 2024 nullptr, 2, true, for_info.parsing_result.descriptor.declaration_pos); |
| 2025 init_block->statements()->Add( |
| 2026 factory()->NewExpressionStatement( |
| 2027 factory()->NewAssignment(Token::ASSIGN, single_var, |
| 2028 decl.initializer, kNoSourcePosition), |
| 2029 kNoSourcePosition), |
| 2030 zone()); |
| 2031 return init_block; |
| 2032 } |
| 2033 return nullptr; |
| 2034 } |
| 2035 |
| 2036 // Rewrite a for-in/of statement of the form |
| 2037 // |
| 2038 // for (let/const/var x in/of e) b |
| 2039 // |
| 2040 // into |
| 2041 // |
| 2042 // { |
| 2043 // <let x' be a temporary variable> |
| 2044 // for (x' in/of e) { |
| 2045 // let/const/var x; |
| 2046 // x = x'; |
| 2047 // b; |
| 2048 // } |
| 2049 // let x; // for TDZ |
| 2050 // } |
| 2051 void Parser::DesugarBindingInForEachStatement(ForInfo* for_info, |
| 2052 Block** body_block, |
| 2053 Expression** each_variable, |
| 2054 bool* ok) { |
| 2055 DeclarationParsingResult::Declaration& decl = |
| 2056 for_info->parsing_result.declarations[0]; |
| 2057 Variable* temp = NewTemporary(ast_value_factory()->dot_for_string()); |
| 2058 auto each_initialization_block = |
| 2059 factory()->NewBlock(nullptr, 1, true, kNoSourcePosition); |
| 2060 { |
| 2061 auto descriptor = for_info->parsing_result.descriptor; |
| 2062 descriptor.declaration_pos = kNoSourcePosition; |
| 2063 descriptor.initialization_pos = kNoSourcePosition; |
| 2064 decl.initializer = factory()->NewVariableProxy(temp); |
| 2065 |
| 2066 bool is_for_var_of = |
| 2067 for_info->mode == ForEachStatement::ITERATE && |
| 2068 for_info->parsing_result.descriptor.mode == VariableMode::VAR; |
| 2069 |
| 2070 PatternRewriter::DeclareAndInitializeVariables( |
| 2071 this, each_initialization_block, &descriptor, &decl, |
| 2072 (IsLexicalVariableMode(for_info->parsing_result.descriptor.mode) || |
| 2073 is_for_var_of) |
| 2074 ? &for_info->bound_names |
| 2075 : nullptr, |
| 2076 CHECK_OK_VOID); |
| 2077 |
| 2078 // Annex B.3.5 prohibits the form |
| 2079 // `try {} catch(e) { for (var e of {}); }` |
| 2080 // So if we are parsing a statement like `for (var ... of ...)` |
| 2081 // we need to walk up the scope chain and look for catch scopes |
| 2082 // which have a simple binding, then compare their binding against |
| 2083 // all of the names declared in the init of the for-of we're |
| 2084 // parsing. |
| 2085 if (is_for_var_of) { |
| 2086 Scope* catch_scope = scope(); |
| 2087 while (catch_scope != nullptr && !catch_scope->is_declaration_scope()) { |
| 2088 if (catch_scope->is_catch_scope()) { |
| 2089 auto name = catch_scope->catch_variable_name(); |
| 2090 // If it's a simple binding and the name is declared in the for loop. |
| 2091 if (name != ast_value_factory()->dot_catch_string() && |
| 2092 for_info->bound_names.Contains(name)) { |
| 2093 ReportMessageAt(for_info->parsing_result.bindings_loc, |
| 2094 MessageTemplate::kVarRedeclaration, name); |
| 2095 *ok = false; |
| 2096 return; |
| 2097 } |
| 2098 } |
| 2099 catch_scope = catch_scope->outer_scope(); |
| 2100 } |
| 2101 } |
| 2102 } |
| 2103 |
| 2104 *body_block = factory()->NewBlock(nullptr, 3, false, kNoSourcePosition); |
| 2105 (*body_block)->statements()->Add(each_initialization_block, zone()); |
| 2106 *each_variable = factory()->NewVariableProxy(temp, for_info->each_loc.beg_pos, |
| 2107 for_info->each_loc.end_pos); |
| 2108 } |
| 2109 |
| 2110 // Create a TDZ for any lexically-bound names in for in/of statements. |
| 2111 Block* Parser::CreateForEachStatementTDZ(Block* init_block, |
| 2112 const ForInfo& for_info, bool* ok) { |
| 2113 if (IsLexicalVariableMode(for_info.parsing_result.descriptor.mode)) { |
| 2114 DCHECK_NULL(init_block); |
| 2115 |
| 2116 init_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); |
| 2117 |
| 2118 for (int i = 0; i < for_info.bound_names.length(); ++i) { |
| 2119 // TODO(adamk): This needs to be some sort of special |
| 2120 // INTERNAL variable that's invisible to the debugger |
| 2121 // but visible to everything else. |
| 2122 Declaration* tdz_decl = DeclareVariable(for_info.bound_names[i], LET, |
| 2123 kNoSourcePosition, CHECK_OK); |
| 2124 tdz_decl->proxy()->var()->set_initializer_position(position()); |
| 2125 } |
| 2126 } |
| 2127 return init_block; |
| 2128 } |
| 2129 |
| 1998 Statement* Parser::InitializeForOfStatement(ForOfStatement* for_of, | 2130 Statement* Parser::InitializeForOfStatement(ForOfStatement* for_of, |
| 1999 Expression* each, | 2131 Expression* each, |
| 2000 Expression* iterable, | 2132 Expression* iterable, |
| 2001 Statement* body, bool finalize, | 2133 Statement* body, bool finalize, |
| 2002 int next_result_pos) { | 2134 int next_result_pos) { |
| 2003 // Create the auxiliary expressions needed for iterating over the iterable, | 2135 // Create the auxiliary expressions needed for iterating over the iterable, |
| 2004 // and initialize the given ForOfStatement with them. | 2136 // and initialize the given ForOfStatement with them. |
| 2005 // If finalize is true, also instrument the loop with code that performs the | 2137 // If finalize is true, also instrument the loop with code that performs the |
| 2006 // proper ES6 iterator finalization. In that case, the result is not | 2138 // proper ES6 iterator finalization. In that case, the result is not |
| 2007 // immediately a ForOfStatement. | 2139 // immediately a ForOfStatement. |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2112 block->statements()->Add(set_completion_normal, zone()); | 2244 block->statements()->Add(set_completion_normal, zone()); |
| 2113 body = block; | 2245 body = block; |
| 2114 } | 2246 } |
| 2115 | 2247 |
| 2116 for_of->Initialize(body, iterator, assign_iterator, next_result, result_done, | 2248 for_of->Initialize(body, iterator, assign_iterator, next_result, result_done, |
| 2117 assign_each); | 2249 assign_each); |
| 2118 return finalize ? FinalizeForOfStatement(for_of, completion, nopos) : for_of; | 2250 return finalize ? FinalizeForOfStatement(for_of, completion, nopos) : for_of; |
| 2119 } | 2251 } |
| 2120 | 2252 |
| 2121 Statement* Parser::DesugarLexicalBindingsInForStatement( | 2253 Statement* Parser::DesugarLexicalBindingsInForStatement( |
| 2122 Scope* inner_scope, VariableMode mode, ZoneList<const AstRawString*>* names, | |
| 2123 ForStatement* loop, Statement* init, Expression* cond, Statement* next, | 2254 ForStatement* loop, Statement* init, Expression* cond, Statement* next, |
| 2124 Statement* body, bool* ok) { | 2255 Statement* body, Scope* inner_scope, const ForInfo& for_info, bool* ok) { |
| 2125 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are | 2256 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are |
| 2126 // copied into a new environment. Moreover, the "next" statement must be | 2257 // copied into a new environment. Moreover, the "next" statement must be |
| 2127 // evaluated not in the environment of the just completed iteration but in | 2258 // evaluated not in the environment of the just completed iteration but in |
| 2128 // that of the upcoming one. We achieve this with the following desugaring. | 2259 // that of the upcoming one. We achieve this with the following desugaring. |
| 2129 // Extra care is needed to preserve the completion value of the original loop. | 2260 // Extra care is needed to preserve the completion value of the original loop. |
| 2130 // | 2261 // |
| 2131 // We are given a for statement of the form | 2262 // We are given a for statement of the form |
| 2132 // | 2263 // |
| 2133 // labels: for (let/const x = i; cond; next) body | 2264 // labels: for (let/const x = i; cond; next) body |
| 2134 // | 2265 // |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2152 // }} | 2283 // }} |
| 2153 // labels: for (; flag == 1; flag = 0, temp_x = x) { | 2284 // labels: for (; flag == 1; flag = 0, temp_x = x) { |
| 2154 // body | 2285 // body |
| 2155 // } | 2286 // } |
| 2156 // {{ if (flag == 1) // Body used break. | 2287 // {{ if (flag == 1) // Body used break. |
| 2157 // break; | 2288 // break; |
| 2158 // }} | 2289 // }} |
| 2159 // } | 2290 // } |
| 2160 // } | 2291 // } |
| 2161 | 2292 |
| 2162 DCHECK(names->length() > 0); | 2293 DCHECK(for_info.bound_names.length() > 0); |
| 2163 ZoneList<Variable*> temps(names->length(), zone()); | 2294 ZoneList<Variable*> temps(for_info.bound_names.length(), zone()); |
| 2164 | 2295 |
| 2165 Block* outer_block = | 2296 Block* outer_block = factory()->NewBlock( |
| 2166 factory()->NewBlock(NULL, names->length() + 4, false, kNoSourcePosition); | 2297 nullptr, for_info.bound_names.length() + 4, false, kNoSourcePosition); |
| 2167 | 2298 |
| 2168 // Add statement: let/const x = i. | 2299 // Add statement: let/const x = i. |
| 2169 outer_block->statements()->Add(init, zone()); | 2300 outer_block->statements()->Add(init, zone()); |
| 2170 | 2301 |
| 2171 const AstRawString* temp_name = ast_value_factory()->dot_for_string(); | 2302 const AstRawString* temp_name = ast_value_factory()->dot_for_string(); |
| 2172 | 2303 |
| 2173 // For each lexical variable x: | 2304 // For each lexical variable x: |
| 2174 // make statement: temp_x = x. | 2305 // make statement: temp_x = x. |
| 2175 for (int i = 0; i < names->length(); i++) { | 2306 for (int i = 0; i < for_info.bound_names.length(); i++) { |
| 2176 VariableProxy* proxy = NewUnresolved(names->at(i)); | 2307 VariableProxy* proxy = NewUnresolved(for_info.bound_names[i]); |
| 2177 Variable* temp = NewTemporary(temp_name); | 2308 Variable* temp = NewTemporary(temp_name); |
| 2178 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); | 2309 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); |
| 2179 Assignment* assignment = factory()->NewAssignment(Token::ASSIGN, temp_proxy, | 2310 Assignment* assignment = factory()->NewAssignment(Token::ASSIGN, temp_proxy, |
| 2180 proxy, kNoSourcePosition); | 2311 proxy, kNoSourcePosition); |
| 2181 Statement* assignment_statement = | 2312 Statement* assignment_statement = |
| 2182 factory()->NewExpressionStatement(assignment, kNoSourcePosition); | 2313 factory()->NewExpressionStatement(assignment, kNoSourcePosition); |
| 2183 outer_block->statements()->Add(assignment_statement, zone()); | 2314 outer_block->statements()->Add(assignment_statement, zone()); |
| 2184 temps.Add(temp, zone()); | 2315 temps.Add(temp, zone()); |
| 2185 } | 2316 } |
| 2186 | 2317 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2210 // in this function that looks up break targets. | 2341 // in this function that looks up break targets. |
| 2211 ForStatement* outer_loop = | 2342 ForStatement* outer_loop = |
| 2212 factory()->NewForStatement(NULL, kNoSourcePosition); | 2343 factory()->NewForStatement(NULL, kNoSourcePosition); |
| 2213 outer_block->statements()->Add(outer_loop, zone()); | 2344 outer_block->statements()->Add(outer_loop, zone()); |
| 2214 outer_block->set_scope(scope()); | 2345 outer_block->set_scope(scope()); |
| 2215 | 2346 |
| 2216 Block* inner_block = factory()->NewBlock(NULL, 3, false, kNoSourcePosition); | 2347 Block* inner_block = factory()->NewBlock(NULL, 3, false, kNoSourcePosition); |
| 2217 { | 2348 { |
| 2218 BlockState block_state(&scope_state_, inner_scope); | 2349 BlockState block_state(&scope_state_, inner_scope); |
| 2219 | 2350 |
| 2220 Block* ignore_completion_block = | 2351 Block* ignore_completion_block = factory()->NewBlock( |
| 2221 factory()->NewBlock(NULL, names->length() + 3, true, kNoSourcePosition); | 2352 nullptr, for_info.bound_names.length() + 3, true, kNoSourcePosition); |
| 2222 ZoneList<Variable*> inner_vars(names->length(), zone()); | 2353 ZoneList<Variable*> inner_vars(for_info.bound_names.length(), zone()); |
| 2223 // For each let variable x: | 2354 // For each let variable x: |
| 2224 // make statement: let/const x = temp_x. | 2355 // make statement: let/const x = temp_x. |
| 2225 for (int i = 0; i < names->length(); i++) { | 2356 for (int i = 0; i < for_info.bound_names.length(); i++) { |
| 2226 Declaration* decl = | 2357 Declaration* decl = DeclareVariable( |
| 2227 DeclareVariable(names->at(i), mode, kNoSourcePosition, CHECK_OK); | 2358 for_info.bound_names[i], for_info.parsing_result.descriptor.mode, |
| 2359 kNoSourcePosition, CHECK_OK); |
| 2228 inner_vars.Add(decl->proxy()->var(), zone()); | 2360 inner_vars.Add(decl->proxy()->var(), zone()); |
| 2229 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); | 2361 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); |
| 2230 Assignment* assignment = factory()->NewAssignment( | 2362 Assignment* assignment = factory()->NewAssignment( |
| 2231 Token::INIT, decl->proxy(), temp_proxy, kNoSourcePosition); | 2363 Token::INIT, decl->proxy(), temp_proxy, kNoSourcePosition); |
| 2232 Statement* assignment_statement = | 2364 Statement* assignment_statement = |
| 2233 factory()->NewExpressionStatement(assignment, kNoSourcePosition); | 2365 factory()->NewExpressionStatement(assignment, kNoSourcePosition); |
| 2234 DCHECK(init->position() != kNoSourcePosition); | 2366 DCHECK(init->position() != kNoSourcePosition); |
| 2235 decl->proxy()->var()->set_initializer_position(init->position()); | 2367 decl->proxy()->var()->set_initializer_position(init->position()); |
| 2236 ignore_completion_block->statements()->Add(assignment_statement, zone()); | 2368 ignore_completion_block->statements()->Add(assignment_statement, zone()); |
| 2237 } | 2369 } |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2301 // Make expression: flag = 0. | 2433 // Make expression: flag = 0. |
| 2302 { | 2434 { |
| 2303 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); | 2435 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); |
| 2304 Expression* const0 = factory()->NewSmiLiteral(0, kNoSourcePosition); | 2436 Expression* const0 = factory()->NewSmiLiteral(0, kNoSourcePosition); |
| 2305 compound_next = factory()->NewAssignment(Token::ASSIGN, flag_proxy, | 2437 compound_next = factory()->NewAssignment(Token::ASSIGN, flag_proxy, |
| 2306 const0, kNoSourcePosition); | 2438 const0, kNoSourcePosition); |
| 2307 } | 2439 } |
| 2308 | 2440 |
| 2309 // Make the comma-separated list of temp_x = x assignments. | 2441 // Make the comma-separated list of temp_x = x assignments. |
| 2310 int inner_var_proxy_pos = scanner()->location().beg_pos; | 2442 int inner_var_proxy_pos = scanner()->location().beg_pos; |
| 2311 for (int i = 0; i < names->length(); i++) { | 2443 for (int i = 0; i < for_info.bound_names.length(); i++) { |
| 2312 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); | 2444 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); |
| 2313 VariableProxy* proxy = | 2445 VariableProxy* proxy = |
| 2314 factory()->NewVariableProxy(inner_vars.at(i), inner_var_proxy_pos); | 2446 factory()->NewVariableProxy(inner_vars.at(i), inner_var_proxy_pos); |
| 2315 Assignment* assignment = factory()->NewAssignment( | 2447 Assignment* assignment = factory()->NewAssignment( |
| 2316 Token::ASSIGN, temp_proxy, proxy, kNoSourcePosition); | 2448 Token::ASSIGN, temp_proxy, proxy, kNoSourcePosition); |
| 2317 compound_next = factory()->NewBinaryOperation( | 2449 compound_next = factory()->NewBinaryOperation( |
| 2318 Token::COMMA, compound_next, assignment, kNoSourcePosition); | 2450 Token::COMMA, compound_next, assignment, kNoSourcePosition); |
| 2319 } | 2451 } |
| 2320 | 2452 |
| 2321 compound_next_statement = | 2453 compound_next_statement = |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2351 } | 2483 } |
| 2352 | 2484 |
| 2353 inner_scope->set_end_position(scanner()->location().end_pos); | 2485 inner_scope->set_end_position(scanner()->location().end_pos); |
| 2354 inner_block->set_scope(inner_scope); | 2486 inner_block->set_scope(inner_scope); |
| 2355 } | 2487 } |
| 2356 | 2488 |
| 2357 outer_loop->Initialize(NULL, NULL, NULL, inner_block); | 2489 outer_loop->Initialize(NULL, NULL, NULL, inner_block); |
| 2358 return outer_block; | 2490 return outer_block; |
| 2359 } | 2491 } |
| 2360 | 2492 |
| 2361 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, | |
| 2362 bool* ok) { | |
| 2363 int stmt_pos = peek_position(); | |
| 2364 Statement* init = NULL; | |
| 2365 ZoneList<const AstRawString*> bound_names(1, zone()); | |
| 2366 bool bound_names_are_lexical = false; | |
| 2367 | |
| 2368 // Create an in-between scope for let-bound iteration variables. | |
| 2369 BlockState for_state(&scope_state_); | |
| 2370 Expect(Token::FOR, CHECK_OK); | |
| 2371 Expect(Token::LPAREN, CHECK_OK); | |
| 2372 for_state.set_start_position(scanner()->location().beg_pos); | |
| 2373 for_state.set_is_hidden(); | |
| 2374 DeclarationParsingResult parsing_result; | |
| 2375 if (peek() != Token::SEMICOLON) { | |
| 2376 if (peek() == Token::VAR || peek() == Token::CONST || | |
| 2377 (peek() == Token::LET && IsNextLetKeyword())) { | |
| 2378 ParseVariableDeclarations(kForStatement, &parsing_result, nullptr, | |
| 2379 CHECK_OK); | |
| 2380 | |
| 2381 ForEachStatement::VisitMode mode = ForEachStatement::ENUMERATE; | |
| 2382 int each_beg_pos = scanner()->location().beg_pos; | |
| 2383 int each_end_pos = scanner()->location().end_pos; | |
| 2384 | |
| 2385 if (CheckInOrOf(&mode)) { | |
| 2386 if (parsing_result.declarations.length() != 1) { | |
| 2387 ReportMessageAt(parsing_result.bindings_loc, | |
| 2388 MessageTemplate::kForInOfLoopMultiBindings, | |
| 2389 ForEachStatement::VisitModeString(mode)); | |
| 2390 *ok = false; | |
| 2391 return nullptr; | |
| 2392 } | |
| 2393 DeclarationParsingResult::Declaration& decl = | |
| 2394 parsing_result.declarations[0]; | |
| 2395 if (parsing_result.first_initializer_loc.IsValid() && | |
| 2396 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE || | |
| 2397 IsLexicalVariableMode(parsing_result.descriptor.mode) || | |
| 2398 !decl.pattern->IsVariableProxy() || allow_harmony_for_in())) { | |
| 2399 // Only increment the use count if we would have let this through | |
| 2400 // without the flag. | |
| 2401 if (allow_harmony_for_in()) { | |
| 2402 ++use_counts_[v8::Isolate::kForInInitializer]; | |
| 2403 } | |
| 2404 ReportMessageAt(parsing_result.first_initializer_loc, | |
| 2405 MessageTemplate::kForInOfLoopInitializer, | |
| 2406 ForEachStatement::VisitModeString(mode)); | |
| 2407 *ok = false; | |
| 2408 return nullptr; | |
| 2409 } | |
| 2410 | |
| 2411 Block* init_block = nullptr; | |
| 2412 bound_names_are_lexical = | |
| 2413 IsLexicalVariableMode(parsing_result.descriptor.mode); | |
| 2414 | |
| 2415 // special case for legacy for (var ... = ... in ...) | |
| 2416 if (!bound_names_are_lexical && decl.pattern->IsVariableProxy() && | |
| 2417 decl.initializer != nullptr) { | |
| 2418 DCHECK(!allow_harmony_for_in()); | |
| 2419 ++use_counts_[v8::Isolate::kForInInitializer]; | |
| 2420 const AstRawString* name = | |
| 2421 decl.pattern->AsVariableProxy()->raw_name(); | |
| 2422 VariableProxy* single_var = NewUnresolved(name); | |
| 2423 init_block = factory()->NewBlock( | |
| 2424 nullptr, 2, true, parsing_result.descriptor.declaration_pos); | |
| 2425 init_block->statements()->Add( | |
| 2426 factory()->NewExpressionStatement( | |
| 2427 factory()->NewAssignment(Token::ASSIGN, single_var, | |
| 2428 decl.initializer, kNoSourcePosition), | |
| 2429 kNoSourcePosition), | |
| 2430 zone()); | |
| 2431 } | |
| 2432 | |
| 2433 // Rewrite a for-in/of statement of the form | |
| 2434 // | |
| 2435 // for (let/const/var x in/of e) b | |
| 2436 // | |
| 2437 // into | |
| 2438 // | |
| 2439 // { | |
| 2440 // <let x' be a temporary variable> | |
| 2441 // for (x' in/of e) { | |
| 2442 // let/const/var x; | |
| 2443 // x = x'; | |
| 2444 // b; | |
| 2445 // } | |
| 2446 // let x; // for TDZ | |
| 2447 // } | |
| 2448 | |
| 2449 Variable* temp = NewTemporary(ast_value_factory()->dot_for_string()); | |
| 2450 ForEachStatement* loop = | |
| 2451 factory()->NewForEachStatement(mode, labels, stmt_pos); | |
| 2452 ParserTarget target(this, loop); | |
| 2453 | |
| 2454 int each_keyword_position = scanner()->location().beg_pos; | |
| 2455 | |
| 2456 Expression* enumerable; | |
| 2457 if (mode == ForEachStatement::ITERATE) { | |
| 2458 ExpressionClassifier classifier(this); | |
| 2459 enumerable = ParseAssignmentExpression(true, CHECK_OK); | |
| 2460 RewriteNonPattern(CHECK_OK); | |
| 2461 } else { | |
| 2462 enumerable = ParseExpression(true, CHECK_OK); | |
| 2463 } | |
| 2464 | |
| 2465 Expect(Token::RPAREN, CHECK_OK); | |
| 2466 | |
| 2467 | |
| 2468 Block* body_block = | |
| 2469 factory()->NewBlock(NULL, 3, false, kNoSourcePosition); | |
| 2470 | |
| 2471 Statement* final_loop; | |
| 2472 { | |
| 2473 ReturnExprScope no_tail_calls(function_state_, | |
| 2474 ReturnExprContext::kInsideForInOfBody); | |
| 2475 BlockState block_state(&scope_state_); | |
| 2476 block_state.set_start_position(scanner()->location().beg_pos); | |
| 2477 | |
| 2478 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK); | |
| 2479 | |
| 2480 auto each_initialization_block = | |
| 2481 factory()->NewBlock(nullptr, 1, true, kNoSourcePosition); | |
| 2482 { | |
| 2483 auto descriptor = parsing_result.descriptor; | |
| 2484 descriptor.declaration_pos = kNoSourcePosition; | |
| 2485 descriptor.initialization_pos = kNoSourcePosition; | |
| 2486 decl.initializer = factory()->NewVariableProxy(temp); | |
| 2487 | |
| 2488 bool is_for_var_of = | |
| 2489 mode == ForEachStatement::ITERATE && | |
| 2490 parsing_result.descriptor.mode == VariableMode::VAR; | |
| 2491 | |
| 2492 PatternRewriter::DeclareAndInitializeVariables( | |
| 2493 this, each_initialization_block, &descriptor, &decl, | |
| 2494 bound_names_are_lexical || is_for_var_of ? &bound_names | |
| 2495 : nullptr, | |
| 2496 CHECK_OK); | |
| 2497 | |
| 2498 // Annex B.3.5 prohibits the form | |
| 2499 // `try {} catch(e) { for (var e of {}); }` | |
| 2500 // So if we are parsing a statement like `for (var ... of ...)` | |
| 2501 // we need to walk up the scope chain and look for catch scopes | |
| 2502 // which have a simple binding, then compare their binding against | |
| 2503 // all of the names declared in the init of the for-of we're | |
| 2504 // parsing. | |
| 2505 if (is_for_var_of) { | |
| 2506 Scope* catch_scope = scope(); | |
| 2507 while (catch_scope != nullptr && | |
| 2508 !catch_scope->is_declaration_scope()) { | |
| 2509 if (catch_scope->is_catch_scope()) { | |
| 2510 auto name = catch_scope->catch_variable_name(); | |
| 2511 if (name != | |
| 2512 ast_value_factory() | |
| 2513 ->dot_catch_string()) { // i.e. is a simple binding | |
| 2514 if (bound_names.Contains(name)) { | |
| 2515 ReportMessageAt(parsing_result.bindings_loc, | |
| 2516 MessageTemplate::kVarRedeclaration, name); | |
| 2517 *ok = false; | |
| 2518 return nullptr; | |
| 2519 } | |
| 2520 } | |
| 2521 } | |
| 2522 catch_scope = catch_scope->outer_scope(); | |
| 2523 } | |
| 2524 } | |
| 2525 } | |
| 2526 | |
| 2527 body_block->statements()->Add(each_initialization_block, zone()); | |
| 2528 body_block->statements()->Add(body, zone()); | |
| 2529 VariableProxy* temp_proxy = | |
| 2530 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); | |
| 2531 final_loop = InitializeForEachStatement( | |
| 2532 loop, temp_proxy, enumerable, body_block, each_keyword_position); | |
| 2533 block_state.set_end_position(scanner()->location().end_pos); | |
| 2534 body_block->set_scope(block_state.FinalizedBlockScope()); | |
| 2535 } | |
| 2536 | |
| 2537 // Create a TDZ for any lexically-bound names. | |
| 2538 if (bound_names_are_lexical) { | |
| 2539 DCHECK_NULL(init_block); | |
| 2540 | |
| 2541 init_block = | |
| 2542 factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); | |
| 2543 | |
| 2544 for (int i = 0; i < bound_names.length(); ++i) { | |
| 2545 // TODO(adamk): This needs to be some sort of special | |
| 2546 // INTERNAL variable that's invisible to the debugger | |
| 2547 // but visible to everything else. | |
| 2548 Declaration* tdz_decl = DeclareVariable( | |
| 2549 bound_names[i], LET, kNoSourcePosition, CHECK_OK); | |
| 2550 tdz_decl->proxy()->var()->set_initializer_position(position()); | |
| 2551 } | |
| 2552 } | |
| 2553 | |
| 2554 for_state.set_end_position(scanner()->location().end_pos); | |
| 2555 Scope* for_scope = for_state.FinalizedBlockScope(); | |
| 2556 // Parsed for-in loop w/ variable declarations. | |
| 2557 if (init_block != nullptr) { | |
| 2558 init_block->statements()->Add(final_loop, zone()); | |
| 2559 init_block->set_scope(for_scope); | |
| 2560 return init_block; | |
| 2561 } else { | |
| 2562 DCHECK_NULL(for_scope); | |
| 2563 return final_loop; | |
| 2564 } | |
| 2565 } else { | |
| 2566 bound_names_are_lexical = | |
| 2567 IsLexicalVariableMode(parsing_result.descriptor.mode); | |
| 2568 init = BuildInitializationBlock( | |
| 2569 &parsing_result, bound_names_are_lexical ? &bound_names : nullptr, | |
| 2570 CHECK_OK); | |
| 2571 } | |
| 2572 } else { | |
| 2573 int lhs_beg_pos = peek_position(); | |
| 2574 ExpressionClassifier classifier(this); | |
| 2575 Expression* expression = ParseExpressionCoverGrammar(false, CHECK_OK); | |
| 2576 int lhs_end_pos = scanner()->location().end_pos; | |
| 2577 ForEachStatement::VisitMode mode = ForEachStatement::ENUMERATE; | |
| 2578 | |
| 2579 bool is_for_each = CheckInOrOf(&mode); | |
| 2580 bool is_destructuring = is_for_each && (expression->IsArrayLiteral() || | |
| 2581 expression->IsObjectLiteral()); | |
| 2582 | |
| 2583 if (is_destructuring) { | |
| 2584 ValidateAssignmentPattern(CHECK_OK); | |
| 2585 } else { | |
| 2586 RewriteNonPattern(CHECK_OK); | |
| 2587 } | |
| 2588 | |
| 2589 if (is_for_each) { | |
| 2590 if (!is_destructuring) { | |
| 2591 expression = CheckAndRewriteReferenceExpression( | |
| 2592 expression, lhs_beg_pos, lhs_end_pos, | |
| 2593 MessageTemplate::kInvalidLhsInFor, kSyntaxError, CHECK_OK); | |
| 2594 } | |
| 2595 | |
| 2596 ForEachStatement* loop = | |
| 2597 factory()->NewForEachStatement(mode, labels, stmt_pos); | |
| 2598 ParserTarget target(this, loop); | |
| 2599 | |
| 2600 int each_keyword_position = scanner()->location().beg_pos; | |
| 2601 | |
| 2602 Expression* enumerable; | |
| 2603 if (mode == ForEachStatement::ITERATE) { | |
| 2604 ExpressionClassifier classifier(this); | |
| 2605 enumerable = ParseAssignmentExpression(true, CHECK_OK); | |
| 2606 RewriteNonPattern(CHECK_OK); | |
| 2607 } else { | |
| 2608 enumerable = ParseExpression(true, CHECK_OK); | |
| 2609 } | |
| 2610 | |
| 2611 Expect(Token::RPAREN, CHECK_OK); | |
| 2612 | |
| 2613 { | |
| 2614 ReturnExprScope no_tail_calls(function_state_, | |
| 2615 ReturnExprContext::kInsideForInOfBody); | |
| 2616 BlockState block_state(&scope_state_); | |
| 2617 block_state.set_start_position(scanner()->location().beg_pos); | |
| 2618 | |
| 2619 // For legacy compat reasons, give for loops similar treatment to | |
| 2620 // if statements in allowing a function declaration for a body | |
| 2621 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK); | |
| 2622 block_state.set_end_position(scanner()->location().end_pos); | |
| 2623 Statement* final_loop = InitializeForEachStatement( | |
| 2624 loop, expression, enumerable, body, each_keyword_position); | |
| 2625 | |
| 2626 Scope* for_scope = for_state.FinalizedBlockScope(); | |
| 2627 DCHECK_NULL(for_scope); | |
| 2628 USE(for_scope); | |
| 2629 Scope* block_scope = block_state.FinalizedBlockScope(); | |
| 2630 DCHECK_NULL(block_scope); | |
| 2631 USE(block_scope); | |
| 2632 return final_loop; | |
| 2633 } | |
| 2634 } else { | |
| 2635 init = factory()->NewExpressionStatement(expression, lhs_beg_pos); | |
| 2636 } | |
| 2637 } | |
| 2638 } | |
| 2639 | |
| 2640 // Standard 'for' loop | |
| 2641 ForStatement* loop = factory()->NewForStatement(labels, stmt_pos); | |
| 2642 ParserTarget target(this, loop); | |
| 2643 | |
| 2644 // Parsed initializer at this point. | |
| 2645 Expect(Token::SEMICOLON, CHECK_OK); | |
| 2646 | |
| 2647 Expression* cond = NULL; | |
| 2648 Statement* next = NULL; | |
| 2649 Statement* body = NULL; | |
| 2650 | |
| 2651 // If there are let bindings, then condition and the next statement of the | |
| 2652 // for loop must be parsed in a new scope. | |
| 2653 Scope* inner_scope = scope(); | |
| 2654 // TODO(verwaest): Allocate this through a ScopeState as well. | |
| 2655 if (bound_names_are_lexical && bound_names.length() > 0) { | |
| 2656 inner_scope = NewScopeWithParent(inner_scope, BLOCK_SCOPE); | |
| 2657 inner_scope->set_start_position(scanner()->location().beg_pos); | |
| 2658 } | |
| 2659 { | |
| 2660 BlockState block_state(&scope_state_, inner_scope); | |
| 2661 | |
| 2662 if (peek() != Token::SEMICOLON) { | |
| 2663 cond = ParseExpression(true, CHECK_OK); | |
| 2664 } | |
| 2665 Expect(Token::SEMICOLON, CHECK_OK); | |
| 2666 | |
| 2667 if (peek() != Token::RPAREN) { | |
| 2668 Expression* exp = ParseExpression(true, CHECK_OK); | |
| 2669 next = factory()->NewExpressionStatement(exp, exp->position()); | |
| 2670 } | |
| 2671 Expect(Token::RPAREN, CHECK_OK); | |
| 2672 | |
| 2673 body = ParseScopedStatement(NULL, true, CHECK_OK); | |
| 2674 } | |
| 2675 | |
| 2676 Statement* result = NULL; | |
| 2677 if (bound_names_are_lexical && bound_names.length() > 0) { | |
| 2678 result = DesugarLexicalBindingsInForStatement( | |
| 2679 inner_scope, parsing_result.descriptor.mode, &bound_names, loop, init, | |
| 2680 cond, next, body, CHECK_OK); | |
| 2681 for_state.set_end_position(scanner()->location().end_pos); | |
| 2682 } else { | |
| 2683 for_state.set_end_position(scanner()->location().end_pos); | |
| 2684 Scope* for_scope = for_state.FinalizedBlockScope(); | |
| 2685 if (for_scope) { | |
| 2686 // Rewrite a for statement of the form | |
| 2687 // for (const x = i; c; n) b | |
| 2688 // | |
| 2689 // into | |
| 2690 // | |
| 2691 // { | |
| 2692 // const x = i; | |
| 2693 // for (; c; n) b | |
| 2694 // } | |
| 2695 // | |
| 2696 // or, desugar | |
| 2697 // for (; c; n) b | |
| 2698 // into | |
| 2699 // { | |
| 2700 // for (; c; n) b | |
| 2701 // } | |
| 2702 // just in case b introduces a lexical binding some other way, e.g., if b | |
| 2703 // is a FunctionDeclaration. | |
| 2704 Block* block = factory()->NewBlock(NULL, 2, false, kNoSourcePosition); | |
| 2705 if (init != nullptr) { | |
| 2706 block->statements()->Add(init, zone()); | |
| 2707 } | |
| 2708 block->statements()->Add(loop, zone()); | |
| 2709 block->set_scope(for_scope); | |
| 2710 loop->Initialize(NULL, cond, next, body); | |
| 2711 result = block; | |
| 2712 } else { | |
| 2713 loop->Initialize(init, cond, next, body); | |
| 2714 result = loop; | |
| 2715 } | |
| 2716 } | |
| 2717 return result; | |
| 2718 } | |
| 2719 | |
| 2720 void Parser::ParseArrowFunctionFormalParameters( | 2493 void Parser::ParseArrowFunctionFormalParameters( |
| 2721 ParserFormalParameters* parameters, Expression* expr, int end_pos, | 2494 ParserFormalParameters* parameters, Expression* expr, int end_pos, |
| 2722 bool* ok) { | 2495 bool* ok) { |
| 2723 // ArrowFunctionFormals :: | 2496 // ArrowFunctionFormals :: |
| 2724 // Binary(Token::COMMA, NonTailArrowFunctionFormals, Tail) | 2497 // Binary(Token::COMMA, NonTailArrowFunctionFormals, Tail) |
| 2725 // Tail | 2498 // Tail |
| 2726 // NonTailArrowFunctionFormals :: | 2499 // NonTailArrowFunctionFormals :: |
| 2727 // Binary(Token::COMMA, NonTailArrowFunctionFormals, VariableProxy) | 2500 // Binary(Token::COMMA, NonTailArrowFunctionFormals, VariableProxy) |
| 2728 // VariableProxy | 2501 // VariableProxy |
| 2729 // Tail :: | 2502 // Tail :: |
| (...skipping 3097 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5827 | 5600 |
| 5828 return final_loop; | 5601 return final_loop; |
| 5829 } | 5602 } |
| 5830 | 5603 |
| 5831 #undef CHECK_OK | 5604 #undef CHECK_OK |
| 5832 #undef CHECK_OK_VOID | 5605 #undef CHECK_OK_VOID |
| 5833 #undef CHECK_FAILED | 5606 #undef CHECK_FAILED |
| 5834 | 5607 |
| 5835 } // namespace internal | 5608 } // namespace internal |
| 5836 } // namespace v8 | 5609 } // namespace v8 |
| OLD | NEW |