OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 <cmath> | 5 #include <cmath> |
6 | 6 |
7 #include "src/allocation.h" | 7 #include "src/allocation.h" |
8 #include "src/base/logging.h" | 8 #include "src/base/logging.h" |
9 #include "src/conversions-inl.h" | 9 #include "src/conversions-inl.h" |
10 #include "src/conversions.h" | 10 #include "src/conversions.h" |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 // The PreParser checks that the syntax follows the grammar for JavaScript, | 115 // The PreParser checks that the syntax follows the grammar for JavaScript, |
116 // and collects some information about the program along the way. | 116 // and collects some information about the program along the way. |
117 // The grammar check is only performed in order to understand the program | 117 // The grammar check is only performed in order to understand the program |
118 // sufficiently to deduce some information about it, that can be used | 118 // sufficiently to deduce some information about it, that can be used |
119 // to speed up later parsing. Finding errors is not the goal of pre-parsing, | 119 // to speed up later parsing. Finding errors is not the goal of pre-parsing, |
120 // rather it is to speed up properly written and correct programs. | 120 // rather it is to speed up properly written and correct programs. |
121 // That means that contextual checks (like a label being declared where | 121 // That means that contextual checks (like a label being declared where |
122 // it is used) are generally omitted. | 122 // it is used) are generally omitted. |
123 | 123 |
124 | 124 |
125 PreParser::Statement PreParser::ParseStatementListItem(bool* ok) { | |
126 // ECMA 262 6th Edition | |
127 // StatementListItem[Yield, Return] : | |
128 // Statement[?Yield, ?Return] | |
129 // Declaration[?Yield] | |
130 // | |
131 // Declaration[Yield] : | |
132 // HoistableDeclaration[?Yield] | |
133 // ClassDeclaration[?Yield] | |
134 // LexicalDeclaration[In, ?Yield] | |
135 // | |
136 // HoistableDeclaration[Yield, Default] : | |
137 // FunctionDeclaration[?Yield, ?Default] | |
138 // GeneratorDeclaration[?Yield, ?Default] | |
139 // | |
140 // LexicalDeclaration[In, Yield] : | |
141 // LetOrConst BindingList[?In, ?Yield] ; | |
142 | |
143 switch (peek()) { | |
144 case Token::FUNCTION: | |
145 return ParseHoistableDeclaration(ok); | |
146 case Token::CLASS: | |
147 return ParseClassDeclaration(ok); | |
148 case Token::CONST: | |
149 return ParseVariableStatement(kStatementListItem, ok); | |
150 case Token::LET: | |
151 if (IsNextLetKeyword()) { | |
152 return ParseVariableStatement(kStatementListItem, ok); | |
153 } | |
154 break; | |
155 case Token::ASYNC: | |
156 if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION && | |
157 !scanner()->HasAnyLineTerminatorAfterNext()) { | |
158 Consume(Token::ASYNC); | |
159 return ParseAsyncFunctionDeclaration(ok); | |
160 } | |
161 /* falls through */ | |
162 default: | |
163 break; | |
164 } | |
165 return ParseStatement(kAllowLabelledFunctionStatement, ok); | |
166 } | |
167 | |
168 PreParser::LazyParsingResult PreParser::ParseStatementList(int end_token, | |
169 bool may_abort, | |
170 bool* ok) { | |
171 // SourceElements :: | |
172 // (Statement)* <end_token> | |
173 | |
174 int count_statements = 0; | |
175 | |
176 bool directive_prologue = true; | |
177 while (peek() != end_token) { | |
178 if (directive_prologue && peek() != Token::STRING) { | |
179 directive_prologue = false; | |
180 } | |
181 bool starts_with_identifier = peek() == Token::IDENTIFIER; | |
182 Scanner::Location token_loc = scanner()->peek_location(); | |
183 Statement statement = | |
184 ParseStatementListItem(CHECK_OK_VALUE(kLazyParsingComplete)); | |
185 | |
186 if (directive_prologue) { | |
187 bool use_strict_found = statement.IsUseStrictLiteral(); | |
188 | |
189 if (use_strict_found) { | |
190 scope()->SetLanguageMode( | |
191 static_cast<LanguageMode>(scope()->language_mode() | STRICT)); | |
192 } else if (!statement.IsStringLiteral()) { | |
193 directive_prologue = false; | |
194 } | |
195 | |
196 if (use_strict_found && !scope()->HasSimpleParameters()) { | |
197 // TC39 deemed "use strict" directives to be an error when occurring | |
198 // in the body of a function with non-simple parameter list, on | |
199 // 29/7/2015. https://goo.gl/ueA7Ln | |
200 ReportMessageAt(token_loc, | |
201 MessageTemplate::kIllegalLanguageModeDirective, | |
202 "use strict"); | |
203 *ok = false; | |
204 return kLazyParsingComplete; | |
205 } | |
206 } | |
207 | |
208 // If we're allowed to reset to a bookmark, we will do so when we see a long | |
209 // and trivial function. | |
210 // Our current definition of 'long and trivial' is: | |
211 // - over 200 statements | |
212 // - all starting with an identifier (i.e., no if, for, while, etc.) | |
213 if (may_abort) { | |
214 if (!starts_with_identifier) { | |
215 may_abort = false; | |
216 } else if (++count_statements > kLazyParseTrialLimit) { | |
217 return kLazyParsingAborted; | |
218 } | |
219 } | |
220 } | |
221 return kLazyParsingComplete; | |
222 } | |
223 | |
224 | |
225 PreParser::Statement PreParser::ParseStatement( | |
226 AllowLabelledFunctionStatement allow_function, bool* ok) { | |
227 // Statement :: | |
228 // EmptyStatement | |
229 // ... | |
230 | |
231 if (peek() == Token::SEMICOLON) { | |
232 Next(); | |
233 return Statement::Default(); | |
234 } | |
235 return ParseSubStatement(allow_function, ok); | |
236 } | |
237 | |
238 PreParser::Statement PreParser::ParseScopedStatement(bool legacy, bool* ok) { | 125 PreParser::Statement PreParser::ParseScopedStatement(bool legacy, bool* ok) { |
239 if (is_strict(language_mode()) || peek() != Token::FUNCTION || | 126 if (is_strict(language_mode()) || peek() != Token::FUNCTION || |
240 (legacy && allow_harmony_restrictive_declarations())) { | 127 (legacy && allow_harmony_restrictive_declarations())) { |
241 return ParseSubStatement(kDisallowLabelledFunctionStatement, ok); | 128 return ParseStatement(nullptr, kDisallowLabelledFunctionStatement, ok); |
242 } else { | 129 } else { |
243 BlockState block_state(&scope_state_); | 130 BlockState block_state(&scope_state_); |
244 return ParseFunctionDeclaration(ok); | 131 return ParseFunctionDeclaration(ok); |
245 } | 132 } |
246 } | 133 } |
247 | 134 |
248 PreParser::Statement PreParser::ParseSubStatement( | |
249 AllowLabelledFunctionStatement allow_function, bool* ok) { | |
250 // Statement :: | |
251 // Block | |
252 // VariableStatement | |
253 // EmptyStatement | |
254 // ExpressionStatement | |
255 // IfStatement | |
256 // IterationStatement | |
257 // ContinueStatement | |
258 // BreakStatement | |
259 // ReturnStatement | |
260 // WithStatement | |
261 // LabelledStatement | |
262 // SwitchStatement | |
263 // ThrowStatement | |
264 // TryStatement | |
265 // DebuggerStatement | |
266 | |
267 // Note: Since labels can only be used by 'break' and 'continue' | |
268 // statements, which themselves are only valid within blocks, | |
269 // iterations or 'switch' statements (i.e., BreakableStatements), | |
270 // labels can be simply ignored in all other cases; except for | |
271 // trivial labeled break statements 'label: break label' which is | |
272 // parsed into an empty statement. | |
273 | |
274 // Keep the source position of the statement | |
275 switch (peek()) { | |
276 case Token::LBRACE: | |
277 return ParseBlock(ok); | |
278 | |
279 case Token::SEMICOLON: | |
280 Next(); | |
281 return Statement::Default(); | |
282 | |
283 case Token::IF: | |
284 return ParseIfStatement(ok); | |
285 | |
286 case Token::DO: | |
287 return ParseDoWhileStatement(ok); | |
288 | |
289 case Token::WHILE: | |
290 return ParseWhileStatement(ok); | |
291 | |
292 case Token::FOR: | |
293 return ParseForStatement(ok); | |
294 | |
295 case Token::CONTINUE: | |
296 return ParseContinueStatement(ok); | |
297 | |
298 case Token::BREAK: | |
299 return ParseBreakStatement(ok); | |
300 | |
301 case Token::RETURN: | |
302 return ParseReturnStatement(ok); | |
303 | |
304 case Token::WITH: | |
305 return ParseWithStatement(ok); | |
306 | |
307 case Token::SWITCH: | |
308 return ParseSwitchStatement(ok); | |
309 | |
310 case Token::THROW: | |
311 return ParseThrowStatement(ok); | |
312 | |
313 case Token::TRY: | |
314 return ParseTryStatement(ok); | |
315 | |
316 case Token::FUNCTION: | |
317 // FunctionDeclaration only allowed as a StatementListItem, not in | |
318 // an arbitrary Statement position. Exceptions such as | |
319 // ES#sec-functiondeclarations-in-ifstatement-statement-clauses | |
320 // are handled by calling ParseScopedStatement rather than | |
321 // ParseSubStatement directly. | |
322 ReportMessageAt(scanner()->peek_location(), | |
323 is_strict(language_mode()) | |
324 ? MessageTemplate::kStrictFunction | |
325 : MessageTemplate::kSloppyFunction); | |
326 *ok = false; | |
327 return Statement::Default(); | |
328 | |
329 case Token::DEBUGGER: | |
330 return ParseDebuggerStatement(ok); | |
331 | |
332 case Token::VAR: | |
333 return ParseVariableStatement(kStatement, ok); | |
334 | |
335 default: | |
336 return ParseExpressionOrLabelledStatement(allow_function, ok); | |
337 } | |
338 } | |
339 | |
340 PreParser::Statement PreParser::ParseHoistableDeclaration( | 135 PreParser::Statement PreParser::ParseHoistableDeclaration( |
341 int pos, ParseFunctionFlags flags, bool* ok) { | 136 int pos, ParseFunctionFlags flags, ZoneList<const AstRawString*>* names, |
| 137 bool default_export, bool* ok) { |
342 const bool is_generator = flags & ParseFunctionFlags::kIsGenerator; | 138 const bool is_generator = flags & ParseFunctionFlags::kIsGenerator; |
343 const bool is_async = flags & ParseFunctionFlags::kIsAsync; | 139 const bool is_async = flags & ParseFunctionFlags::kIsAsync; |
344 DCHECK(!is_generator || !is_async); | 140 DCHECK(!is_generator || !is_async); |
345 | 141 |
346 bool is_strict_reserved = false; | 142 bool is_strict_reserved = false; |
347 Identifier name = ParseIdentifierOrStrictReservedWord( | 143 Identifier name = ParseIdentifierOrStrictReservedWord( |
348 &is_strict_reserved, CHECK_OK); | 144 &is_strict_reserved, CHECK_OK); |
349 | 145 |
350 ParseFunctionLiteral(name, scanner()->location(), | 146 ParseFunctionLiteral(name, scanner()->location(), |
351 is_strict_reserved ? kFunctionNameIsStrictReserved | 147 is_strict_reserved ? kFunctionNameIsStrictReserved |
352 : kFunctionNameValidityUnknown, | 148 : kFunctionNameValidityUnknown, |
353 is_generator ? FunctionKind::kGeneratorFunction | 149 is_generator ? FunctionKind::kGeneratorFunction |
354 : is_async ? FunctionKind::kAsyncFunction | 150 : is_async ? FunctionKind::kAsyncFunction |
355 : FunctionKind::kNormalFunction, | 151 : FunctionKind::kNormalFunction, |
356 pos, FunctionLiteral::kDeclaration, language_mode(), | 152 pos, FunctionLiteral::kDeclaration, language_mode(), |
357 CHECK_OK); | 153 CHECK_OK); |
358 return Statement::FunctionDeclaration(); | 154 return Statement::FunctionDeclaration(); |
359 } | 155 } |
360 | 156 |
361 PreParser::Statement PreParser::ParseAsyncFunctionDeclaration(bool* ok) { | 157 PreParser::Statement PreParser::ParseAsyncFunctionDeclaration( |
| 158 ZoneList<const AstRawString*>* names, bool default_export, bool* ok) { |
362 // AsyncFunctionDeclaration :: | 159 // AsyncFunctionDeclaration :: |
363 // async [no LineTerminator here] function BindingIdentifier[Await] | 160 // async [no LineTerminator here] function BindingIdentifier[Await] |
364 // ( FormalParameters[Await] ) { AsyncFunctionBody } | 161 // ( FormalParameters[Await] ) { AsyncFunctionBody } |
365 DCHECK_EQ(scanner()->current_token(), Token::ASYNC); | 162 DCHECK_EQ(scanner()->current_token(), Token::ASYNC); |
366 int pos = position(); | 163 int pos = position(); |
367 Expect(Token::FUNCTION, CHECK_OK); | 164 Expect(Token::FUNCTION, CHECK_OK); |
368 ParseFunctionFlags flags = ParseFunctionFlags::kIsAsync; | 165 ParseFunctionFlags flags = ParseFunctionFlags::kIsAsync; |
369 return ParseHoistableDeclaration(pos, flags, ok); | 166 return ParseHoistableDeclaration(pos, flags, names, default_export, ok); |
370 } | 167 } |
371 | 168 |
372 PreParser::Statement PreParser::ParseHoistableDeclaration(bool* ok) { | 169 PreParser::Statement PreParser::ParseHoistableDeclaration( |
| 170 ZoneList<const AstRawString*>* names, bool default_export, bool* ok) { |
373 // FunctionDeclaration :: | 171 // FunctionDeclaration :: |
374 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' | 172 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' |
375 // GeneratorDeclaration :: | 173 // GeneratorDeclaration :: |
376 // 'function' '*' Identifier '(' FormalParameterListopt ')' | 174 // 'function' '*' Identifier '(' FormalParameterListopt ')' |
377 // '{' FunctionBody '}' | 175 // '{' FunctionBody '}' |
378 | 176 |
379 Expect(Token::FUNCTION, CHECK_OK); | 177 Expect(Token::FUNCTION, CHECK_OK); |
380 int pos = position(); | 178 int pos = position(); |
381 ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal; | 179 ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal; |
382 if (Check(Token::MUL)) { | 180 if (Check(Token::MUL)) { |
383 flags |= ParseFunctionFlags::kIsGenerator; | 181 flags |= ParseFunctionFlags::kIsGenerator; |
384 } | 182 } |
385 return ParseHoistableDeclaration(pos, flags, ok); | 183 return ParseHoistableDeclaration(pos, flags, names, default_export, ok); |
386 } | 184 } |
387 | 185 |
388 | 186 PreParser::Statement PreParser::ParseClassDeclaration( |
389 PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) { | 187 ZoneList<const AstRawString*>* names, bool default_export, bool* ok) { |
390 Expect(Token::CLASS, CHECK_OK); | |
391 | |
392 int pos = position(); | 188 int pos = position(); |
393 bool is_strict_reserved = false; | 189 bool is_strict_reserved = false; |
394 Identifier name = | 190 Identifier name = |
395 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); | 191 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
396 ExpressionClassifier no_classifier(this); | 192 ExpressionClassifier no_classifier(this); |
397 ParseClassLiteral(name, scanner()->location(), is_strict_reserved, pos, | 193 ParseClassLiteral(name, scanner()->location(), is_strict_reserved, pos, |
398 CHECK_OK); | 194 CHECK_OK); |
399 return Statement::Default(); | 195 return Statement::Default(); |
400 } | 196 } |
401 | 197 |
402 | 198 PreParser::Statement PreParser::ParseBlock( |
403 PreParser::Statement PreParser::ParseBlock(bool* ok) { | 199 ZoneList<const AstRawString*>* labels, bool* ok) { |
404 // Block :: | 200 // Block :: |
405 // '{' StatementList '}' | 201 // '{' StatementList '}' |
406 | 202 |
407 Expect(Token::LBRACE, CHECK_OK); | 203 Expect(Token::LBRACE, CHECK_OK); |
408 Statement final = Statement::Default(); | 204 Statement final = Statement::Default(); |
409 { | 205 { |
410 BlockState block_state(&scope_state_); | 206 BlockState block_state(&scope_state_); |
411 while (peek() != Token::RBRACE) { | 207 while (peek() != Token::RBRACE) { |
412 final = ParseStatementListItem(CHECK_OK); | 208 final = ParseStatementListItem(CHECK_OK); |
413 } | 209 } |
414 } | 210 } |
415 Expect(Token::RBRACE, ok); | 211 Expect(Token::RBRACE, ok); |
416 return final; | 212 return final; |
417 } | 213 } |
418 | 214 |
419 | |
420 PreParser::Statement PreParser::ParseVariableStatement( | 215 PreParser::Statement PreParser::ParseVariableStatement( |
421 VariableDeclarationContext var_context, | 216 VariableDeclarationContext var_context, |
422 bool* ok) { | 217 ZoneList<const AstRawString*>* names, bool* ok) { |
423 // VariableStatement :: | 218 // VariableStatement :: |
424 // VariableDeclarations ';' | 219 // VariableDeclarations ';' |
425 | 220 |
426 Statement result = | 221 Statement result = |
427 ParseVariableDeclarations(var_context, nullptr, nullptr, CHECK_OK); | 222 ParseVariableDeclarations(var_context, nullptr, names, CHECK_OK); |
428 ExpectSemicolon(CHECK_OK); | 223 ExpectSemicolon(CHECK_OK); |
429 return result; | 224 return result; |
430 } | 225 } |
431 | 226 |
432 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { | 227 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { |
433 Consume(Token::FUNCTION); | 228 Consume(Token::FUNCTION); |
434 int pos = position(); | 229 int pos = position(); |
435 ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal; | 230 ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal; |
436 if (Check(Token::MUL)) { | 231 if (Check(Token::MUL)) { |
437 flags |= ParseFunctionFlags::kIsGenerator; | 232 flags |= ParseFunctionFlags::kIsGenerator; |
438 if (allow_harmony_restrictive_declarations()) { | 233 if (allow_harmony_restrictive_declarations()) { |
439 ReportMessageAt(scanner()->location(), | 234 ReportMessageAt(scanner()->location(), |
440 MessageTemplate::kGeneratorInLegacyContext); | 235 MessageTemplate::kGeneratorInLegacyContext); |
441 *ok = false; | 236 *ok = false; |
442 return Statement::Default(); | 237 return Statement::Default(); |
443 } | 238 } |
444 } | 239 } |
445 return ParseHoistableDeclaration(pos, flags, ok); | 240 return ParseHoistableDeclaration(pos, flags, nullptr, false, ok); |
446 } | 241 } |
447 | 242 |
448 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement( | 243 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement( |
| 244 ZoneList<const AstRawString*>* names, |
449 AllowLabelledFunctionStatement allow_function, bool* ok) { | 245 AllowLabelledFunctionStatement allow_function, bool* ok) { |
450 // ExpressionStatement | LabelledStatement :: | 246 // ExpressionStatement | LabelledStatement :: |
451 // Expression ';' | 247 // Expression ';' |
452 // Identifier ':' Statement | 248 // Identifier ':' Statement |
453 | 249 |
454 switch (peek()) { | 250 switch (peek()) { |
455 case Token::FUNCTION: | 251 case Token::FUNCTION: |
456 case Token::LBRACE: | 252 case Token::LBRACE: |
457 UNREACHABLE(); // Always handled by the callers. | 253 UNREACHABLE(); // Always handled by the callers. |
458 case Token::CLASS: | 254 case Token::CLASS: |
(...skipping 23 matching lines...) Expand all Loading... |
482 Consume(Token::COLON); | 278 Consume(Token::COLON); |
483 // ES#sec-labelled-function-declarations Labelled Function Declarations | 279 // ES#sec-labelled-function-declarations Labelled Function Declarations |
484 if (peek() == Token::FUNCTION && is_sloppy(language_mode())) { | 280 if (peek() == Token::FUNCTION && is_sloppy(language_mode())) { |
485 if (allow_function == kAllowLabelledFunctionStatement) { | 281 if (allow_function == kAllowLabelledFunctionStatement) { |
486 return ParseFunctionDeclaration(ok); | 282 return ParseFunctionDeclaration(ok); |
487 } else { | 283 } else { |
488 return ParseScopedStatement(true, ok); | 284 return ParseScopedStatement(true, ok); |
489 } | 285 } |
490 } | 286 } |
491 Statement statement = | 287 Statement statement = |
492 ParseStatement(kDisallowLabelledFunctionStatement, ok); | 288 ParseStatement(nullptr, kDisallowLabelledFunctionStatement, ok); |
493 return statement.IsJumpStatement() ? Statement::Default() : statement; | 289 return statement.IsJumpStatement() ? Statement::Default() : statement; |
494 // Preparsing is disabled for extensions (because the extension details | 290 // Preparsing is disabled for extensions (because the extension details |
495 // aren't passed to lazily compiled functions), so we don't | 291 // aren't passed to lazily compiled functions), so we don't |
496 // accept "native function" in the preparser. | 292 // accept "native function" in the preparser. |
497 } | 293 } |
498 // Parsed expression statement. | 294 // Parsed expression statement. |
499 ExpectSemicolon(CHECK_OK); | 295 ExpectSemicolon(CHECK_OK); |
500 return Statement::ExpressionStatement(expr); | 296 return Statement::ExpressionStatement(expr); |
501 } | 297 } |
502 | 298 |
503 | 299 PreParser::Statement PreParser::ParseIfStatement( |
504 PreParser::Statement PreParser::ParseIfStatement(bool* ok) { | 300 ZoneList<const AstRawString*>* labels, bool* ok) { |
505 // IfStatement :: | 301 // IfStatement :: |
506 // 'if' '(' Expression ')' Statement ('else' Statement)? | 302 // 'if' '(' Expression ')' Statement ('else' Statement)? |
507 | 303 |
508 Expect(Token::IF, CHECK_OK); | 304 Expect(Token::IF, CHECK_OK); |
509 Expect(Token::LPAREN, CHECK_OK); | 305 Expect(Token::LPAREN, CHECK_OK); |
510 ParseExpression(true, CHECK_OK); | 306 ParseExpression(true, CHECK_OK); |
511 Expect(Token::RPAREN, CHECK_OK); | 307 Expect(Token::RPAREN, CHECK_OK); |
512 Statement stat = ParseScopedStatement(false, CHECK_OK); | 308 Statement stat = ParseScopedStatement(false, CHECK_OK); |
513 if (peek() == Token::ELSE) { | 309 if (peek() == Token::ELSE) { |
514 Next(); | 310 Next(); |
(...skipping 17 matching lines...) Expand all Loading... |
532 tok != Token::SEMICOLON && | 328 tok != Token::SEMICOLON && |
533 tok != Token::RBRACE && | 329 tok != Token::RBRACE && |
534 tok != Token::EOS) { | 330 tok != Token::EOS) { |
535 // ECMA allows "eval" or "arguments" as labels even in strict mode. | 331 // ECMA allows "eval" or "arguments" as labels even in strict mode. |
536 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | 332 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
537 } | 333 } |
538 ExpectSemicolon(CHECK_OK); | 334 ExpectSemicolon(CHECK_OK); |
539 return Statement::Jump(); | 335 return Statement::Jump(); |
540 } | 336 } |
541 | 337 |
542 | 338 PreParser::Statement PreParser::ParseBreakStatement( |
543 PreParser::Statement PreParser::ParseBreakStatement(bool* ok) { | 339 ZoneList<const AstRawString*>* labels, bool* ok) { |
544 // BreakStatement :: | 340 // BreakStatement :: |
545 // 'break' [no line terminator] Identifier? ';' | 341 // 'break' [no line terminator] Identifier? ';' |
546 | 342 |
547 Expect(Token::BREAK, CHECK_OK); | 343 Expect(Token::BREAK, CHECK_OK); |
548 Token::Value tok = peek(); | 344 Token::Value tok = peek(); |
549 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | 345 if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
550 tok != Token::SEMICOLON && | 346 tok != Token::SEMICOLON && |
551 tok != Token::RBRACE && | 347 tok != Token::RBRACE && |
552 tok != Token::EOS) { | 348 tok != Token::EOS) { |
553 // ECMA allows "eval" or "arguments" as labels even in strict mode. | 349 // ECMA allows "eval" or "arguments" as labels even in strict mode. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
586 : ReturnExprContext::kInsideValidReturnStatement; | 382 : ReturnExprContext::kInsideValidReturnStatement; |
587 | 383 |
588 ReturnExprScope maybe_allow_tail_calls(function_state_, | 384 ReturnExprScope maybe_allow_tail_calls(function_state_, |
589 return_expr_context); | 385 return_expr_context); |
590 ParseExpression(true, CHECK_OK); | 386 ParseExpression(true, CHECK_OK); |
591 } | 387 } |
592 ExpectSemicolon(CHECK_OK); | 388 ExpectSemicolon(CHECK_OK); |
593 return Statement::Jump(); | 389 return Statement::Jump(); |
594 } | 390 } |
595 | 391 |
596 | 392 PreParser::Statement PreParser::ParseWithStatement( |
597 PreParser::Statement PreParser::ParseWithStatement(bool* ok) { | 393 ZoneList<const AstRawString*>* labels, bool* ok) { |
598 // WithStatement :: | 394 // WithStatement :: |
599 // 'with' '(' Expression ')' Statement | 395 // 'with' '(' Expression ')' Statement |
600 Expect(Token::WITH, CHECK_OK); | 396 Expect(Token::WITH, CHECK_OK); |
601 if (is_strict(language_mode())) { | 397 if (is_strict(language_mode())) { |
602 ReportMessageAt(scanner()->location(), MessageTemplate::kStrictWith); | 398 ReportMessageAt(scanner()->location(), MessageTemplate::kStrictWith); |
603 *ok = false; | 399 *ok = false; |
604 return Statement::Default(); | 400 return Statement::Default(); |
605 } | 401 } |
606 Expect(Token::LPAREN, CHECK_OK); | 402 Expect(Token::LPAREN, CHECK_OK); |
607 ParseExpression(true, CHECK_OK); | 403 ParseExpression(true, CHECK_OK); |
608 Expect(Token::RPAREN, CHECK_OK); | 404 Expect(Token::RPAREN, CHECK_OK); |
609 | 405 |
610 Scope* with_scope = NewScope(WITH_SCOPE); | 406 Scope* with_scope = NewScope(WITH_SCOPE); |
611 BlockState block_state(&scope_state_, with_scope); | 407 BlockState block_state(&scope_state_, with_scope); |
612 ParseScopedStatement(true, CHECK_OK); | 408 ParseScopedStatement(true, CHECK_OK); |
613 return Statement::Default(); | 409 return Statement::Default(); |
614 } | 410 } |
615 | 411 |
616 | 412 PreParser::Statement PreParser::ParseSwitchStatement( |
617 PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) { | 413 ZoneList<const AstRawString*>* labels, bool* ok) { |
618 // SwitchStatement :: | 414 // SwitchStatement :: |
619 // 'switch' '(' Expression ')' '{' CaseClause* '}' | 415 // 'switch' '(' Expression ')' '{' CaseClause* '}' |
620 | 416 |
621 Expect(Token::SWITCH, CHECK_OK); | 417 Expect(Token::SWITCH, CHECK_OK); |
622 Expect(Token::LPAREN, CHECK_OK); | 418 Expect(Token::LPAREN, CHECK_OK); |
623 ParseExpression(true, CHECK_OK); | 419 ParseExpression(true, CHECK_OK); |
624 Expect(Token::RPAREN, CHECK_OK); | 420 Expect(Token::RPAREN, CHECK_OK); |
625 | 421 |
626 { | 422 { |
627 BlockState cases_block_state(&scope_state_); | 423 BlockState cases_block_state(&scope_state_); |
(...skipping 14 matching lines...) Expand all Loading... |
642 token != Token::RBRACE) { | 438 token != Token::RBRACE) { |
643 statement = ParseStatementListItem(CHECK_OK); | 439 statement = ParseStatementListItem(CHECK_OK); |
644 token = peek(); | 440 token = peek(); |
645 } | 441 } |
646 } | 442 } |
647 } | 443 } |
648 Expect(Token::RBRACE, ok); | 444 Expect(Token::RBRACE, ok); |
649 return Statement::Default(); | 445 return Statement::Default(); |
650 } | 446 } |
651 | 447 |
652 | 448 PreParser::Statement PreParser::ParseDoWhileStatement( |
653 PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) { | 449 ZoneList<const AstRawString*>* labels, bool* ok) { |
654 // DoStatement :: | 450 // DoStatement :: |
655 // 'do' Statement 'while' '(' Expression ')' ';' | 451 // 'do' Statement 'while' '(' Expression ')' ';' |
656 | 452 |
657 Expect(Token::DO, CHECK_OK); | 453 Expect(Token::DO, CHECK_OK); |
658 ParseScopedStatement(true, CHECK_OK); | 454 ParseScopedStatement(true, CHECK_OK); |
659 Expect(Token::WHILE, CHECK_OK); | 455 Expect(Token::WHILE, CHECK_OK); |
660 Expect(Token::LPAREN, CHECK_OK); | 456 Expect(Token::LPAREN, CHECK_OK); |
661 ParseExpression(true, CHECK_OK); | 457 ParseExpression(true, CHECK_OK); |
662 Expect(Token::RPAREN, ok); | 458 Expect(Token::RPAREN, ok); |
663 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON); | 459 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON); |
664 return Statement::Default(); | 460 return Statement::Default(); |
665 } | 461 } |
666 | 462 |
667 | 463 PreParser::Statement PreParser::ParseWhileStatement( |
668 PreParser::Statement PreParser::ParseWhileStatement(bool* ok) { | 464 ZoneList<const AstRawString*>* labels, bool* ok) { |
669 // WhileStatement :: | 465 // WhileStatement :: |
670 // 'while' '(' Expression ')' Statement | 466 // 'while' '(' Expression ')' Statement |
671 | 467 |
672 Expect(Token::WHILE, CHECK_OK); | 468 Expect(Token::WHILE, CHECK_OK); |
673 Expect(Token::LPAREN, CHECK_OK); | 469 Expect(Token::LPAREN, CHECK_OK); |
674 ParseExpression(true, CHECK_OK); | 470 ParseExpression(true, CHECK_OK); |
675 Expect(Token::RPAREN, CHECK_OK); | 471 Expect(Token::RPAREN, CHECK_OK); |
676 ParseScopedStatement(true, ok); | 472 ParseScopedStatement(true, ok); |
677 return Statement::Default(); | 473 return Statement::Default(); |
678 } | 474 } |
679 | 475 |
680 | 476 PreParser::Statement PreParser::ParseForStatement( |
681 PreParser::Statement PreParser::ParseForStatement(bool* ok) { | 477 ZoneList<const AstRawString*>* labels, bool* ok) { |
682 // ForStatement :: | 478 // ForStatement :: |
683 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 479 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
684 | 480 |
685 // Create an in-between scope for let-bound iteration variables. | 481 // Create an in-between scope for let-bound iteration variables. |
686 bool has_lexical = false; | 482 bool has_lexical = false; |
687 | 483 |
688 BlockState block_state(&scope_state_); | 484 BlockState block_state(&scope_state_); |
689 Expect(Token::FOR, CHECK_OK); | 485 Expect(Token::FOR, CHECK_OK); |
690 Expect(Token::LPAREN, CHECK_OK); | 486 Expect(Token::LPAREN, CHECK_OK); |
691 if (peek() != Token::SEMICOLON) { | 487 if (peek() != Token::SEMICOLON) { |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
837 // 'catch' '(' Identifier ')' Block | 633 // 'catch' '(' Identifier ')' Block |
838 // | 634 // |
839 // Finally :: | 635 // Finally :: |
840 // 'finally' Block | 636 // 'finally' Block |
841 | 637 |
842 Expect(Token::TRY, CHECK_OK); | 638 Expect(Token::TRY, CHECK_OK); |
843 | 639 |
844 { | 640 { |
845 ReturnExprScope no_tail_calls(function_state_, | 641 ReturnExprScope no_tail_calls(function_state_, |
846 ReturnExprContext::kInsideTryBlock); | 642 ReturnExprContext::kInsideTryBlock); |
847 ParseBlock(CHECK_OK); | 643 ParseBlock(nullptr, CHECK_OK); |
848 } | 644 } |
849 | 645 |
850 Token::Value tok = peek(); | 646 Token::Value tok = peek(); |
851 if (tok != Token::CATCH && tok != Token::FINALLY) { | 647 if (tok != Token::CATCH && tok != Token::FINALLY) { |
852 ReportMessageAt(scanner()->location(), MessageTemplate::kNoCatchOrFinally); | 648 ReportMessageAt(scanner()->location(), MessageTemplate::kNoCatchOrFinally); |
853 *ok = false; | 649 *ok = false; |
854 return Statement::Default(); | 650 return Statement::Default(); |
855 } | 651 } |
856 TailCallExpressionList tail_call_expressions_in_catch_block(zone()); | 652 TailCallExpressionList tail_call_expressions_in_catch_block(zone()); |
857 bool catch_block_exists = false; | 653 bool catch_block_exists = false; |
858 if (tok == Token::CATCH) { | 654 if (tok == Token::CATCH) { |
859 Consume(Token::CATCH); | 655 Consume(Token::CATCH); |
860 Expect(Token::LPAREN, CHECK_OK); | 656 Expect(Token::LPAREN, CHECK_OK); |
861 Scope* catch_scope = NewScope(CATCH_SCOPE); | 657 Scope* catch_scope = NewScope(CATCH_SCOPE); |
862 ExpressionClassifier pattern_classifier(this); | 658 ExpressionClassifier pattern_classifier(this); |
863 ParsePrimaryExpression(CHECK_OK); | 659 ParsePrimaryExpression(CHECK_OK); |
864 ValidateBindingPattern(CHECK_OK); | 660 ValidateBindingPattern(CHECK_OK); |
865 Expect(Token::RPAREN, CHECK_OK); | 661 Expect(Token::RPAREN, CHECK_OK); |
866 { | 662 { |
867 CollectExpressionsInTailPositionToListScope | 663 CollectExpressionsInTailPositionToListScope |
868 collect_tail_call_expressions_scope( | 664 collect_tail_call_expressions_scope( |
869 function_state_, &tail_call_expressions_in_catch_block); | 665 function_state_, &tail_call_expressions_in_catch_block); |
870 BlockState block_state(&scope_state_, catch_scope); | 666 BlockState block_state(&scope_state_, catch_scope); |
871 { | 667 { |
872 BlockState block_state(&scope_state_); | 668 BlockState block_state(&scope_state_); |
873 ParseBlock(CHECK_OK); | 669 ParseBlock(nullptr, CHECK_OK); |
874 } | 670 } |
875 } | 671 } |
876 catch_block_exists = true; | 672 catch_block_exists = true; |
877 tok = peek(); | 673 tok = peek(); |
878 } | 674 } |
879 if (tok == Token::FINALLY) { | 675 if (tok == Token::FINALLY) { |
880 Consume(Token::FINALLY); | 676 Consume(Token::FINALLY); |
881 ParseBlock(CHECK_OK); | 677 ParseBlock(nullptr, CHECK_OK); |
882 if (FLAG_harmony_explicit_tailcalls && catch_block_exists && | 678 if (FLAG_harmony_explicit_tailcalls && catch_block_exists && |
883 tail_call_expressions_in_catch_block.has_explicit_tail_calls()) { | 679 tail_call_expressions_in_catch_block.has_explicit_tail_calls()) { |
884 // TODO(ishell): update chapter number. | 680 // TODO(ishell): update chapter number. |
885 // ES8 XX.YY.ZZ | 681 // ES8 XX.YY.ZZ |
886 ReportMessageAt(tail_call_expressions_in_catch_block.location(), | 682 ReportMessageAt(tail_call_expressions_in_catch_block.location(), |
887 MessageTemplate::kUnexpectedTailCallInCatchBlock); | 683 MessageTemplate::kUnexpectedTailCallInCatchBlock); |
888 *ok = false; | 684 *ok = false; |
889 return Statement::Default(); | 685 return Statement::Default(); |
890 } | 686 } |
891 } | 687 } |
(...skipping 20 matching lines...) Expand all Loading... |
912 | 708 |
913 PreParser::Expression PreParser::ParseFunctionLiteral( | 709 PreParser::Expression PreParser::ParseFunctionLiteral( |
914 Identifier function_name, Scanner::Location function_name_location, | 710 Identifier function_name, Scanner::Location function_name_location, |
915 FunctionNameValidity function_name_validity, FunctionKind kind, | 711 FunctionNameValidity function_name_validity, FunctionKind kind, |
916 int function_token_pos, FunctionLiteral::FunctionType function_type, | 712 int function_token_pos, FunctionLiteral::FunctionType function_type, |
917 LanguageMode language_mode, bool* ok) { | 713 LanguageMode language_mode, bool* ok) { |
918 // Function :: | 714 // Function :: |
919 // '(' FormalParameterList? ')' '{' FunctionBody '}' | 715 // '(' FormalParameterList? ')' '{' FunctionBody '}' |
920 | 716 |
921 // Parse function body. | 717 // Parse function body. |
| 718 PreParserStatementList body; |
922 bool outer_is_script_scope = scope()->is_script_scope(); | 719 bool outer_is_script_scope = scope()->is_script_scope(); |
923 DeclarationScope* function_scope = NewFunctionScope(kind); | 720 DeclarationScope* function_scope = NewFunctionScope(kind); |
924 function_scope->SetLanguageMode(language_mode); | 721 function_scope->SetLanguageMode(language_mode); |
925 FunctionState function_state(&function_state_, &scope_state_, function_scope, | 722 FunctionState function_state(&function_state_, &scope_state_, function_scope, |
926 kind); | 723 kind); |
927 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); | 724 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); |
928 ExpressionClassifier formals_classifier(this, &duplicate_finder); | 725 ExpressionClassifier formals_classifier(this, &duplicate_finder); |
929 | 726 |
930 Expect(Token::LPAREN, CHECK_OK); | 727 Expect(Token::LPAREN, CHECK_OK); |
931 int start_position = scanner()->location().beg_pos; | 728 int start_position = scanner()->location().beg_pos; |
932 function_scope->set_start_position(start_position); | 729 function_scope->set_start_position(start_position); |
933 PreParserFormalParameters formals(function_scope); | 730 PreParserFormalParameters formals(function_scope); |
934 ParseFormalParameterList(&formals, CHECK_OK); | 731 ParseFormalParameterList(&formals, CHECK_OK); |
935 Expect(Token::RPAREN, CHECK_OK); | 732 Expect(Token::RPAREN, CHECK_OK); |
936 int formals_end_position = scanner()->location().end_pos; | 733 int formals_end_position = scanner()->location().end_pos; |
937 | 734 |
938 CheckArityRestrictions(formals.arity, kind, formals.has_rest, start_position, | 735 CheckArityRestrictions(formals.arity, kind, formals.has_rest, start_position, |
939 formals_end_position, CHECK_OK); | 736 formals_end_position, CHECK_OK); |
940 | 737 |
941 // See Parser::ParseFunctionLiteral for more information about lazy parsing | 738 // See Parser::ParseFunctionLiteral for more information about lazy parsing |
942 // and lazy compilation. | 739 // and lazy compilation. |
943 bool is_lazily_parsed = (outer_is_script_scope && allow_lazy() && | 740 bool is_lazily_parsed = (outer_is_script_scope && allow_lazy() && |
944 !function_state_->this_function_is_parenthesized()); | 741 !function_state_->this_function_is_parenthesized()); |
945 | 742 |
946 Expect(Token::LBRACE, CHECK_OK); | 743 Expect(Token::LBRACE, CHECK_OK); |
947 if (is_lazily_parsed) { | 744 if (is_lazily_parsed) { |
948 ParseLazyFunctionLiteralBody(false, CHECK_OK); | 745 ParseLazyFunctionLiteralBody(false, CHECK_OK); |
949 } else { | 746 } else { |
950 ParseStatementList(Token::RBRACE, CHECK_OK); | 747 ParseStatementList(body, Token::RBRACE, CHECK_OK); |
951 } | 748 } |
952 Expect(Token::RBRACE, CHECK_OK); | 749 Expect(Token::RBRACE, CHECK_OK); |
953 | 750 |
954 // Parsing the body may change the language mode in our scope. | 751 // Parsing the body may change the language mode in our scope. |
955 language_mode = function_scope->language_mode(); | 752 language_mode = function_scope->language_mode(); |
956 | 753 |
957 // Validate name and parameter names. We can do this only after parsing the | 754 // Validate name and parameter names. We can do this only after parsing the |
958 // function, since the function can declare itself strict. | 755 // function, since the function can declare itself strict. |
959 CheckFunctionName(language_mode, function_name, function_name_validity, | 756 CheckFunctionName(language_mode, function_name, function_name_validity, |
960 function_name_location, CHECK_OK); | 757 function_name_location, CHECK_OK); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
995 is_strict_reserved ? kFunctionNameIsStrictReserved | 792 is_strict_reserved ? kFunctionNameIsStrictReserved |
996 : kFunctionNameValidityUnknown, | 793 : kFunctionNameValidityUnknown, |
997 FunctionKind::kAsyncFunction, pos, type, language_mode(), | 794 FunctionKind::kAsyncFunction, pos, type, language_mode(), |
998 CHECK_OK); | 795 CHECK_OK); |
999 return Expression::Default(); | 796 return Expression::Default(); |
1000 } | 797 } |
1001 | 798 |
1002 PreParser::LazyParsingResult PreParser::ParseLazyFunctionLiteralBody( | 799 PreParser::LazyParsingResult PreParser::ParseLazyFunctionLiteralBody( |
1003 bool may_abort, bool* ok) { | 800 bool may_abort, bool* ok) { |
1004 int body_start = position(); | 801 int body_start = position(); |
| 802 PreParserStatementList body; |
1005 LazyParsingResult result = ParseStatementList( | 803 LazyParsingResult result = ParseStatementList( |
1006 Token::RBRACE, may_abort, CHECK_OK_VALUE(kLazyParsingComplete)); | 804 body, Token::RBRACE, may_abort, CHECK_OK_VALUE(kLazyParsingComplete)); |
1007 if (result == kLazyParsingAborted) return result; | 805 if (result == kLazyParsingAborted) return result; |
1008 | 806 |
1009 // Position right after terminal '}'. | 807 // Position right after terminal '}'. |
1010 DCHECK_EQ(Token::RBRACE, scanner()->peek()); | 808 DCHECK_EQ(Token::RBRACE, scanner()->peek()); |
1011 int body_end = scanner()->peek_location().end_pos; | 809 int body_end = scanner()->peek_location().end_pos; |
1012 DeclarationScope* scope = this->scope()->AsDeclarationScope(); | 810 DeclarationScope* scope = this->scope()->AsDeclarationScope(); |
1013 DCHECK(scope->is_function_scope()); | 811 DCHECK(scope->is_function_scope()); |
1014 log_->LogFunction(body_start, body_end, | 812 log_->LogFunction(body_start, body_end, |
1015 function_state_->materialized_literal_count(), | 813 function_state_->materialized_literal_count(), |
1016 function_state_->expected_property_count(), language_mode(), | 814 function_state_->expected_property_count(), language_mode(), |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1116 | 914 |
1117 body->Add(PreParserStatement::ExpressionStatement(return_value), zone()); | 915 body->Add(PreParserStatement::ExpressionStatement(return_value), zone()); |
1118 } | 916 } |
1119 | 917 |
1120 #undef CHECK_OK | 918 #undef CHECK_OK |
1121 #undef CHECK_OK_CUSTOM | 919 #undef CHECK_OK_CUSTOM |
1122 | 920 |
1123 | 921 |
1124 } // namespace internal | 922 } // namespace internal |
1125 } // namespace v8 | 923 } // namespace v8 |
OLD | NEW |