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 |