OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "src/parser.h" | |
6 | |
7 #include "src/api.h" | |
8 #include "src/ast.h" | |
9 #include "src/ast-literal-reindexer.h" | |
10 #include "src/bailout-reason.h" | |
11 #include "src/base/platform/platform.h" | |
12 #include "src/bootstrapper.h" | |
13 #include "src/char-predicates-inl.h" | |
14 #include "src/codegen.h" | |
15 #include "src/compiler.h" | |
16 #include "src/messages.h" | |
17 #include "src/parameter-initializer-rewriter.h" | |
18 #include "src/preparser.h" | |
19 #include "src/rewriter.h" | |
20 #include "src/runtime/runtime.h" | |
21 #include "src/scanner-character-streams.h" | |
22 #include "src/scopeinfo.h" | |
23 #include "src/string-stream.h" | |
24 | |
25 namespace v8 { | |
26 namespace internal { | |
27 | |
28 ScriptData::ScriptData(const byte* data, int length) | |
29 : owns_data_(false), rejected_(false), data_(data), length_(length) { | |
30 if (!IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment)) { | |
31 byte* copy = NewArray<byte>(length); | |
32 DCHECK(IsAligned(reinterpret_cast<intptr_t>(copy), kPointerAlignment)); | |
33 CopyBytes(copy, data, length); | |
34 data_ = copy; | |
35 AcquireDataOwnership(); | |
36 } | |
37 } | |
38 | |
39 | |
40 ParseInfo::ParseInfo(Zone* zone) | |
41 : zone_(zone), | |
42 flags_(0), | |
43 source_stream_(nullptr), | |
44 source_stream_encoding_(ScriptCompiler::StreamedSource::ONE_BYTE), | |
45 extension_(nullptr), | |
46 compile_options_(ScriptCompiler::kNoCompileOptions), | |
47 script_scope_(nullptr), | |
48 unicode_cache_(nullptr), | |
49 stack_limit_(0), | |
50 hash_seed_(0), | |
51 cached_data_(nullptr), | |
52 ast_value_factory_(nullptr), | |
53 literal_(nullptr), | |
54 scope_(nullptr) {} | |
55 | |
56 | |
57 ParseInfo::ParseInfo(Zone* zone, Handle<JSFunction> function) | |
58 : ParseInfo(zone, Handle<SharedFunctionInfo>(function->shared())) { | |
59 set_closure(function); | |
60 set_context(Handle<Context>(function->context())); | |
61 } | |
62 | |
63 | |
64 ParseInfo::ParseInfo(Zone* zone, Handle<SharedFunctionInfo> shared) | |
65 : ParseInfo(zone) { | |
66 isolate_ = shared->GetIsolate(); | |
67 | |
68 set_lazy(); | |
69 set_hash_seed(isolate_->heap()->HashSeed()); | |
70 set_stack_limit(isolate_->stack_guard()->real_climit()); | |
71 set_unicode_cache(isolate_->unicode_cache()); | |
72 set_language_mode(shared->language_mode()); | |
73 set_shared_info(shared); | |
74 | |
75 Handle<Script> script(Script::cast(shared->script())); | |
76 set_script(script); | |
77 if (!script.is_null() && script->type() == Script::TYPE_NATIVE) { | |
78 set_native(); | |
79 } | |
80 } | |
81 | |
82 | |
83 ParseInfo::ParseInfo(Zone* zone, Handle<Script> script) : ParseInfo(zone) { | |
84 isolate_ = script->GetIsolate(); | |
85 | |
86 set_hash_seed(isolate_->heap()->HashSeed()); | |
87 set_stack_limit(isolate_->stack_guard()->real_climit()); | |
88 set_unicode_cache(isolate_->unicode_cache()); | |
89 set_script(script); | |
90 | |
91 if (script->type() == Script::TYPE_NATIVE) { | |
92 set_native(); | |
93 } | |
94 } | |
95 | |
96 | |
97 RegExpBuilder::RegExpBuilder(Zone* zone) | |
98 : zone_(zone), | |
99 pending_empty_(false), | |
100 characters_(NULL), | |
101 terms_(), | |
102 alternatives_() | |
103 #ifdef DEBUG | |
104 , last_added_(ADD_NONE) | |
105 #endif | |
106 {} | |
107 | |
108 | |
109 void RegExpBuilder::FlushCharacters() { | |
110 pending_empty_ = false; | |
111 if (characters_ != NULL) { | |
112 RegExpTree* atom = new(zone()) RegExpAtom(characters_->ToConstVector()); | |
113 characters_ = NULL; | |
114 text_.Add(atom, zone()); | |
115 LAST(ADD_ATOM); | |
116 } | |
117 } | |
118 | |
119 | |
120 void RegExpBuilder::FlushText() { | |
121 FlushCharacters(); | |
122 int num_text = text_.length(); | |
123 if (num_text == 0) { | |
124 return; | |
125 } else if (num_text == 1) { | |
126 terms_.Add(text_.last(), zone()); | |
127 } else { | |
128 RegExpText* text = new(zone()) RegExpText(zone()); | |
129 for (int i = 0; i < num_text; i++) | |
130 text_.Get(i)->AppendToText(text, zone()); | |
131 terms_.Add(text, zone()); | |
132 } | |
133 text_.Clear(); | |
134 } | |
135 | |
136 | |
137 void RegExpBuilder::AddCharacter(uc16 c) { | |
138 pending_empty_ = false; | |
139 if (characters_ == NULL) { | |
140 characters_ = new(zone()) ZoneList<uc16>(4, zone()); | |
141 } | |
142 characters_->Add(c, zone()); | |
143 LAST(ADD_CHAR); | |
144 } | |
145 | |
146 | |
147 void RegExpBuilder::AddEmpty() { | |
148 pending_empty_ = true; | |
149 } | |
150 | |
151 | |
152 void RegExpBuilder::AddAtom(RegExpTree* term) { | |
153 if (term->IsEmpty()) { | |
154 AddEmpty(); | |
155 return; | |
156 } | |
157 if (term->IsTextElement()) { | |
158 FlushCharacters(); | |
159 text_.Add(term, zone()); | |
160 } else { | |
161 FlushText(); | |
162 terms_.Add(term, zone()); | |
163 } | |
164 LAST(ADD_ATOM); | |
165 } | |
166 | |
167 | |
168 void RegExpBuilder::AddAssertion(RegExpTree* assert) { | |
169 FlushText(); | |
170 terms_.Add(assert, zone()); | |
171 LAST(ADD_ASSERT); | |
172 } | |
173 | |
174 | |
175 void RegExpBuilder::NewAlternative() { | |
176 FlushTerms(); | |
177 } | |
178 | |
179 | |
180 void RegExpBuilder::FlushTerms() { | |
181 FlushText(); | |
182 int num_terms = terms_.length(); | |
183 RegExpTree* alternative; | |
184 if (num_terms == 0) { | |
185 alternative = new (zone()) RegExpEmpty(); | |
186 } else if (num_terms == 1) { | |
187 alternative = terms_.last(); | |
188 } else { | |
189 alternative = new(zone()) RegExpAlternative(terms_.GetList(zone())); | |
190 } | |
191 alternatives_.Add(alternative, zone()); | |
192 terms_.Clear(); | |
193 LAST(ADD_NONE); | |
194 } | |
195 | |
196 | |
197 RegExpTree* RegExpBuilder::ToRegExp() { | |
198 FlushTerms(); | |
199 int num_alternatives = alternatives_.length(); | |
200 if (num_alternatives == 0) return new (zone()) RegExpEmpty(); | |
201 if (num_alternatives == 1) return alternatives_.last(); | |
202 return new(zone()) RegExpDisjunction(alternatives_.GetList(zone())); | |
203 } | |
204 | |
205 | |
206 void RegExpBuilder::AddQuantifierToAtom( | |
207 int min, int max, RegExpQuantifier::QuantifierType quantifier_type) { | |
208 if (pending_empty_) { | |
209 pending_empty_ = false; | |
210 return; | |
211 } | |
212 RegExpTree* atom; | |
213 if (characters_ != NULL) { | |
214 DCHECK(last_added_ == ADD_CHAR); | |
215 // Last atom was character. | |
216 Vector<const uc16> char_vector = characters_->ToConstVector(); | |
217 int num_chars = char_vector.length(); | |
218 if (num_chars > 1) { | |
219 Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1); | |
220 text_.Add(new(zone()) RegExpAtom(prefix), zone()); | |
221 char_vector = char_vector.SubVector(num_chars - 1, num_chars); | |
222 } | |
223 characters_ = NULL; | |
224 atom = new(zone()) RegExpAtom(char_vector); | |
225 FlushText(); | |
226 } else if (text_.length() > 0) { | |
227 DCHECK(last_added_ == ADD_ATOM); | |
228 atom = text_.RemoveLast(); | |
229 FlushText(); | |
230 } else if (terms_.length() > 0) { | |
231 DCHECK(last_added_ == ADD_ATOM); | |
232 atom = terms_.RemoveLast(); | |
233 if (atom->max_match() == 0) { | |
234 // Guaranteed to only match an empty string. | |
235 LAST(ADD_TERM); | |
236 if (min == 0) { | |
237 return; | |
238 } | |
239 terms_.Add(atom, zone()); | |
240 return; | |
241 } | |
242 } else { | |
243 // Only call immediately after adding an atom or character! | |
244 UNREACHABLE(); | |
245 return; | |
246 } | |
247 terms_.Add( | |
248 new(zone()) RegExpQuantifier(min, max, quantifier_type, atom), zone()); | |
249 LAST(ADD_TERM); | |
250 } | |
251 | |
252 | |
253 FunctionEntry ParseData::GetFunctionEntry(int start) { | |
254 // The current pre-data entry must be a FunctionEntry with the given | |
255 // start position. | |
256 if ((function_index_ + FunctionEntry::kSize <= Length()) && | |
257 (static_cast<int>(Data()[function_index_]) == start)) { | |
258 int index = function_index_; | |
259 function_index_ += FunctionEntry::kSize; | |
260 Vector<unsigned> subvector(&(Data()[index]), FunctionEntry::kSize); | |
261 return FunctionEntry(subvector); | |
262 } | |
263 return FunctionEntry(); | |
264 } | |
265 | |
266 | |
267 int ParseData::FunctionCount() { | |
268 int functions_size = FunctionsSize(); | |
269 if (functions_size < 0) return 0; | |
270 if (functions_size % FunctionEntry::kSize != 0) return 0; | |
271 return functions_size / FunctionEntry::kSize; | |
272 } | |
273 | |
274 | |
275 bool ParseData::IsSane() { | |
276 if (!IsAligned(script_data_->length(), sizeof(unsigned))) return false; | |
277 // Check that the header data is valid and doesn't specify | |
278 // point to positions outside the store. | |
279 int data_length = Length(); | |
280 if (data_length < PreparseDataConstants::kHeaderSize) return false; | |
281 if (Magic() != PreparseDataConstants::kMagicNumber) return false; | |
282 if (Version() != PreparseDataConstants::kCurrentVersion) return false; | |
283 if (HasError()) return false; | |
284 // Check that the space allocated for function entries is sane. | |
285 int functions_size = FunctionsSize(); | |
286 if (functions_size < 0) return false; | |
287 if (functions_size % FunctionEntry::kSize != 0) return false; | |
288 // Check that the total size has room for header and function entries. | |
289 int minimum_size = | |
290 PreparseDataConstants::kHeaderSize + functions_size; | |
291 if (data_length < minimum_size) return false; | |
292 return true; | |
293 } | |
294 | |
295 | |
296 void ParseData::Initialize() { | |
297 // Prepares state for use. | |
298 int data_length = Length(); | |
299 if (data_length >= PreparseDataConstants::kHeaderSize) { | |
300 function_index_ = PreparseDataConstants::kHeaderSize; | |
301 } | |
302 } | |
303 | |
304 | |
305 bool ParseData::HasError() { | |
306 return Data()[PreparseDataConstants::kHasErrorOffset]; | |
307 } | |
308 | |
309 | |
310 unsigned ParseData::Magic() { | |
311 return Data()[PreparseDataConstants::kMagicOffset]; | |
312 } | |
313 | |
314 | |
315 unsigned ParseData::Version() { | |
316 return Data()[PreparseDataConstants::kVersionOffset]; | |
317 } | |
318 | |
319 | |
320 int ParseData::FunctionsSize() { | |
321 return static_cast<int>(Data()[PreparseDataConstants::kFunctionsSizeOffset]); | |
322 } | |
323 | |
324 | |
325 void Parser::SetCachedData(ParseInfo* info) { | |
326 if (compile_options_ == ScriptCompiler::kNoCompileOptions) { | |
327 cached_parse_data_ = NULL; | |
328 } else { | |
329 DCHECK(info->cached_data() != NULL); | |
330 if (compile_options_ == ScriptCompiler::kConsumeParserCache) { | |
331 cached_parse_data_ = ParseData::FromCachedData(*info->cached_data()); | |
332 } | |
333 } | |
334 } | |
335 | |
336 | |
337 FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope, | |
338 int pos, int end_pos, | |
339 LanguageMode language_mode) { | |
340 int materialized_literal_count = -1; | |
341 int expected_property_count = -1; | |
342 int parameter_count = 0; | |
343 const AstRawString* name = ast_value_factory()->empty_string(); | |
344 | |
345 | |
346 FunctionKind kind = call_super ? FunctionKind::kDefaultSubclassConstructor | |
347 : FunctionKind::kDefaultBaseConstructor; | |
348 Scope* function_scope = NewScope(scope, FUNCTION_SCOPE, kind); | |
349 SetLanguageMode(function_scope, | |
350 static_cast<LanguageMode>(language_mode | STRICT)); | |
351 // Set start and end position to the same value | |
352 function_scope->set_start_position(pos); | |
353 function_scope->set_end_position(pos); | |
354 ZoneList<Statement*>* body = NULL; | |
355 | |
356 { | |
357 AstNodeFactory function_factory(ast_value_factory()); | |
358 FunctionState function_state(&function_state_, &scope_, function_scope, | |
359 kind, &function_factory); | |
360 | |
361 body = new (zone()) ZoneList<Statement*>(call_super ? 2 : 1, zone()); | |
362 if (call_super) { | |
363 // %_DefaultConstructorCallSuper(new.target, %GetPrototype(<this-fun>)) | |
364 ZoneList<Expression*>* args = | |
365 new (zone()) ZoneList<Expression*>(2, zone()); | |
366 VariableProxy* new_target_proxy = scope_->NewUnresolved( | |
367 factory(), ast_value_factory()->new_target_string(), Variable::NORMAL, | |
368 pos); | |
369 args->Add(new_target_proxy, zone()); | |
370 VariableProxy* this_function_proxy = scope_->NewUnresolved( | |
371 factory(), ast_value_factory()->this_function_string(), | |
372 Variable::NORMAL, pos); | |
373 ZoneList<Expression*>* tmp = | |
374 new (zone()) ZoneList<Expression*>(1, zone()); | |
375 tmp->Add(this_function_proxy, zone()); | |
376 Expression* get_prototype = | |
377 factory()->NewCallRuntime(Runtime::kGetPrototype, tmp, pos); | |
378 args->Add(get_prototype, zone()); | |
379 CallRuntime* call = factory()->NewCallRuntime( | |
380 Runtime::kInlineDefaultConstructorCallSuper, args, pos); | |
381 body->Add(factory()->NewReturnStatement(call, pos), zone()); | |
382 } | |
383 | |
384 materialized_literal_count = function_state.materialized_literal_count(); | |
385 expected_property_count = function_state.expected_property_count(); | |
386 } | |
387 | |
388 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( | |
389 name, ast_value_factory(), function_scope, body, | |
390 materialized_literal_count, expected_property_count, parameter_count, | |
391 FunctionLiteral::kNoDuplicateParameters, | |
392 FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kIsFunction, | |
393 FunctionLiteral::kShouldLazyCompile, kind, pos); | |
394 | |
395 return function_literal; | |
396 } | |
397 | |
398 | |
399 // ---------------------------------------------------------------------------- | |
400 // Target is a support class to facilitate manipulation of the | |
401 // Parser's target_stack_ (the stack of potential 'break' and | |
402 // 'continue' statement targets). Upon construction, a new target is | |
403 // added; it is removed upon destruction. | |
404 | |
405 class Target BASE_EMBEDDED { | |
406 public: | |
407 Target(Target** variable, BreakableStatement* statement) | |
408 : variable_(variable), statement_(statement), previous_(*variable) { | |
409 *variable = this; | |
410 } | |
411 | |
412 ~Target() { | |
413 *variable_ = previous_; | |
414 } | |
415 | |
416 Target* previous() { return previous_; } | |
417 BreakableStatement* statement() { return statement_; } | |
418 | |
419 private: | |
420 Target** variable_; | |
421 BreakableStatement* statement_; | |
422 Target* previous_; | |
423 }; | |
424 | |
425 | |
426 class TargetScope BASE_EMBEDDED { | |
427 public: | |
428 explicit TargetScope(Target** variable) | |
429 : variable_(variable), previous_(*variable) { | |
430 *variable = NULL; | |
431 } | |
432 | |
433 ~TargetScope() { | |
434 *variable_ = previous_; | |
435 } | |
436 | |
437 private: | |
438 Target** variable_; | |
439 Target* previous_; | |
440 }; | |
441 | |
442 | |
443 // ---------------------------------------------------------------------------- | |
444 // The CHECK_OK macro is a convenient macro to enforce error | |
445 // handling for functions that may fail (by returning !*ok). | |
446 // | |
447 // CAUTION: This macro appends extra statements after a call, | |
448 // thus it must never be used where only a single statement | |
449 // is correct (e.g. an if statement branch w/o braces)! | |
450 | |
451 #define CHECK_OK ok); \ | |
452 if (!*ok) return NULL; \ | |
453 ((void)0 | |
454 #define DUMMY ) // to make indentation work | |
455 #undef DUMMY | |
456 | |
457 #define CHECK_FAILED /**/); \ | |
458 if (failed_) return NULL; \ | |
459 ((void)0 | |
460 #define DUMMY ) // to make indentation work | |
461 #undef DUMMY | |
462 | |
463 // ---------------------------------------------------------------------------- | |
464 // Implementation of Parser | |
465 | |
466 bool ParserTraits::IsEval(const AstRawString* identifier) const { | |
467 return identifier == parser_->ast_value_factory()->eval_string(); | |
468 } | |
469 | |
470 | |
471 bool ParserTraits::IsArguments(const AstRawString* identifier) const { | |
472 return identifier == parser_->ast_value_factory()->arguments_string(); | |
473 } | |
474 | |
475 | |
476 bool ParserTraits::IsEvalOrArguments(const AstRawString* identifier) const { | |
477 return IsEval(identifier) || IsArguments(identifier); | |
478 } | |
479 | |
480 bool ParserTraits::IsUndefined(const AstRawString* identifier) const { | |
481 return identifier == parser_->ast_value_factory()->undefined_string(); | |
482 } | |
483 | |
484 bool ParserTraits::IsPrototype(const AstRawString* identifier) const { | |
485 return identifier == parser_->ast_value_factory()->prototype_string(); | |
486 } | |
487 | |
488 | |
489 bool ParserTraits::IsConstructor(const AstRawString* identifier) const { | |
490 return identifier == parser_->ast_value_factory()->constructor_string(); | |
491 } | |
492 | |
493 | |
494 bool ParserTraits::IsThisProperty(Expression* expression) { | |
495 DCHECK(expression != NULL); | |
496 Property* property = expression->AsProperty(); | |
497 return property != NULL && property->obj()->IsVariableProxy() && | |
498 property->obj()->AsVariableProxy()->is_this(); | |
499 } | |
500 | |
501 | |
502 bool ParserTraits::IsIdentifier(Expression* expression) { | |
503 VariableProxy* operand = expression->AsVariableProxy(); | |
504 return operand != NULL && !operand->is_this(); | |
505 } | |
506 | |
507 | |
508 void ParserTraits::PushPropertyName(FuncNameInferrer* fni, | |
509 Expression* expression) { | |
510 if (expression->IsPropertyName()) { | |
511 fni->PushLiteralName(expression->AsLiteral()->AsRawPropertyName()); | |
512 } else { | |
513 fni->PushLiteralName( | |
514 parser_->ast_value_factory()->anonymous_function_string()); | |
515 } | |
516 } | |
517 | |
518 | |
519 void ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left, | |
520 Expression* right) { | |
521 DCHECK(left != NULL); | |
522 if (left->IsProperty() && right->IsFunctionLiteral()) { | |
523 right->AsFunctionLiteral()->set_pretenure(); | |
524 } | |
525 } | |
526 | |
527 | |
528 void ParserTraits::CheckPossibleEvalCall(Expression* expression, | |
529 Scope* scope) { | |
530 VariableProxy* callee = expression->AsVariableProxy(); | |
531 if (callee != NULL && | |
532 callee->raw_name() == parser_->ast_value_factory()->eval_string()) { | |
533 scope->DeclarationScope()->RecordEvalCall(); | |
534 scope->RecordEvalCall(); | |
535 } | |
536 } | |
537 | |
538 | |
539 Expression* ParserTraits::MarkExpressionAsAssigned(Expression* expression) { | |
540 VariableProxy* proxy = | |
541 expression != NULL ? expression->AsVariableProxy() : NULL; | |
542 if (proxy != NULL) proxy->set_is_assigned(); | |
543 return expression; | |
544 } | |
545 | |
546 | |
547 bool ParserTraits::ShortcutNumericLiteralBinaryExpression( | |
548 Expression** x, Expression* y, Token::Value op, int pos, | |
549 AstNodeFactory* factory) { | |
550 if ((*x)->AsLiteral() && (*x)->AsLiteral()->raw_value()->IsNumber() && | |
551 y->AsLiteral() && y->AsLiteral()->raw_value()->IsNumber()) { | |
552 double x_val = (*x)->AsLiteral()->raw_value()->AsNumber(); | |
553 double y_val = y->AsLiteral()->raw_value()->AsNumber(); | |
554 switch (op) { | |
555 case Token::ADD: | |
556 *x = factory->NewNumberLiteral(x_val + y_val, pos); | |
557 return true; | |
558 case Token::SUB: | |
559 *x = factory->NewNumberLiteral(x_val - y_val, pos); | |
560 return true; | |
561 case Token::MUL: | |
562 *x = factory->NewNumberLiteral(x_val * y_val, pos); | |
563 return true; | |
564 case Token::DIV: | |
565 *x = factory->NewNumberLiteral(x_val / y_val, pos); | |
566 return true; | |
567 case Token::BIT_OR: { | |
568 int value = DoubleToInt32(x_val) | DoubleToInt32(y_val); | |
569 *x = factory->NewNumberLiteral(value, pos); | |
570 return true; | |
571 } | |
572 case Token::BIT_AND: { | |
573 int value = DoubleToInt32(x_val) & DoubleToInt32(y_val); | |
574 *x = factory->NewNumberLiteral(value, pos); | |
575 return true; | |
576 } | |
577 case Token::BIT_XOR: { | |
578 int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val); | |
579 *x = factory->NewNumberLiteral(value, pos); | |
580 return true; | |
581 } | |
582 case Token::SHL: { | |
583 int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f); | |
584 *x = factory->NewNumberLiteral(value, pos); | |
585 return true; | |
586 } | |
587 case Token::SHR: { | |
588 uint32_t shift = DoubleToInt32(y_val) & 0x1f; | |
589 uint32_t value = DoubleToUint32(x_val) >> shift; | |
590 *x = factory->NewNumberLiteral(value, pos); | |
591 return true; | |
592 } | |
593 case Token::SAR: { | |
594 uint32_t shift = DoubleToInt32(y_val) & 0x1f; | |
595 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift); | |
596 *x = factory->NewNumberLiteral(value, pos); | |
597 return true; | |
598 } | |
599 default: | |
600 break; | |
601 } | |
602 } | |
603 return false; | |
604 } | |
605 | |
606 | |
607 Expression* ParserTraits::BuildUnaryExpression(Expression* expression, | |
608 Token::Value op, int pos, | |
609 AstNodeFactory* factory) { | |
610 DCHECK(expression != NULL); | |
611 if (expression->IsLiteral()) { | |
612 const AstValue* literal = expression->AsLiteral()->raw_value(); | |
613 if (op == Token::NOT) { | |
614 // Convert the literal to a boolean condition and negate it. | |
615 bool condition = literal->BooleanValue(); | |
616 return factory->NewBooleanLiteral(!condition, pos); | |
617 } else if (literal->IsNumber()) { | |
618 // Compute some expressions involving only number literals. | |
619 double value = literal->AsNumber(); | |
620 switch (op) { | |
621 case Token::ADD: | |
622 return expression; | |
623 case Token::SUB: | |
624 return factory->NewNumberLiteral(-value, pos); | |
625 case Token::BIT_NOT: | |
626 return factory->NewNumberLiteral(~DoubleToInt32(value), pos); | |
627 default: | |
628 break; | |
629 } | |
630 } | |
631 } | |
632 // Desugar '+foo' => 'foo*1' | |
633 if (op == Token::ADD) { | |
634 return factory->NewBinaryOperation( | |
635 Token::MUL, expression, factory->NewNumberLiteral(1, pos, true), pos); | |
636 } | |
637 // The same idea for '-foo' => 'foo*(-1)'. | |
638 if (op == Token::SUB) { | |
639 return factory->NewBinaryOperation( | |
640 Token::MUL, expression, factory->NewNumberLiteral(-1, pos), pos); | |
641 } | |
642 // ...and one more time for '~foo' => 'foo^(~0)'. | |
643 if (op == Token::BIT_NOT) { | |
644 return factory->NewBinaryOperation( | |
645 Token::BIT_XOR, expression, factory->NewNumberLiteral(~0, pos), pos); | |
646 } | |
647 return factory->NewUnaryOperation(op, expression, pos); | |
648 } | |
649 | |
650 | |
651 Expression* ParserTraits::NewThrowReferenceError( | |
652 MessageTemplate::Template message, int pos) { | |
653 return NewThrowError(Runtime::kNewReferenceError, message, | |
654 parser_->ast_value_factory()->empty_string(), pos); | |
655 } | |
656 | |
657 | |
658 Expression* ParserTraits::NewThrowSyntaxError(MessageTemplate::Template message, | |
659 const AstRawString* arg, | |
660 int pos) { | |
661 return NewThrowError(Runtime::kNewSyntaxError, message, arg, pos); | |
662 } | |
663 | |
664 | |
665 Expression* ParserTraits::NewThrowTypeError(MessageTemplate::Template message, | |
666 const AstRawString* arg, int pos) { | |
667 return NewThrowError(Runtime::kNewTypeError, message, arg, pos); | |
668 } | |
669 | |
670 | |
671 Expression* ParserTraits::NewThrowError(Runtime::FunctionId id, | |
672 MessageTemplate::Template message, | |
673 const AstRawString* arg, int pos) { | |
674 Zone* zone = parser_->zone(); | |
675 ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(2, zone); | |
676 args->Add(parser_->factory()->NewSmiLiteral(message, pos), zone); | |
677 args->Add(parser_->factory()->NewStringLiteral(arg, pos), zone); | |
678 CallRuntime* call_constructor = | |
679 parser_->factory()->NewCallRuntime(id, args, pos); | |
680 return parser_->factory()->NewThrow(call_constructor, pos); | |
681 } | |
682 | |
683 | |
684 void ParserTraits::ReportMessageAt(Scanner::Location source_location, | |
685 MessageTemplate::Template message, | |
686 const char* arg, ParseErrorType error_type) { | |
687 if (parser_->stack_overflow()) { | |
688 // Suppress the error message (syntax error or such) in the presence of a | |
689 // stack overflow. The isolate allows only one pending exception at at time | |
690 // and we want to report the stack overflow later. | |
691 return; | |
692 } | |
693 parser_->pending_error_handler_.ReportMessageAt(source_location.beg_pos, | |
694 source_location.end_pos, | |
695 message, arg, error_type); | |
696 } | |
697 | |
698 | |
699 void ParserTraits::ReportMessage(MessageTemplate::Template message, | |
700 const char* arg, ParseErrorType error_type) { | |
701 Scanner::Location source_location = parser_->scanner()->location(); | |
702 ReportMessageAt(source_location, message, arg, error_type); | |
703 } | |
704 | |
705 | |
706 void ParserTraits::ReportMessage(MessageTemplate::Template message, | |
707 const AstRawString* arg, | |
708 ParseErrorType error_type) { | |
709 Scanner::Location source_location = parser_->scanner()->location(); | |
710 ReportMessageAt(source_location, message, arg, error_type); | |
711 } | |
712 | |
713 | |
714 void ParserTraits::ReportMessageAt(Scanner::Location source_location, | |
715 MessageTemplate::Template message, | |
716 const AstRawString* arg, | |
717 ParseErrorType error_type) { | |
718 if (parser_->stack_overflow()) { | |
719 // Suppress the error message (syntax error or such) in the presence of a | |
720 // stack overflow. The isolate allows only one pending exception at at time | |
721 // and we want to report the stack overflow later. | |
722 return; | |
723 } | |
724 parser_->pending_error_handler_.ReportMessageAt(source_location.beg_pos, | |
725 source_location.end_pos, | |
726 message, arg, error_type); | |
727 } | |
728 | |
729 | |
730 const AstRawString* ParserTraits::GetSymbol(Scanner* scanner) { | |
731 const AstRawString* result = | |
732 parser_->scanner()->CurrentSymbol(parser_->ast_value_factory()); | |
733 DCHECK(result != NULL); | |
734 return result; | |
735 } | |
736 | |
737 | |
738 const AstRawString* ParserTraits::GetNumberAsSymbol(Scanner* scanner) { | |
739 double double_value = parser_->scanner()->DoubleValue(); | |
740 char array[100]; | |
741 const char* string = | |
742 DoubleToCString(double_value, Vector<char>(array, arraysize(array))); | |
743 return parser_->ast_value_factory()->GetOneByteString(string); | |
744 } | |
745 | |
746 | |
747 const AstRawString* ParserTraits::GetNextSymbol(Scanner* scanner) { | |
748 return parser_->scanner()->NextSymbol(parser_->ast_value_factory()); | |
749 } | |
750 | |
751 | |
752 Expression* ParserTraits::ThisExpression(Scope* scope, AstNodeFactory* factory, | |
753 int pos) { | |
754 return scope->NewUnresolved(factory, | |
755 parser_->ast_value_factory()->this_string(), | |
756 Variable::THIS, pos, pos + 4); | |
757 } | |
758 | |
759 | |
760 Expression* ParserTraits::SuperPropertyReference(Scope* scope, | |
761 AstNodeFactory* factory, | |
762 int pos) { | |
763 // this_function[home_object_symbol] | |
764 VariableProxy* this_function_proxy = scope->NewUnresolved( | |
765 factory, parser_->ast_value_factory()->this_function_string(), | |
766 Variable::NORMAL, pos); | |
767 Expression* home_object_symbol_literal = | |
768 factory->NewSymbolLiteral("home_object_symbol", RelocInfo::kNoPosition); | |
769 Expression* home_object = factory->NewProperty( | |
770 this_function_proxy, home_object_symbol_literal, pos); | |
771 return factory->NewSuperPropertyReference( | |
772 ThisExpression(scope, factory, pos)->AsVariableProxy(), home_object, pos); | |
773 } | |
774 | |
775 | |
776 Expression* ParserTraits::SuperCallReference(Scope* scope, | |
777 AstNodeFactory* factory, int pos) { | |
778 VariableProxy* new_target_proxy = scope->NewUnresolved( | |
779 factory, parser_->ast_value_factory()->new_target_string(), | |
780 Variable::NORMAL, pos); | |
781 VariableProxy* this_function_proxy = scope->NewUnresolved( | |
782 factory, parser_->ast_value_factory()->this_function_string(), | |
783 Variable::NORMAL, pos); | |
784 return factory->NewSuperCallReference( | |
785 ThisExpression(scope, factory, pos)->AsVariableProxy(), new_target_proxy, | |
786 this_function_proxy, pos); | |
787 } | |
788 | |
789 | |
790 Expression* ParserTraits::NewTargetExpression(Scope* scope, | |
791 AstNodeFactory* factory, | |
792 int pos) { | |
793 static const int kNewTargetStringLength = 10; | |
794 auto proxy = scope->NewUnresolved( | |
795 factory, parser_->ast_value_factory()->new_target_string(), | |
796 Variable::NORMAL, pos, pos + kNewTargetStringLength); | |
797 proxy->set_is_new_target(); | |
798 return proxy; | |
799 } | |
800 | |
801 | |
802 Expression* ParserTraits::DefaultConstructor(bool call_super, Scope* scope, | |
803 int pos, int end_pos, | |
804 LanguageMode mode) { | |
805 return parser_->DefaultConstructor(call_super, scope, pos, end_pos, mode); | |
806 } | |
807 | |
808 | |
809 Literal* ParserTraits::ExpressionFromLiteral(Token::Value token, int pos, | |
810 Scanner* scanner, | |
811 AstNodeFactory* factory) { | |
812 switch (token) { | |
813 case Token::NULL_LITERAL: | |
814 return factory->NewNullLiteral(pos); | |
815 case Token::TRUE_LITERAL: | |
816 return factory->NewBooleanLiteral(true, pos); | |
817 case Token::FALSE_LITERAL: | |
818 return factory->NewBooleanLiteral(false, pos); | |
819 case Token::SMI: { | |
820 int value = scanner->smi_value(); | |
821 return factory->NewSmiLiteral(value, pos); | |
822 } | |
823 case Token::NUMBER: { | |
824 bool has_dot = scanner->ContainsDot(); | |
825 double value = scanner->DoubleValue(); | |
826 return factory->NewNumberLiteral(value, pos, has_dot); | |
827 } | |
828 default: | |
829 DCHECK(false); | |
830 } | |
831 return NULL; | |
832 } | |
833 | |
834 | |
835 Expression* ParserTraits::ExpressionFromIdentifier(const AstRawString* name, | |
836 int start_position, | |
837 int end_position, | |
838 Scope* scope, | |
839 AstNodeFactory* factory) { | |
840 if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name); | |
841 return scope->NewUnresolved(factory, name, Variable::NORMAL, start_position, | |
842 end_position); | |
843 } | |
844 | |
845 | |
846 Expression* ParserTraits::ExpressionFromString(int pos, Scanner* scanner, | |
847 AstNodeFactory* factory) { | |
848 const AstRawString* symbol = GetSymbol(scanner); | |
849 if (parser_->fni_ != NULL) parser_->fni_->PushLiteralName(symbol); | |
850 return factory->NewStringLiteral(symbol, pos); | |
851 } | |
852 | |
853 | |
854 Expression* ParserTraits::GetIterator(Expression* iterable, | |
855 AstNodeFactory* factory) { | |
856 Expression* iterator_symbol_literal = | |
857 factory->NewSymbolLiteral("iterator_symbol", RelocInfo::kNoPosition); | |
858 int pos = iterable->position(); | |
859 Expression* prop = | |
860 factory->NewProperty(iterable, iterator_symbol_literal, pos); | |
861 Zone* zone = parser_->zone(); | |
862 ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(0, zone); | |
863 return factory->NewCall(prop, args, pos); | |
864 } | |
865 | |
866 | |
867 Literal* ParserTraits::GetLiteralTheHole(int position, | |
868 AstNodeFactory* factory) { | |
869 return factory->NewTheHoleLiteral(RelocInfo::kNoPosition); | |
870 } | |
871 | |
872 | |
873 Expression* ParserTraits::ParseV8Intrinsic(bool* ok) { | |
874 return parser_->ParseV8Intrinsic(ok); | |
875 } | |
876 | |
877 | |
878 FunctionLiteral* ParserTraits::ParseFunctionLiteral( | |
879 const AstRawString* name, Scanner::Location function_name_location, | |
880 FunctionNameValidity function_name_validity, FunctionKind kind, | |
881 int function_token_position, FunctionLiteral::FunctionType type, | |
882 FunctionLiteral::ArityRestriction arity_restriction, | |
883 LanguageMode language_mode, bool* ok) { | |
884 return parser_->ParseFunctionLiteral( | |
885 name, function_name_location, function_name_validity, kind, | |
886 function_token_position, type, arity_restriction, language_mode, ok); | |
887 } | |
888 | |
889 | |
890 ClassLiteral* ParserTraits::ParseClassLiteral( | |
891 const AstRawString* name, Scanner::Location class_name_location, | |
892 bool name_is_strict_reserved, int pos, bool* ok) { | |
893 return parser_->ParseClassLiteral(name, class_name_location, | |
894 name_is_strict_reserved, pos, ok); | |
895 } | |
896 | |
897 | |
898 Parser::Parser(ParseInfo* info) | |
899 : ParserBase<ParserTraits>(info->zone(), &scanner_, info->stack_limit(), | |
900 info->extension(), info->ast_value_factory(), | |
901 NULL, this), | |
902 scanner_(info->unicode_cache()), | |
903 reusable_preparser_(NULL), | |
904 original_scope_(NULL), | |
905 target_stack_(NULL), | |
906 compile_options_(info->compile_options()), | |
907 cached_parse_data_(NULL), | |
908 total_preparse_skipped_(0), | |
909 pre_parse_timer_(NULL), | |
910 parsing_on_main_thread_(true) { | |
911 // Even though we were passed ParseInfo, we should not store it in | |
912 // Parser - this makes sure that Isolate is not accidentally accessed via | |
913 // ParseInfo during background parsing. | |
914 DCHECK(!info->script().is_null() || info->source_stream() != NULL); | |
915 set_allow_lazy(info->allow_lazy_parsing()); | |
916 set_allow_natives(FLAG_allow_natives_syntax || info->is_native()); | |
917 set_allow_harmony_sloppy(FLAG_harmony_sloppy); | |
918 set_allow_harmony_sloppy_function(FLAG_harmony_sloppy_function); | |
919 set_allow_harmony_sloppy_let(FLAG_harmony_sloppy_let); | |
920 set_allow_harmony_rest_parameters(FLAG_harmony_rest_parameters); | |
921 set_allow_harmony_default_parameters(FLAG_harmony_default_parameters); | |
922 set_allow_harmony_destructuring_bind(FLAG_harmony_destructuring_bind); | |
923 set_allow_strong_mode(FLAG_strong_mode); | |
924 set_allow_legacy_const(FLAG_legacy_const); | |
925 set_allow_harmony_do_expressions(FLAG_harmony_do_expressions); | |
926 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; | |
927 ++feature) { | |
928 use_counts_[feature] = 0; | |
929 } | |
930 if (info->ast_value_factory() == NULL) { | |
931 // info takes ownership of AstValueFactory. | |
932 info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed())); | |
933 info->set_ast_value_factory_owned(); | |
934 ast_value_factory_ = info->ast_value_factory(); | |
935 } | |
936 } | |
937 | |
938 | |
939 FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) { | |
940 // TODO(bmeurer): We temporarily need to pass allow_nesting = true here, | |
941 // see comment for HistogramTimerScope class. | |
942 | |
943 // It's OK to use the Isolate & counters here, since this function is only | |
944 // called in the main thread. | |
945 DCHECK(parsing_on_main_thread_); | |
946 | |
947 HistogramTimerScope timer_scope(isolate->counters()->parse(), true); | |
948 Handle<String> source(String::cast(info->script()->source())); | |
949 isolate->counters()->total_parse_size()->Increment(source->length()); | |
950 base::ElapsedTimer timer; | |
951 if (FLAG_trace_parse) { | |
952 timer.Start(); | |
953 } | |
954 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); | |
955 | |
956 // Initialize parser state. | |
957 CompleteParserRecorder recorder; | |
958 | |
959 if (produce_cached_parse_data()) { | |
960 log_ = &recorder; | |
961 } else if (consume_cached_parse_data()) { | |
962 cached_parse_data_->Initialize(); | |
963 } | |
964 | |
965 source = String::Flatten(source); | |
966 FunctionLiteral* result; | |
967 | |
968 if (source->IsExternalTwoByteString()) { | |
969 // Notice that the stream is destroyed at the end of the branch block. | |
970 // The last line of the blocks can't be moved outside, even though they're | |
971 // identical calls. | |
972 ExternalTwoByteStringUtf16CharacterStream stream( | |
973 Handle<ExternalTwoByteString>::cast(source), 0, source->length()); | |
974 scanner_.Initialize(&stream); | |
975 result = DoParseProgram(info); | |
976 } else { | |
977 GenericStringUtf16CharacterStream stream(source, 0, source->length()); | |
978 scanner_.Initialize(&stream); | |
979 result = DoParseProgram(info); | |
980 } | |
981 if (result != NULL) { | |
982 DCHECK_EQ(scanner_.peek_location().beg_pos, source->length()); | |
983 } | |
984 HandleSourceURLComments(isolate, info->script()); | |
985 | |
986 if (FLAG_trace_parse && result != NULL) { | |
987 double ms = timer.Elapsed().InMillisecondsF(); | |
988 if (info->is_eval()) { | |
989 PrintF("[parsing eval"); | |
990 } else if (info->script()->name()->IsString()) { | |
991 String* name = String::cast(info->script()->name()); | |
992 base::SmartArrayPointer<char> name_chars = name->ToCString(); | |
993 PrintF("[parsing script: %s", name_chars.get()); | |
994 } else { | |
995 PrintF("[parsing script"); | |
996 } | |
997 PrintF(" - took %0.3f ms]\n", ms); | |
998 } | |
999 if (produce_cached_parse_data()) { | |
1000 if (result != NULL) *info->cached_data() = recorder.GetScriptData(); | |
1001 log_ = NULL; | |
1002 } | |
1003 return result; | |
1004 } | |
1005 | |
1006 | |
1007 FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { | |
1008 // Note that this function can be called from the main thread or from a | |
1009 // background thread. We should not access anything Isolate / heap dependent | |
1010 // via ParseInfo, and also not pass it forward. | |
1011 DCHECK(scope_ == NULL); | |
1012 DCHECK(target_stack_ == NULL); | |
1013 | |
1014 Mode parsing_mode = FLAG_lazy && allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY; | |
1015 if (allow_natives() || extension_ != NULL) parsing_mode = PARSE_EAGERLY; | |
1016 | |
1017 FunctionLiteral* result = NULL; | |
1018 { | |
1019 // TODO(wingo): Add an outer SCRIPT_SCOPE corresponding to the native | |
1020 // context, which will have the "this" binding for script scopes. | |
1021 Scope* scope = NewScope(scope_, SCRIPT_SCOPE); | |
1022 info->set_script_scope(scope); | |
1023 if (!info->context().is_null() && !info->context()->IsNativeContext()) { | |
1024 scope = Scope::DeserializeScopeChain(info->isolate(), zone(), | |
1025 *info->context(), scope); | |
1026 // The Scope is backed up by ScopeInfo (which is in the V8 heap); this | |
1027 // means the Parser cannot operate independent of the V8 heap. Tell the | |
1028 // string table to internalize strings and values right after they're | |
1029 // created. This kind of parsing can only be done in the main thread. | |
1030 DCHECK(parsing_on_main_thread_); | |
1031 ast_value_factory()->Internalize(info->isolate()); | |
1032 } | |
1033 original_scope_ = scope; | |
1034 if (info->is_eval()) { | |
1035 if (!scope->is_script_scope() || is_strict(info->language_mode())) { | |
1036 parsing_mode = PARSE_EAGERLY; | |
1037 } | |
1038 scope = NewScope(scope, EVAL_SCOPE); | |
1039 } else if (info->is_module()) { | |
1040 scope = NewScope(scope, MODULE_SCOPE); | |
1041 } | |
1042 | |
1043 scope->set_start_position(0); | |
1044 | |
1045 // Enter 'scope' with the given parsing mode. | |
1046 ParsingModeScope parsing_mode_scope(this, parsing_mode); | |
1047 AstNodeFactory function_factory(ast_value_factory()); | |
1048 FunctionState function_state(&function_state_, &scope_, scope, | |
1049 kNormalFunction, &function_factory); | |
1050 | |
1051 // Don't count the mode in the use counters--give the program a chance | |
1052 // to enable script/module-wide strict/strong mode below. | |
1053 scope_->SetLanguageMode(info->language_mode()); | |
1054 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); | |
1055 bool ok = true; | |
1056 int beg_pos = scanner()->location().beg_pos; | |
1057 if (info->is_module()) { | |
1058 ParseModuleItemList(body, &ok); | |
1059 } else { | |
1060 ParseStatementList(body, Token::EOS, &ok); | |
1061 } | |
1062 | |
1063 // The parser will peek but not consume EOS. Our scope logically goes all | |
1064 // the way to the EOS, though. | |
1065 scope->set_end_position(scanner()->peek_location().beg_pos); | |
1066 | |
1067 if (ok && is_strict(language_mode())) { | |
1068 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); | |
1069 } | |
1070 if (ok && is_sloppy(language_mode()) && allow_harmony_sloppy_function()) { | |
1071 // TODO(littledan): Function bindings on the global object that modify | |
1072 // pre-existing bindings should be made writable, enumerable and | |
1073 // nonconfigurable if possible, whereas this code will leave attributes | |
1074 // unchanged if the property already exists. | |
1075 InsertSloppyBlockFunctionVarBindings(scope, &ok); | |
1076 } | |
1077 if (ok && (is_strict(language_mode()) || allow_harmony_sloppy() || | |
1078 allow_harmony_destructuring_bind())) { | |
1079 CheckConflictingVarDeclarations(scope_, &ok); | |
1080 } | |
1081 | |
1082 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { | |
1083 if (body->length() != 1 || | |
1084 !body->at(0)->IsExpressionStatement() || | |
1085 !body->at(0)->AsExpressionStatement()-> | |
1086 expression()->IsFunctionLiteral()) { | |
1087 ReportMessage(MessageTemplate::kSingleFunctionLiteral); | |
1088 ok = false; | |
1089 } | |
1090 } | |
1091 | |
1092 if (ok) { | |
1093 result = factory()->NewFunctionLiteral( | |
1094 ast_value_factory()->empty_string(), ast_value_factory(), scope_, | |
1095 body, function_state.materialized_literal_count(), | |
1096 function_state.expected_property_count(), 0, | |
1097 FunctionLiteral::kNoDuplicateParameters, | |
1098 FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kGlobalOrEval, | |
1099 FunctionLiteral::kShouldLazyCompile, FunctionKind::kNormalFunction, | |
1100 0); | |
1101 } | |
1102 } | |
1103 | |
1104 // Make sure the target stack is empty. | |
1105 DCHECK(target_stack_ == NULL); | |
1106 | |
1107 return result; | |
1108 } | |
1109 | |
1110 | |
1111 FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info) { | |
1112 // It's OK to use the Isolate & counters here, since this function is only | |
1113 // called in the main thread. | |
1114 DCHECK(parsing_on_main_thread_); | |
1115 HistogramTimerScope timer_scope(isolate->counters()->parse_lazy()); | |
1116 Handle<String> source(String::cast(info->script()->source())); | |
1117 isolate->counters()->total_parse_size()->Increment(source->length()); | |
1118 base::ElapsedTimer timer; | |
1119 if (FLAG_trace_parse) { | |
1120 timer.Start(); | |
1121 } | |
1122 Handle<SharedFunctionInfo> shared_info = info->shared_info(); | |
1123 | |
1124 // Initialize parser state. | |
1125 source = String::Flatten(source); | |
1126 FunctionLiteral* result; | |
1127 if (source->IsExternalTwoByteString()) { | |
1128 ExternalTwoByteStringUtf16CharacterStream stream( | |
1129 Handle<ExternalTwoByteString>::cast(source), | |
1130 shared_info->start_position(), | |
1131 shared_info->end_position()); | |
1132 result = ParseLazy(isolate, info, &stream); | |
1133 } else { | |
1134 GenericStringUtf16CharacterStream stream(source, | |
1135 shared_info->start_position(), | |
1136 shared_info->end_position()); | |
1137 result = ParseLazy(isolate, info, &stream); | |
1138 } | |
1139 | |
1140 if (FLAG_trace_parse && result != NULL) { | |
1141 double ms = timer.Elapsed().InMillisecondsF(); | |
1142 base::SmartArrayPointer<char> name_chars = | |
1143 result->debug_name()->ToCString(); | |
1144 PrintF("[parsing function: %s - took %0.3f ms]\n", name_chars.get(), ms); | |
1145 } | |
1146 return result; | |
1147 } | |
1148 | |
1149 | |
1150 FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info, | |
1151 Utf16CharacterStream* source) { | |
1152 Handle<SharedFunctionInfo> shared_info = info->shared_info(); | |
1153 scanner_.Initialize(source); | |
1154 DCHECK(scope_ == NULL); | |
1155 DCHECK(target_stack_ == NULL); | |
1156 | |
1157 Handle<String> name(String::cast(shared_info->name())); | |
1158 DCHECK(ast_value_factory()); | |
1159 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); | |
1160 const AstRawString* raw_name = ast_value_factory()->GetString(name); | |
1161 fni_->PushEnclosingName(raw_name); | |
1162 | |
1163 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); | |
1164 | |
1165 // Place holder for the result. | |
1166 FunctionLiteral* result = NULL; | |
1167 | |
1168 { | |
1169 // Parse the function literal. | |
1170 Scope* scope = NewScope(scope_, SCRIPT_SCOPE); | |
1171 info->set_script_scope(scope); | |
1172 if (!info->closure().is_null()) { | |
1173 // Ok to use Isolate here, since lazy function parsing is only done in the | |
1174 // main thread. | |
1175 DCHECK(parsing_on_main_thread_); | |
1176 scope = Scope::DeserializeScopeChain(isolate, zone(), | |
1177 info->closure()->context(), scope); | |
1178 } | |
1179 original_scope_ = scope; | |
1180 AstNodeFactory function_factory(ast_value_factory()); | |
1181 FunctionState function_state(&function_state_, &scope_, scope, | |
1182 shared_info->kind(), &function_factory); | |
1183 DCHECK(is_sloppy(scope->language_mode()) || | |
1184 is_strict(info->language_mode())); | |
1185 DCHECK(info->language_mode() == shared_info->language_mode()); | |
1186 FunctionLiteral::FunctionType function_type = shared_info->is_expression() | |
1187 ? (shared_info->is_anonymous() | |
1188 ? FunctionLiteral::ANONYMOUS_EXPRESSION | |
1189 : FunctionLiteral::NAMED_EXPRESSION) | |
1190 : FunctionLiteral::DECLARATION; | |
1191 bool ok = true; | |
1192 | |
1193 if (shared_info->is_arrow()) { | |
1194 Scope* scope = | |
1195 NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction); | |
1196 SetLanguageMode(scope, shared_info->language_mode()); | |
1197 scope->set_start_position(shared_info->start_position()); | |
1198 ExpressionClassifier formals_classifier; | |
1199 ParserFormalParameters formals(scope); | |
1200 Checkpoint checkpoint(this); | |
1201 { | |
1202 // Parsing patterns as variable reference expression creates | |
1203 // NewUnresolved references in current scope. Entrer arrow function | |
1204 // scope for formal parameter parsing. | |
1205 BlockState block_state(&scope_, scope); | |
1206 if (Check(Token::LPAREN)) { | |
1207 // '(' StrictFormalParameters ')' | |
1208 ParseFormalParameterList(&formals, &formals_classifier, &ok); | |
1209 if (ok) ok = Check(Token::RPAREN); | |
1210 } else { | |
1211 // BindingIdentifier | |
1212 ParseFormalParameter(&formals, &formals_classifier, &ok); | |
1213 if (ok) { | |
1214 DeclareFormalParameter(formals.scope, formals.at(0), | |
1215 &formals_classifier); | |
1216 } | |
1217 } | |
1218 } | |
1219 | |
1220 if (ok) { | |
1221 checkpoint.Restore(&formals.materialized_literals_count); | |
1222 // Pass `accept_IN=true` to ParseArrowFunctionLiteral --- This should | |
1223 // not be observable, or else the preparser would have failed. | |
1224 Expression* expression = | |
1225 ParseArrowFunctionLiteral(true, formals, formals_classifier, &ok); | |
1226 if (ok) { | |
1227 // Scanning must end at the same position that was recorded | |
1228 // previously. If not, parsing has been interrupted due to a stack | |
1229 // overflow, at which point the partially parsed arrow function | |
1230 // concise body happens to be a valid expression. This is a problem | |
1231 // only for arrow functions with single expression bodies, since there | |
1232 // is no end token such as "}" for normal functions. | |
1233 if (scanner()->location().end_pos == shared_info->end_position()) { | |
1234 // The pre-parser saw an arrow function here, so the full parser | |
1235 // must produce a FunctionLiteral. | |
1236 DCHECK(expression->IsFunctionLiteral()); | |
1237 result = expression->AsFunctionLiteral(); | |
1238 } else { | |
1239 ok = false; | |
1240 } | |
1241 } | |
1242 } | |
1243 } else if (shared_info->is_default_constructor()) { | |
1244 result = DefaultConstructor(IsSubclassConstructor(shared_info->kind()), | |
1245 scope, shared_info->start_position(), | |
1246 shared_info->end_position(), | |
1247 shared_info->language_mode()); | |
1248 } else { | |
1249 result = ParseFunctionLiteral( | |
1250 raw_name, Scanner::Location::invalid(), kSkipFunctionNameCheck, | |
1251 shared_info->kind(), RelocInfo::kNoPosition, function_type, | |
1252 FunctionLiteral::NORMAL_ARITY, shared_info->language_mode(), &ok); | |
1253 } | |
1254 // Make sure the results agree. | |
1255 DCHECK(ok == (result != NULL)); | |
1256 } | |
1257 | |
1258 // Make sure the target stack is empty. | |
1259 DCHECK(target_stack_ == NULL); | |
1260 | |
1261 if (result != NULL) { | |
1262 Handle<String> inferred_name(shared_info->inferred_name()); | |
1263 result->set_inferred_name(inferred_name); | |
1264 } | |
1265 return result; | |
1266 } | |
1267 | |
1268 | |
1269 void* Parser::ParseStatementList(ZoneList<Statement*>* body, int end_token, | |
1270 bool* ok) { | |
1271 // StatementList :: | |
1272 // (StatementListItem)* <end_token> | |
1273 | |
1274 // Allocate a target stack to use for this set of source | |
1275 // elements. This way, all scripts and functions get their own | |
1276 // target stack thus avoiding illegal breaks and continues across | |
1277 // functions. | |
1278 TargetScope scope(&this->target_stack_); | |
1279 | |
1280 DCHECK(body != NULL); | |
1281 bool directive_prologue = true; // Parsing directive prologue. | |
1282 | |
1283 while (peek() != end_token) { | |
1284 if (directive_prologue && peek() != Token::STRING) { | |
1285 directive_prologue = false; | |
1286 } | |
1287 | |
1288 Scanner::Location token_loc = scanner()->peek_location(); | |
1289 Scanner::Location old_this_loc = function_state_->this_location(); | |
1290 Scanner::Location old_super_loc = function_state_->super_location(); | |
1291 Statement* stat = ParseStatementListItem(CHECK_OK); | |
1292 | |
1293 if (is_strong(language_mode()) && scope_->is_function_scope() && | |
1294 IsClassConstructor(function_state_->kind())) { | |
1295 Scanner::Location this_loc = function_state_->this_location(); | |
1296 Scanner::Location super_loc = function_state_->super_location(); | |
1297 if (this_loc.beg_pos != old_this_loc.beg_pos && | |
1298 this_loc.beg_pos != token_loc.beg_pos) { | |
1299 ReportMessageAt(this_loc, MessageTemplate::kStrongConstructorThis); | |
1300 *ok = false; | |
1301 return nullptr; | |
1302 } | |
1303 if (super_loc.beg_pos != old_super_loc.beg_pos && | |
1304 super_loc.beg_pos != token_loc.beg_pos) { | |
1305 ReportMessageAt(super_loc, MessageTemplate::kStrongConstructorSuper); | |
1306 *ok = false; | |
1307 return nullptr; | |
1308 } | |
1309 } | |
1310 | |
1311 if (stat == NULL || stat->IsEmpty()) { | |
1312 directive_prologue = false; // End of directive prologue. | |
1313 continue; | |
1314 } | |
1315 | |
1316 if (directive_prologue) { | |
1317 // A shot at a directive. | |
1318 ExpressionStatement* e_stat; | |
1319 Literal* literal; | |
1320 // Still processing directive prologue? | |
1321 if ((e_stat = stat->AsExpressionStatement()) != NULL && | |
1322 (literal = e_stat->expression()->AsLiteral()) != NULL && | |
1323 literal->raw_value()->IsString()) { | |
1324 // Check "use strict" directive (ES5 14.1), "use asm" directive, and | |
1325 // "use strong" directive (experimental). | |
1326 bool use_strict_found = | |
1327 literal->raw_value()->AsString() == | |
1328 ast_value_factory()->use_strict_string() && | |
1329 token_loc.end_pos - token_loc.beg_pos == | |
1330 ast_value_factory()->use_strict_string()->length() + 2; | |
1331 bool use_strong_found = | |
1332 allow_strong_mode() && | |
1333 literal->raw_value()->AsString() == | |
1334 ast_value_factory()->use_strong_string() && | |
1335 token_loc.end_pos - token_loc.beg_pos == | |
1336 ast_value_factory()->use_strong_string()->length() + 2; | |
1337 if (use_strict_found || use_strong_found) { | |
1338 // Strong mode implies strict mode. If there are several "use strict" | |
1339 // / "use strong" directives, do the strict mode changes only once. | |
1340 if (is_sloppy(scope_->language_mode())) { | |
1341 RaiseLanguageMode(STRICT); | |
1342 } | |
1343 | |
1344 if (use_strong_found) { | |
1345 RaiseLanguageMode(STRONG); | |
1346 if (IsClassConstructor(function_state_->kind())) { | |
1347 // "use strong" cannot occur in a class constructor body, to avoid | |
1348 // unintuitive strong class object semantics. | |
1349 ParserTraits::ReportMessageAt( | |
1350 token_loc, MessageTemplate::kStrongConstructorDirective); | |
1351 *ok = false; | |
1352 return nullptr; | |
1353 } | |
1354 } | |
1355 if (!scope_->HasSimpleParameters()) { | |
1356 // TC39 deemed "use strict" directives to be an error when occurring | |
1357 // in the body of a function with non-simple parameter list, on | |
1358 // 29/7/2015. https://goo.gl/ueA7Ln | |
1359 // | |
1360 // In V8, this also applies to "use strong " directives. | |
1361 const AstRawString* string = literal->raw_value()->AsString(); | |
1362 ParserTraits::ReportMessageAt( | |
1363 token_loc, MessageTemplate::kIllegalLanguageModeDirective, | |
1364 string); | |
1365 *ok = false; | |
1366 return nullptr; | |
1367 } | |
1368 // Because declarations in strict eval code don't leak into the scope | |
1369 // of the eval call, it is likely that functions declared in strict | |
1370 // eval code will be used within the eval code, so lazy parsing is | |
1371 // probably not a win. | |
1372 if (scope_->is_eval_scope()) mode_ = PARSE_EAGERLY; | |
1373 } else if (literal->raw_value()->AsString() == | |
1374 ast_value_factory()->use_asm_string() && | |
1375 token_loc.end_pos - token_loc.beg_pos == | |
1376 ast_value_factory()->use_asm_string()->length() + 2) { | |
1377 // Store the usage count; The actual use counter on the isolate is | |
1378 // incremented after parsing is done. | |
1379 ++use_counts_[v8::Isolate::kUseAsm]; | |
1380 scope_->SetAsmModule(); | |
1381 } else { | |
1382 // Should not change mode, but will increment UseCounter | |
1383 // if appropriate. Ditto usages below. | |
1384 RaiseLanguageMode(SLOPPY); | |
1385 } | |
1386 } else { | |
1387 // End of the directive prologue. | |
1388 directive_prologue = false; | |
1389 RaiseLanguageMode(SLOPPY); | |
1390 } | |
1391 } else { | |
1392 RaiseLanguageMode(SLOPPY); | |
1393 } | |
1394 | |
1395 body->Add(stat, zone()); | |
1396 } | |
1397 | |
1398 return 0; | |
1399 } | |
1400 | |
1401 | |
1402 Statement* Parser::ParseStatementListItem(bool* ok) { | |
1403 // (Ecma 262 6th Edition, 13.1): | |
1404 // StatementListItem: | |
1405 // Statement | |
1406 // Declaration | |
1407 | |
1408 if (peek() != Token::CLASS) { | |
1409 // No more classes follow; reset the start position for the consecutive | |
1410 // class declaration group. | |
1411 scope_->set_class_declaration_group_start(-1); | |
1412 } | |
1413 | |
1414 switch (peek()) { | |
1415 case Token::FUNCTION: | |
1416 return ParseFunctionDeclaration(NULL, ok); | |
1417 case Token::CLASS: | |
1418 if (scope_->class_declaration_group_start() < 0) { | |
1419 scope_->set_class_declaration_group_start( | |
1420 scanner()->peek_location().beg_pos); | |
1421 } | |
1422 return ParseClassDeclaration(NULL, ok); | |
1423 case Token::CONST: | |
1424 if (allow_const()) { | |
1425 return ParseVariableStatement(kStatementListItem, NULL, ok); | |
1426 } | |
1427 break; | |
1428 case Token::VAR: | |
1429 return ParseVariableStatement(kStatementListItem, NULL, ok); | |
1430 case Token::LET: | |
1431 if (IsNextLetKeyword()) { | |
1432 return ParseVariableStatement(kStatementListItem, NULL, ok); | |
1433 } | |
1434 break; | |
1435 default: | |
1436 break; | |
1437 } | |
1438 return ParseStatement(NULL, ok); | |
1439 } | |
1440 | |
1441 | |
1442 Statement* Parser::ParseModuleItem(bool* ok) { | |
1443 // (Ecma 262 6th Edition, 15.2): | |
1444 // ModuleItem : | |
1445 // ImportDeclaration | |
1446 // ExportDeclaration | |
1447 // StatementListItem | |
1448 | |
1449 switch (peek()) { | |
1450 case Token::IMPORT: | |
1451 return ParseImportDeclaration(ok); | |
1452 case Token::EXPORT: | |
1453 return ParseExportDeclaration(ok); | |
1454 default: | |
1455 return ParseStatementListItem(ok); | |
1456 } | |
1457 } | |
1458 | |
1459 | |
1460 void* Parser::ParseModuleItemList(ZoneList<Statement*>* body, bool* ok) { | |
1461 // (Ecma 262 6th Edition, 15.2): | |
1462 // Module : | |
1463 // ModuleBody? | |
1464 // | |
1465 // ModuleBody : | |
1466 // ModuleItem* | |
1467 | |
1468 DCHECK(scope_->is_module_scope()); | |
1469 RaiseLanguageMode(STRICT); | |
1470 | |
1471 while (peek() != Token::EOS) { | |
1472 Statement* stat = ParseModuleItem(CHECK_OK); | |
1473 if (stat && !stat->IsEmpty()) { | |
1474 body->Add(stat, zone()); | |
1475 } | |
1476 } | |
1477 | |
1478 // Check that all exports are bound. | |
1479 ModuleDescriptor* descriptor = scope_->module(); | |
1480 for (ModuleDescriptor::Iterator it = descriptor->iterator(); !it.done(); | |
1481 it.Advance()) { | |
1482 if (scope_->LookupLocal(it.local_name()) == NULL) { | |
1483 // TODO(adamk): Pass both local_name and export_name once ParserTraits | |
1484 // supports multiple arg error messages. | |
1485 // Also try to report this at a better location. | |
1486 ParserTraits::ReportMessage(MessageTemplate::kModuleExportUndefined, | |
1487 it.local_name()); | |
1488 *ok = false; | |
1489 return NULL; | |
1490 } | |
1491 } | |
1492 | |
1493 scope_->module()->Freeze(); | |
1494 return NULL; | |
1495 } | |
1496 | |
1497 | |
1498 const AstRawString* Parser::ParseModuleSpecifier(bool* ok) { | |
1499 // ModuleSpecifier : | |
1500 // StringLiteral | |
1501 | |
1502 Expect(Token::STRING, CHECK_OK); | |
1503 return GetSymbol(scanner()); | |
1504 } | |
1505 | |
1506 | |
1507 void* Parser::ParseExportClause(ZoneList<const AstRawString*>* export_names, | |
1508 ZoneList<Scanner::Location>* export_locations, | |
1509 ZoneList<const AstRawString*>* local_names, | |
1510 Scanner::Location* reserved_loc, bool* ok) { | |
1511 // ExportClause : | |
1512 // '{' '}' | |
1513 // '{' ExportsList '}' | |
1514 // '{' ExportsList ',' '}' | |
1515 // | |
1516 // ExportsList : | |
1517 // ExportSpecifier | |
1518 // ExportsList ',' ExportSpecifier | |
1519 // | |
1520 // ExportSpecifier : | |
1521 // IdentifierName | |
1522 // IdentifierName 'as' IdentifierName | |
1523 | |
1524 Expect(Token::LBRACE, CHECK_OK); | |
1525 | |
1526 Token::Value name_tok; | |
1527 while ((name_tok = peek()) != Token::RBRACE) { | |
1528 // Keep track of the first reserved word encountered in case our | |
1529 // caller needs to report an error. | |
1530 if (!reserved_loc->IsValid() && | |
1531 !Token::IsIdentifier(name_tok, STRICT, false)) { | |
1532 *reserved_loc = scanner()->location(); | |
1533 } | |
1534 const AstRawString* local_name = ParseIdentifierName(CHECK_OK); | |
1535 const AstRawString* export_name = NULL; | |
1536 if (CheckContextualKeyword(CStrVector("as"))) { | |
1537 export_name = ParseIdentifierName(CHECK_OK); | |
1538 } | |
1539 if (export_name == NULL) { | |
1540 export_name = local_name; | |
1541 } | |
1542 export_names->Add(export_name, zone()); | |
1543 local_names->Add(local_name, zone()); | |
1544 export_locations->Add(scanner()->location(), zone()); | |
1545 if (peek() == Token::RBRACE) break; | |
1546 Expect(Token::COMMA, CHECK_OK); | |
1547 } | |
1548 | |
1549 Expect(Token::RBRACE, CHECK_OK); | |
1550 | |
1551 return 0; | |
1552 } | |
1553 | |
1554 | |
1555 ZoneList<ImportDeclaration*>* Parser::ParseNamedImports(int pos, bool* ok) { | |
1556 // NamedImports : | |
1557 // '{' '}' | |
1558 // '{' ImportsList '}' | |
1559 // '{' ImportsList ',' '}' | |
1560 // | |
1561 // ImportsList : | |
1562 // ImportSpecifier | |
1563 // ImportsList ',' ImportSpecifier | |
1564 // | |
1565 // ImportSpecifier : | |
1566 // BindingIdentifier | |
1567 // IdentifierName 'as' BindingIdentifier | |
1568 | |
1569 Expect(Token::LBRACE, CHECK_OK); | |
1570 | |
1571 ZoneList<ImportDeclaration*>* result = | |
1572 new (zone()) ZoneList<ImportDeclaration*>(1, zone()); | |
1573 while (peek() != Token::RBRACE) { | |
1574 const AstRawString* import_name = ParseIdentifierName(CHECK_OK); | |
1575 const AstRawString* local_name = import_name; | |
1576 // In the presence of 'as', the left-side of the 'as' can | |
1577 // be any IdentifierName. But without 'as', it must be a valid | |
1578 // BindingIdentifier. | |
1579 if (CheckContextualKeyword(CStrVector("as"))) { | |
1580 local_name = ParseIdentifierName(CHECK_OK); | |
1581 } | |
1582 if (!Token::IsIdentifier(scanner()->current_token(), STRICT, false)) { | |
1583 *ok = false; | |
1584 ReportMessage(MessageTemplate::kUnexpectedReserved); | |
1585 return NULL; | |
1586 } else if (IsEvalOrArguments(local_name)) { | |
1587 *ok = false; | |
1588 ReportMessage(MessageTemplate::kStrictEvalArguments); | |
1589 return NULL; | |
1590 } else if (is_strong(language_mode()) && IsUndefined(local_name)) { | |
1591 *ok = false; | |
1592 ReportMessage(MessageTemplate::kStrongUndefined); | |
1593 return NULL; | |
1594 } | |
1595 VariableProxy* proxy = NewUnresolved(local_name, IMPORT); | |
1596 ImportDeclaration* declaration = | |
1597 factory()->NewImportDeclaration(proxy, import_name, NULL, scope_, pos); | |
1598 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); | |
1599 result->Add(declaration, zone()); | |
1600 if (peek() == Token::RBRACE) break; | |
1601 Expect(Token::COMMA, CHECK_OK); | |
1602 } | |
1603 | |
1604 Expect(Token::RBRACE, CHECK_OK); | |
1605 | |
1606 return result; | |
1607 } | |
1608 | |
1609 | |
1610 Statement* Parser::ParseImportDeclaration(bool* ok) { | |
1611 // ImportDeclaration : | |
1612 // 'import' ImportClause 'from' ModuleSpecifier ';' | |
1613 // 'import' ModuleSpecifier ';' | |
1614 // | |
1615 // ImportClause : | |
1616 // NameSpaceImport | |
1617 // NamedImports | |
1618 // ImportedDefaultBinding | |
1619 // ImportedDefaultBinding ',' NameSpaceImport | |
1620 // ImportedDefaultBinding ',' NamedImports | |
1621 // | |
1622 // NameSpaceImport : | |
1623 // '*' 'as' ImportedBinding | |
1624 | |
1625 int pos = peek_position(); | |
1626 Expect(Token::IMPORT, CHECK_OK); | |
1627 | |
1628 Token::Value tok = peek(); | |
1629 | |
1630 // 'import' ModuleSpecifier ';' | |
1631 if (tok == Token::STRING) { | |
1632 const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK); | |
1633 scope_->module()->AddModuleRequest(module_specifier, zone()); | |
1634 ExpectSemicolon(CHECK_OK); | |
1635 return factory()->NewEmptyStatement(pos); | |
1636 } | |
1637 | |
1638 // Parse ImportedDefaultBinding if present. | |
1639 ImportDeclaration* import_default_declaration = NULL; | |
1640 if (tok != Token::MUL && tok != Token::LBRACE) { | |
1641 const AstRawString* local_name = | |
1642 ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK); | |
1643 VariableProxy* proxy = NewUnresolved(local_name, IMPORT); | |
1644 import_default_declaration = factory()->NewImportDeclaration( | |
1645 proxy, ast_value_factory()->default_string(), NULL, scope_, pos); | |
1646 Declare(import_default_declaration, DeclarationDescriptor::NORMAL, true, | |
1647 CHECK_OK); | |
1648 } | |
1649 | |
1650 const AstRawString* module_instance_binding = NULL; | |
1651 ZoneList<ImportDeclaration*>* named_declarations = NULL; | |
1652 if (import_default_declaration == NULL || Check(Token::COMMA)) { | |
1653 switch (peek()) { | |
1654 case Token::MUL: { | |
1655 Consume(Token::MUL); | |
1656 ExpectContextualKeyword(CStrVector("as"), CHECK_OK); | |
1657 module_instance_binding = | |
1658 ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK); | |
1659 // TODO(ES6): Add an appropriate declaration. | |
1660 break; | |
1661 } | |
1662 | |
1663 case Token::LBRACE: | |
1664 named_declarations = ParseNamedImports(pos, CHECK_OK); | |
1665 break; | |
1666 | |
1667 default: | |
1668 *ok = false; | |
1669 ReportUnexpectedToken(scanner()->current_token()); | |
1670 return NULL; | |
1671 } | |
1672 } | |
1673 | |
1674 ExpectContextualKeyword(CStrVector("from"), CHECK_OK); | |
1675 const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK); | |
1676 scope_->module()->AddModuleRequest(module_specifier, zone()); | |
1677 | |
1678 if (module_instance_binding != NULL) { | |
1679 // TODO(ES6): Set the module specifier for the module namespace binding. | |
1680 } | |
1681 | |
1682 if (import_default_declaration != NULL) { | |
1683 import_default_declaration->set_module_specifier(module_specifier); | |
1684 } | |
1685 | |
1686 if (named_declarations != NULL) { | |
1687 for (int i = 0; i < named_declarations->length(); ++i) { | |
1688 named_declarations->at(i)->set_module_specifier(module_specifier); | |
1689 } | |
1690 } | |
1691 | |
1692 ExpectSemicolon(CHECK_OK); | |
1693 return factory()->NewEmptyStatement(pos); | |
1694 } | |
1695 | |
1696 | |
1697 Statement* Parser::ParseExportDefault(bool* ok) { | |
1698 // Supports the following productions, starting after the 'default' token: | |
1699 // 'export' 'default' FunctionDeclaration | |
1700 // 'export' 'default' ClassDeclaration | |
1701 // 'export' 'default' AssignmentExpression[In] ';' | |
1702 | |
1703 Expect(Token::DEFAULT, CHECK_OK); | |
1704 Scanner::Location default_loc = scanner()->location(); | |
1705 | |
1706 ZoneList<const AstRawString*> names(1, zone()); | |
1707 Statement* result = NULL; | |
1708 switch (peek()) { | |
1709 case Token::FUNCTION: | |
1710 // TODO(ES6): Support parsing anonymous function declarations here. | |
1711 result = ParseFunctionDeclaration(&names, CHECK_OK); | |
1712 break; | |
1713 | |
1714 case Token::CLASS: | |
1715 // TODO(ES6): Support parsing anonymous class declarations here. | |
1716 result = ParseClassDeclaration(&names, CHECK_OK); | |
1717 break; | |
1718 | |
1719 default: { | |
1720 int pos = peek_position(); | |
1721 ExpressionClassifier classifier; | |
1722 Expression* expr = ParseAssignmentExpression(true, &classifier, CHECK_OK); | |
1723 ValidateExpression(&classifier, CHECK_OK); | |
1724 | |
1725 ExpectSemicolon(CHECK_OK); | |
1726 result = factory()->NewExpressionStatement(expr, pos); | |
1727 break; | |
1728 } | |
1729 } | |
1730 | |
1731 const AstRawString* default_string = ast_value_factory()->default_string(); | |
1732 | |
1733 DCHECK_LE(names.length(), 1); | |
1734 if (names.length() == 1) { | |
1735 scope_->module()->AddLocalExport(default_string, names.first(), zone(), ok); | |
1736 if (!*ok) { | |
1737 ParserTraits::ReportMessageAt( | |
1738 default_loc, MessageTemplate::kDuplicateExport, default_string); | |
1739 return NULL; | |
1740 } | |
1741 } else { | |
1742 // TODO(ES6): Assign result to a const binding with the name "*default*" | |
1743 // and add an export entry with "*default*" as the local name. | |
1744 } | |
1745 | |
1746 return result; | |
1747 } | |
1748 | |
1749 | |
1750 Statement* Parser::ParseExportDeclaration(bool* ok) { | |
1751 // ExportDeclaration: | |
1752 // 'export' '*' 'from' ModuleSpecifier ';' | |
1753 // 'export' ExportClause ('from' ModuleSpecifier)? ';' | |
1754 // 'export' VariableStatement | |
1755 // 'export' Declaration | |
1756 // 'export' 'default' ... (handled in ParseExportDefault) | |
1757 | |
1758 int pos = peek_position(); | |
1759 Expect(Token::EXPORT, CHECK_OK); | |
1760 | |
1761 Statement* result = NULL; | |
1762 ZoneList<const AstRawString*> names(1, zone()); | |
1763 switch (peek()) { | |
1764 case Token::DEFAULT: | |
1765 return ParseExportDefault(ok); | |
1766 | |
1767 case Token::MUL: { | |
1768 Consume(Token::MUL); | |
1769 ExpectContextualKeyword(CStrVector("from"), CHECK_OK); | |
1770 const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK); | |
1771 scope_->module()->AddModuleRequest(module_specifier, zone()); | |
1772 // TODO(ES6): scope_->module()->AddStarExport(...) | |
1773 ExpectSemicolon(CHECK_OK); | |
1774 return factory()->NewEmptyStatement(pos); | |
1775 } | |
1776 | |
1777 case Token::LBRACE: { | |
1778 // There are two cases here: | |
1779 // | |
1780 // 'export' ExportClause ';' | |
1781 // and | |
1782 // 'export' ExportClause FromClause ';' | |
1783 // | |
1784 // In the first case, the exported identifiers in ExportClause must | |
1785 // not be reserved words, while in the latter they may be. We | |
1786 // pass in a location that gets filled with the first reserved word | |
1787 // encountered, and then throw a SyntaxError if we are in the | |
1788 // non-FromClause case. | |
1789 Scanner::Location reserved_loc = Scanner::Location::invalid(); | |
1790 ZoneList<const AstRawString*> export_names(1, zone()); | |
1791 ZoneList<Scanner::Location> export_locations(1, zone()); | |
1792 ZoneList<const AstRawString*> local_names(1, zone()); | |
1793 ParseExportClause(&export_names, &export_locations, &local_names, | |
1794 &reserved_loc, CHECK_OK); | |
1795 const AstRawString* indirect_export_module_specifier = NULL; | |
1796 if (CheckContextualKeyword(CStrVector("from"))) { | |
1797 indirect_export_module_specifier = ParseModuleSpecifier(CHECK_OK); | |
1798 } else if (reserved_loc.IsValid()) { | |
1799 // No FromClause, so reserved words are invalid in ExportClause. | |
1800 *ok = false; | |
1801 ReportMessageAt(reserved_loc, MessageTemplate::kUnexpectedReserved); | |
1802 return NULL; | |
1803 } | |
1804 ExpectSemicolon(CHECK_OK); | |
1805 const int length = export_names.length(); | |
1806 DCHECK_EQ(length, local_names.length()); | |
1807 DCHECK_EQ(length, export_locations.length()); | |
1808 if (indirect_export_module_specifier == NULL) { | |
1809 for (int i = 0; i < length; ++i) { | |
1810 scope_->module()->AddLocalExport(export_names[i], local_names[i], | |
1811 zone(), ok); | |
1812 if (!*ok) { | |
1813 ParserTraits::ReportMessageAt(export_locations[i], | |
1814 MessageTemplate::kDuplicateExport, | |
1815 export_names[i]); | |
1816 return NULL; | |
1817 } | |
1818 } | |
1819 } else { | |
1820 scope_->module()->AddModuleRequest(indirect_export_module_specifier, | |
1821 zone()); | |
1822 for (int i = 0; i < length; ++i) { | |
1823 // TODO(ES6): scope_->module()->AddIndirectExport(...);( | |
1824 } | |
1825 } | |
1826 return factory()->NewEmptyStatement(pos); | |
1827 } | |
1828 | |
1829 case Token::FUNCTION: | |
1830 result = ParseFunctionDeclaration(&names, CHECK_OK); | |
1831 break; | |
1832 | |
1833 case Token::CLASS: | |
1834 result = ParseClassDeclaration(&names, CHECK_OK); | |
1835 break; | |
1836 | |
1837 case Token::VAR: | |
1838 case Token::LET: | |
1839 case Token::CONST: | |
1840 result = ParseVariableStatement(kStatementListItem, &names, CHECK_OK); | |
1841 break; | |
1842 | |
1843 default: | |
1844 *ok = false; | |
1845 ReportUnexpectedToken(scanner()->current_token()); | |
1846 return NULL; | |
1847 } | |
1848 | |
1849 // Extract declared names into export declarations. | |
1850 ModuleDescriptor* descriptor = scope_->module(); | |
1851 for (int i = 0; i < names.length(); ++i) { | |
1852 descriptor->AddLocalExport(names[i], names[i], zone(), ok); | |
1853 if (!*ok) { | |
1854 // TODO(adamk): Possibly report this error at the right place. | |
1855 ParserTraits::ReportMessage(MessageTemplate::kDuplicateExport, names[i]); | |
1856 return NULL; | |
1857 } | |
1858 } | |
1859 | |
1860 DCHECK_NOT_NULL(result); | |
1861 return result; | |
1862 } | |
1863 | |
1864 | |
1865 Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels, | |
1866 bool* ok) { | |
1867 // Statement :: | |
1868 // EmptyStatement | |
1869 // ... | |
1870 | |
1871 if (peek() == Token::SEMICOLON) { | |
1872 Next(); | |
1873 return factory()->NewEmptyStatement(RelocInfo::kNoPosition); | |
1874 } | |
1875 return ParseSubStatement(labels, ok); | |
1876 } | |
1877 | |
1878 | |
1879 Statement* Parser::ParseSubStatement(ZoneList<const AstRawString*>* labels, | |
1880 bool* ok) { | |
1881 // Statement :: | |
1882 // Block | |
1883 // VariableStatement | |
1884 // EmptyStatement | |
1885 // ExpressionStatement | |
1886 // IfStatement | |
1887 // IterationStatement | |
1888 // ContinueStatement | |
1889 // BreakStatement | |
1890 // ReturnStatement | |
1891 // WithStatement | |
1892 // LabelledStatement | |
1893 // SwitchStatement | |
1894 // ThrowStatement | |
1895 // TryStatement | |
1896 // DebuggerStatement | |
1897 | |
1898 // Note: Since labels can only be used by 'break' and 'continue' | |
1899 // statements, which themselves are only valid within blocks, | |
1900 // iterations or 'switch' statements (i.e., BreakableStatements), | |
1901 // labels can be simply ignored in all other cases; except for | |
1902 // trivial labeled break statements 'label: break label' which is | |
1903 // parsed into an empty statement. | |
1904 switch (peek()) { | |
1905 case Token::LBRACE: | |
1906 return ParseBlock(labels, ok); | |
1907 | |
1908 case Token::SEMICOLON: | |
1909 if (is_strong(language_mode())) { | |
1910 ReportMessageAt(scanner()->peek_location(), | |
1911 MessageTemplate::kStrongEmpty); | |
1912 *ok = false; | |
1913 return NULL; | |
1914 } | |
1915 Next(); | |
1916 return factory()->NewEmptyStatement(RelocInfo::kNoPosition); | |
1917 | |
1918 case Token::IF: | |
1919 return ParseIfStatement(labels, ok); | |
1920 | |
1921 case Token::DO: | |
1922 return ParseDoWhileStatement(labels, ok); | |
1923 | |
1924 case Token::WHILE: | |
1925 return ParseWhileStatement(labels, ok); | |
1926 | |
1927 case Token::FOR: | |
1928 return ParseForStatement(labels, ok); | |
1929 | |
1930 case Token::CONTINUE: | |
1931 case Token::BREAK: | |
1932 case Token::RETURN: | |
1933 case Token::THROW: | |
1934 case Token::TRY: { | |
1935 // These statements must have their labels preserved in an enclosing | |
1936 // block | |
1937 if (labels == NULL) { | |
1938 return ParseStatementAsUnlabelled(labels, ok); | |
1939 } else { | |
1940 Block* result = | |
1941 factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition); | |
1942 Target target(&this->target_stack_, result); | |
1943 Statement* statement = ParseStatementAsUnlabelled(labels, CHECK_OK); | |
1944 if (result) result->statements()->Add(statement, zone()); | |
1945 return result; | |
1946 } | |
1947 } | |
1948 | |
1949 case Token::WITH: | |
1950 return ParseWithStatement(labels, ok); | |
1951 | |
1952 case Token::SWITCH: | |
1953 return ParseSwitchStatement(labels, ok); | |
1954 | |
1955 case Token::FUNCTION: { | |
1956 // FunctionDeclaration is only allowed in the context of SourceElements | |
1957 // (Ecma 262 5th Edition, clause 14): | |
1958 // SourceElement: | |
1959 // Statement | |
1960 // FunctionDeclaration | |
1961 // Common language extension is to allow function declaration in place | |
1962 // of any statement. This language extension is disabled in strict mode. | |
1963 // | |
1964 // In Harmony mode, this case also handles the extension: | |
1965 // Statement: | |
1966 // GeneratorDeclaration | |
1967 if (is_strict(language_mode())) { | |
1968 ReportMessageAt(scanner()->peek_location(), | |
1969 MessageTemplate::kStrictFunction); | |
1970 *ok = false; | |
1971 return NULL; | |
1972 } | |
1973 return ParseFunctionDeclaration(NULL, ok); | |
1974 } | |
1975 | |
1976 case Token::DEBUGGER: | |
1977 return ParseDebuggerStatement(ok); | |
1978 | |
1979 case Token::VAR: | |
1980 return ParseVariableStatement(kStatement, NULL, ok); | |
1981 | |
1982 case Token::CONST: | |
1983 // In ES6 CONST is not allowed as a Statement, only as a | |
1984 // LexicalDeclaration, however we continue to allow it in sloppy mode for | |
1985 // backwards compatibility. | |
1986 if (is_sloppy(language_mode()) && allow_legacy_const()) { | |
1987 return ParseVariableStatement(kStatement, NULL, ok); | |
1988 } | |
1989 | |
1990 // Fall through. | |
1991 default: | |
1992 return ParseExpressionOrLabelledStatement(labels, ok); | |
1993 } | |
1994 } | |
1995 | |
1996 Statement* Parser::ParseStatementAsUnlabelled( | |
1997 ZoneList<const AstRawString*>* labels, bool* ok) { | |
1998 switch (peek()) { | |
1999 case Token::CONTINUE: | |
2000 return ParseContinueStatement(ok); | |
2001 | |
2002 case Token::BREAK: | |
2003 return ParseBreakStatement(labels, ok); | |
2004 | |
2005 case Token::RETURN: | |
2006 return ParseReturnStatement(ok); | |
2007 | |
2008 case Token::THROW: | |
2009 return ParseThrowStatement(ok); | |
2010 | |
2011 case Token::TRY: | |
2012 return ParseTryStatement(ok); | |
2013 | |
2014 default: | |
2015 UNREACHABLE(); | |
2016 return NULL; | |
2017 } | |
2018 } | |
2019 | |
2020 | |
2021 VariableProxy* Parser::NewUnresolved(const AstRawString* name, | |
2022 VariableMode mode) { | |
2023 // If we are inside a function, a declaration of a var/const variable is a | |
2024 // truly local variable, and the scope of the variable is always the function | |
2025 // scope. | |
2026 // Let/const variables in harmony mode are always added to the immediately | |
2027 // enclosing scope. | |
2028 return DeclarationScope(mode)->NewUnresolved( | |
2029 factory(), name, Variable::NORMAL, scanner()->location().beg_pos, | |
2030 scanner()->location().end_pos); | |
2031 } | |
2032 | |
2033 | |
2034 Variable* Parser::Declare(Declaration* declaration, | |
2035 DeclarationDescriptor::Kind declaration_kind, | |
2036 bool resolve, bool* ok, Scope* scope) { | |
2037 VariableProxy* proxy = declaration->proxy(); | |
2038 DCHECK(proxy->raw_name() != NULL); | |
2039 const AstRawString* name = proxy->raw_name(); | |
2040 VariableMode mode = declaration->mode(); | |
2041 if (scope == nullptr) scope = scope_; | |
2042 Scope* declaration_scope = | |
2043 IsLexicalVariableMode(mode) ? scope : scope->DeclarationScope(); | |
2044 Variable* var = NULL; | |
2045 | |
2046 // If a suitable scope exists, then we can statically declare this | |
2047 // variable and also set its mode. In any case, a Declaration node | |
2048 // will be added to the scope so that the declaration can be added | |
2049 // to the corresponding activation frame at runtime if necessary. | |
2050 // For instance, var declarations inside a sloppy eval scope need | |
2051 // to be added to the calling function context. Similarly, strict | |
2052 // mode eval scope and lexical eval bindings do not leak variable | |
2053 // declarations to the caller's scope so we declare all locals, too. | |
2054 if (declaration_scope->is_function_scope() || | |
2055 declaration_scope->is_block_scope() || | |
2056 declaration_scope->is_module_scope() || | |
2057 declaration_scope->is_script_scope() || | |
2058 (declaration_scope->is_eval_scope() && | |
2059 (is_strict(declaration_scope->language_mode()) || | |
2060 IsLexicalVariableMode(mode)))) { | |
2061 // Declare the variable in the declaration scope. | |
2062 var = declaration_scope->LookupLocal(name); | |
2063 if (var == NULL) { | |
2064 // Declare the name. | |
2065 Variable::Kind kind = Variable::NORMAL; | |
2066 int declaration_group_start = -1; | |
2067 if (declaration->IsFunctionDeclaration()) { | |
2068 kind = Variable::FUNCTION; | |
2069 } else if (declaration->IsVariableDeclaration() && | |
2070 declaration->AsVariableDeclaration()->is_class_declaration()) { | |
2071 kind = Variable::CLASS; | |
2072 declaration_group_start = | |
2073 declaration->AsVariableDeclaration()->declaration_group_start(); | |
2074 } | |
2075 var = declaration_scope->DeclareLocal( | |
2076 name, mode, declaration->initialization(), kind, kNotAssigned, | |
2077 declaration_group_start); | |
2078 } else if (IsLexicalVariableMode(mode) || | |
2079 IsLexicalVariableMode(var->mode()) || | |
2080 ((mode == CONST_LEGACY || var->mode() == CONST_LEGACY) && | |
2081 !declaration_scope->is_script_scope())) { | |
2082 // The name was declared in this scope before; check for conflicting | |
2083 // re-declarations. We have a conflict if either of the declarations is | |
2084 // not a var (in script scope, we also have to ignore legacy const for | |
2085 // compatibility). There is similar code in runtime.cc in the Declare | |
2086 // functions. The function CheckConflictingVarDeclarations checks for | |
2087 // var and let bindings from different scopes whereas this is a check for | |
2088 // conflicting declarations within the same scope. This check also covers | |
2089 // the special case | |
2090 // | |
2091 // function () { let x; { var x; } } | |
2092 // | |
2093 // because the var declaration is hoisted to the function scope where 'x' | |
2094 // is already bound. | |
2095 DCHECK(IsDeclaredVariableMode(var->mode())); | |
2096 if (is_strict(language_mode()) || allow_harmony_sloppy()) { | |
2097 // In harmony we treat re-declarations as early errors. See | |
2098 // ES5 16 for a definition of early errors. | |
2099 if (declaration_kind == DeclarationDescriptor::NORMAL) { | |
2100 ParserTraits::ReportMessage(MessageTemplate::kVarRedeclaration, name); | |
2101 } else { | |
2102 ParserTraits::ReportMessage(MessageTemplate::kParamDupe); | |
2103 } | |
2104 *ok = false; | |
2105 return nullptr; | |
2106 } | |
2107 Expression* expression = NewThrowSyntaxError( | |
2108 MessageTemplate::kVarRedeclaration, name, declaration->position()); | |
2109 declaration_scope->SetIllegalRedeclaration(expression); | |
2110 } else if (mode == VAR) { | |
2111 var->set_maybe_assigned(); | |
2112 } | |
2113 } else if (declaration_scope->is_eval_scope() && | |
2114 is_sloppy(declaration_scope->language_mode()) && | |
2115 !IsLexicalVariableMode(mode)) { | |
2116 // In a var binding in a sloppy direct eval, pollute the enclosing scope | |
2117 // with this new binding by doing the following: | |
2118 // The proxy is bound to a lookup variable to force a dynamic declaration | |
2119 // using the DeclareLookupSlot runtime function. | |
2120 Variable::Kind kind = Variable::NORMAL; | |
2121 // TODO(sigurds) figure out if kNotAssigned is OK here | |
2122 var = new (zone()) Variable(declaration_scope, name, mode, kind, | |
2123 declaration->initialization(), kNotAssigned); | |
2124 var->AllocateTo(VariableLocation::LOOKUP, -1); | |
2125 var->SetFromEval(); | |
2126 resolve = true; | |
2127 } | |
2128 | |
2129 | |
2130 // We add a declaration node for every declaration. The compiler | |
2131 // will only generate code if necessary. In particular, declarations | |
2132 // for inner local variables that do not represent functions won't | |
2133 // result in any generated code. | |
2134 // | |
2135 // Note that we always add an unresolved proxy even if it's not | |
2136 // used, simply because we don't know in this method (w/o extra | |
2137 // parameters) if the proxy is needed or not. The proxy will be | |
2138 // bound during variable resolution time unless it was pre-bound | |
2139 // below. | |
2140 // | |
2141 // WARNING: This will lead to multiple declaration nodes for the | |
2142 // same variable if it is declared several times. This is not a | |
2143 // semantic issue as long as we keep the source order, but it may be | |
2144 // a performance issue since it may lead to repeated | |
2145 // RuntimeHidden_DeclareLookupSlot calls. | |
2146 declaration_scope->AddDeclaration(declaration); | |
2147 | |
2148 if (mode == CONST_LEGACY && declaration_scope->is_script_scope()) { | |
2149 // For global const variables we bind the proxy to a variable. | |
2150 DCHECK(resolve); // should be set by all callers | |
2151 Variable::Kind kind = Variable::NORMAL; | |
2152 var = new (zone()) Variable(declaration_scope, name, mode, kind, | |
2153 kNeedsInitialization, kNotAssigned); | |
2154 } | |
2155 | |
2156 // If requested and we have a local variable, bind the proxy to the variable | |
2157 // at parse-time. This is used for functions (and consts) declared inside | |
2158 // statements: the corresponding function (or const) variable must be in the | |
2159 // function scope and not a statement-local scope, e.g. as provided with a | |
2160 // 'with' statement: | |
2161 // | |
2162 // with (obj) { | |
2163 // function f() {} | |
2164 // } | |
2165 // | |
2166 // which is translated into: | |
2167 // | |
2168 // with (obj) { | |
2169 // // in this case this is not: 'var f; f = function () {};' | |
2170 // var f = function () {}; | |
2171 // } | |
2172 // | |
2173 // Note that if 'f' is accessed from inside the 'with' statement, it | |
2174 // will be allocated in the context (because we must be able to look | |
2175 // it up dynamically) but it will also be accessed statically, i.e., | |
2176 // with a context slot index and a context chain length for this | |
2177 // initialization code. Thus, inside the 'with' statement, we need | |
2178 // both access to the static and the dynamic context chain; the | |
2179 // runtime needs to provide both. | |
2180 if (resolve && var != NULL) { | |
2181 proxy->BindTo(var); | |
2182 } | |
2183 return var; | |
2184 } | |
2185 | |
2186 | |
2187 // Language extension which is only enabled for source files loaded | |
2188 // through the API's extension mechanism. A native function | |
2189 // declaration is resolved by looking up the function through a | |
2190 // callback provided by the extension. | |
2191 Statement* Parser::ParseNativeDeclaration(bool* ok) { | |
2192 int pos = peek_position(); | |
2193 Expect(Token::FUNCTION, CHECK_OK); | |
2194 // Allow "eval" or "arguments" for backward compatibility. | |
2195 const AstRawString* name = | |
2196 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | |
2197 Expect(Token::LPAREN, CHECK_OK); | |
2198 bool done = (peek() == Token::RPAREN); | |
2199 while (!done) { | |
2200 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | |
2201 done = (peek() == Token::RPAREN); | |
2202 if (!done) { | |
2203 Expect(Token::COMMA, CHECK_OK); | |
2204 } | |
2205 } | |
2206 Expect(Token::RPAREN, CHECK_OK); | |
2207 Expect(Token::SEMICOLON, CHECK_OK); | |
2208 | |
2209 // Make sure that the function containing the native declaration | |
2210 // isn't lazily compiled. The extension structures are only | |
2211 // accessible while parsing the first time not when reparsing | |
2212 // because of lazy compilation. | |
2213 DeclarationScope(VAR)->ForceEagerCompilation(); | |
2214 | |
2215 // TODO(1240846): It's weird that native function declarations are | |
2216 // introduced dynamically when we meet their declarations, whereas | |
2217 // other functions are set up when entering the surrounding scope. | |
2218 VariableProxy* proxy = NewUnresolved(name, VAR); | |
2219 Declaration* declaration = | |
2220 factory()->NewVariableDeclaration(proxy, VAR, scope_, pos); | |
2221 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); | |
2222 NativeFunctionLiteral* lit = factory()->NewNativeFunctionLiteral( | |
2223 name, extension_, RelocInfo::kNoPosition); | |
2224 return factory()->NewExpressionStatement( | |
2225 factory()->NewAssignment(Token::INIT, proxy, lit, RelocInfo::kNoPosition), | |
2226 pos); | |
2227 } | |
2228 | |
2229 | |
2230 Statement* Parser::ParseFunctionDeclaration( | |
2231 ZoneList<const AstRawString*>* names, bool* ok) { | |
2232 // FunctionDeclaration :: | |
2233 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' | |
2234 // GeneratorDeclaration :: | |
2235 // 'function' '*' Identifier '(' FormalParameterListopt ')' | |
2236 // '{' FunctionBody '}' | |
2237 Expect(Token::FUNCTION, CHECK_OK); | |
2238 int pos = position(); | |
2239 bool is_generator = Check(Token::MUL); | |
2240 bool is_strict_reserved = false; | |
2241 const AstRawString* name = ParseIdentifierOrStrictReservedWord( | |
2242 &is_strict_reserved, CHECK_OK); | |
2243 | |
2244 if (fni_ != NULL) { | |
2245 fni_->Enter(); | |
2246 fni_->PushEnclosingName(name); | |
2247 } | |
2248 FunctionLiteral* fun = ParseFunctionLiteral( | |
2249 name, scanner()->location(), | |
2250 is_strict_reserved ? kFunctionNameIsStrictReserved | |
2251 : kFunctionNameValidityUnknown, | |
2252 is_generator ? FunctionKind::kGeneratorFunction | |
2253 : FunctionKind::kNormalFunction, | |
2254 pos, FunctionLiteral::DECLARATION, FunctionLiteral::NORMAL_ARITY, | |
2255 language_mode(), CHECK_OK); | |
2256 if (fni_ != NULL) fni_->Leave(); | |
2257 | |
2258 // Even if we're not at the top-level of the global or a function | |
2259 // scope, we treat it as such and introduce the function with its | |
2260 // initial value upon entering the corresponding scope. | |
2261 // In ES6, a function behaves as a lexical binding, except in | |
2262 // a script scope, or the initial scope of eval or another function. | |
2263 VariableMode mode = | |
2264 is_strong(language_mode()) | |
2265 ? CONST | |
2266 : (is_strict(language_mode()) || allow_harmony_sloppy_function()) && | |
2267 !scope_->is_declaration_scope() | |
2268 ? LET | |
2269 : VAR; | |
2270 VariableProxy* proxy = NewUnresolved(name, mode); | |
2271 Declaration* declaration = | |
2272 factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos); | |
2273 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); | |
2274 if (names) names->Add(name, zone()); | |
2275 EmptyStatement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition); | |
2276 if (is_sloppy(language_mode()) && allow_harmony_sloppy_function() && | |
2277 !scope_->is_declaration_scope()) { | |
2278 SloppyBlockFunctionStatement* delegate = | |
2279 factory()->NewSloppyBlockFunctionStatement(empty, scope_); | |
2280 scope_->DeclarationScope()->sloppy_block_function_map()->Declare(name, | |
2281 delegate); | |
2282 return delegate; | |
2283 } | |
2284 return empty; | |
2285 } | |
2286 | |
2287 | |
2288 Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, | |
2289 bool* ok) { | |
2290 // ClassDeclaration :: | |
2291 // 'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}' | |
2292 // | |
2293 // A ClassDeclaration | |
2294 // | |
2295 // class C { ... } | |
2296 // | |
2297 // has the same semantics as: | |
2298 // | |
2299 // let C = class C { ... }; | |
2300 // | |
2301 // so rewrite it as such. | |
2302 | |
2303 Expect(Token::CLASS, CHECK_OK); | |
2304 if (!allow_harmony_sloppy() && is_sloppy(language_mode())) { | |
2305 ReportMessage(MessageTemplate::kSloppyLexical); | |
2306 *ok = false; | |
2307 return NULL; | |
2308 } | |
2309 | |
2310 int pos = position(); | |
2311 bool is_strict_reserved = false; | |
2312 const AstRawString* name = | |
2313 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); | |
2314 ClassLiteral* value = ParseClassLiteral(name, scanner()->location(), | |
2315 is_strict_reserved, pos, CHECK_OK); | |
2316 | |
2317 VariableMode mode = is_strong(language_mode()) ? CONST : LET; | |
2318 VariableProxy* proxy = NewUnresolved(name, mode); | |
2319 const bool is_class_declaration = true; | |
2320 Declaration* declaration = factory()->NewVariableDeclaration( | |
2321 proxy, mode, scope_, pos, is_class_declaration, | |
2322 scope_->class_declaration_group_start()); | |
2323 Variable* outer_class_variable = | |
2324 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); | |
2325 proxy->var()->set_initializer_position(position()); | |
2326 // This is needed because a class ("class Name { }") creates two bindings (one | |
2327 // in the outer scope, and one in the class scope). The method is a function | |
2328 // scope inside the inner scope (class scope). The consecutive class | |
2329 // declarations are in the outer scope. | |
2330 if (value->class_variable_proxy() && value->class_variable_proxy()->var() && | |
2331 outer_class_variable->is_class()) { | |
2332 // In some cases, the outer variable is not detected as a class variable; | |
2333 // this happens e.g., for lazy methods. They are excluded from strong mode | |
2334 // checks for now. TODO(marja, rossberg): re-create variables with the | |
2335 // correct Kind and remove this hack. | |
2336 value->class_variable_proxy() | |
2337 ->var() | |
2338 ->AsClassVariable() | |
2339 ->set_declaration_group_start( | |
2340 outer_class_variable->AsClassVariable()->declaration_group_start()); | |
2341 } | |
2342 | |
2343 Assignment* assignment = | |
2344 factory()->NewAssignment(Token::INIT, proxy, value, pos); | |
2345 Statement* assignment_statement = | |
2346 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); | |
2347 if (names) names->Add(name, zone()); | |
2348 return assignment_statement; | |
2349 } | |
2350 | |
2351 | |
2352 Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) { | |
2353 // The harmony mode uses block elements instead of statements. | |
2354 // | |
2355 // Block :: | |
2356 // '{' StatementList '}' | |
2357 | |
2358 // Construct block expecting 16 statements. | |
2359 Block* body = | |
2360 factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition); | |
2361 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); | |
2362 | |
2363 // Parse the statements and collect escaping labels. | |
2364 Expect(Token::LBRACE, CHECK_OK); | |
2365 block_scope->set_start_position(scanner()->location().beg_pos); | |
2366 { BlockState block_state(&scope_, block_scope); | |
2367 Target target(&this->target_stack_, body); | |
2368 | |
2369 while (peek() != Token::RBRACE) { | |
2370 Statement* stat = ParseStatementListItem(CHECK_OK); | |
2371 if (stat && !stat->IsEmpty()) { | |
2372 body->statements()->Add(stat, zone()); | |
2373 } | |
2374 } | |
2375 } | |
2376 Expect(Token::RBRACE, CHECK_OK); | |
2377 block_scope->set_end_position(scanner()->location().end_pos); | |
2378 block_scope = block_scope->FinalizeBlockScope(); | |
2379 body->set_scope(block_scope); | |
2380 return body; | |
2381 } | |
2382 | |
2383 | |
2384 Block* Parser::DeclarationParsingResult::BuildInitializationBlock( | |
2385 ZoneList<const AstRawString*>* names, bool* ok) { | |
2386 Block* result = descriptor.parser->factory()->NewBlock( | |
2387 NULL, 1, true, descriptor.declaration_pos); | |
2388 for (auto declaration : declarations) { | |
2389 PatternRewriter::DeclareAndInitializeVariables( | |
2390 result, &descriptor, &declaration, names, CHECK_OK); | |
2391 } | |
2392 return result; | |
2393 } | |
2394 | |
2395 | |
2396 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, | |
2397 ZoneList<const AstRawString*>* names, | |
2398 bool* ok) { | |
2399 // VariableStatement :: | |
2400 // VariableDeclarations ';' | |
2401 | |
2402 // The scope of a var/const declared variable anywhere inside a function | |
2403 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can | |
2404 // transform a source-level var/const declaration into a (Function) | |
2405 // Scope declaration, and rewrite the source-level initialization into an | |
2406 // assignment statement. We use a block to collect multiple assignments. | |
2407 // | |
2408 // We mark the block as initializer block because we don't want the | |
2409 // rewriter to add a '.result' assignment to such a block (to get compliant | |
2410 // behavior for code such as print(eval('var x = 7')), and for cosmetic | |
2411 // reasons when pretty-printing. Also, unless an assignment (initialization) | |
2412 // is inside an initializer block, it is ignored. | |
2413 | |
2414 DeclarationParsingResult parsing_result; | |
2415 ParseVariableDeclarations(var_context, &parsing_result, CHECK_OK); | |
2416 ExpectSemicolon(CHECK_OK); | |
2417 | |
2418 Block* result = parsing_result.BuildInitializationBlock(names, CHECK_OK); | |
2419 return result; | |
2420 } | |
2421 | |
2422 | |
2423 void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context, | |
2424 DeclarationParsingResult* parsing_result, | |
2425 bool* ok) { | |
2426 // VariableDeclarations :: | |
2427 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[','] | |
2428 // | |
2429 // The ES6 Draft Rev3 specifies the following grammar for const declarations | |
2430 // | |
2431 // ConstDeclaration :: | |
2432 // const ConstBinding (',' ConstBinding)* ';' | |
2433 // ConstBinding :: | |
2434 // Identifier '=' AssignmentExpression | |
2435 // | |
2436 // TODO(ES6): | |
2437 // ConstBinding :: | |
2438 // BindingPattern '=' AssignmentExpression | |
2439 | |
2440 parsing_result->descriptor.parser = this; | |
2441 parsing_result->descriptor.declaration_kind = DeclarationDescriptor::NORMAL; | |
2442 parsing_result->descriptor.declaration_pos = peek_position(); | |
2443 parsing_result->descriptor.initialization_pos = peek_position(); | |
2444 parsing_result->descriptor.mode = VAR; | |
2445 // True if the binding needs initialization. 'let' and 'const' declared | |
2446 // bindings are created uninitialized by their declaration nodes and | |
2447 // need initialization. 'var' declared bindings are always initialized | |
2448 // immediately by their declaration nodes. | |
2449 parsing_result->descriptor.needs_init = false; | |
2450 parsing_result->descriptor.is_const = false; | |
2451 if (peek() == Token::VAR) { | |
2452 if (is_strong(language_mode())) { | |
2453 Scanner::Location location = scanner()->peek_location(); | |
2454 ReportMessageAt(location, MessageTemplate::kStrongVar); | |
2455 *ok = false; | |
2456 return; | |
2457 } | |
2458 Consume(Token::VAR); | |
2459 } else if (peek() == Token::CONST && allow_const()) { | |
2460 Consume(Token::CONST); | |
2461 if (is_sloppy(language_mode()) && allow_legacy_const()) { | |
2462 parsing_result->descriptor.mode = CONST_LEGACY; | |
2463 ++use_counts_[v8::Isolate::kLegacyConst]; | |
2464 } else { | |
2465 DCHECK(is_strict(language_mode()) || allow_harmony_sloppy()); | |
2466 DCHECK(var_context != kStatement); | |
2467 parsing_result->descriptor.mode = CONST; | |
2468 } | |
2469 parsing_result->descriptor.is_const = true; | |
2470 parsing_result->descriptor.needs_init = true; | |
2471 } else if (peek() == Token::LET && allow_let()) { | |
2472 Consume(Token::LET); | |
2473 DCHECK(var_context != kStatement); | |
2474 parsing_result->descriptor.mode = LET; | |
2475 parsing_result->descriptor.needs_init = true; | |
2476 } else { | |
2477 UNREACHABLE(); // by current callers | |
2478 } | |
2479 | |
2480 parsing_result->descriptor.declaration_scope = | |
2481 DeclarationScope(parsing_result->descriptor.mode); | |
2482 parsing_result->descriptor.scope = scope_; | |
2483 parsing_result->descriptor.hoist_scope = nullptr; | |
2484 | |
2485 | |
2486 bool first_declaration = true; | |
2487 int bindings_start = peek_position(); | |
2488 bool is_for_iteration_variable; | |
2489 do { | |
2490 if (fni_ != NULL) fni_->Enter(); | |
2491 | |
2492 // Parse name. | |
2493 if (!first_declaration) Consume(Token::COMMA); | |
2494 | |
2495 Expression* pattern; | |
2496 int decl_pos = peek_position(); | |
2497 { | |
2498 ExpressionClassifier pattern_classifier; | |
2499 Token::Value next = peek(); | |
2500 pattern = ParsePrimaryExpression(&pattern_classifier, ok); | |
2501 if (!*ok) return; | |
2502 ValidateBindingPattern(&pattern_classifier, ok); | |
2503 if (!*ok) return; | |
2504 if (IsLexicalVariableMode(parsing_result->descriptor.mode)) { | |
2505 ValidateLetPattern(&pattern_classifier, ok); | |
2506 if (!*ok) return; | |
2507 } | |
2508 if (!allow_harmony_destructuring_bind() && !pattern->IsVariableProxy()) { | |
2509 ReportUnexpectedToken(next); | |
2510 *ok = false; | |
2511 return; | |
2512 } | |
2513 } | |
2514 | |
2515 bool is_pattern = pattern->IsObjectLiteral() || pattern->IsArrayLiteral(); | |
2516 | |
2517 Scanner::Location variable_loc = scanner()->location(); | |
2518 const AstRawString* single_name = | |
2519 pattern->IsVariableProxy() ? pattern->AsVariableProxy()->raw_name() | |
2520 : nullptr; | |
2521 if (single_name != nullptr) { | |
2522 if (fni_ != NULL) fni_->PushVariableName(single_name); | |
2523 } | |
2524 | |
2525 is_for_iteration_variable = | |
2526 var_context == kForStatement && | |
2527 (peek() == Token::IN || PeekContextualKeyword(CStrVector("of"))); | |
2528 if (is_for_iteration_variable && | |
2529 (parsing_result->descriptor.mode == CONST || | |
2530 parsing_result->descriptor.mode == CONST_LEGACY)) { | |
2531 parsing_result->descriptor.needs_init = false; | |
2532 } | |
2533 | |
2534 Expression* value = NULL; | |
2535 // Harmony consts have non-optional initializers. | |
2536 int initializer_position = RelocInfo::kNoPosition; | |
2537 if (Check(Token::ASSIGN)) { | |
2538 ExpressionClassifier classifier; | |
2539 value = ParseAssignmentExpression(var_context != kForStatement, | |
2540 &classifier, ok); | |
2541 if (!*ok) return; | |
2542 ValidateExpression(&classifier, ok); | |
2543 if (!*ok) return; | |
2544 variable_loc.end_pos = scanner()->location().end_pos; | |
2545 | |
2546 if (!parsing_result->first_initializer_loc.IsValid()) { | |
2547 parsing_result->first_initializer_loc = variable_loc; | |
2548 } | |
2549 | |
2550 // Don't infer if it is "a = function(){...}();"-like expression. | |
2551 if (single_name) { | |
2552 if (fni_ != NULL && value->AsCall() == NULL && | |
2553 value->AsCallNew() == NULL) { | |
2554 fni_->Infer(); | |
2555 } else { | |
2556 fni_->RemoveLastFunction(); | |
2557 } | |
2558 } | |
2559 // End position of the initializer is after the assignment expression. | |
2560 initializer_position = scanner()->location().end_pos; | |
2561 } else { | |
2562 if ((parsing_result->descriptor.mode == CONST || is_pattern) && | |
2563 !is_for_iteration_variable) { | |
2564 ParserTraits::ReportMessageAt( | |
2565 Scanner::Location(decl_pos, scanner()->location().end_pos), | |
2566 MessageTemplate::kDeclarationMissingInitializer, | |
2567 is_pattern ? "destructuring" : "const"); | |
2568 *ok = false; | |
2569 return; | |
2570 } | |
2571 // End position of the initializer is after the variable. | |
2572 initializer_position = position(); | |
2573 } | |
2574 | |
2575 // Make sure that 'const x' and 'let x' initialize 'x' to undefined. | |
2576 if (value == NULL && parsing_result->descriptor.needs_init) { | |
2577 value = GetLiteralUndefined(position()); | |
2578 } | |
2579 | |
2580 if (single_name && fni_ != NULL) fni_->Leave(); | |
2581 parsing_result->declarations.Add(DeclarationParsingResult::Declaration( | |
2582 pattern, initializer_position, value)); | |
2583 first_declaration = false; | |
2584 } while (peek() == Token::COMMA); | |
2585 | |
2586 parsing_result->bindings_loc = | |
2587 Scanner::Location(bindings_start, scanner()->location().end_pos); | |
2588 } | |
2589 | |
2590 | |
2591 static bool ContainsLabel(ZoneList<const AstRawString*>* labels, | |
2592 const AstRawString* label) { | |
2593 DCHECK(label != NULL); | |
2594 if (labels != NULL) { | |
2595 for (int i = labels->length(); i-- > 0; ) { | |
2596 if (labels->at(i) == label) { | |
2597 return true; | |
2598 } | |
2599 } | |
2600 } | |
2601 return false; | |
2602 } | |
2603 | |
2604 | |
2605 Statement* Parser::ParseExpressionOrLabelledStatement( | |
2606 ZoneList<const AstRawString*>* labels, bool* ok) { | |
2607 // ExpressionStatement | LabelledStatement :: | |
2608 // Expression ';' | |
2609 // Identifier ':' Statement | |
2610 // | |
2611 // ExpressionStatement[Yield] : | |
2612 // [lookahead ∉ {{, function, class, let [}] Expression[In, ?Yield] ; | |
2613 | |
2614 int pos = peek_position(); | |
2615 | |
2616 switch (peek()) { | |
2617 case Token::FUNCTION: | |
2618 case Token::LBRACE: | |
2619 UNREACHABLE(); // Always handled by the callers. | |
2620 case Token::CLASS: | |
2621 ReportUnexpectedToken(Next()); | |
2622 *ok = false; | |
2623 return nullptr; | |
2624 | |
2625 case Token::THIS: | |
2626 if (!FLAG_strong_this) break; | |
2627 // Fall through. | |
2628 case Token::SUPER: | |
2629 if (is_strong(language_mode()) && | |
2630 IsClassConstructor(function_state_->kind())) { | |
2631 bool is_this = peek() == Token::THIS; | |
2632 Expression* expr; | |
2633 ExpressionClassifier classifier; | |
2634 if (is_this) { | |
2635 expr = ParseStrongInitializationExpression(&classifier, CHECK_OK); | |
2636 } else { | |
2637 expr = ParseStrongSuperCallExpression(&classifier, CHECK_OK); | |
2638 } | |
2639 ValidateExpression(&classifier, CHECK_OK); | |
2640 switch (peek()) { | |
2641 case Token::SEMICOLON: | |
2642 Consume(Token::SEMICOLON); | |
2643 break; | |
2644 case Token::RBRACE: | |
2645 case Token::EOS: | |
2646 break; | |
2647 default: | |
2648 if (!scanner()->HasAnyLineTerminatorBeforeNext()) { | |
2649 ReportMessageAt(function_state_->this_location(), | |
2650 is_this | |
2651 ? MessageTemplate::kStrongConstructorThis | |
2652 : MessageTemplate::kStrongConstructorSuper); | |
2653 *ok = false; | |
2654 return nullptr; | |
2655 } | |
2656 } | |
2657 return factory()->NewExpressionStatement(expr, pos); | |
2658 } | |
2659 break; | |
2660 | |
2661 default: | |
2662 break; | |
2663 } | |
2664 | |
2665 bool starts_with_idenfifier = peek_any_identifier(); | |
2666 Expression* expr = ParseExpression(true, CHECK_OK); | |
2667 if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL && | |
2668 expr->AsVariableProxy() != NULL && | |
2669 !expr->AsVariableProxy()->is_this()) { | |
2670 // Expression is a single identifier, and not, e.g., a parenthesized | |
2671 // identifier. | |
2672 VariableProxy* var = expr->AsVariableProxy(); | |
2673 const AstRawString* label = var->raw_name(); | |
2674 // TODO(1240780): We don't check for redeclaration of labels | |
2675 // during preparsing since keeping track of the set of active | |
2676 // labels requires nontrivial changes to the way scopes are | |
2677 // structured. However, these are probably changes we want to | |
2678 // make later anyway so we should go back and fix this then. | |
2679 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) { | |
2680 ParserTraits::ReportMessage(MessageTemplate::kLabelRedeclaration, label); | |
2681 *ok = false; | |
2682 return NULL; | |
2683 } | |
2684 if (labels == NULL) { | |
2685 labels = new(zone()) ZoneList<const AstRawString*>(4, zone()); | |
2686 } | |
2687 labels->Add(label, zone()); | |
2688 // Remove the "ghost" variable that turned out to be a label | |
2689 // from the top scope. This way, we don't try to resolve it | |
2690 // during the scope processing. | |
2691 scope_->RemoveUnresolved(var); | |
2692 Expect(Token::COLON, CHECK_OK); | |
2693 return ParseStatement(labels, ok); | |
2694 } | |
2695 | |
2696 // If we have an extension, we allow a native function declaration. | |
2697 // A native function declaration starts with "native function" with | |
2698 // no line-terminator between the two words. | |
2699 if (extension_ != NULL && peek() == Token::FUNCTION && | |
2700 !scanner()->HasAnyLineTerminatorBeforeNext() && expr != NULL && | |
2701 expr->AsVariableProxy() != NULL && | |
2702 expr->AsVariableProxy()->raw_name() == | |
2703 ast_value_factory()->native_string() && | |
2704 !scanner()->literal_contains_escapes()) { | |
2705 return ParseNativeDeclaration(ok); | |
2706 } | |
2707 | |
2708 // Parsed expression statement, followed by semicolon. | |
2709 // Detect attempts at 'let' declarations in sloppy mode. | |
2710 if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER && | |
2711 expr->AsVariableProxy() != NULL && | |
2712 expr->AsVariableProxy()->raw_name() == | |
2713 ast_value_factory()->let_string()) { | |
2714 ReportMessage(MessageTemplate::kSloppyLexical, NULL); | |
2715 *ok = false; | |
2716 return NULL; | |
2717 } | |
2718 ExpectSemicolon(CHECK_OK); | |
2719 return factory()->NewExpressionStatement(expr, pos); | |
2720 } | |
2721 | |
2722 | |
2723 IfStatement* Parser::ParseIfStatement(ZoneList<const AstRawString*>* labels, | |
2724 bool* ok) { | |
2725 // IfStatement :: | |
2726 // 'if' '(' Expression ')' Statement ('else' Statement)? | |
2727 | |
2728 int pos = peek_position(); | |
2729 Expect(Token::IF, CHECK_OK); | |
2730 Expect(Token::LPAREN, CHECK_OK); | |
2731 Expression* condition = ParseExpression(true, CHECK_OK); | |
2732 Expect(Token::RPAREN, CHECK_OK); | |
2733 Statement* then_statement = ParseSubStatement(labels, CHECK_OK); | |
2734 Statement* else_statement = NULL; | |
2735 if (peek() == Token::ELSE) { | |
2736 Next(); | |
2737 else_statement = ParseSubStatement(labels, CHECK_OK); | |
2738 } else { | |
2739 else_statement = factory()->NewEmptyStatement(RelocInfo::kNoPosition); | |
2740 } | |
2741 return factory()->NewIfStatement( | |
2742 condition, then_statement, else_statement, pos); | |
2743 } | |
2744 | |
2745 | |
2746 Statement* Parser::ParseContinueStatement(bool* ok) { | |
2747 // ContinueStatement :: | |
2748 // 'continue' Identifier? ';' | |
2749 | |
2750 int pos = peek_position(); | |
2751 Expect(Token::CONTINUE, CHECK_OK); | |
2752 const AstRawString* label = NULL; | |
2753 Token::Value tok = peek(); | |
2754 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | |
2755 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { | |
2756 // ECMA allows "eval" or "arguments" as labels even in strict mode. | |
2757 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | |
2758 } | |
2759 IterationStatement* target = LookupContinueTarget(label, CHECK_OK); | |
2760 if (target == NULL) { | |
2761 // Illegal continue statement. | |
2762 MessageTemplate::Template message = MessageTemplate::kIllegalContinue; | |
2763 if (label != NULL) { | |
2764 message = MessageTemplate::kUnknownLabel; | |
2765 } | |
2766 ParserTraits::ReportMessage(message, label); | |
2767 *ok = false; | |
2768 return NULL; | |
2769 } | |
2770 ExpectSemicolon(CHECK_OK); | |
2771 return factory()->NewContinueStatement(target, pos); | |
2772 } | |
2773 | |
2774 | |
2775 Statement* Parser::ParseBreakStatement(ZoneList<const AstRawString*>* labels, | |
2776 bool* ok) { | |
2777 // BreakStatement :: | |
2778 // 'break' Identifier? ';' | |
2779 | |
2780 int pos = peek_position(); | |
2781 Expect(Token::BREAK, CHECK_OK); | |
2782 const AstRawString* label = NULL; | |
2783 Token::Value tok = peek(); | |
2784 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | |
2785 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { | |
2786 // ECMA allows "eval" or "arguments" as labels even in strict mode. | |
2787 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | |
2788 } | |
2789 // Parse labeled break statements that target themselves into | |
2790 // empty statements, e.g. 'l1: l2: l3: break l2;' | |
2791 if (label != NULL && ContainsLabel(labels, label)) { | |
2792 ExpectSemicolon(CHECK_OK); | |
2793 return factory()->NewEmptyStatement(pos); | |
2794 } | |
2795 BreakableStatement* target = NULL; | |
2796 target = LookupBreakTarget(label, CHECK_OK); | |
2797 if (target == NULL) { | |
2798 // Illegal break statement. | |
2799 MessageTemplate::Template message = MessageTemplate::kIllegalBreak; | |
2800 if (label != NULL) { | |
2801 message = MessageTemplate::kUnknownLabel; | |
2802 } | |
2803 ParserTraits::ReportMessage(message, label); | |
2804 *ok = false; | |
2805 return NULL; | |
2806 } | |
2807 ExpectSemicolon(CHECK_OK); | |
2808 return factory()->NewBreakStatement(target, pos); | |
2809 } | |
2810 | |
2811 | |
2812 Statement* Parser::ParseReturnStatement(bool* ok) { | |
2813 // ReturnStatement :: | |
2814 // 'return' Expression? ';' | |
2815 | |
2816 // Consume the return token. It is necessary to do that before | |
2817 // reporting any errors on it, because of the way errors are | |
2818 // reported (underlining). | |
2819 Expect(Token::RETURN, CHECK_OK); | |
2820 Scanner::Location loc = scanner()->location(); | |
2821 function_state_->set_return_location(loc); | |
2822 | |
2823 Token::Value tok = peek(); | |
2824 Statement* result; | |
2825 Expression* return_value; | |
2826 if (scanner()->HasAnyLineTerminatorBeforeNext() || | |
2827 tok == Token::SEMICOLON || | |
2828 tok == Token::RBRACE || | |
2829 tok == Token::EOS) { | |
2830 if (IsSubclassConstructor(function_state_->kind())) { | |
2831 return_value = ThisExpression(scope_, factory(), loc.beg_pos); | |
2832 } else { | |
2833 return_value = GetLiteralUndefined(position()); | |
2834 } | |
2835 } else { | |
2836 if (is_strong(language_mode()) && | |
2837 IsClassConstructor(function_state_->kind())) { | |
2838 int pos = peek_position(); | |
2839 ReportMessageAt(Scanner::Location(pos, pos + 1), | |
2840 MessageTemplate::kStrongConstructorReturnValue); | |
2841 *ok = false; | |
2842 return NULL; | |
2843 } | |
2844 | |
2845 int pos = peek_position(); | |
2846 return_value = ParseExpression(true, CHECK_OK); | |
2847 | |
2848 if (IsSubclassConstructor(function_state_->kind())) { | |
2849 // For subclass constructors we need to return this in case of undefined | |
2850 // and throw an exception in case of a non object. | |
2851 // | |
2852 // return expr; | |
2853 // | |
2854 // Is rewritten as: | |
2855 // | |
2856 // return (temp = expr) === undefined ? this : | |
2857 // %_IsSpecObject(temp) ? temp : throw new TypeError(...); | |
2858 Variable* temp = scope_->NewTemporary( | |
2859 ast_value_factory()->empty_string()); | |
2860 Assignment* assign = factory()->NewAssignment( | |
2861 Token::ASSIGN, factory()->NewVariableProxy(temp), return_value, pos); | |
2862 | |
2863 Expression* throw_expression = | |
2864 NewThrowTypeError(MessageTemplate::kDerivedConstructorReturn, | |
2865 ast_value_factory()->empty_string(), pos); | |
2866 | |
2867 // %_IsSpecObject(temp) | |
2868 ZoneList<Expression*>* is_spec_object_args = | |
2869 new (zone()) ZoneList<Expression*>(1, zone()); | |
2870 is_spec_object_args->Add(factory()->NewVariableProxy(temp), zone()); | |
2871 Expression* is_spec_object_call = factory()->NewCallRuntime( | |
2872 Runtime::kInlineIsSpecObject, is_spec_object_args, pos); | |
2873 | |
2874 // %_IsSpecObject(temp) ? temp : throw_expression | |
2875 Expression* is_object_conditional = factory()->NewConditional( | |
2876 is_spec_object_call, factory()->NewVariableProxy(temp), | |
2877 throw_expression, pos); | |
2878 | |
2879 // temp === undefined | |
2880 Expression* is_undefined = factory()->NewCompareOperation( | |
2881 Token::EQ_STRICT, assign, | |
2882 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), pos); | |
2883 | |
2884 // is_undefined ? this : is_object_conditional | |
2885 return_value = factory()->NewConditional( | |
2886 is_undefined, ThisExpression(scope_, factory(), pos), | |
2887 is_object_conditional, pos); | |
2888 } | |
2889 } | |
2890 ExpectSemicolon(CHECK_OK); | |
2891 | |
2892 if (is_generator()) { | |
2893 Expression* generator = factory()->NewVariableProxy( | |
2894 function_state_->generator_object_variable()); | |
2895 Expression* yield = factory()->NewYield( | |
2896 generator, return_value, Yield::kFinal, loc.beg_pos); | |
2897 result = factory()->NewExpressionStatement(yield, loc.beg_pos); | |
2898 } else { | |
2899 result = factory()->NewReturnStatement(return_value, loc.beg_pos); | |
2900 } | |
2901 | |
2902 Scope* decl_scope = scope_->DeclarationScope(); | |
2903 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) { | |
2904 ReportMessageAt(loc, MessageTemplate::kIllegalReturn); | |
2905 *ok = false; | |
2906 return NULL; | |
2907 } | |
2908 return result; | |
2909 } | |
2910 | |
2911 | |
2912 Statement* Parser::ParseWithStatement(ZoneList<const AstRawString*>* labels, | |
2913 bool* ok) { | |
2914 // WithStatement :: | |
2915 // 'with' '(' Expression ')' Statement | |
2916 | |
2917 Expect(Token::WITH, CHECK_OK); | |
2918 int pos = position(); | |
2919 | |
2920 if (is_strict(language_mode())) { | |
2921 ReportMessage(MessageTemplate::kStrictWith); | |
2922 *ok = false; | |
2923 return NULL; | |
2924 } | |
2925 | |
2926 Expect(Token::LPAREN, CHECK_OK); | |
2927 Expression* expr = ParseExpression(true, CHECK_OK); | |
2928 Expect(Token::RPAREN, CHECK_OK); | |
2929 | |
2930 scope_->DeclarationScope()->RecordWithStatement(); | |
2931 Scope* with_scope = NewScope(scope_, WITH_SCOPE); | |
2932 Block* body; | |
2933 { BlockState block_state(&scope_, with_scope); | |
2934 with_scope->set_start_position(scanner()->peek_location().beg_pos); | |
2935 | |
2936 // The body of the with statement must be enclosed in an additional | |
2937 // lexical scope in case the body is a FunctionDeclaration. | |
2938 body = factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition); | |
2939 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); | |
2940 block_scope->set_start_position(scanner()->location().beg_pos); | |
2941 { | |
2942 BlockState block_state(&scope_, block_scope); | |
2943 Target target(&this->target_stack_, body); | |
2944 Statement* stmt = ParseSubStatement(labels, CHECK_OK); | |
2945 body->statements()->Add(stmt, zone()); | |
2946 block_scope->set_end_position(scanner()->location().end_pos); | |
2947 block_scope = block_scope->FinalizeBlockScope(); | |
2948 body->set_scope(block_scope); | |
2949 } | |
2950 | |
2951 with_scope->set_end_position(scanner()->location().end_pos); | |
2952 } | |
2953 return factory()->NewWithStatement(with_scope, expr, body, pos); | |
2954 } | |
2955 | |
2956 | |
2957 CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { | |
2958 // CaseClause :: | |
2959 // 'case' Expression ':' StatementList | |
2960 // 'default' ':' StatementList | |
2961 | |
2962 Expression* label = NULL; // NULL expression indicates default case | |
2963 if (peek() == Token::CASE) { | |
2964 Expect(Token::CASE, CHECK_OK); | |
2965 label = ParseExpression(true, CHECK_OK); | |
2966 } else { | |
2967 Expect(Token::DEFAULT, CHECK_OK); | |
2968 if (*default_seen_ptr) { | |
2969 ReportMessage(MessageTemplate::kMultipleDefaultsInSwitch); | |
2970 *ok = false; | |
2971 return NULL; | |
2972 } | |
2973 *default_seen_ptr = true; | |
2974 } | |
2975 Expect(Token::COLON, CHECK_OK); | |
2976 int pos = position(); | |
2977 ZoneList<Statement*>* statements = | |
2978 new(zone()) ZoneList<Statement*>(5, zone()); | |
2979 Statement* stat = NULL; | |
2980 while (peek() != Token::CASE && | |
2981 peek() != Token::DEFAULT && | |
2982 peek() != Token::RBRACE) { | |
2983 stat = ParseStatementListItem(CHECK_OK); | |
2984 statements->Add(stat, zone()); | |
2985 } | |
2986 if (is_strong(language_mode()) && stat != NULL && !stat->IsJump() && | |
2987 peek() != Token::RBRACE) { | |
2988 ReportMessageAt(scanner()->location(), | |
2989 MessageTemplate::kStrongSwitchFallthrough); | |
2990 *ok = false; | |
2991 return NULL; | |
2992 } | |
2993 return factory()->NewCaseClause(label, statements, pos); | |
2994 } | |
2995 | |
2996 | |
2997 Statement* Parser::ParseSwitchStatement(ZoneList<const AstRawString*>* labels, | |
2998 bool* ok) { | |
2999 // SwitchStatement :: | |
3000 // 'switch' '(' Expression ')' '{' CaseClause* '}' | |
3001 // In order to get the CaseClauses to execute in their own lexical scope, | |
3002 // but without requiring downstream code to have special scope handling | |
3003 // code for switch statements, desugar into blocks as follows: | |
3004 // { // To group the statements--harmless to evaluate Expression in scope | |
3005 // .tag_variable = Expression; | |
3006 // { // To give CaseClauses a scope | |
3007 // switch (.tag_variable) { CaseClause* } | |
3008 // } | |
3009 // } | |
3010 | |
3011 Block* switch_block = | |
3012 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); | |
3013 int switch_pos = peek_position(); | |
3014 | |
3015 Expect(Token::SWITCH, CHECK_OK); | |
3016 Expect(Token::LPAREN, CHECK_OK); | |
3017 Expression* tag = ParseExpression(true, CHECK_OK); | |
3018 Expect(Token::RPAREN, CHECK_OK); | |
3019 | |
3020 Variable* tag_variable = | |
3021 scope_->NewTemporary(ast_value_factory()->dot_switch_tag_string()); | |
3022 Assignment* tag_assign = factory()->NewAssignment( | |
3023 Token::ASSIGN, factory()->NewVariableProxy(tag_variable), tag, | |
3024 tag->position()); | |
3025 Statement* tag_statement = | |
3026 factory()->NewExpressionStatement(tag_assign, RelocInfo::kNoPosition); | |
3027 switch_block->statements()->Add(tag_statement, zone()); | |
3028 | |
3029 // make statement: undefined; | |
3030 // This is needed so the tag isn't returned as the value, in case the switch | |
3031 // statements don't have a value. | |
3032 switch_block->statements()->Add( | |
3033 factory()->NewExpressionStatement( | |
3034 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), | |
3035 RelocInfo::kNoPosition), | |
3036 zone()); | |
3037 | |
3038 Block* cases_block = | |
3039 factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); | |
3040 Scope* cases_scope = NewScope(scope_, BLOCK_SCOPE); | |
3041 cases_scope->SetNonlinear(); | |
3042 | |
3043 SwitchStatement* switch_statement = | |
3044 factory()->NewSwitchStatement(labels, switch_pos); | |
3045 | |
3046 cases_scope->set_start_position(scanner()->location().beg_pos); | |
3047 { | |
3048 BlockState cases_block_state(&scope_, cases_scope); | |
3049 Target target(&this->target_stack_, switch_statement); | |
3050 | |
3051 Expression* tag_read = factory()->NewVariableProxy(tag_variable); | |
3052 | |
3053 bool default_seen = false; | |
3054 ZoneList<CaseClause*>* cases = | |
3055 new (zone()) ZoneList<CaseClause*>(4, zone()); | |
3056 Expect(Token::LBRACE, CHECK_OK); | |
3057 while (peek() != Token::RBRACE) { | |
3058 CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK); | |
3059 cases->Add(clause, zone()); | |
3060 } | |
3061 switch_statement->Initialize(tag_read, cases); | |
3062 cases_block->statements()->Add(switch_statement, zone()); | |
3063 } | |
3064 Expect(Token::RBRACE, CHECK_OK); | |
3065 | |
3066 cases_scope->set_end_position(scanner()->location().end_pos); | |
3067 cases_scope = cases_scope->FinalizeBlockScope(); | |
3068 cases_block->set_scope(cases_scope); | |
3069 | |
3070 switch_block->statements()->Add(cases_block, zone()); | |
3071 | |
3072 return switch_block; | |
3073 } | |
3074 | |
3075 | |
3076 Statement* Parser::ParseThrowStatement(bool* ok) { | |
3077 // ThrowStatement :: | |
3078 // 'throw' Expression ';' | |
3079 | |
3080 Expect(Token::THROW, CHECK_OK); | |
3081 int pos = position(); | |
3082 if (scanner()->HasAnyLineTerminatorBeforeNext()) { | |
3083 ReportMessage(MessageTemplate::kNewlineAfterThrow); | |
3084 *ok = false; | |
3085 return NULL; | |
3086 } | |
3087 Expression* exception = ParseExpression(true, CHECK_OK); | |
3088 ExpectSemicolon(CHECK_OK); | |
3089 | |
3090 return factory()->NewExpressionStatement( | |
3091 factory()->NewThrow(exception, pos), pos); | |
3092 } | |
3093 | |
3094 | |
3095 TryStatement* Parser::ParseTryStatement(bool* ok) { | |
3096 // TryStatement :: | |
3097 // 'try' Block Catch | |
3098 // 'try' Block Finally | |
3099 // 'try' Block Catch Finally | |
3100 // | |
3101 // Catch :: | |
3102 // 'catch' '(' Identifier ')' Block | |
3103 // | |
3104 // Finally :: | |
3105 // 'finally' Block | |
3106 | |
3107 Expect(Token::TRY, CHECK_OK); | |
3108 int pos = position(); | |
3109 | |
3110 Block* try_block = ParseBlock(NULL, CHECK_OK); | |
3111 | |
3112 Token::Value tok = peek(); | |
3113 if (tok != Token::CATCH && tok != Token::FINALLY) { | |
3114 ReportMessage(MessageTemplate::kNoCatchOrFinally); | |
3115 *ok = false; | |
3116 return NULL; | |
3117 } | |
3118 | |
3119 Scope* catch_scope = NULL; | |
3120 Variable* catch_variable = NULL; | |
3121 Block* catch_block = NULL; | |
3122 if (tok == Token::CATCH) { | |
3123 Consume(Token::CATCH); | |
3124 | |
3125 Expect(Token::LPAREN, CHECK_OK); | |
3126 catch_scope = NewScope(scope_, CATCH_SCOPE); | |
3127 catch_scope->set_start_position(scanner()->location().beg_pos); | |
3128 | |
3129 ExpressionClassifier pattern_classifier; | |
3130 Expression* pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK); | |
3131 ValidateBindingPattern(&pattern_classifier, CHECK_OK); | |
3132 | |
3133 const AstRawString* name = ast_value_factory()->dot_catch_string(); | |
3134 bool is_simple = pattern->IsVariableProxy(); | |
3135 if (is_simple) { | |
3136 auto proxy = pattern->AsVariableProxy(); | |
3137 scope_->RemoveUnresolved(proxy); | |
3138 name = proxy->raw_name(); | |
3139 } | |
3140 | |
3141 catch_variable = catch_scope->DeclareLocal(name, VAR, kCreatedInitialized, | |
3142 Variable::NORMAL); | |
3143 | |
3144 Expect(Token::RPAREN, CHECK_OK); | |
3145 | |
3146 { | |
3147 BlockState block_state(&scope_, catch_scope); | |
3148 | |
3149 // TODO(adamk): Make a version of ParseBlock that takes a scope and | |
3150 // a block. | |
3151 catch_block = | |
3152 factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition); | |
3153 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); | |
3154 | |
3155 block_scope->set_start_position(scanner()->location().beg_pos); | |
3156 { | |
3157 BlockState block_state(&scope_, block_scope); | |
3158 Target target(&this->target_stack_, catch_block); | |
3159 | |
3160 if (!is_simple) { | |
3161 DeclarationDescriptor descriptor; | |
3162 descriptor.declaration_kind = DeclarationDescriptor::NORMAL; | |
3163 descriptor.parser = this; | |
3164 descriptor.declaration_scope = scope_; | |
3165 descriptor.scope = scope_; | |
3166 descriptor.hoist_scope = nullptr; | |
3167 descriptor.mode = LET; | |
3168 descriptor.is_const = false; | |
3169 descriptor.needs_init = true; | |
3170 descriptor.declaration_pos = pattern->position(); | |
3171 descriptor.initialization_pos = pattern->position(); | |
3172 | |
3173 DeclarationParsingResult::Declaration decl( | |
3174 pattern, pattern->position(), | |
3175 factory()->NewVariableProxy(catch_variable)); | |
3176 | |
3177 PatternRewriter::DeclareAndInitializeVariables( | |
3178 catch_block, &descriptor, &decl, nullptr, CHECK_OK); | |
3179 } | |
3180 | |
3181 Expect(Token::LBRACE, CHECK_OK); | |
3182 while (peek() != Token::RBRACE) { | |
3183 Statement* stat = ParseStatementListItem(CHECK_OK); | |
3184 if (stat && !stat->IsEmpty()) { | |
3185 catch_block->statements()->Add(stat, zone()); | |
3186 } | |
3187 } | |
3188 Consume(Token::RBRACE); | |
3189 } | |
3190 block_scope->set_end_position(scanner()->location().end_pos); | |
3191 block_scope = block_scope->FinalizeBlockScope(); | |
3192 catch_block->set_scope(block_scope); | |
3193 } | |
3194 | |
3195 catch_scope->set_end_position(scanner()->location().end_pos); | |
3196 tok = peek(); | |
3197 } | |
3198 | |
3199 Block* finally_block = NULL; | |
3200 DCHECK(tok == Token::FINALLY || catch_block != NULL); | |
3201 if (tok == Token::FINALLY) { | |
3202 Consume(Token::FINALLY); | |
3203 finally_block = ParseBlock(NULL, CHECK_OK); | |
3204 } | |
3205 | |
3206 // Simplify the AST nodes by converting: | |
3207 // 'try B0 catch B1 finally B2' | |
3208 // to: | |
3209 // 'try { try B0 catch B1 } finally B2' | |
3210 | |
3211 if (catch_block != NULL && finally_block != NULL) { | |
3212 // If we have both, create an inner try/catch. | |
3213 DCHECK(catch_scope != NULL && catch_variable != NULL); | |
3214 TryCatchStatement* statement = | |
3215 factory()->NewTryCatchStatement(try_block, catch_scope, catch_variable, | |
3216 catch_block, RelocInfo::kNoPosition); | |
3217 try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); | |
3218 try_block->statements()->Add(statement, zone()); | |
3219 catch_block = NULL; // Clear to indicate it's been handled. | |
3220 } | |
3221 | |
3222 TryStatement* result = NULL; | |
3223 if (catch_block != NULL) { | |
3224 DCHECK(finally_block == NULL); | |
3225 DCHECK(catch_scope != NULL && catch_variable != NULL); | |
3226 result = factory()->NewTryCatchStatement(try_block, catch_scope, | |
3227 catch_variable, catch_block, pos); | |
3228 } else { | |
3229 DCHECK(finally_block != NULL); | |
3230 result = factory()->NewTryFinallyStatement(try_block, finally_block, pos); | |
3231 } | |
3232 | |
3233 return result; | |
3234 } | |
3235 | |
3236 | |
3237 DoWhileStatement* Parser::ParseDoWhileStatement( | |
3238 ZoneList<const AstRawString*>* labels, bool* ok) { | |
3239 // DoStatement :: | |
3240 // 'do' Statement 'while' '(' Expression ')' ';' | |
3241 | |
3242 DoWhileStatement* loop = | |
3243 factory()->NewDoWhileStatement(labels, peek_position()); | |
3244 Target target(&this->target_stack_, loop); | |
3245 | |
3246 Expect(Token::DO, CHECK_OK); | |
3247 Statement* body = ParseSubStatement(NULL, CHECK_OK); | |
3248 Expect(Token::WHILE, CHECK_OK); | |
3249 Expect(Token::LPAREN, CHECK_OK); | |
3250 | |
3251 Expression* cond = ParseExpression(true, CHECK_OK); | |
3252 Expect(Token::RPAREN, CHECK_OK); | |
3253 | |
3254 // Allow do-statements to be terminated with and without | |
3255 // semi-colons. This allows code such as 'do;while(0)return' to | |
3256 // parse, which would not be the case if we had used the | |
3257 // ExpectSemicolon() functionality here. | |
3258 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON); | |
3259 | |
3260 if (loop != NULL) loop->Initialize(cond, body); | |
3261 return loop; | |
3262 } | |
3263 | |
3264 | |
3265 WhileStatement* Parser::ParseWhileStatement( | |
3266 ZoneList<const AstRawString*>* labels, bool* ok) { | |
3267 // WhileStatement :: | |
3268 // 'while' '(' Expression ')' Statement | |
3269 | |
3270 WhileStatement* loop = factory()->NewWhileStatement(labels, peek_position()); | |
3271 Target target(&this->target_stack_, loop); | |
3272 | |
3273 Expect(Token::WHILE, CHECK_OK); | |
3274 Expect(Token::LPAREN, CHECK_OK); | |
3275 Expression* cond = ParseExpression(true, CHECK_OK); | |
3276 Expect(Token::RPAREN, CHECK_OK); | |
3277 Statement* body = ParseSubStatement(NULL, CHECK_OK); | |
3278 | |
3279 if (loop != NULL) loop->Initialize(cond, body); | |
3280 return loop; | |
3281 } | |
3282 | |
3283 | |
3284 // !%_IsSpecObject(result = iterator.next()) && | |
3285 // %ThrowIteratorResultNotAnObject(result) | |
3286 Expression* Parser::BuildIteratorNextResult(Expression* iterator, | |
3287 Variable* result, int pos) { | |
3288 Expression* next_literal = factory()->NewStringLiteral( | |
3289 ast_value_factory()->next_string(), RelocInfo::kNoPosition); | |
3290 Expression* next_property = | |
3291 factory()->NewProperty(iterator, next_literal, RelocInfo::kNoPosition); | |
3292 ZoneList<Expression*>* next_arguments = | |
3293 new (zone()) ZoneList<Expression*>(0, zone()); | |
3294 Expression* next_call = | |
3295 factory()->NewCall(next_property, next_arguments, pos); | |
3296 Expression* result_proxy = factory()->NewVariableProxy(result); | |
3297 Expression* left = | |
3298 factory()->NewAssignment(Token::ASSIGN, result_proxy, next_call, pos); | |
3299 | |
3300 // %_IsSpecObject(...) | |
3301 ZoneList<Expression*>* is_spec_object_args = | |
3302 new (zone()) ZoneList<Expression*>(1, zone()); | |
3303 is_spec_object_args->Add(left, zone()); | |
3304 Expression* is_spec_object_call = factory()->NewCallRuntime( | |
3305 Runtime::kInlineIsSpecObject, is_spec_object_args, pos); | |
3306 | |
3307 // %ThrowIteratorResultNotAnObject(result) | |
3308 Expression* result_proxy_again = factory()->NewVariableProxy(result); | |
3309 ZoneList<Expression*>* throw_arguments = | |
3310 new (zone()) ZoneList<Expression*>(1, zone()); | |
3311 throw_arguments->Add(result_proxy_again, zone()); | |
3312 Expression* throw_call = factory()->NewCallRuntime( | |
3313 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos); | |
3314 | |
3315 return factory()->NewBinaryOperation( | |
3316 Token::AND, | |
3317 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos), | |
3318 throw_call, pos); | |
3319 } | |
3320 | |
3321 | |
3322 void Parser::InitializeForEachStatement(ForEachStatement* stmt, | |
3323 Expression* each, | |
3324 Expression* subject, | |
3325 Statement* body) { | |
3326 ForOfStatement* for_of = stmt->AsForOfStatement(); | |
3327 | |
3328 if (for_of != NULL) { | |
3329 Variable* iterator = scope_->NewTemporary( | |
3330 ast_value_factory()->dot_iterator_string()); | |
3331 Variable* result = scope_->NewTemporary( | |
3332 ast_value_factory()->dot_result_string()); | |
3333 | |
3334 Expression* assign_iterator; | |
3335 Expression* next_result; | |
3336 Expression* result_done; | |
3337 Expression* assign_each; | |
3338 | |
3339 // iterator = subject[Symbol.iterator]() | |
3340 assign_iterator = factory()->NewAssignment( | |
3341 Token::ASSIGN, factory()->NewVariableProxy(iterator), | |
3342 GetIterator(subject, factory()), subject->position()); | |
3343 | |
3344 // !%_IsSpecObject(result = iterator.next()) && | |
3345 // %ThrowIteratorResultNotAnObject(result) | |
3346 { | |
3347 // result = iterator.next() | |
3348 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); | |
3349 next_result = | |
3350 BuildIteratorNextResult(iterator_proxy, result, subject->position()); | |
3351 } | |
3352 | |
3353 // result.done | |
3354 { | |
3355 Expression* done_literal = factory()->NewStringLiteral( | |
3356 ast_value_factory()->done_string(), RelocInfo::kNoPosition); | |
3357 Expression* result_proxy = factory()->NewVariableProxy(result); | |
3358 result_done = factory()->NewProperty( | |
3359 result_proxy, done_literal, RelocInfo::kNoPosition); | |
3360 } | |
3361 | |
3362 // each = result.value | |
3363 { | |
3364 Expression* value_literal = factory()->NewStringLiteral( | |
3365 ast_value_factory()->value_string(), RelocInfo::kNoPosition); | |
3366 Expression* result_proxy = factory()->NewVariableProxy(result); | |
3367 Expression* result_value = factory()->NewProperty( | |
3368 result_proxy, value_literal, RelocInfo::kNoPosition); | |
3369 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value, | |
3370 RelocInfo::kNoPosition); | |
3371 } | |
3372 | |
3373 for_of->Initialize(each, subject, body, | |
3374 assign_iterator, | |
3375 next_result, | |
3376 result_done, | |
3377 assign_each); | |
3378 } else { | |
3379 stmt->Initialize(each, subject, body); | |
3380 } | |
3381 } | |
3382 | |
3383 | |
3384 Statement* Parser::DesugarLexicalBindingsInForStatement( | |
3385 Scope* inner_scope, bool is_const, ZoneList<const AstRawString*>* names, | |
3386 ForStatement* loop, Statement* init, Expression* cond, Statement* next, | |
3387 Statement* body, bool* ok) { | |
3388 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are | |
3389 // copied into a new environment. Moreover, the "next" statement must be | |
3390 // evaluated not in the environment of the just completed iteration but in | |
3391 // that of the upcoming one. We achieve this with the following desugaring. | |
3392 // Extra care is needed to preserve the completion value of the original loop. | |
3393 // | |
3394 // We are given a for statement of the form | |
3395 // | |
3396 // labels: for (let/const x = i; cond; next) body | |
3397 // | |
3398 // and rewrite it as follows. Here we write {{ ... }} for init-blocks, ie., | |
3399 // blocks whose ignore_completion_value_ flag is set. | |
3400 // | |
3401 // { | |
3402 // let/const x = i; | |
3403 // temp_x = x; | |
3404 // first = 1; | |
3405 // undefined; | |
3406 // outer: for (;;) { | |
3407 // let/const x = temp_x; | |
3408 // {{ if (first == 1) { | |
3409 // first = 0; | |
3410 // } else { | |
3411 // next; | |
3412 // } | |
3413 // flag = 1; | |
3414 // if (!cond) break; | |
3415 // }} | |
3416 // labels: for (; flag == 1; flag = 0, temp_x = x) { | |
3417 // body | |
3418 // } | |
3419 // {{ if (flag == 1) // Body used break. | |
3420 // break; | |
3421 // }} | |
3422 // } | |
3423 // } | |
3424 | |
3425 DCHECK(names->length() > 0); | |
3426 Scope* for_scope = scope_; | |
3427 ZoneList<Variable*> temps(names->length(), zone()); | |
3428 | |
3429 Block* outer_block = factory()->NewBlock(NULL, names->length() + 4, false, | |
3430 RelocInfo::kNoPosition); | |
3431 | |
3432 // Add statement: let/const x = i. | |
3433 outer_block->statements()->Add(init, zone()); | |
3434 | |
3435 const AstRawString* temp_name = ast_value_factory()->dot_for_string(); | |
3436 | |
3437 // For each lexical variable x: | |
3438 // make statement: temp_x = x. | |
3439 for (int i = 0; i < names->length(); i++) { | |
3440 VariableProxy* proxy = NewUnresolved(names->at(i), LET); | |
3441 Variable* temp = scope_->NewTemporary(temp_name); | |
3442 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); | |
3443 Assignment* assignment = factory()->NewAssignment( | |
3444 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition); | |
3445 Statement* assignment_statement = factory()->NewExpressionStatement( | |
3446 assignment, RelocInfo::kNoPosition); | |
3447 outer_block->statements()->Add(assignment_statement, zone()); | |
3448 temps.Add(temp, zone()); | |
3449 } | |
3450 | |
3451 Variable* first = NULL; | |
3452 // Make statement: first = 1. | |
3453 if (next) { | |
3454 first = scope_->NewTemporary(temp_name); | |
3455 VariableProxy* first_proxy = factory()->NewVariableProxy(first); | |
3456 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); | |
3457 Assignment* assignment = factory()->NewAssignment( | |
3458 Token::ASSIGN, first_proxy, const1, RelocInfo::kNoPosition); | |
3459 Statement* assignment_statement = | |
3460 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); | |
3461 outer_block->statements()->Add(assignment_statement, zone()); | |
3462 } | |
3463 | |
3464 // make statement: undefined; | |
3465 outer_block->statements()->Add( | |
3466 factory()->NewExpressionStatement( | |
3467 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), | |
3468 RelocInfo::kNoPosition), | |
3469 zone()); | |
3470 | |
3471 // Make statement: outer: for (;;) | |
3472 // Note that we don't actually create the label, or set this loop up as an | |
3473 // explicit break target, instead handing it directly to those nodes that | |
3474 // need to know about it. This should be safe because we don't run any code | |
3475 // in this function that looks up break targets. | |
3476 ForStatement* outer_loop = | |
3477 factory()->NewForStatement(NULL, RelocInfo::kNoPosition); | |
3478 outer_block->statements()->Add(outer_loop, zone()); | |
3479 | |
3480 outer_block->set_scope(for_scope); | |
3481 scope_ = inner_scope; | |
3482 | |
3483 Block* inner_block = | |
3484 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); | |
3485 Block* ignore_completion_block = factory()->NewBlock( | |
3486 NULL, names->length() + 3, true, RelocInfo::kNoPosition); | |
3487 ZoneList<Variable*> inner_vars(names->length(), zone()); | |
3488 // For each let variable x: | |
3489 // make statement: let/const x = temp_x. | |
3490 VariableMode mode = is_const ? CONST : LET; | |
3491 for (int i = 0; i < names->length(); i++) { | |
3492 VariableProxy* proxy = NewUnresolved(names->at(i), mode); | |
3493 Declaration* declaration = factory()->NewVariableDeclaration( | |
3494 proxy, mode, scope_, RelocInfo::kNoPosition); | |
3495 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); | |
3496 inner_vars.Add(declaration->proxy()->var(), zone()); | |
3497 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); | |
3498 Assignment* assignment = factory()->NewAssignment( | |
3499 Token::INIT, proxy, temp_proxy, RelocInfo::kNoPosition); | |
3500 Statement* assignment_statement = | |
3501 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); | |
3502 DCHECK(init->position() != RelocInfo::kNoPosition); | |
3503 proxy->var()->set_initializer_position(init->position()); | |
3504 ignore_completion_block->statements()->Add(assignment_statement, zone()); | |
3505 } | |
3506 | |
3507 // Make statement: if (first == 1) { first = 0; } else { next; } | |
3508 if (next) { | |
3509 DCHECK(first); | |
3510 Expression* compare = NULL; | |
3511 // Make compare expression: first == 1. | |
3512 { | |
3513 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); | |
3514 VariableProxy* first_proxy = factory()->NewVariableProxy(first); | |
3515 compare = factory()->NewCompareOperation(Token::EQ, first_proxy, const1, | |
3516 RelocInfo::kNoPosition); | |
3517 } | |
3518 Statement* clear_first = NULL; | |
3519 // Make statement: first = 0. | |
3520 { | |
3521 VariableProxy* first_proxy = factory()->NewVariableProxy(first); | |
3522 Expression* const0 = factory()->NewSmiLiteral(0, RelocInfo::kNoPosition); | |
3523 Assignment* assignment = factory()->NewAssignment( | |
3524 Token::ASSIGN, first_proxy, const0, RelocInfo::kNoPosition); | |
3525 clear_first = | |
3526 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); | |
3527 } | |
3528 Statement* clear_first_or_next = factory()->NewIfStatement( | |
3529 compare, clear_first, next, RelocInfo::kNoPosition); | |
3530 ignore_completion_block->statements()->Add(clear_first_or_next, zone()); | |
3531 } | |
3532 | |
3533 Variable* flag = scope_->NewTemporary(temp_name); | |
3534 // Make statement: flag = 1. | |
3535 { | |
3536 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); | |
3537 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); | |
3538 Assignment* assignment = factory()->NewAssignment( | |
3539 Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition); | |
3540 Statement* assignment_statement = | |
3541 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); | |
3542 ignore_completion_block->statements()->Add(assignment_statement, zone()); | |
3543 } | |
3544 | |
3545 // Make statement: if (!cond) break. | |
3546 if (cond) { | |
3547 Statement* stop = | |
3548 factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition); | |
3549 Statement* noop = factory()->NewEmptyStatement(RelocInfo::kNoPosition); | |
3550 ignore_completion_block->statements()->Add( | |
3551 factory()->NewIfStatement(cond, noop, stop, cond->position()), zone()); | |
3552 } | |
3553 | |
3554 inner_block->statements()->Add(ignore_completion_block, zone()); | |
3555 // Make cond expression for main loop: flag == 1. | |
3556 Expression* flag_cond = NULL; | |
3557 { | |
3558 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); | |
3559 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); | |
3560 flag_cond = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1, | |
3561 RelocInfo::kNoPosition); | |
3562 } | |
3563 | |
3564 // Create chain of expressions "flag = 0, temp_x = x, ..." | |
3565 Statement* compound_next_statement = NULL; | |
3566 { | |
3567 Expression* compound_next = NULL; | |
3568 // Make expression: flag = 0. | |
3569 { | |
3570 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); | |
3571 Expression* const0 = factory()->NewSmiLiteral(0, RelocInfo::kNoPosition); | |
3572 compound_next = factory()->NewAssignment(Token::ASSIGN, flag_proxy, | |
3573 const0, RelocInfo::kNoPosition); | |
3574 } | |
3575 | |
3576 // Make the comma-separated list of temp_x = x assignments. | |
3577 int inner_var_proxy_pos = scanner()->location().beg_pos; | |
3578 for (int i = 0; i < names->length(); i++) { | |
3579 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); | |
3580 VariableProxy* proxy = | |
3581 factory()->NewVariableProxy(inner_vars.at(i), inner_var_proxy_pos); | |
3582 Assignment* assignment = factory()->NewAssignment( | |
3583 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition); | |
3584 compound_next = factory()->NewBinaryOperation( | |
3585 Token::COMMA, compound_next, assignment, RelocInfo::kNoPosition); | |
3586 } | |
3587 | |
3588 compound_next_statement = factory()->NewExpressionStatement( | |
3589 compound_next, RelocInfo::kNoPosition); | |
3590 } | |
3591 | |
3592 // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x) | |
3593 // Note that we re-use the original loop node, which retains its labels | |
3594 // and ensures that any break or continue statements in body point to | |
3595 // the right place. | |
3596 loop->Initialize(NULL, flag_cond, compound_next_statement, body); | |
3597 inner_block->statements()->Add(loop, zone()); | |
3598 | |
3599 // Make statement: {{if (flag == 1) break;}} | |
3600 { | |
3601 Expression* compare = NULL; | |
3602 // Make compare expresion: flag == 1. | |
3603 { | |
3604 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); | |
3605 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); | |
3606 compare = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1, | |
3607 RelocInfo::kNoPosition); | |
3608 } | |
3609 Statement* stop = | |
3610 factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition); | |
3611 Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition); | |
3612 Statement* if_flag_break = | |
3613 factory()->NewIfStatement(compare, stop, empty, RelocInfo::kNoPosition); | |
3614 Block* ignore_completion_block = | |
3615 factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition); | |
3616 ignore_completion_block->statements()->Add(if_flag_break, zone()); | |
3617 inner_block->statements()->Add(ignore_completion_block, zone()); | |
3618 } | |
3619 | |
3620 inner_scope->set_end_position(scanner()->location().end_pos); | |
3621 inner_block->set_scope(inner_scope); | |
3622 scope_ = for_scope; | |
3623 | |
3624 outer_loop->Initialize(NULL, NULL, NULL, inner_block); | |
3625 return outer_block; | |
3626 } | |
3627 | |
3628 | |
3629 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, | |
3630 bool* ok) { | |
3631 // ForStatement :: | |
3632 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | |
3633 | |
3634 int stmt_pos = peek_position(); | |
3635 bool is_const = false; | |
3636 Statement* init = NULL; | |
3637 ZoneList<const AstRawString*> lexical_bindings(1, zone()); | |
3638 | |
3639 // Create an in-between scope for let-bound iteration variables. | |
3640 Scope* saved_scope = scope_; | |
3641 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); | |
3642 scope_ = for_scope; | |
3643 Expect(Token::FOR, CHECK_OK); | |
3644 Expect(Token::LPAREN, CHECK_OK); | |
3645 for_scope->set_start_position(scanner()->location().beg_pos); | |
3646 bool is_let_identifier_expression = false; | |
3647 DeclarationParsingResult parsing_result; | |
3648 if (peek() != Token::SEMICOLON) { | |
3649 if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) || | |
3650 (peek() == Token::LET && IsNextLetKeyword())) { | |
3651 ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK); | |
3652 is_const = parsing_result.descriptor.mode == CONST; | |
3653 | |
3654 int num_decl = parsing_result.declarations.length(); | |
3655 bool accept_IN = num_decl >= 1; | |
3656 ForEachStatement::VisitMode mode; | |
3657 int each_beg_pos = scanner()->location().beg_pos; | |
3658 int each_end_pos = scanner()->location().end_pos; | |
3659 | |
3660 if (accept_IN && CheckInOrOf(&mode, ok)) { | |
3661 if (!*ok) return nullptr; | |
3662 if (num_decl != 1) { | |
3663 const char* loop_type = | |
3664 mode == ForEachStatement::ITERATE ? "for-of" : "for-in"; | |
3665 ParserTraits::ReportMessageAt( | |
3666 parsing_result.bindings_loc, | |
3667 MessageTemplate::kForInOfLoopMultiBindings, loop_type); | |
3668 *ok = false; | |
3669 return nullptr; | |
3670 } | |
3671 DeclarationParsingResult::Declaration& decl = | |
3672 parsing_result.declarations[0]; | |
3673 if (parsing_result.first_initializer_loc.IsValid() && | |
3674 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE || | |
3675 IsLexicalVariableMode(parsing_result.descriptor.mode) || | |
3676 !decl.pattern->IsVariableProxy())) { | |
3677 if (mode == ForEachStatement::ITERATE) { | |
3678 ReportMessageAt(parsing_result.first_initializer_loc, | |
3679 MessageTemplate::kForOfLoopInitializer); | |
3680 } else { | |
3681 // TODO(caitp): This should be an error in sloppy mode too. | |
3682 ReportMessageAt(parsing_result.first_initializer_loc, | |
3683 MessageTemplate::kForInLoopInitializer); | |
3684 } | |
3685 *ok = false; | |
3686 return nullptr; | |
3687 } | |
3688 | |
3689 Block* init_block = nullptr; | |
3690 | |
3691 // special case for legacy for (var/const x =.... in) | |
3692 if (!IsLexicalVariableMode(parsing_result.descriptor.mode) && | |
3693 decl.pattern->IsVariableProxy() && decl.initializer != nullptr) { | |
3694 const AstRawString* name = | |
3695 decl.pattern->AsVariableProxy()->raw_name(); | |
3696 VariableProxy* single_var = scope_->NewUnresolved( | |
3697 factory(), name, Variable::NORMAL, each_beg_pos, each_end_pos); | |
3698 init_block = factory()->NewBlock( | |
3699 nullptr, 2, true, parsing_result.descriptor.declaration_pos); | |
3700 init_block->statements()->Add( | |
3701 factory()->NewExpressionStatement( | |
3702 factory()->NewAssignment(Token::ASSIGN, single_var, | |
3703 decl.initializer, | |
3704 RelocInfo::kNoPosition), | |
3705 RelocInfo::kNoPosition), | |
3706 zone()); | |
3707 } | |
3708 | |
3709 // Rewrite a for-in/of statement of the form | |
3710 // | |
3711 // for (let/const/var x in/of e) b | |
3712 // | |
3713 // into | |
3714 // | |
3715 // { | |
3716 // <let x' be a temporary variable> | |
3717 // for (x' in/of e) { | |
3718 // let/const/var x; | |
3719 // x = x'; | |
3720 // b; | |
3721 // } | |
3722 // let x; // for TDZ | |
3723 // } | |
3724 | |
3725 Variable* temp = scope_->NewTemporary( | |
3726 ast_value_factory()->dot_for_string()); | |
3727 ForEachStatement* loop = | |
3728 factory()->NewForEachStatement(mode, labels, stmt_pos); | |
3729 Target target(&this->target_stack_, loop); | |
3730 | |
3731 Expression* enumerable = ParseExpression(true, CHECK_OK); | |
3732 | |
3733 Expect(Token::RPAREN, CHECK_OK); | |
3734 | |
3735 Scope* body_scope = NewScope(scope_, BLOCK_SCOPE); | |
3736 body_scope->set_start_position(scanner()->location().beg_pos); | |
3737 scope_ = body_scope; | |
3738 | |
3739 Statement* body = ParseSubStatement(NULL, CHECK_OK); | |
3740 | |
3741 Block* body_block = | |
3742 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); | |
3743 | |
3744 auto each_initialization_block = | |
3745 factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition); | |
3746 { | |
3747 auto descriptor = parsing_result.descriptor; | |
3748 descriptor.declaration_pos = RelocInfo::kNoPosition; | |
3749 descriptor.initialization_pos = RelocInfo::kNoPosition; | |
3750 decl.initializer = factory()->NewVariableProxy(temp); | |
3751 | |
3752 PatternRewriter::DeclareAndInitializeVariables( | |
3753 each_initialization_block, &descriptor, &decl, | |
3754 IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings | |
3755 : nullptr, | |
3756 CHECK_OK); | |
3757 } | |
3758 | |
3759 body_block->statements()->Add(each_initialization_block, zone()); | |
3760 body_block->statements()->Add(body, zone()); | |
3761 VariableProxy* temp_proxy = | |
3762 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); | |
3763 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block); | |
3764 scope_ = for_scope; | |
3765 body_scope->set_end_position(scanner()->location().end_pos); | |
3766 body_scope = body_scope->FinalizeBlockScope(); | |
3767 if (body_scope != nullptr) { | |
3768 body_block->set_scope(body_scope); | |
3769 } | |
3770 | |
3771 // Create a TDZ for any lexically-bound names. | |
3772 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) { | |
3773 DCHECK_NULL(init_block); | |
3774 | |
3775 init_block = | |
3776 factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition); | |
3777 | |
3778 for (int i = 0; i < lexical_bindings.length(); ++i) { | |
3779 // TODO(adamk): This needs to be some sort of special | |
3780 // INTERNAL variable that's invisible to the debugger | |
3781 // but visible to everything else. | |
3782 VariableProxy* tdz_proxy = NewUnresolved(lexical_bindings[i], LET); | |
3783 Declaration* tdz_decl = factory()->NewVariableDeclaration( | |
3784 tdz_proxy, LET, scope_, RelocInfo::kNoPosition); | |
3785 Variable* tdz_var = Declare(tdz_decl, DeclarationDescriptor::NORMAL, | |
3786 true, CHECK_OK); | |
3787 tdz_var->set_initializer_position(position()); | |
3788 } | |
3789 } | |
3790 | |
3791 scope_ = saved_scope; | |
3792 for_scope->set_end_position(scanner()->location().end_pos); | |
3793 for_scope = for_scope->FinalizeBlockScope(); | |
3794 // Parsed for-in loop w/ variable declarations. | |
3795 if (init_block != nullptr) { | |
3796 init_block->statements()->Add(loop, zone()); | |
3797 if (for_scope != nullptr) { | |
3798 init_block->set_scope(for_scope); | |
3799 } | |
3800 return init_block; | |
3801 } else { | |
3802 DCHECK_NULL(for_scope); | |
3803 return loop; | |
3804 } | |
3805 } else { | |
3806 init = parsing_result.BuildInitializationBlock( | |
3807 IsLexicalVariableMode(parsing_result.descriptor.mode) | |
3808 ? &lexical_bindings | |
3809 : nullptr, | |
3810 CHECK_OK); | |
3811 } | |
3812 } else { | |
3813 int lhs_beg_pos = peek_position(); | |
3814 Expression* expression = ParseExpression(false, CHECK_OK); | |
3815 int lhs_end_pos = scanner()->location().end_pos; | |
3816 ForEachStatement::VisitMode mode; | |
3817 is_let_identifier_expression = | |
3818 expression->IsVariableProxy() && | |
3819 expression->AsVariableProxy()->raw_name() == | |
3820 ast_value_factory()->let_string(); | |
3821 | |
3822 if (CheckInOrOf(&mode, ok)) { | |
3823 if (!*ok) return nullptr; | |
3824 expression = this->CheckAndRewriteReferenceExpression( | |
3825 expression, lhs_beg_pos, lhs_end_pos, | |
3826 MessageTemplate::kInvalidLhsInFor, kSyntaxError, CHECK_OK); | |
3827 | |
3828 ForEachStatement* loop = | |
3829 factory()->NewForEachStatement(mode, labels, stmt_pos); | |
3830 Target target(&this->target_stack_, loop); | |
3831 | |
3832 Expression* enumerable = ParseExpression(true, CHECK_OK); | |
3833 Expect(Token::RPAREN, CHECK_OK); | |
3834 | |
3835 // Make a block around the statement in case a lexical binding | |
3836 // is introduced, e.g. by a FunctionDeclaration. | |
3837 // This block must not use for_scope as its scope because if a | |
3838 // lexical binding is introduced which overlaps with the for-in/of, | |
3839 // expressions in head of the loop should actually have variables | |
3840 // resolved in the outer scope. | |
3841 Scope* body_scope = NewScope(for_scope, BLOCK_SCOPE); | |
3842 scope_ = body_scope; | |
3843 Block* block = | |
3844 factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); | |
3845 Statement* body = ParseSubStatement(NULL, CHECK_OK); | |
3846 block->statements()->Add(body, zone()); | |
3847 InitializeForEachStatement(loop, expression, enumerable, block); | |
3848 scope_ = saved_scope; | |
3849 body_scope->set_end_position(scanner()->location().end_pos); | |
3850 body_scope = body_scope->FinalizeBlockScope(); | |
3851 if (body_scope != nullptr) { | |
3852 block->set_scope(body_scope); | |
3853 } | |
3854 for_scope->set_end_position(scanner()->location().end_pos); | |
3855 for_scope = for_scope->FinalizeBlockScope(); | |
3856 DCHECK(for_scope == nullptr); | |
3857 // Parsed for-in loop. | |
3858 return loop; | |
3859 | |
3860 } else { | |
3861 init = factory()->NewExpressionStatement(expression, lhs_beg_pos); | |
3862 } | |
3863 } | |
3864 } | |
3865 | |
3866 // Standard 'for' loop | |
3867 ForStatement* loop = factory()->NewForStatement(labels, stmt_pos); | |
3868 Target target(&this->target_stack_, loop); | |
3869 | |
3870 // Parsed initializer at this point. | |
3871 // Detect attempts at 'let' declarations in sloppy mode. | |
3872 if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER && | |
3873 is_sloppy(language_mode()) && is_let_identifier_expression) { | |
3874 ReportMessage(MessageTemplate::kSloppyLexical, NULL); | |
3875 *ok = false; | |
3876 return NULL; | |
3877 } | |
3878 Expect(Token::SEMICOLON, CHECK_OK); | |
3879 | |
3880 // If there are let bindings, then condition and the next statement of the | |
3881 // for loop must be parsed in a new scope. | |
3882 Scope* inner_scope = NULL; | |
3883 if (lexical_bindings.length() > 0) { | |
3884 inner_scope = NewScope(for_scope, BLOCK_SCOPE); | |
3885 inner_scope->set_start_position(scanner()->location().beg_pos); | |
3886 scope_ = inner_scope; | |
3887 } | |
3888 | |
3889 Expression* cond = NULL; | |
3890 if (peek() != Token::SEMICOLON) { | |
3891 cond = ParseExpression(true, CHECK_OK); | |
3892 } | |
3893 Expect(Token::SEMICOLON, CHECK_OK); | |
3894 | |
3895 Statement* next = NULL; | |
3896 if (peek() != Token::RPAREN) { | |
3897 Expression* exp = ParseExpression(true, CHECK_OK); | |
3898 next = factory()->NewExpressionStatement(exp, exp->position()); | |
3899 } | |
3900 Expect(Token::RPAREN, CHECK_OK); | |
3901 | |
3902 Statement* body = ParseSubStatement(NULL, CHECK_OK); | |
3903 | |
3904 Statement* result = NULL; | |
3905 if (lexical_bindings.length() > 0) { | |
3906 scope_ = for_scope; | |
3907 result = DesugarLexicalBindingsInForStatement( | |
3908 inner_scope, is_const, &lexical_bindings, loop, init, cond, | |
3909 next, body, CHECK_OK); | |
3910 scope_ = saved_scope; | |
3911 for_scope->set_end_position(scanner()->location().end_pos); | |
3912 } else { | |
3913 scope_ = saved_scope; | |
3914 for_scope->set_end_position(scanner()->location().end_pos); | |
3915 for_scope = for_scope->FinalizeBlockScope(); | |
3916 if (for_scope) { | |
3917 // Rewrite a for statement of the form | |
3918 // for (const x = i; c; n) b | |
3919 // | |
3920 // into | |
3921 // | |
3922 // { | |
3923 // const x = i; | |
3924 // for (; c; n) b | |
3925 // } | |
3926 // | |
3927 // or, desugar | |
3928 // for (; c; n) b | |
3929 // into | |
3930 // { | |
3931 // for (; c; n) b | |
3932 // } | |
3933 // just in case b introduces a lexical binding some other way, e.g., if b | |
3934 // is a FunctionDeclaration. | |
3935 Block* block = | |
3936 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); | |
3937 if (init != nullptr) { | |
3938 block->statements()->Add(init, zone()); | |
3939 } | |
3940 block->statements()->Add(loop, zone()); | |
3941 block->set_scope(for_scope); | |
3942 loop->Initialize(NULL, cond, next, body); | |
3943 result = block; | |
3944 } else { | |
3945 loop->Initialize(init, cond, next, body); | |
3946 result = loop; | |
3947 } | |
3948 } | |
3949 return result; | |
3950 } | |
3951 | |
3952 | |
3953 DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) { | |
3954 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser | |
3955 // contexts this is used as a statement which invokes the debugger as i a | |
3956 // break point is present. | |
3957 // DebuggerStatement :: | |
3958 // 'debugger' ';' | |
3959 | |
3960 int pos = peek_position(); | |
3961 Expect(Token::DEBUGGER, CHECK_OK); | |
3962 ExpectSemicolon(CHECK_OK); | |
3963 return factory()->NewDebuggerStatement(pos); | |
3964 } | |
3965 | |
3966 | |
3967 bool CompileTimeValue::IsCompileTimeValue(Expression* expression) { | |
3968 if (expression->IsLiteral()) return true; | |
3969 MaterializedLiteral* lit = expression->AsMaterializedLiteral(); | |
3970 return lit != NULL && lit->is_simple(); | |
3971 } | |
3972 | |
3973 | |
3974 Handle<FixedArray> CompileTimeValue::GetValue(Isolate* isolate, | |
3975 Expression* expression) { | |
3976 Factory* factory = isolate->factory(); | |
3977 DCHECK(IsCompileTimeValue(expression)); | |
3978 Handle<FixedArray> result = factory->NewFixedArray(2, TENURED); | |
3979 ObjectLiteral* object_literal = expression->AsObjectLiteral(); | |
3980 if (object_literal != NULL) { | |
3981 DCHECK(object_literal->is_simple()); | |
3982 if (object_literal->fast_elements()) { | |
3983 result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS)); | |
3984 } else { | |
3985 result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS)); | |
3986 } | |
3987 result->set(kElementsSlot, *object_literal->constant_properties()); | |
3988 } else { | |
3989 ArrayLiteral* array_literal = expression->AsArrayLiteral(); | |
3990 DCHECK(array_literal != NULL && array_literal->is_simple()); | |
3991 result->set(kLiteralTypeSlot, Smi::FromInt(ARRAY_LITERAL)); | |
3992 result->set(kElementsSlot, *array_literal->constant_elements()); | |
3993 } | |
3994 return result; | |
3995 } | |
3996 | |
3997 | |
3998 CompileTimeValue::LiteralType CompileTimeValue::GetLiteralType( | |
3999 Handle<FixedArray> value) { | |
4000 Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot)); | |
4001 return static_cast<LiteralType>(literal_type->value()); | |
4002 } | |
4003 | |
4004 | |
4005 Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) { | |
4006 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot))); | |
4007 } | |
4008 | |
4009 | |
4010 void ParserTraits::ParseArrowFunctionFormalParameters( | |
4011 ParserFormalParameters* parameters, Expression* expr, | |
4012 const Scanner::Location& params_loc, bool* ok) { | |
4013 if (parameters->Arity() >= Code::kMaxArguments) { | |
4014 ReportMessageAt(params_loc, MessageTemplate::kMalformedArrowFunParamList); | |
4015 *ok = false; | |
4016 return; | |
4017 } | |
4018 | |
4019 // ArrowFunctionFormals :: | |
4020 // Binary(Token::COMMA, NonTailArrowFunctionFormals, Tail) | |
4021 // Tail | |
4022 // NonTailArrowFunctionFormals :: | |
4023 // Binary(Token::COMMA, NonTailArrowFunctionFormals, VariableProxy) | |
4024 // VariableProxy | |
4025 // Tail :: | |
4026 // VariableProxy | |
4027 // Spread(VariableProxy) | |
4028 // | |
4029 // As we need to visit the parameters in left-to-right order, we recurse on | |
4030 // the left-hand side of comma expressions. | |
4031 // | |
4032 if (expr->IsBinaryOperation()) { | |
4033 BinaryOperation* binop = expr->AsBinaryOperation(); | |
4034 // The classifier has already run, so we know that the expression is a valid | |
4035 // arrow function formals production. | |
4036 DCHECK_EQ(binop->op(), Token::COMMA); | |
4037 Expression* left = binop->left(); | |
4038 Expression* right = binop->right(); | |
4039 ParseArrowFunctionFormalParameters(parameters, left, params_loc, ok); | |
4040 if (!*ok) return; | |
4041 // LHS of comma expression should be unparenthesized. | |
4042 expr = right; | |
4043 } | |
4044 | |
4045 // Only the right-most expression may be a rest parameter. | |
4046 DCHECK(!parameters->has_rest); | |
4047 | |
4048 bool is_rest = expr->IsSpread(); | |
4049 if (is_rest) { | |
4050 expr = expr->AsSpread()->expression(); | |
4051 parameters->has_rest = true; | |
4052 parameters->rest_array_literal_index = | |
4053 parser_->function_state_->NextMaterializedLiteralIndex(); | |
4054 ++parameters->materialized_literals_count; | |
4055 } | |
4056 if (parameters->is_simple) { | |
4057 parameters->is_simple = !is_rest && expr->IsVariableProxy(); | |
4058 } | |
4059 | |
4060 Expression* initializer = nullptr; | |
4061 if (expr->IsVariableProxy()) { | |
4062 // When the formal parameter was originally seen, it was parsed as a | |
4063 // VariableProxy and recorded as unresolved in the scope. Here we undo that | |
4064 // parse-time side-effect for parameters that are single-names (not | |
4065 // patterns; for patterns that happens uniformly in | |
4066 // PatternRewriter::VisitVariableProxy). | |
4067 parser_->scope_->RemoveUnresolved(expr->AsVariableProxy()); | |
4068 } else if (expr->IsAssignment()) { | |
4069 Assignment* assignment = expr->AsAssignment(); | |
4070 DCHECK(parser_->allow_harmony_default_parameters()); | |
4071 DCHECK(!assignment->is_compound()); | |
4072 initializer = assignment->value(); | |
4073 expr = assignment->target(); | |
4074 | |
4075 // TODO(adamk): Only call this if necessary. | |
4076 RewriteParameterInitializerScope(parser_->stack_limit(), initializer, | |
4077 parser_->scope_, parameters->scope); | |
4078 } | |
4079 | |
4080 // TODO(adamk): params_loc.end_pos is not the correct initializer position, | |
4081 // but it should be conservative enough to trigger hole checks for variables | |
4082 // referenced in the initializer (if any). | |
4083 AddFormalParameter(parameters, expr, initializer, params_loc.end_pos, | |
4084 is_rest); | |
4085 } | |
4086 | |
4087 | |
4088 DoExpression* Parser::ParseDoExpression(bool* ok) { | |
4089 // AssignmentExpression :: | |
4090 // do '{' StatementList '}' | |
4091 int pos = peek_position(); | |
4092 | |
4093 Expect(Token::DO, CHECK_OK); | |
4094 Variable* result = | |
4095 scope_->NewTemporary(ast_value_factory()->dot_result_string()); | |
4096 Block* block = ParseBlock(nullptr, CHECK_OK); | |
4097 DoExpression* expr = factory()->NewDoExpression(block, result, pos); | |
4098 if (!Rewriter::Rewrite(this, expr, ast_value_factory())) { | |
4099 *ok = false; | |
4100 return nullptr; | |
4101 } | |
4102 return expr; | |
4103 } | |
4104 | |
4105 | |
4106 void ParserTraits::ParseArrowFunctionFormalParameterList( | |
4107 ParserFormalParameters* parameters, Expression* expr, | |
4108 const Scanner::Location& params_loc, | |
4109 Scanner::Location* duplicate_loc, bool* ok) { | |
4110 if (expr->IsEmptyParentheses()) return; | |
4111 | |
4112 ParseArrowFunctionFormalParameters(parameters, expr, params_loc, ok); | |
4113 if (!*ok) return; | |
4114 | |
4115 ExpressionClassifier classifier; | |
4116 if (!parameters->is_simple) { | |
4117 classifier.RecordNonSimpleParameter(); | |
4118 } | |
4119 for (int i = 0; i < parameters->Arity(); ++i) { | |
4120 auto parameter = parameters->at(i); | |
4121 DeclareFormalParameter(parameters->scope, parameter, &classifier); | |
4122 if (!duplicate_loc->IsValid()) { | |
4123 *duplicate_loc = classifier.duplicate_formal_parameter_error().location; | |
4124 } | |
4125 } | |
4126 DCHECK_EQ(parameters->is_simple, parameters->scope->has_simple_parameters()); | |
4127 } | |
4128 | |
4129 | |
4130 void ParserTraits::ReindexLiterals(const ParserFormalParameters& parameters) { | |
4131 if (parser_->function_state_->materialized_literal_count() > 0) { | |
4132 AstLiteralReindexer reindexer; | |
4133 | |
4134 for (const auto p : parameters.params) { | |
4135 if (p.pattern != nullptr) reindexer.Reindex(p.pattern); | |
4136 if (p.initializer != nullptr) reindexer.Reindex(p.initializer); | |
4137 } | |
4138 | |
4139 if (parameters.has_rest) { | |
4140 parameters.rest_array_literal_index = reindexer.NextIndex(); | |
4141 } | |
4142 | |
4143 DCHECK(reindexer.count() <= | |
4144 parser_->function_state_->materialized_literal_count()); | |
4145 } | |
4146 } | |
4147 | |
4148 | |
4149 FunctionLiteral* Parser::ParseFunctionLiteral( | |
4150 const AstRawString* function_name, Scanner::Location function_name_location, | |
4151 FunctionNameValidity function_name_validity, FunctionKind kind, | |
4152 int function_token_pos, FunctionLiteral::FunctionType function_type, | |
4153 FunctionLiteral::ArityRestriction arity_restriction, | |
4154 LanguageMode language_mode, bool* ok) { | |
4155 // Function :: | |
4156 // '(' FormalParameterList? ')' '{' FunctionBody '}' | |
4157 // | |
4158 // Getter :: | |
4159 // '(' ')' '{' FunctionBody '}' | |
4160 // | |
4161 // Setter :: | |
4162 // '(' PropertySetParameterList ')' '{' FunctionBody '}' | |
4163 | |
4164 int pos = function_token_pos == RelocInfo::kNoPosition | |
4165 ? peek_position() : function_token_pos; | |
4166 | |
4167 bool is_generator = IsGeneratorFunction(kind); | |
4168 | |
4169 // Anonymous functions were passed either the empty symbol or a null | |
4170 // handle as the function name. Remember if we were passed a non-empty | |
4171 // handle to decide whether to invoke function name inference. | |
4172 bool should_infer_name = function_name == NULL; | |
4173 | |
4174 // We want a non-null handle as the function name. | |
4175 if (should_infer_name) { | |
4176 function_name = ast_value_factory()->empty_string(); | |
4177 } | |
4178 | |
4179 // Function declarations are function scoped in normal mode, so they are | |
4180 // hoisted. In harmony block scoping mode they are block scoped, so they | |
4181 // are not hoisted. | |
4182 // | |
4183 // One tricky case are function declarations in a local sloppy-mode eval: | |
4184 // their declaration is hoisted, but they still see the local scope. E.g., | |
4185 // | |
4186 // function() { | |
4187 // var x = 0 | |
4188 // try { throw 1 } catch (x) { eval("function g() { return x }") } | |
4189 // return g() | |
4190 // } | |
4191 // | |
4192 // needs to return 1. To distinguish such cases, we need to detect | |
4193 // (1) whether a function stems from a sloppy eval, and | |
4194 // (2) whether it actually hoists across the eval. | |
4195 // Unfortunately, we do not represent sloppy eval scopes, so we do not have | |
4196 // either information available directly, especially not when lazily compiling | |
4197 // a function like 'g'. We hence rely on the following invariants: | |
4198 // - (1) is the case iff the innermost scope of the deserialized scope chain | |
4199 // under which we compile is _not_ a declaration scope. This holds because | |
4200 // in all normal cases, function declarations are fully hoisted to a | |
4201 // declaration scope and compiled relative to that. | |
4202 // - (2) is the case iff the current declaration scope is still the original | |
4203 // one relative to the deserialized scope chain. Otherwise we must be | |
4204 // compiling a function in an inner declaration scope in the eval, e.g. a | |
4205 // nested function, and hoisting works normally relative to that. | |
4206 Scope* declaration_scope = scope_->DeclarationScope(); | |
4207 Scope* original_declaration_scope = original_scope_->DeclarationScope(); | |
4208 Scope* scope = function_type == FunctionLiteral::DECLARATION && | |
4209 is_sloppy(language_mode) && | |
4210 !allow_harmony_sloppy_function() && | |
4211 (original_scope_ == original_declaration_scope || | |
4212 declaration_scope != original_declaration_scope) | |
4213 ? NewScope(declaration_scope, FUNCTION_SCOPE, kind) | |
4214 : NewScope(scope_, FUNCTION_SCOPE, kind); | |
4215 SetLanguageMode(scope, language_mode); | |
4216 ZoneList<Statement*>* body = NULL; | |
4217 int arity = -1; | |
4218 int materialized_literal_count = -1; | |
4219 int expected_property_count = -1; | |
4220 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); | |
4221 ExpressionClassifier formals_classifier(&duplicate_finder); | |
4222 FunctionLiteral::EagerCompileHint eager_compile_hint = | |
4223 parenthesized_function_ ? FunctionLiteral::kShouldEagerCompile | |
4224 : FunctionLiteral::kShouldLazyCompile; | |
4225 bool should_be_used_once_hint = false; | |
4226 // Parse function. | |
4227 { | |
4228 AstNodeFactory function_factory(ast_value_factory()); | |
4229 FunctionState function_state(&function_state_, &scope_, scope, kind, | |
4230 &function_factory); | |
4231 scope_->SetScopeName(function_name); | |
4232 | |
4233 if (is_generator) { | |
4234 // For generators, allocating variables in contexts is currently a win | |
4235 // because it minimizes the work needed to suspend and resume an | |
4236 // activation. | |
4237 scope_->ForceContextAllocation(); | |
4238 | |
4239 // Calling a generator returns a generator object. That object is stored | |
4240 // in a temporary variable, a definition that is used by "yield" | |
4241 // expressions. This also marks the FunctionState as a generator. | |
4242 Variable* temp = scope_->NewTemporary( | |
4243 ast_value_factory()->dot_generator_object_string()); | |
4244 function_state.set_generator_object_variable(temp); | |
4245 } | |
4246 | |
4247 Expect(Token::LPAREN, CHECK_OK); | |
4248 int start_position = scanner()->location().beg_pos; | |
4249 scope_->set_start_position(start_position); | |
4250 ParserFormalParameters formals(scope); | |
4251 ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK); | |
4252 arity = formals.Arity(); | |
4253 Expect(Token::RPAREN, CHECK_OK); | |
4254 int formals_end_position = scanner()->location().end_pos; | |
4255 | |
4256 CheckArityRestrictions(arity, arity_restriction, | |
4257 formals.has_rest, start_position, | |
4258 formals_end_position, CHECK_OK); | |
4259 Expect(Token::LBRACE, CHECK_OK); | |
4260 | |
4261 // Determine if the function can be parsed lazily. Lazy parsing is different | |
4262 // from lazy compilation; we need to parse more eagerly than we compile. | |
4263 | |
4264 // We can only parse lazily if we also compile lazily. The heuristics for | |
4265 // lazy compilation are: | |
4266 // - It must not have been prohibited by the caller to Parse (some callers | |
4267 // need a full AST). | |
4268 // - The outer scope must allow lazy compilation of inner functions. | |
4269 // - The function mustn't be a function expression with an open parenthesis | |
4270 // before; we consider that a hint that the function will be called | |
4271 // immediately, and it would be a waste of time to make it lazily | |
4272 // compiled. | |
4273 // These are all things we can know at this point, without looking at the | |
4274 // function itself. | |
4275 | |
4276 // In addition, we need to distinguish between these cases: | |
4277 // (function foo() { | |
4278 // bar = function() { return 1; } | |
4279 // })(); | |
4280 // and | |
4281 // (function foo() { | |
4282 // var a = 1; | |
4283 // bar = function() { return a; } | |
4284 // })(); | |
4285 | |
4286 // Now foo will be parsed eagerly and compiled eagerly (optimization: assume | |
4287 // parenthesis before the function means that it will be called | |
4288 // immediately). The inner function *must* be parsed eagerly to resolve the | |
4289 // possible reference to the variable in foo's scope. However, it's possible | |
4290 // that it will be compiled lazily. | |
4291 | |
4292 // To make this additional case work, both Parser and PreParser implement a | |
4293 // logic where only top-level functions will be parsed lazily. | |
4294 bool is_lazily_parsed = mode() == PARSE_LAZILY && | |
4295 scope_->AllowsLazyParsing() && | |
4296 !parenthesized_function_; | |
4297 parenthesized_function_ = false; // The bit was set for this function only. | |
4298 | |
4299 // Eager or lazy parse? | |
4300 // If is_lazily_parsed, we'll parse lazy. If we can set a bookmark, we'll | |
4301 // pass it to SkipLazyFunctionBody, which may use it to abort lazy | |
4302 // parsing if it suspect that wasn't a good idea. If so, or if we didn't | |
4303 // try to lazy parse in the first place, we'll have to parse eagerly. | |
4304 Scanner::BookmarkScope bookmark(scanner()); | |
4305 if (is_lazily_parsed) { | |
4306 Scanner::BookmarkScope* maybe_bookmark = | |
4307 bookmark.Set() ? &bookmark : nullptr; | |
4308 SkipLazyFunctionBody(&materialized_literal_count, | |
4309 &expected_property_count, /*CHECK_OK*/ ok, | |
4310 maybe_bookmark); | |
4311 | |
4312 materialized_literal_count += formals.materialized_literals_count + | |
4313 function_state.materialized_literal_count(); | |
4314 | |
4315 if (bookmark.HasBeenReset()) { | |
4316 // Trigger eager (re-)parsing, just below this block. | |
4317 is_lazily_parsed = false; | |
4318 | |
4319 // This is probably an initialization function. Inform the compiler it | |
4320 // should also eager-compile this function, and that we expect it to be | |
4321 // used once. | |
4322 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; | |
4323 should_be_used_once_hint = true; | |
4324 } | |
4325 } | |
4326 if (!is_lazily_parsed) { | |
4327 // Determine whether the function body can be discarded after parsing. | |
4328 // The preconditions are: | |
4329 // - Lazy compilation has to be enabled. | |
4330 // - Neither V8 natives nor native function declarations can be allowed, | |
4331 // since parsing one would retroactively force the function to be | |
4332 // eagerly compiled. | |
4333 // - The invoker of this parser can't depend on the AST being eagerly | |
4334 // built (either because the function is about to be compiled, or | |
4335 // because the AST is going to be inspected for some reason). | |
4336 // - Because of the above, we can't be attempting to parse a | |
4337 // FunctionExpression; even without enclosing parentheses it might be | |
4338 // immediately invoked. | |
4339 // - The function literal shouldn't be hinted to eagerly compile. | |
4340 bool use_temp_zone = | |
4341 FLAG_lazy && !allow_natives() && extension_ == NULL && allow_lazy() && | |
4342 function_type == FunctionLiteral::DECLARATION && | |
4343 eager_compile_hint != FunctionLiteral::kShouldEagerCompile; | |
4344 // Open a new BodyScope, which sets our AstNodeFactory to allocate in the | |
4345 // new temporary zone if the preconditions are satisfied, and ensures that | |
4346 // the previous zone is always restored after parsing the body. | |
4347 // For the purpose of scope analysis, some ZoneObjects allocated by the | |
4348 // factory must persist after the function body is thrown away and | |
4349 // temp_zone is deallocated. These objects are instead allocated in a | |
4350 // parser-persistent zone (see parser_zone_ in AstNodeFactory). | |
4351 { | |
4352 Zone temp_zone; | |
4353 AstNodeFactory::BodyScope inner(factory(), &temp_zone, use_temp_zone); | |
4354 | |
4355 body = ParseEagerFunctionBody(function_name, pos, formals, kind, | |
4356 function_type, CHECK_OK); | |
4357 } | |
4358 materialized_literal_count = function_state.materialized_literal_count(); | |
4359 expected_property_count = function_state.expected_property_count(); | |
4360 if (use_temp_zone) { | |
4361 // If the preconditions are correct the function body should never be | |
4362 // accessed, but do this anyway for better behaviour if they're wrong. | |
4363 body = NULL; | |
4364 } | |
4365 } | |
4366 | |
4367 // Parsing the body may change the language mode in our scope. | |
4368 language_mode = scope->language_mode(); | |
4369 | |
4370 if (is_strong(language_mode) && IsSubclassConstructor(kind)) { | |
4371 if (!function_state.super_location().IsValid()) { | |
4372 ReportMessageAt(function_name_location, | |
4373 MessageTemplate::kStrongSuperCallMissing, | |
4374 kReferenceError); | |
4375 *ok = false; | |
4376 return nullptr; | |
4377 } | |
4378 } | |
4379 | |
4380 // Validate name and parameter names. We can do this only after parsing the | |
4381 // function, since the function can declare itself strict. | |
4382 CheckFunctionName(language_mode, function_name, function_name_validity, | |
4383 function_name_location, CHECK_OK); | |
4384 const bool allow_duplicate_parameters = | |
4385 is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind); | |
4386 ValidateFormalParameters(&formals_classifier, language_mode, | |
4387 allow_duplicate_parameters, CHECK_OK); | |
4388 | |
4389 if (is_strict(language_mode)) { | |
4390 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), | |
4391 CHECK_OK); | |
4392 } | |
4393 if (is_sloppy(language_mode) && allow_harmony_sloppy_function()) { | |
4394 InsertSloppyBlockFunctionVarBindings(scope, CHECK_OK); | |
4395 } | |
4396 if (is_strict(language_mode) || allow_harmony_sloppy() || | |
4397 allow_harmony_destructuring_bind()) { | |
4398 CheckConflictingVarDeclarations(scope, CHECK_OK); | |
4399 } | |
4400 } | |
4401 | |
4402 bool has_duplicate_parameters = | |
4403 !formals_classifier.is_valid_formal_parameter_list_without_duplicates(); | |
4404 FunctionLiteral::ParameterFlag duplicate_parameters = | |
4405 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters | |
4406 : FunctionLiteral::kNoDuplicateParameters; | |
4407 | |
4408 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( | |
4409 function_name, ast_value_factory(), scope, body, | |
4410 materialized_literal_count, expected_property_count, arity, | |
4411 duplicate_parameters, function_type, FunctionLiteral::kIsFunction, | |
4412 eager_compile_hint, kind, pos); | |
4413 function_literal->set_function_token_position(function_token_pos); | |
4414 if (should_be_used_once_hint) | |
4415 function_literal->set_should_be_used_once_hint(); | |
4416 | |
4417 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal); | |
4418 return function_literal; | |
4419 } | |
4420 | |
4421 | |
4422 void Parser::SkipLazyFunctionBody(int* materialized_literal_count, | |
4423 int* expected_property_count, bool* ok, | |
4424 Scanner::BookmarkScope* bookmark) { | |
4425 DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet()); | |
4426 if (produce_cached_parse_data()) CHECK(log_); | |
4427 | |
4428 int function_block_pos = position(); | |
4429 if (consume_cached_parse_data() && !cached_parse_data_->rejected()) { | |
4430 // If we have cached data, we use it to skip parsing the function body. The | |
4431 // data contains the information we need to construct the lazy function. | |
4432 FunctionEntry entry = | |
4433 cached_parse_data_->GetFunctionEntry(function_block_pos); | |
4434 // Check that cached data is valid. If not, mark it as invalid (the embedder | |
4435 // handles it). Note that end position greater than end of stream is safe, | |
4436 // and hard to check. | |
4437 if (entry.is_valid() && entry.end_pos() > function_block_pos) { | |
4438 scanner()->SeekForward(entry.end_pos() - 1); | |
4439 | |
4440 scope_->set_end_position(entry.end_pos()); | |
4441 Expect(Token::RBRACE, ok); | |
4442 if (!*ok) { | |
4443 return; | |
4444 } | |
4445 total_preparse_skipped_ += scope_->end_position() - function_block_pos; | |
4446 *materialized_literal_count = entry.literal_count(); | |
4447 *expected_property_count = entry.property_count(); | |
4448 SetLanguageMode(scope_, entry.language_mode()); | |
4449 if (entry.uses_super_property()) scope_->RecordSuperPropertyUsage(); | |
4450 if (entry.calls_eval()) scope_->RecordEvalCall(); | |
4451 return; | |
4452 } | |
4453 cached_parse_data_->Reject(); | |
4454 } | |
4455 // With no cached data, we partially parse the function, without building an | |
4456 // AST. This gathers the data needed to build a lazy function. | |
4457 SingletonLogger logger; | |
4458 PreParser::PreParseResult result = | |
4459 ParseLazyFunctionBodyWithPreParser(&logger, bookmark); | |
4460 if (bookmark && bookmark->HasBeenReset()) { | |
4461 return; // Return immediately if pre-parser devided to abort parsing. | |
4462 } | |
4463 if (result == PreParser::kPreParseStackOverflow) { | |
4464 // Propagate stack overflow. | |
4465 set_stack_overflow(); | |
4466 *ok = false; | |
4467 return; | |
4468 } | |
4469 if (logger.has_error()) { | |
4470 ParserTraits::ReportMessageAt( | |
4471 Scanner::Location(logger.start(), logger.end()), logger.message(), | |
4472 logger.argument_opt(), logger.error_type()); | |
4473 *ok = false; | |
4474 return; | |
4475 } | |
4476 scope_->set_end_position(logger.end()); | |
4477 Expect(Token::RBRACE, ok); | |
4478 if (!*ok) { | |
4479 return; | |
4480 } | |
4481 total_preparse_skipped_ += scope_->end_position() - function_block_pos; | |
4482 *materialized_literal_count = logger.literals(); | |
4483 *expected_property_count = logger.properties(); | |
4484 SetLanguageMode(scope_, logger.language_mode()); | |
4485 if (logger.uses_super_property()) { | |
4486 scope_->RecordSuperPropertyUsage(); | |
4487 } | |
4488 if (logger.calls_eval()) { | |
4489 scope_->RecordEvalCall(); | |
4490 } | |
4491 if (produce_cached_parse_data()) { | |
4492 DCHECK(log_); | |
4493 // Position right after terminal '}'. | |
4494 int body_end = scanner()->location().end_pos; | |
4495 log_->LogFunction(function_block_pos, body_end, *materialized_literal_count, | |
4496 *expected_property_count, scope_->language_mode(), | |
4497 scope_->uses_super_property(), scope_->calls_eval()); | |
4498 } | |
4499 } | |
4500 | |
4501 | |
4502 Statement* Parser::BuildAssertIsCoercible(Variable* var) { | |
4503 // if (var === null || var === undefined) | |
4504 // throw /* type error kNonCoercible) */; | |
4505 | |
4506 Expression* condition = factory()->NewBinaryOperation( | |
4507 Token::OR, factory()->NewCompareOperation( | |
4508 Token::EQ_STRICT, factory()->NewVariableProxy(var), | |
4509 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), | |
4510 RelocInfo::kNoPosition), | |
4511 factory()->NewCompareOperation( | |
4512 Token::EQ_STRICT, factory()->NewVariableProxy(var), | |
4513 factory()->NewNullLiteral(RelocInfo::kNoPosition), | |
4514 RelocInfo::kNoPosition), | |
4515 RelocInfo::kNoPosition); | |
4516 Expression* throw_type_error = this->NewThrowTypeError( | |
4517 MessageTemplate::kNonCoercible, ast_value_factory()->empty_string(), | |
4518 RelocInfo::kNoPosition); | |
4519 IfStatement* if_statement = factory()->NewIfStatement( | |
4520 condition, factory()->NewExpressionStatement(throw_type_error, | |
4521 RelocInfo::kNoPosition), | |
4522 factory()->NewEmptyStatement(RelocInfo::kNoPosition), | |
4523 RelocInfo::kNoPosition); | |
4524 return if_statement; | |
4525 } | |
4526 | |
4527 | |
4528 Block* Parser::BuildParameterInitializationBlock( | |
4529 const ParserFormalParameters& parameters, bool* ok) { | |
4530 DCHECK(!parameters.is_simple); | |
4531 DCHECK(scope_->is_function_scope()); | |
4532 Block* init_block = | |
4533 factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition); | |
4534 for (int i = 0; i < parameters.params.length(); ++i) { | |
4535 auto parameter = parameters.params[i]; | |
4536 DeclarationDescriptor descriptor; | |
4537 descriptor.declaration_kind = DeclarationDescriptor::PARAMETER; | |
4538 descriptor.parser = this; | |
4539 descriptor.declaration_scope = scope_; | |
4540 descriptor.scope = scope_; | |
4541 descriptor.hoist_scope = nullptr; | |
4542 descriptor.mode = LET; | |
4543 descriptor.is_const = false; | |
4544 descriptor.needs_init = true; | |
4545 descriptor.declaration_pos = parameter.pattern->position(); | |
4546 // The position that will be used by the AssignmentExpression | |
4547 // which copies from the temp parameter to the pattern. | |
4548 // | |
4549 // TODO(adamk): Should this be RelocInfo::kNoPosition, since | |
4550 // it's just copying from a temp var to the real param var? | |
4551 descriptor.initialization_pos = parameter.pattern->position(); | |
4552 // The initializer position which will end up in, | |
4553 // Variable::initializer_position(), used for hole check elimination. | |
4554 int initializer_position = parameter.pattern->position(); | |
4555 Expression* initial_value = | |
4556 factory()->NewVariableProxy(parameters.scope->parameter(i)); | |
4557 if (parameter.initializer != nullptr) { | |
4558 // IS_UNDEFINED($param) ? initializer : $param | |
4559 DCHECK(!parameter.is_rest); | |
4560 auto condition = factory()->NewCompareOperation( | |
4561 Token::EQ_STRICT, | |
4562 factory()->NewVariableProxy(parameters.scope->parameter(i)), | |
4563 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), | |
4564 RelocInfo::kNoPosition); | |
4565 initial_value = factory()->NewConditional( | |
4566 condition, parameter.initializer, initial_value, | |
4567 RelocInfo::kNoPosition); | |
4568 descriptor.initialization_pos = parameter.initializer->position(); | |
4569 initializer_position = parameter.initializer_end_position; | |
4570 } else if (parameter.is_rest) { | |
4571 // $rest = []; | |
4572 // for (var $argument_index = $rest_index; | |
4573 // $argument_index < %_ArgumentsLength(); | |
4574 // ++$argument_index) { | |
4575 // %AppendElement($rest, %_Arguments($argument_index)); | |
4576 // } | |
4577 // let <param> = $rest; | |
4578 DCHECK(parameter.pattern->IsVariableProxy()); | |
4579 DCHECK_EQ(i, parameters.params.length() - 1); | |
4580 | |
4581 Variable* temp_var = parameters.scope->parameter(i); | |
4582 auto empty_values = new (zone()) ZoneList<Expression*>(0, zone()); | |
4583 auto empty_array = factory()->NewArrayLiteral( | |
4584 empty_values, parameters.rest_array_literal_index, | |
4585 is_strong(language_mode()), RelocInfo::kNoPosition); | |
4586 | |
4587 auto init_array = factory()->NewAssignment( | |
4588 Token::INIT, factory()->NewVariableProxy(temp_var), empty_array, | |
4589 RelocInfo::kNoPosition); | |
4590 | |
4591 auto loop = factory()->NewForStatement(NULL, RelocInfo::kNoPosition); | |
4592 | |
4593 auto argument_index = | |
4594 parameters.scope->NewTemporary(ast_value_factory()->empty_string()); | |
4595 auto init = factory()->NewExpressionStatement( | |
4596 factory()->NewAssignment( | |
4597 Token::INIT, factory()->NewVariableProxy(argument_index), | |
4598 factory()->NewSmiLiteral(i, RelocInfo::kNoPosition), | |
4599 RelocInfo::kNoPosition), | |
4600 RelocInfo::kNoPosition); | |
4601 | |
4602 auto empty_arguments = new (zone()) ZoneList<Expression*>(0, zone()); | |
4603 | |
4604 // $arguments_index < arguments.length | |
4605 auto cond = factory()->NewCompareOperation( | |
4606 Token::LT, factory()->NewVariableProxy(argument_index), | |
4607 factory()->NewCallRuntime(Runtime::kInlineArgumentsLength, | |
4608 empty_arguments, RelocInfo::kNoPosition), | |
4609 RelocInfo::kNoPosition); | |
4610 | |
4611 // ++argument_index | |
4612 auto next = factory()->NewExpressionStatement( | |
4613 factory()->NewCountOperation( | |
4614 Token::INC, true, factory()->NewVariableProxy(argument_index), | |
4615 RelocInfo::kNoPosition), | |
4616 RelocInfo::kNoPosition); | |
4617 | |
4618 // %_Arguments($arguments_index) | |
4619 auto arguments_args = new (zone()) ZoneList<Expression*>(1, zone()); | |
4620 arguments_args->Add(factory()->NewVariableProxy(argument_index), zone()); | |
4621 | |
4622 // %AppendElement($rest, %_Arguments($arguments_index)) | |
4623 auto append_element_args = new (zone()) ZoneList<Expression*>(2, zone()); | |
4624 | |
4625 append_element_args->Add(factory()->NewVariableProxy(temp_var), zone()); | |
4626 append_element_args->Add( | |
4627 factory()->NewCallRuntime(Runtime::kInlineArguments, arguments_args, | |
4628 RelocInfo::kNoPosition), | |
4629 zone()); | |
4630 | |
4631 auto body = factory()->NewExpressionStatement( | |
4632 factory()->NewCallRuntime(Runtime::kAppendElement, | |
4633 append_element_args, | |
4634 RelocInfo::kNoPosition), | |
4635 RelocInfo::kNoPosition); | |
4636 | |
4637 loop->Initialize(init, cond, next, body); | |
4638 | |
4639 init_block->statements()->Add( | |
4640 factory()->NewExpressionStatement(init_array, RelocInfo::kNoPosition), | |
4641 zone()); | |
4642 | |
4643 init_block->statements()->Add(loop, zone()); | |
4644 } | |
4645 | |
4646 Scope* param_scope = scope_; | |
4647 Block* param_block = init_block; | |
4648 if (!parameter.is_simple() && scope_->calls_sloppy_eval()) { | |
4649 param_scope = NewScope(scope_, BLOCK_SCOPE); | |
4650 param_scope->set_is_declaration_scope(); | |
4651 param_scope->set_start_position(parameter.pattern->position()); | |
4652 param_scope->set_end_position(RelocInfo::kNoPosition); | |
4653 param_scope->RecordEvalCall(); | |
4654 param_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition); | |
4655 param_block->set_scope(param_scope); | |
4656 descriptor.hoist_scope = scope_; | |
4657 } | |
4658 | |
4659 { | |
4660 BlockState block_state(&scope_, param_scope); | |
4661 DeclarationParsingResult::Declaration decl( | |
4662 parameter.pattern, initializer_position, initial_value); | |
4663 PatternRewriter::DeclareAndInitializeVariables(param_block, &descriptor, | |
4664 &decl, nullptr, CHECK_OK); | |
4665 } | |
4666 | |
4667 if (!parameter.is_simple() && scope_->calls_sloppy_eval()) { | |
4668 param_scope = param_scope->FinalizeBlockScope(); | |
4669 if (param_scope != nullptr) { | |
4670 CheckConflictingVarDeclarations(param_scope, CHECK_OK); | |
4671 } | |
4672 init_block->statements()->Add(param_block, zone()); | |
4673 } | |
4674 } | |
4675 return init_block; | |
4676 } | |
4677 | |
4678 | |
4679 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( | |
4680 const AstRawString* function_name, int pos, | |
4681 const ParserFormalParameters& parameters, FunctionKind kind, | |
4682 FunctionLiteral::FunctionType function_type, bool* ok) { | |
4683 // Everything inside an eagerly parsed function will be parsed eagerly | |
4684 // (see comment above). | |
4685 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); | |
4686 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); | |
4687 | |
4688 static const int kFunctionNameAssignmentIndex = 0; | |
4689 if (function_type == FunctionLiteral::NAMED_EXPRESSION) { | |
4690 DCHECK(function_name != NULL); | |
4691 // If we have a named function expression, we add a local variable | |
4692 // declaration to the body of the function with the name of the | |
4693 // function and let it refer to the function itself (closure). | |
4694 // Not having parsed the function body, the language mode may still change, | |
4695 // so we reserve a spot and create the actual const assignment later. | |
4696 DCHECK_EQ(kFunctionNameAssignmentIndex, result->length()); | |
4697 result->Add(NULL, zone()); | |
4698 } | |
4699 | |
4700 ZoneList<Statement*>* body = result; | |
4701 Scope* inner_scope = scope_; | |
4702 Block* inner_block = nullptr; | |
4703 if (!parameters.is_simple) { | |
4704 inner_scope = NewScope(scope_, BLOCK_SCOPE); | |
4705 inner_scope->set_is_declaration_scope(); | |
4706 inner_scope->set_start_position(scanner()->location().beg_pos); | |
4707 inner_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition); | |
4708 inner_block->set_scope(inner_scope); | |
4709 body = inner_block->statements(); | |
4710 } | |
4711 | |
4712 { | |
4713 BlockState block_state(&scope_, inner_scope); | |
4714 | |
4715 // For generators, allocate and yield an iterator on function entry. | |
4716 if (IsGeneratorFunction(kind)) { | |
4717 ZoneList<Expression*>* arguments = | |
4718 new(zone()) ZoneList<Expression*>(0, zone()); | |
4719 CallRuntime* allocation = factory()->NewCallRuntime( | |
4720 Runtime::kCreateJSGeneratorObject, arguments, pos); | |
4721 VariableProxy* init_proxy = factory()->NewVariableProxy( | |
4722 function_state_->generator_object_variable()); | |
4723 Assignment* assignment = factory()->NewAssignment( | |
4724 Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition); | |
4725 VariableProxy* get_proxy = factory()->NewVariableProxy( | |
4726 function_state_->generator_object_variable()); | |
4727 Yield* yield = factory()->NewYield( | |
4728 get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition); | |
4729 body->Add(factory()->NewExpressionStatement( | |
4730 yield, RelocInfo::kNoPosition), zone()); | |
4731 } | |
4732 | |
4733 ParseStatementList(body, Token::RBRACE, CHECK_OK); | |
4734 | |
4735 if (IsGeneratorFunction(kind)) { | |
4736 VariableProxy* get_proxy = factory()->NewVariableProxy( | |
4737 function_state_->generator_object_variable()); | |
4738 Expression* undefined = | |
4739 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition); | |
4740 Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal, | |
4741 RelocInfo::kNoPosition); | |
4742 body->Add(factory()->NewExpressionStatement( | |
4743 yield, RelocInfo::kNoPosition), zone()); | |
4744 } | |
4745 | |
4746 if (IsSubclassConstructor(kind)) { | |
4747 body->Add( | |
4748 factory()->NewReturnStatement( | |
4749 this->ThisExpression(scope_, factory(), RelocInfo::kNoPosition), | |
4750 RelocInfo::kNoPosition), | |
4751 zone()); | |
4752 } | |
4753 } | |
4754 | |
4755 Expect(Token::RBRACE, CHECK_OK); | |
4756 scope_->set_end_position(scanner()->location().end_pos); | |
4757 | |
4758 if (!parameters.is_simple) { | |
4759 DCHECK_NOT_NULL(inner_scope); | |
4760 DCHECK_EQ(body, inner_block->statements()); | |
4761 SetLanguageMode(scope_, inner_scope->language_mode()); | |
4762 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); | |
4763 DCHECK_NOT_NULL(init_block); | |
4764 | |
4765 inner_scope->set_end_position(scanner()->location().end_pos); | |
4766 inner_scope = inner_scope->FinalizeBlockScope(); | |
4767 if (inner_scope != nullptr) { | |
4768 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); | |
4769 InsertShadowingVarBindingInitializers(inner_block); | |
4770 } | |
4771 | |
4772 result->Add(init_block, zone()); | |
4773 result->Add(inner_block, zone()); | |
4774 } | |
4775 | |
4776 if (function_type == FunctionLiteral::NAMED_EXPRESSION) { | |
4777 // Now that we know the language mode, we can create the const assignment | |
4778 // in the previously reserved spot. | |
4779 // NOTE: We create a proxy and resolve it here so that in the | |
4780 // future we can change the AST to only refer to VariableProxies | |
4781 // instead of Variables and Proxies as is the case now. | |
4782 VariableMode fvar_mode = is_strict(language_mode()) ? CONST : CONST_LEGACY; | |
4783 Variable* fvar = new (zone()) | |
4784 Variable(scope_, function_name, fvar_mode, Variable::NORMAL, | |
4785 kCreatedInitialized, kNotAssigned); | |
4786 VariableProxy* proxy = factory()->NewVariableProxy(fvar); | |
4787 VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration( | |
4788 proxy, fvar_mode, scope_, RelocInfo::kNoPosition); | |
4789 scope_->DeclareFunctionVar(fvar_declaration); | |
4790 | |
4791 VariableProxy* fproxy = factory()->NewVariableProxy(fvar); | |
4792 result->Set(kFunctionNameAssignmentIndex, | |
4793 factory()->NewExpressionStatement( | |
4794 factory()->NewAssignment(Token::INIT, fproxy, | |
4795 factory()->NewThisFunction(pos), | |
4796 RelocInfo::kNoPosition), | |
4797 RelocInfo::kNoPosition)); | |
4798 } | |
4799 | |
4800 return result; | |
4801 } | |
4802 | |
4803 | |
4804 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( | |
4805 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) { | |
4806 // This function may be called on a background thread too; record only the | |
4807 // main thread preparse times. | |
4808 if (pre_parse_timer_ != NULL) { | |
4809 pre_parse_timer_->Start(); | |
4810 } | |
4811 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); | |
4812 | |
4813 if (reusable_preparser_ == NULL) { | |
4814 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(), | |
4815 NULL, stack_limit_); | |
4816 reusable_preparser_->set_allow_lazy(true); | |
4817 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name()); | |
4818 SET_ALLOW(natives); | |
4819 SET_ALLOW(harmony_sloppy); | |
4820 SET_ALLOW(harmony_sloppy_let); | |
4821 SET_ALLOW(harmony_rest_parameters); | |
4822 SET_ALLOW(harmony_default_parameters); | |
4823 SET_ALLOW(harmony_destructuring_bind); | |
4824 SET_ALLOW(strong_mode); | |
4825 SET_ALLOW(harmony_do_expressions); | |
4826 #undef SET_ALLOW | |
4827 } | |
4828 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( | |
4829 language_mode(), function_state_->kind(), scope_->has_simple_parameters(), | |
4830 logger, bookmark); | |
4831 if (pre_parse_timer_ != NULL) { | |
4832 pre_parse_timer_->Stop(); | |
4833 } | |
4834 return result; | |
4835 } | |
4836 | |
4837 | |
4838 ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name, | |
4839 Scanner::Location class_name_location, | |
4840 bool name_is_strict_reserved, int pos, | |
4841 bool* ok) { | |
4842 // All parts of a ClassDeclaration and ClassExpression are strict code. | |
4843 if (name_is_strict_reserved) { | |
4844 ReportMessageAt(class_name_location, | |
4845 MessageTemplate::kUnexpectedStrictReserved); | |
4846 *ok = false; | |
4847 return NULL; | |
4848 } | |
4849 if (IsEvalOrArguments(name)) { | |
4850 ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments); | |
4851 *ok = false; | |
4852 return NULL; | |
4853 } | |
4854 if (is_strong(language_mode()) && IsUndefined(name)) { | |
4855 ReportMessageAt(class_name_location, MessageTemplate::kStrongUndefined); | |
4856 *ok = false; | |
4857 return NULL; | |
4858 } | |
4859 | |
4860 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); | |
4861 BlockState block_state(&scope_, block_scope); | |
4862 RaiseLanguageMode(STRICT); | |
4863 scope_->SetScopeName(name); | |
4864 | |
4865 VariableProxy* proxy = NULL; | |
4866 if (name != NULL) { | |
4867 proxy = NewUnresolved(name, CONST); | |
4868 const bool is_class_declaration = true; | |
4869 Declaration* declaration = factory()->NewVariableDeclaration( | |
4870 proxy, CONST, block_scope, pos, is_class_declaration, | |
4871 scope_->class_declaration_group_start()); | |
4872 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); | |
4873 } | |
4874 | |
4875 Expression* extends = NULL; | |
4876 if (Check(Token::EXTENDS)) { | |
4877 block_scope->set_start_position(scanner()->location().end_pos); | |
4878 ExpressionClassifier classifier; | |
4879 extends = ParseLeftHandSideExpression(&classifier, CHECK_OK); | |
4880 ValidateExpression(&classifier, CHECK_OK); | |
4881 } else { | |
4882 block_scope->set_start_position(scanner()->location().end_pos); | |
4883 } | |
4884 | |
4885 | |
4886 ClassLiteralChecker checker(this); | |
4887 ZoneList<ObjectLiteral::Property*>* properties = NewPropertyList(4, zone()); | |
4888 FunctionLiteral* constructor = NULL; | |
4889 bool has_seen_constructor = false; | |
4890 | |
4891 Expect(Token::LBRACE, CHECK_OK); | |
4892 | |
4893 const bool has_extends = extends != nullptr; | |
4894 while (peek() != Token::RBRACE) { | |
4895 if (Check(Token::SEMICOLON)) continue; | |
4896 if (fni_ != NULL) fni_->Enter(); | |
4897 const bool in_class = true; | |
4898 const bool is_static = false; | |
4899 bool is_computed_name = false; // Classes do not care about computed | |
4900 // property names here. | |
4901 ExpressionClassifier classifier; | |
4902 ObjectLiteral::Property* property = ParsePropertyDefinition( | |
4903 &checker, in_class, has_extends, is_static, &is_computed_name, | |
4904 &has_seen_constructor, &classifier, CHECK_OK); | |
4905 ValidateExpression(&classifier, CHECK_OK); | |
4906 | |
4907 if (has_seen_constructor && constructor == NULL) { | |
4908 constructor = GetPropertyValue(property)->AsFunctionLiteral(); | |
4909 DCHECK_NOT_NULL(constructor); | |
4910 } else { | |
4911 properties->Add(property, zone()); | |
4912 } | |
4913 | |
4914 if (fni_ != NULL) { | |
4915 fni_->Infer(); | |
4916 fni_->Leave(); | |
4917 } | |
4918 } | |
4919 | |
4920 Expect(Token::RBRACE, CHECK_OK); | |
4921 int end_pos = scanner()->location().end_pos; | |
4922 | |
4923 if (constructor == NULL) { | |
4924 constructor = DefaultConstructor(extends != NULL, block_scope, pos, end_pos, | |
4925 block_scope->language_mode()); | |
4926 } | |
4927 | |
4928 // Note that we do not finalize this block scope because strong | |
4929 // mode uses it as a sentinel value indicating an anonymous class. | |
4930 block_scope->set_end_position(end_pos); | |
4931 | |
4932 if (name != NULL) { | |
4933 DCHECK_NOT_NULL(proxy); | |
4934 proxy->var()->set_initializer_position(end_pos); | |
4935 } | |
4936 | |
4937 return factory()->NewClassLiteral(name, block_scope, proxy, extends, | |
4938 constructor, properties, pos, end_pos); | |
4939 } | |
4940 | |
4941 | |
4942 Expression* Parser::ParseV8Intrinsic(bool* ok) { | |
4943 // CallRuntime :: | |
4944 // '%' Identifier Arguments | |
4945 | |
4946 int pos = peek_position(); | |
4947 Expect(Token::MOD, CHECK_OK); | |
4948 // Allow "eval" or "arguments" for backward compatibility. | |
4949 const AstRawString* name = ParseIdentifier(kAllowRestrictedIdentifiers, | |
4950 CHECK_OK); | |
4951 Scanner::Location spread_pos; | |
4952 ExpressionClassifier classifier; | |
4953 ZoneList<Expression*>* args = | |
4954 ParseArguments(&spread_pos, &classifier, CHECK_OK); | |
4955 ValidateExpression(&classifier, CHECK_OK); | |
4956 | |
4957 DCHECK(!spread_pos.IsValid()); | |
4958 | |
4959 if (extension_ != NULL) { | |
4960 // The extension structures are only accessible while parsing the | |
4961 // very first time not when reparsing because of lazy compilation. | |
4962 scope_->DeclarationScope()->ForceEagerCompilation(); | |
4963 } | |
4964 | |
4965 const Runtime::Function* function = Runtime::FunctionForName(name->string()); | |
4966 | |
4967 if (function != NULL) { | |
4968 // Check for possible name clash. | |
4969 DCHECK_EQ(Context::kNotFound, | |
4970 Context::IntrinsicIndexForName(name->string())); | |
4971 // Check for built-in IS_VAR macro. | |
4972 if (function->function_id == Runtime::kIS_VAR) { | |
4973 DCHECK_EQ(Runtime::RUNTIME, function->intrinsic_type); | |
4974 // %IS_VAR(x) evaluates to x if x is a variable, | |
4975 // leads to a parse error otherwise. Could be implemented as an | |
4976 // inline function %_IS_VAR(x) to eliminate this special case. | |
4977 if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) { | |
4978 return args->at(0); | |
4979 } else { | |
4980 ReportMessage(MessageTemplate::kNotIsvar); | |
4981 *ok = false; | |
4982 return NULL; | |
4983 } | |
4984 } | |
4985 | |
4986 // Check that the expected number of arguments are being passed. | |
4987 if (function->nargs != -1 && function->nargs != args->length()) { | |
4988 ReportMessage(MessageTemplate::kIllegalAccess); | |
4989 *ok = false; | |
4990 return NULL; | |
4991 } | |
4992 | |
4993 return factory()->NewCallRuntime(function, args, pos); | |
4994 } | |
4995 | |
4996 int context_index = Context::IntrinsicIndexForName(name->string()); | |
4997 | |
4998 // Check that the function is defined. | |
4999 if (context_index == Context::kNotFound) { | |
5000 ParserTraits::ReportMessage(MessageTemplate::kNotDefined, name); | |
5001 *ok = false; | |
5002 return NULL; | |
5003 } | |
5004 | |
5005 return factory()->NewCallRuntime(context_index, args, pos); | |
5006 } | |
5007 | |
5008 | |
5009 Literal* Parser::GetLiteralUndefined(int position) { | |
5010 return factory()->NewUndefinedLiteral(position); | |
5011 } | |
5012 | |
5013 | |
5014 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { | |
5015 Declaration* decl = scope->CheckConflictingVarDeclarations(); | |
5016 if (decl != NULL) { | |
5017 // In ES6, conflicting variable bindings are early errors. | |
5018 const AstRawString* name = decl->proxy()->raw_name(); | |
5019 int position = decl->proxy()->position(); | |
5020 Scanner::Location location = position == RelocInfo::kNoPosition | |
5021 ? Scanner::Location::invalid() | |
5022 : Scanner::Location(position, position + 1); | |
5023 ParserTraits::ReportMessageAt(location, MessageTemplate::kVarRedeclaration, | |
5024 name); | |
5025 *ok = false; | |
5026 } | |
5027 } | |
5028 | |
5029 | |
5030 void Parser::InsertShadowingVarBindingInitializers(Block* inner_block) { | |
5031 // For each var-binding that shadows a parameter, insert an assignment | |
5032 // initializing the variable with the parameter. | |
5033 Scope* inner_scope = inner_block->scope(); | |
5034 DCHECK(inner_scope->is_declaration_scope()); | |
5035 Scope* function_scope = inner_scope->outer_scope(); | |
5036 DCHECK(function_scope->is_function_scope()); | |
5037 ZoneList<Declaration*>* decls = inner_scope->declarations(); | |
5038 for (int i = 0; i < decls->length(); ++i) { | |
5039 Declaration* decl = decls->at(i); | |
5040 if (decl->mode() != VAR || !decl->IsVariableDeclaration()) continue; | |
5041 const AstRawString* name = decl->proxy()->raw_name(); | |
5042 Variable* parameter = function_scope->LookupLocal(name); | |
5043 if (parameter == nullptr) continue; | |
5044 VariableProxy* to = inner_scope->NewUnresolved(factory(), name); | |
5045 VariableProxy* from = factory()->NewVariableProxy(parameter); | |
5046 Expression* assignment = factory()->NewAssignment( | |
5047 Token::ASSIGN, to, from, RelocInfo::kNoPosition); | |
5048 Statement* statement = factory()->NewExpressionStatement( | |
5049 assignment, RelocInfo::kNoPosition); | |
5050 inner_block->statements()->InsertAt(0, statement, zone()); | |
5051 } | |
5052 } | |
5053 | |
5054 | |
5055 void Parser::InsertSloppyBlockFunctionVarBindings(Scope* scope, bool* ok) { | |
5056 // For each variable which is used as a function declaration in a sloppy | |
5057 // block, | |
5058 DCHECK(scope->is_declaration_scope()); | |
5059 SloppyBlockFunctionMap* map = scope->sloppy_block_function_map(); | |
5060 for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) { | |
5061 AstRawString* name = static_cast<AstRawString*>(p->key); | |
5062 // If the variable wouldn't conflict with a lexical declaration, | |
5063 Variable* var = scope->LookupLocal(name); | |
5064 if (var == nullptr || !IsLexicalVariableMode(var->mode())) { | |
5065 // Declare a var-style binding for the function in the outer scope | |
5066 VariableProxy* proxy = scope->NewUnresolved(factory(), name); | |
5067 Declaration* declaration = factory()->NewVariableDeclaration( | |
5068 proxy, VAR, scope, RelocInfo::kNoPosition); | |
5069 Declare(declaration, DeclarationDescriptor::NORMAL, true, ok, scope); | |
5070 DCHECK(ok); // Based on the preceding check, this should not fail | |
5071 if (!ok) return; | |
5072 | |
5073 // Write in assignments to var for each block-scoped function declaration | |
5074 auto delegates = static_cast<SloppyBlockFunctionMap::Vector*>(p->value); | |
5075 for (SloppyBlockFunctionStatement* delegate : *delegates) { | |
5076 // Read from the local lexical scope and write to the function scope | |
5077 VariableProxy* to = scope->NewUnresolved(factory(), name); | |
5078 VariableProxy* from = delegate->scope()->NewUnresolved(factory(), name); | |
5079 Expression* assignment = factory()->NewAssignment( | |
5080 Token::ASSIGN, to, from, RelocInfo::kNoPosition); | |
5081 Statement* statement = factory()->NewExpressionStatement( | |
5082 assignment, RelocInfo::kNoPosition); | |
5083 delegate->set_statement(statement); | |
5084 } | |
5085 } | |
5086 } | |
5087 } | |
5088 | |
5089 | |
5090 // ---------------------------------------------------------------------------- | |
5091 // Parser support | |
5092 | |
5093 bool Parser::TargetStackContainsLabel(const AstRawString* label) { | |
5094 for (Target* t = target_stack_; t != NULL; t = t->previous()) { | |
5095 if (ContainsLabel(t->statement()->labels(), label)) return true; | |
5096 } | |
5097 return false; | |
5098 } | |
5099 | |
5100 | |
5101 BreakableStatement* Parser::LookupBreakTarget(const AstRawString* label, | |
5102 bool* ok) { | |
5103 bool anonymous = label == NULL; | |
5104 for (Target* t = target_stack_; t != NULL; t = t->previous()) { | |
5105 BreakableStatement* stat = t->statement(); | |
5106 if ((anonymous && stat->is_target_for_anonymous()) || | |
5107 (!anonymous && ContainsLabel(stat->labels(), label))) { | |
5108 return stat; | |
5109 } | |
5110 } | |
5111 return NULL; | |
5112 } | |
5113 | |
5114 | |
5115 IterationStatement* Parser::LookupContinueTarget(const AstRawString* label, | |
5116 bool* ok) { | |
5117 bool anonymous = label == NULL; | |
5118 for (Target* t = target_stack_; t != NULL; t = t->previous()) { | |
5119 IterationStatement* stat = t->statement()->AsIterationStatement(); | |
5120 if (stat == NULL) continue; | |
5121 | |
5122 DCHECK(stat->is_target_for_anonymous()); | |
5123 if (anonymous || ContainsLabel(stat->labels(), label)) { | |
5124 return stat; | |
5125 } | |
5126 } | |
5127 return NULL; | |
5128 } | |
5129 | |
5130 | |
5131 void Parser::HandleSourceURLComments(Isolate* isolate, Handle<Script> script) { | |
5132 if (scanner_.source_url()->length() > 0) { | |
5133 Handle<String> source_url = scanner_.source_url()->Internalize(isolate); | |
5134 script->set_source_url(*source_url); | |
5135 } | |
5136 if (scanner_.source_mapping_url()->length() > 0) { | |
5137 Handle<String> source_mapping_url = | |
5138 scanner_.source_mapping_url()->Internalize(isolate); | |
5139 script->set_source_mapping_url(*source_mapping_url); | |
5140 } | |
5141 } | |
5142 | |
5143 | |
5144 void Parser::Internalize(Isolate* isolate, Handle<Script> script, bool error) { | |
5145 // Internalize strings. | |
5146 ast_value_factory()->Internalize(isolate); | |
5147 | |
5148 // Error processing. | |
5149 if (error) { | |
5150 if (stack_overflow()) { | |
5151 isolate->StackOverflow(); | |
5152 } else { | |
5153 DCHECK(pending_error_handler_.has_pending_error()); | |
5154 pending_error_handler_.ThrowPendingError(isolate, script); | |
5155 } | |
5156 } | |
5157 | |
5158 // Move statistics to Isolate. | |
5159 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; | |
5160 ++feature) { | |
5161 for (int i = 0; i < use_counts_[feature]; ++i) { | |
5162 isolate->CountUsage(v8::Isolate::UseCounterFeature(feature)); | |
5163 } | |
5164 } | |
5165 isolate->counters()->total_preparse_skipped()->Increment( | |
5166 total_preparse_skipped_); | |
5167 } | |
5168 | |
5169 | |
5170 // ---------------------------------------------------------------------------- | |
5171 // Regular expressions | |
5172 | |
5173 | |
5174 RegExpParser::RegExpParser(FlatStringReader* in, Handle<String>* error, | |
5175 bool multiline, bool unicode, Isolate* isolate, | |
5176 Zone* zone) | |
5177 : isolate_(isolate), | |
5178 zone_(zone), | |
5179 error_(error), | |
5180 captures_(NULL), | |
5181 in_(in), | |
5182 current_(kEndMarker), | |
5183 next_pos_(0), | |
5184 captures_started_(0), | |
5185 capture_count_(0), | |
5186 has_more_(true), | |
5187 multiline_(multiline), | |
5188 unicode_(unicode), | |
5189 simple_(false), | |
5190 contains_anchor_(false), | |
5191 is_scanned_for_captures_(false), | |
5192 failed_(false) { | |
5193 Advance(); | |
5194 } | |
5195 | |
5196 | |
5197 uc32 RegExpParser::Next() { | |
5198 if (has_next()) { | |
5199 return in()->Get(next_pos_); | |
5200 } else { | |
5201 return kEndMarker; | |
5202 } | |
5203 } | |
5204 | |
5205 | |
5206 void RegExpParser::Advance() { | |
5207 if (next_pos_ < in()->length()) { | |
5208 StackLimitCheck check(isolate()); | |
5209 if (check.HasOverflowed()) { | |
5210 ReportError(CStrVector(Isolate::kStackOverflowMessage)); | |
5211 } else if (zone()->excess_allocation()) { | |
5212 ReportError(CStrVector("Regular expression too large")); | |
5213 } else { | |
5214 current_ = in()->Get(next_pos_); | |
5215 next_pos_++; | |
5216 } | |
5217 } else { | |
5218 current_ = kEndMarker; | |
5219 // Advance so that position() points to 1-after-the-last-character. This is | |
5220 // important so that Reset() to this position works correctly. | |
5221 next_pos_ = in()->length() + 1; | |
5222 has_more_ = false; | |
5223 } | |
5224 } | |
5225 | |
5226 | |
5227 void RegExpParser::Reset(int pos) { | |
5228 next_pos_ = pos; | |
5229 has_more_ = (pos < in()->length()); | |
5230 Advance(); | |
5231 } | |
5232 | |
5233 | |
5234 void RegExpParser::Advance(int dist) { | |
5235 next_pos_ += dist - 1; | |
5236 Advance(); | |
5237 } | |
5238 | |
5239 | |
5240 bool RegExpParser::simple() { | |
5241 return simple_; | |
5242 } | |
5243 | |
5244 | |
5245 bool RegExpParser::IsSyntaxCharacter(uc32 c) { | |
5246 return c == '^' || c == '$' || c == '\\' || c == '.' || c == '*' || | |
5247 c == '+' || c == '?' || c == '(' || c == ')' || c == '[' || c == ']' || | |
5248 c == '{' || c == '}' || c == '|'; | |
5249 } | |
5250 | |
5251 | |
5252 RegExpTree* RegExpParser::ReportError(Vector<const char> message) { | |
5253 failed_ = true; | |
5254 *error_ = isolate()->factory()->NewStringFromAscii(message).ToHandleChecked(); | |
5255 // Zip to the end to make sure the no more input is read. | |
5256 current_ = kEndMarker; | |
5257 next_pos_ = in()->length(); | |
5258 return NULL; | |
5259 } | |
5260 | |
5261 | |
5262 // Pattern :: | |
5263 // Disjunction | |
5264 RegExpTree* RegExpParser::ParsePattern() { | |
5265 RegExpTree* result = ParseDisjunction(CHECK_FAILED); | |
5266 DCHECK(!has_more()); | |
5267 // If the result of parsing is a literal string atom, and it has the | |
5268 // same length as the input, then the atom is identical to the input. | |
5269 if (result->IsAtom() && result->AsAtom()->length() == in()->length()) { | |
5270 simple_ = true; | |
5271 } | |
5272 return result; | |
5273 } | |
5274 | |
5275 | |
5276 // Disjunction :: | |
5277 // Alternative | |
5278 // Alternative | Disjunction | |
5279 // Alternative :: | |
5280 // [empty] | |
5281 // Term Alternative | |
5282 // Term :: | |
5283 // Assertion | |
5284 // Atom | |
5285 // Atom Quantifier | |
5286 RegExpTree* RegExpParser::ParseDisjunction() { | |
5287 // Used to store current state while parsing subexpressions. | |
5288 RegExpParserState initial_state(NULL, INITIAL, RegExpLookaround::LOOKAHEAD, 0, | |
5289 zone()); | |
5290 RegExpParserState* state = &initial_state; | |
5291 // Cache the builder in a local variable for quick access. | |
5292 RegExpBuilder* builder = initial_state.builder(); | |
5293 while (true) { | |
5294 switch (current()) { | |
5295 case kEndMarker: | |
5296 if (state->IsSubexpression()) { | |
5297 // Inside a parenthesized group when hitting end of input. | |
5298 ReportError(CStrVector("Unterminated group") CHECK_FAILED); | |
5299 } | |
5300 DCHECK_EQ(INITIAL, state->group_type()); | |
5301 // Parsing completed successfully. | |
5302 return builder->ToRegExp(); | |
5303 case ')': { | |
5304 if (!state->IsSubexpression()) { | |
5305 ReportError(CStrVector("Unmatched ')'") CHECK_FAILED); | |
5306 } | |
5307 DCHECK_NE(INITIAL, state->group_type()); | |
5308 | |
5309 Advance(); | |
5310 // End disjunction parsing and convert builder content to new single | |
5311 // regexp atom. | |
5312 RegExpTree* body = builder->ToRegExp(); | |
5313 | |
5314 int end_capture_index = captures_started(); | |
5315 | |
5316 int capture_index = state->capture_index(); | |
5317 SubexpressionType group_type = state->group_type(); | |
5318 | |
5319 // Build result of subexpression. | |
5320 if (group_type == CAPTURE) { | |
5321 RegExpCapture* capture = GetCapture(capture_index); | |
5322 capture->set_body(body); | |
5323 body = capture; | |
5324 } else if (group_type != GROUPING) { | |
5325 DCHECK(group_type == POSITIVE_LOOKAROUND || | |
5326 group_type == NEGATIVE_LOOKAROUND); | |
5327 bool is_positive = (group_type == POSITIVE_LOOKAROUND); | |
5328 body = new (zone()) RegExpLookaround( | |
5329 body, is_positive, end_capture_index - capture_index, capture_index, | |
5330 state->lookaround_type()); | |
5331 } | |
5332 | |
5333 // Restore previous state. | |
5334 state = state->previous_state(); | |
5335 builder = state->builder(); | |
5336 | |
5337 builder->AddAtom(body); | |
5338 // For compatability with JSC and ES3, we allow quantifiers after | |
5339 // lookaheads, and break in all cases. | |
5340 break; | |
5341 } | |
5342 case '|': { | |
5343 Advance(); | |
5344 builder->NewAlternative(); | |
5345 continue; | |
5346 } | |
5347 case '*': | |
5348 case '+': | |
5349 case '?': | |
5350 return ReportError(CStrVector("Nothing to repeat")); | |
5351 case '^': { | |
5352 Advance(); | |
5353 if (multiline_) { | |
5354 builder->AddAssertion( | |
5355 new(zone()) RegExpAssertion(RegExpAssertion::START_OF_LINE)); | |
5356 } else { | |
5357 builder->AddAssertion( | |
5358 new(zone()) RegExpAssertion(RegExpAssertion::START_OF_INPUT)); | |
5359 set_contains_anchor(); | |
5360 } | |
5361 continue; | |
5362 } | |
5363 case '$': { | |
5364 Advance(); | |
5365 RegExpAssertion::AssertionType assertion_type = | |
5366 multiline_ ? RegExpAssertion::END_OF_LINE : | |
5367 RegExpAssertion::END_OF_INPUT; | |
5368 builder->AddAssertion(new(zone()) RegExpAssertion(assertion_type)); | |
5369 continue; | |
5370 } | |
5371 case '.': { | |
5372 Advance(); | |
5373 // everything except \x0a, \x0d, \u2028 and \u2029 | |
5374 ZoneList<CharacterRange>* ranges = | |
5375 new(zone()) ZoneList<CharacterRange>(2, zone()); | |
5376 CharacterRange::AddClassEscape('.', ranges, zone()); | |
5377 RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false); | |
5378 builder->AddAtom(atom); | |
5379 break; | |
5380 } | |
5381 case '(': { | |
5382 SubexpressionType subexpr_type = CAPTURE; | |
5383 RegExpLookaround::Type lookaround_type = state->lookaround_type(); | |
5384 Advance(); | |
5385 if (current() == '?') { | |
5386 switch (Next()) { | |
5387 case ':': | |
5388 subexpr_type = GROUPING; | |
5389 break; | |
5390 case '=': | |
5391 lookaround_type = RegExpLookaround::LOOKAHEAD; | |
5392 subexpr_type = POSITIVE_LOOKAROUND; | |
5393 break; | |
5394 case '!': | |
5395 lookaround_type = RegExpLookaround::LOOKAHEAD; | |
5396 subexpr_type = NEGATIVE_LOOKAROUND; | |
5397 break; | |
5398 case '<': | |
5399 if (FLAG_harmony_regexp_lookbehind) { | |
5400 Advance(); | |
5401 lookaround_type = RegExpLookaround::LOOKBEHIND; | |
5402 if (Next() == '=') { | |
5403 subexpr_type = POSITIVE_LOOKAROUND; | |
5404 break; | |
5405 } else if (Next() == '!') { | |
5406 subexpr_type = NEGATIVE_LOOKAROUND; | |
5407 break; | |
5408 } | |
5409 } | |
5410 // Fall through. | |
5411 default: | |
5412 ReportError(CStrVector("Invalid group") CHECK_FAILED); | |
5413 break; | |
5414 } | |
5415 Advance(2); | |
5416 } else { | |
5417 if (captures_started_ >= kMaxCaptures) { | |
5418 ReportError(CStrVector("Too many captures") CHECK_FAILED); | |
5419 } | |
5420 captures_started_++; | |
5421 } | |
5422 // Store current state and begin new disjunction parsing. | |
5423 state = new (zone()) RegExpParserState( | |
5424 state, subexpr_type, lookaround_type, captures_started_, zone()); | |
5425 builder = state->builder(); | |
5426 continue; | |
5427 } | |
5428 case '[': { | |
5429 RegExpTree* atom = ParseCharacterClass(CHECK_FAILED); | |
5430 builder->AddAtom(atom); | |
5431 break; | |
5432 } | |
5433 // Atom :: | |
5434 // \ AtomEscape | |
5435 case '\\': | |
5436 switch (Next()) { | |
5437 case kEndMarker: | |
5438 return ReportError(CStrVector("\\ at end of pattern")); | |
5439 case 'b': | |
5440 Advance(2); | |
5441 builder->AddAssertion( | |
5442 new(zone()) RegExpAssertion(RegExpAssertion::BOUNDARY)); | |
5443 continue; | |
5444 case 'B': | |
5445 Advance(2); | |
5446 builder->AddAssertion( | |
5447 new(zone()) RegExpAssertion(RegExpAssertion::NON_BOUNDARY)); | |
5448 continue; | |
5449 // AtomEscape :: | |
5450 // CharacterClassEscape | |
5451 // | |
5452 // CharacterClassEscape :: one of | |
5453 // d D s S w W | |
5454 case 'd': case 'D': case 's': case 'S': case 'w': case 'W': { | |
5455 uc32 c = Next(); | |
5456 Advance(2); | |
5457 ZoneList<CharacterRange>* ranges = | |
5458 new(zone()) ZoneList<CharacterRange>(2, zone()); | |
5459 CharacterRange::AddClassEscape(c, ranges, zone()); | |
5460 RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false); | |
5461 builder->AddAtom(atom); | |
5462 break; | |
5463 } | |
5464 case '1': case '2': case '3': case '4': case '5': case '6': | |
5465 case '7': case '8': case '9': { | |
5466 int index = 0; | |
5467 if (ParseBackReferenceIndex(&index)) { | |
5468 if (state->IsInsideCaptureGroup(index)) { | |
5469 // The backreference is inside the capture group it refers to. | |
5470 // Nothing can possibly have been captured yet. | |
5471 builder->AddEmpty(); | |
5472 } else { | |
5473 RegExpCapture* capture = GetCapture(index); | |
5474 RegExpTree* atom = new (zone()) RegExpBackReference(capture); | |
5475 builder->AddAtom(atom); | |
5476 } | |
5477 break; | |
5478 } | |
5479 uc32 first_digit = Next(); | |
5480 if (first_digit == '8' || first_digit == '9') { | |
5481 // If the 'u' flag is present, only syntax characters can be escaped, | |
5482 // no other identity escapes are allowed. If the 'u' flag is not | |
5483 // present, all identity escapes are allowed. | |
5484 if (!FLAG_harmony_unicode_regexps || !unicode_) { | |
5485 builder->AddCharacter(first_digit); | |
5486 Advance(2); | |
5487 } else { | |
5488 return ReportError(CStrVector("Invalid escape")); | |
5489 } | |
5490 break; | |
5491 } | |
5492 } | |
5493 // FALLTHROUGH | |
5494 case '0': { | |
5495 Advance(); | |
5496 uc32 octal = ParseOctalLiteral(); | |
5497 builder->AddCharacter(octal); | |
5498 break; | |
5499 } | |
5500 // ControlEscape :: one of | |
5501 // f n r t v | |
5502 case 'f': | |
5503 Advance(2); | |
5504 builder->AddCharacter('\f'); | |
5505 break; | |
5506 case 'n': | |
5507 Advance(2); | |
5508 builder->AddCharacter('\n'); | |
5509 break; | |
5510 case 'r': | |
5511 Advance(2); | |
5512 builder->AddCharacter('\r'); | |
5513 break; | |
5514 case 't': | |
5515 Advance(2); | |
5516 builder->AddCharacter('\t'); | |
5517 break; | |
5518 case 'v': | |
5519 Advance(2); | |
5520 builder->AddCharacter('\v'); | |
5521 break; | |
5522 case 'c': { | |
5523 Advance(); | |
5524 uc32 controlLetter = Next(); | |
5525 // Special case if it is an ASCII letter. | |
5526 // Convert lower case letters to uppercase. | |
5527 uc32 letter = controlLetter & ~('a' ^ 'A'); | |
5528 if (letter < 'A' || 'Z' < letter) { | |
5529 // controlLetter is not in range 'A'-'Z' or 'a'-'z'. | |
5530 // This is outside the specification. We match JSC in | |
5531 // reading the backslash as a literal character instead | |
5532 // of as starting an escape. | |
5533 builder->AddCharacter('\\'); | |
5534 } else { | |
5535 Advance(2); | |
5536 builder->AddCharacter(controlLetter & 0x1f); | |
5537 } | |
5538 break; | |
5539 } | |
5540 case 'x': { | |
5541 Advance(2); | |
5542 uc32 value; | |
5543 if (ParseHexEscape(2, &value)) { | |
5544 builder->AddCharacter(value); | |
5545 } else if (!FLAG_harmony_unicode_regexps || !unicode_) { | |
5546 builder->AddCharacter('x'); | |
5547 } else { | |
5548 // If the 'u' flag is present, invalid escapes are not treated as | |
5549 // identity escapes. | |
5550 return ReportError(CStrVector("Invalid escape")); | |
5551 } | |
5552 break; | |
5553 } | |
5554 case 'u': { | |
5555 Advance(2); | |
5556 uc32 value; | |
5557 if (ParseUnicodeEscape(&value)) { | |
5558 builder->AddCharacter(value); | |
5559 } else if (!FLAG_harmony_unicode_regexps || !unicode_) { | |
5560 builder->AddCharacter('u'); | |
5561 } else { | |
5562 // If the 'u' flag is present, invalid escapes are not treated as | |
5563 // identity escapes. | |
5564 return ReportError(CStrVector("Invalid unicode escape")); | |
5565 } | |
5566 break; | |
5567 } | |
5568 default: | |
5569 Advance(); | |
5570 // If the 'u' flag is present, only syntax characters can be escaped, no | |
5571 // other identity escapes are allowed. If the 'u' flag is not present, | |
5572 // all identity escapes are allowed. | |
5573 if (!FLAG_harmony_unicode_regexps || !unicode_ || | |
5574 IsSyntaxCharacter(current())) { | |
5575 builder->AddCharacter(current()); | |
5576 Advance(); | |
5577 } else { | |
5578 return ReportError(CStrVector("Invalid escape")); | |
5579 } | |
5580 break; | |
5581 } | |
5582 break; | |
5583 case '{': { | |
5584 int dummy; | |
5585 if (ParseIntervalQuantifier(&dummy, &dummy)) { | |
5586 ReportError(CStrVector("Nothing to repeat") CHECK_FAILED); | |
5587 } | |
5588 // fallthrough | |
5589 } | |
5590 default: | |
5591 builder->AddCharacter(current()); | |
5592 Advance(); | |
5593 break; | |
5594 } // end switch(current()) | |
5595 | |
5596 int min; | |
5597 int max; | |
5598 switch (current()) { | |
5599 // QuantifierPrefix :: | |
5600 // * | |
5601 // + | |
5602 // ? | |
5603 // { | |
5604 case '*': | |
5605 min = 0; | |
5606 max = RegExpTree::kInfinity; | |
5607 Advance(); | |
5608 break; | |
5609 case '+': | |
5610 min = 1; | |
5611 max = RegExpTree::kInfinity; | |
5612 Advance(); | |
5613 break; | |
5614 case '?': | |
5615 min = 0; | |
5616 max = 1; | |
5617 Advance(); | |
5618 break; | |
5619 case '{': | |
5620 if (ParseIntervalQuantifier(&min, &max)) { | |
5621 if (max < min) { | |
5622 ReportError(CStrVector("numbers out of order in {} quantifier.") | |
5623 CHECK_FAILED); | |
5624 } | |
5625 break; | |
5626 } else { | |
5627 continue; | |
5628 } | |
5629 default: | |
5630 continue; | |
5631 } | |
5632 RegExpQuantifier::QuantifierType quantifier_type = RegExpQuantifier::GREEDY; | |
5633 if (current() == '?') { | |
5634 quantifier_type = RegExpQuantifier::NON_GREEDY; | |
5635 Advance(); | |
5636 } else if (FLAG_regexp_possessive_quantifier && current() == '+') { | |
5637 // FLAG_regexp_possessive_quantifier is a debug-only flag. | |
5638 quantifier_type = RegExpQuantifier::POSSESSIVE; | |
5639 Advance(); | |
5640 } | |
5641 builder->AddQuantifierToAtom(min, max, quantifier_type); | |
5642 } | |
5643 } | |
5644 | |
5645 | |
5646 #ifdef DEBUG | |
5647 // Currently only used in an DCHECK. | |
5648 static bool IsSpecialClassEscape(uc32 c) { | |
5649 switch (c) { | |
5650 case 'd': case 'D': | |
5651 case 's': case 'S': | |
5652 case 'w': case 'W': | |
5653 return true; | |
5654 default: | |
5655 return false; | |
5656 } | |
5657 } | |
5658 #endif | |
5659 | |
5660 | |
5661 // In order to know whether an escape is a backreference or not we have to scan | |
5662 // the entire regexp and find the number of capturing parentheses. However we | |
5663 // don't want to scan the regexp twice unless it is necessary. This mini-parser | |
5664 // is called when needed. It can see the difference between capturing and | |
5665 // noncapturing parentheses and can skip character classes and backslash-escaped | |
5666 // characters. | |
5667 void RegExpParser::ScanForCaptures() { | |
5668 // Start with captures started previous to current position | |
5669 int capture_count = captures_started(); | |
5670 // Add count of captures after this position. | |
5671 int n; | |
5672 while ((n = current()) != kEndMarker) { | |
5673 Advance(); | |
5674 switch (n) { | |
5675 case '\\': | |
5676 Advance(); | |
5677 break; | |
5678 case '[': { | |
5679 int c; | |
5680 while ((c = current()) != kEndMarker) { | |
5681 Advance(); | |
5682 if (c == '\\') { | |
5683 Advance(); | |
5684 } else { | |
5685 if (c == ']') break; | |
5686 } | |
5687 } | |
5688 break; | |
5689 } | |
5690 case '(': | |
5691 if (current() != '?') capture_count++; | |
5692 break; | |
5693 } | |
5694 } | |
5695 capture_count_ = capture_count; | |
5696 is_scanned_for_captures_ = true; | |
5697 } | |
5698 | |
5699 | |
5700 bool RegExpParser::ParseBackReferenceIndex(int* index_out) { | |
5701 DCHECK_EQ('\\', current()); | |
5702 DCHECK('1' <= Next() && Next() <= '9'); | |
5703 // Try to parse a decimal literal that is no greater than the total number | |
5704 // of left capturing parentheses in the input. | |
5705 int start = position(); | |
5706 int value = Next() - '0'; | |
5707 Advance(2); | |
5708 while (true) { | |
5709 uc32 c = current(); | |
5710 if (IsDecimalDigit(c)) { | |
5711 value = 10 * value + (c - '0'); | |
5712 if (value > kMaxCaptures) { | |
5713 Reset(start); | |
5714 return false; | |
5715 } | |
5716 Advance(); | |
5717 } else { | |
5718 break; | |
5719 } | |
5720 } | |
5721 if (value > captures_started()) { | |
5722 if (!is_scanned_for_captures_) { | |
5723 int saved_position = position(); | |
5724 ScanForCaptures(); | |
5725 Reset(saved_position); | |
5726 } | |
5727 if (value > capture_count_) { | |
5728 Reset(start); | |
5729 return false; | |
5730 } | |
5731 } | |
5732 *index_out = value; | |
5733 return true; | |
5734 } | |
5735 | |
5736 | |
5737 RegExpCapture* RegExpParser::GetCapture(int index) { | |
5738 // The index for the capture groups are one-based. Its index in the list is | |
5739 // zero-based. | |
5740 int know_captures = | |
5741 is_scanned_for_captures_ ? capture_count_ : captures_started_; | |
5742 DCHECK(index <= know_captures); | |
5743 if (captures_ == NULL) { | |
5744 captures_ = new (zone()) ZoneList<RegExpCapture*>(know_captures, zone()); | |
5745 } | |
5746 while (captures_->length() < know_captures) { | |
5747 captures_->Add(new (zone()) RegExpCapture(captures_->length() + 1), zone()); | |
5748 } | |
5749 return captures_->at(index - 1); | |
5750 } | |
5751 | |
5752 | |
5753 bool RegExpParser::RegExpParserState::IsInsideCaptureGroup(int index) { | |
5754 for (RegExpParserState* s = this; s != NULL; s = s->previous_state()) { | |
5755 if (s->group_type() != CAPTURE) continue; | |
5756 // Return true if we found the matching capture index. | |
5757 if (index == s->capture_index()) return true; | |
5758 // Abort if index is larger than what has been parsed up till this state. | |
5759 if (index > s->capture_index()) return false; | |
5760 } | |
5761 return false; | |
5762 } | |
5763 | |
5764 | |
5765 // QuantifierPrefix :: | |
5766 // { DecimalDigits } | |
5767 // { DecimalDigits , } | |
5768 // { DecimalDigits , DecimalDigits } | |
5769 // | |
5770 // Returns true if parsing succeeds, and set the min_out and max_out | |
5771 // values. Values are truncated to RegExpTree::kInfinity if they overflow. | |
5772 bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) { | |
5773 DCHECK_EQ(current(), '{'); | |
5774 int start = position(); | |
5775 Advance(); | |
5776 int min = 0; | |
5777 if (!IsDecimalDigit(current())) { | |
5778 Reset(start); | |
5779 return false; | |
5780 } | |
5781 while (IsDecimalDigit(current())) { | |
5782 int next = current() - '0'; | |
5783 if (min > (RegExpTree::kInfinity - next) / 10) { | |
5784 // Overflow. Skip past remaining decimal digits and return -1. | |
5785 do { | |
5786 Advance(); | |
5787 } while (IsDecimalDigit(current())); | |
5788 min = RegExpTree::kInfinity; | |
5789 break; | |
5790 } | |
5791 min = 10 * min + next; | |
5792 Advance(); | |
5793 } | |
5794 int max = 0; | |
5795 if (current() == '}') { | |
5796 max = min; | |
5797 Advance(); | |
5798 } else if (current() == ',') { | |
5799 Advance(); | |
5800 if (current() == '}') { | |
5801 max = RegExpTree::kInfinity; | |
5802 Advance(); | |
5803 } else { | |
5804 while (IsDecimalDigit(current())) { | |
5805 int next = current() - '0'; | |
5806 if (max > (RegExpTree::kInfinity - next) / 10) { | |
5807 do { | |
5808 Advance(); | |
5809 } while (IsDecimalDigit(current())); | |
5810 max = RegExpTree::kInfinity; | |
5811 break; | |
5812 } | |
5813 max = 10 * max + next; | |
5814 Advance(); | |
5815 } | |
5816 if (current() != '}') { | |
5817 Reset(start); | |
5818 return false; | |
5819 } | |
5820 Advance(); | |
5821 } | |
5822 } else { | |
5823 Reset(start); | |
5824 return false; | |
5825 } | |
5826 *min_out = min; | |
5827 *max_out = max; | |
5828 return true; | |
5829 } | |
5830 | |
5831 | |
5832 uc32 RegExpParser::ParseOctalLiteral() { | |
5833 DCHECK(('0' <= current() && current() <= '7') || current() == kEndMarker); | |
5834 // For compatibility with some other browsers (not all), we parse | |
5835 // up to three octal digits with a value below 256. | |
5836 uc32 value = current() - '0'; | |
5837 Advance(); | |
5838 if ('0' <= current() && current() <= '7') { | |
5839 value = value * 8 + current() - '0'; | |
5840 Advance(); | |
5841 if (value < 32 && '0' <= current() && current() <= '7') { | |
5842 value = value * 8 + current() - '0'; | |
5843 Advance(); | |
5844 } | |
5845 } | |
5846 return value; | |
5847 } | |
5848 | |
5849 | |
5850 bool RegExpParser::ParseHexEscape(int length, uc32* value) { | |
5851 int start = position(); | |
5852 uc32 val = 0; | |
5853 for (int i = 0; i < length; ++i) { | |
5854 uc32 c = current(); | |
5855 int d = HexValue(c); | |
5856 if (d < 0) { | |
5857 Reset(start); | |
5858 return false; | |
5859 } | |
5860 val = val * 16 + d; | |
5861 Advance(); | |
5862 } | |
5863 *value = val; | |
5864 return true; | |
5865 } | |
5866 | |
5867 | |
5868 bool RegExpParser::ParseUnicodeEscape(uc32* value) { | |
5869 // Accept both \uxxxx and \u{xxxxxx} (if harmony unicode escapes are | |
5870 // allowed). In the latter case, the number of hex digits between { } is | |
5871 // arbitrary. \ and u have already been read. | |
5872 if (current() == '{' && FLAG_harmony_unicode_regexps && unicode_) { | |
5873 int start = position(); | |
5874 Advance(); | |
5875 if (ParseUnlimitedLengthHexNumber(0x10ffff, value)) { | |
5876 if (current() == '}') { | |
5877 Advance(); | |
5878 return true; | |
5879 } | |
5880 } | |
5881 Reset(start); | |
5882 return false; | |
5883 } | |
5884 // \u but no {, or \u{...} escapes not allowed. | |
5885 return ParseHexEscape(4, value); | |
5886 } | |
5887 | |
5888 | |
5889 bool RegExpParser::ParseUnlimitedLengthHexNumber(int max_value, uc32* value) { | |
5890 uc32 x = 0; | |
5891 int d = HexValue(current()); | |
5892 if (d < 0) { | |
5893 return false; | |
5894 } | |
5895 while (d >= 0) { | |
5896 x = x * 16 + d; | |
5897 if (x > max_value) { | |
5898 return false; | |
5899 } | |
5900 Advance(); | |
5901 d = HexValue(current()); | |
5902 } | |
5903 *value = x; | |
5904 return true; | |
5905 } | |
5906 | |
5907 | |
5908 uc32 RegExpParser::ParseClassCharacterEscape() { | |
5909 DCHECK(current() == '\\'); | |
5910 DCHECK(has_next() && !IsSpecialClassEscape(Next())); | |
5911 Advance(); | |
5912 switch (current()) { | |
5913 case 'b': | |
5914 Advance(); | |
5915 return '\b'; | |
5916 // ControlEscape :: one of | |
5917 // f n r t v | |
5918 case 'f': | |
5919 Advance(); | |
5920 return '\f'; | |
5921 case 'n': | |
5922 Advance(); | |
5923 return '\n'; | |
5924 case 'r': | |
5925 Advance(); | |
5926 return '\r'; | |
5927 case 't': | |
5928 Advance(); | |
5929 return '\t'; | |
5930 case 'v': | |
5931 Advance(); | |
5932 return '\v'; | |
5933 case 'c': { | |
5934 uc32 controlLetter = Next(); | |
5935 uc32 letter = controlLetter & ~('A' ^ 'a'); | |
5936 // For compatibility with JSC, inside a character class | |
5937 // we also accept digits and underscore as control characters. | |
5938 if ((controlLetter >= '0' && controlLetter <= '9') || | |
5939 controlLetter == '_' || | |
5940 (letter >= 'A' && letter <= 'Z')) { | |
5941 Advance(2); | |
5942 // Control letters mapped to ASCII control characters in the range | |
5943 // 0x00-0x1f. | |
5944 return controlLetter & 0x1f; | |
5945 } | |
5946 // We match JSC in reading the backslash as a literal | |
5947 // character instead of as starting an escape. | |
5948 return '\\'; | |
5949 } | |
5950 case '0': case '1': case '2': case '3': case '4': case '5': | |
5951 case '6': case '7': | |
5952 // For compatibility, we interpret a decimal escape that isn't | |
5953 // a back reference (and therefore either \0 or not valid according | |
5954 // to the specification) as a 1..3 digit octal character code. | |
5955 return ParseOctalLiteral(); | |
5956 case 'x': { | |
5957 Advance(); | |
5958 uc32 value; | |
5959 if (ParseHexEscape(2, &value)) { | |
5960 return value; | |
5961 } | |
5962 if (!FLAG_harmony_unicode_regexps || !unicode_) { | |
5963 // If \x is not followed by a two-digit hexadecimal, treat it | |
5964 // as an identity escape. | |
5965 return 'x'; | |
5966 } | |
5967 // If the 'u' flag is present, invalid escapes are not treated as | |
5968 // identity escapes. | |
5969 ReportError(CStrVector("Invalid escape")); | |
5970 return 0; | |
5971 } | |
5972 case 'u': { | |
5973 Advance(); | |
5974 uc32 value; | |
5975 if (ParseUnicodeEscape(&value)) { | |
5976 return value; | |
5977 } | |
5978 if (!FLAG_harmony_unicode_regexps || !unicode_) { | |
5979 return 'u'; | |
5980 } | |
5981 // If the 'u' flag is present, invalid escapes are not treated as | |
5982 // identity escapes. | |
5983 ReportError(CStrVector("Invalid unicode escape")); | |
5984 return 0; | |
5985 } | |
5986 default: { | |
5987 uc32 result = current(); | |
5988 // If the 'u' flag is present, only syntax characters can be escaped, no | |
5989 // other identity escapes are allowed. If the 'u' flag is not present, all | |
5990 // identity escapes are allowed. | |
5991 if (!FLAG_harmony_unicode_regexps || !unicode_ || | |
5992 IsSyntaxCharacter(result)) { | |
5993 Advance(); | |
5994 return result; | |
5995 } | |
5996 ReportError(CStrVector("Invalid escape")); | |
5997 return 0; | |
5998 } | |
5999 } | |
6000 return 0; | |
6001 } | |
6002 | |
6003 | |
6004 CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) { | |
6005 DCHECK_EQ(0, *char_class); | |
6006 uc32 first = current(); | |
6007 if (first == '\\') { | |
6008 switch (Next()) { | |
6009 case 'w': case 'W': case 'd': case 'D': case 's': case 'S': { | |
6010 *char_class = Next(); | |
6011 Advance(2); | |
6012 return CharacterRange::Singleton(0); // Return dummy value. | |
6013 } | |
6014 case kEndMarker: | |
6015 return ReportError(CStrVector("\\ at end of pattern")); | |
6016 default: | |
6017 uc32 c = ParseClassCharacterEscape(CHECK_FAILED); | |
6018 return CharacterRange::Singleton(c); | |
6019 } | |
6020 } else { | |
6021 Advance(); | |
6022 return CharacterRange::Singleton(first); | |
6023 } | |
6024 } | |
6025 | |
6026 | |
6027 static const uc16 kNoCharClass = 0; | |
6028 | |
6029 // Adds range or pre-defined character class to character ranges. | |
6030 // If char_class is not kInvalidClass, it's interpreted as a class | |
6031 // escape (i.e., 's' means whitespace, from '\s'). | |
6032 static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges, | |
6033 uc16 char_class, | |
6034 CharacterRange range, | |
6035 Zone* zone) { | |
6036 if (char_class != kNoCharClass) { | |
6037 CharacterRange::AddClassEscape(char_class, ranges, zone); | |
6038 } else { | |
6039 ranges->Add(range, zone); | |
6040 } | |
6041 } | |
6042 | |
6043 | |
6044 RegExpTree* RegExpParser::ParseCharacterClass() { | |
6045 static const char* kUnterminated = "Unterminated character class"; | |
6046 static const char* kRangeOutOfOrder = "Range out of order in character class"; | |
6047 | |
6048 DCHECK_EQ(current(), '['); | |
6049 Advance(); | |
6050 bool is_negated = false; | |
6051 if (current() == '^') { | |
6052 is_negated = true; | |
6053 Advance(); | |
6054 } | |
6055 ZoneList<CharacterRange>* ranges = | |
6056 new(zone()) ZoneList<CharacterRange>(2, zone()); | |
6057 while (has_more() && current() != ']') { | |
6058 uc16 char_class = kNoCharClass; | |
6059 CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED); | |
6060 if (current() == '-') { | |
6061 Advance(); | |
6062 if (current() == kEndMarker) { | |
6063 // If we reach the end we break out of the loop and let the | |
6064 // following code report an error. | |
6065 break; | |
6066 } else if (current() == ']') { | |
6067 AddRangeOrEscape(ranges, char_class, first, zone()); | |
6068 ranges->Add(CharacterRange::Singleton('-'), zone()); | |
6069 break; | |
6070 } | |
6071 uc16 char_class_2 = kNoCharClass; | |
6072 CharacterRange next = ParseClassAtom(&char_class_2 CHECK_FAILED); | |
6073 if (char_class != kNoCharClass || char_class_2 != kNoCharClass) { | |
6074 // Either end is an escaped character class. Treat the '-' verbatim. | |
6075 AddRangeOrEscape(ranges, char_class, first, zone()); | |
6076 ranges->Add(CharacterRange::Singleton('-'), zone()); | |
6077 AddRangeOrEscape(ranges, char_class_2, next, zone()); | |
6078 continue; | |
6079 } | |
6080 if (first.from() > next.to()) { | |
6081 return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED); | |
6082 } | |
6083 ranges->Add(CharacterRange::Range(first.from(), next.to()), zone()); | |
6084 } else { | |
6085 AddRangeOrEscape(ranges, char_class, first, zone()); | |
6086 } | |
6087 } | |
6088 if (!has_more()) { | |
6089 return ReportError(CStrVector(kUnterminated) CHECK_FAILED); | |
6090 } | |
6091 Advance(); | |
6092 if (ranges->length() == 0) { | |
6093 ranges->Add(CharacterRange::Everything(), zone()); | |
6094 is_negated = !is_negated; | |
6095 } | |
6096 return new (zone()) RegExpCharacterClass(ranges, is_negated); | |
6097 } | |
6098 | |
6099 | |
6100 // ---------------------------------------------------------------------------- | |
6101 // The Parser interface. | |
6102 | |
6103 bool RegExpParser::ParseRegExp(Isolate* isolate, Zone* zone, | |
6104 FlatStringReader* input, bool multiline, | |
6105 bool unicode, RegExpCompileData* result) { | |
6106 DCHECK(result != NULL); | |
6107 RegExpParser parser(input, &result->error, multiline, unicode, isolate, zone); | |
6108 RegExpTree* tree = parser.ParsePattern(); | |
6109 if (parser.failed()) { | |
6110 DCHECK(tree == NULL); | |
6111 DCHECK(!result->error.is_null()); | |
6112 } else { | |
6113 DCHECK(tree != NULL); | |
6114 DCHECK(result->error.is_null()); | |
6115 result->tree = tree; | |
6116 int capture_count = parser.captures_started(); | |
6117 result->simple = tree->IsAtom() && parser.simple() && capture_count == 0; | |
6118 result->contains_anchor = parser.contains_anchor(); | |
6119 result->capture_count = capture_count; | |
6120 } | |
6121 return !parser.failed(); | |
6122 } | |
6123 | |
6124 | |
6125 bool Parser::ParseStatic(ParseInfo* info) { | |
6126 Parser parser(info); | |
6127 if (parser.Parse(info)) { | |
6128 info->set_language_mode(info->literal()->language_mode()); | |
6129 return true; | |
6130 } | |
6131 return false; | |
6132 } | |
6133 | |
6134 | |
6135 bool Parser::Parse(ParseInfo* info) { | |
6136 DCHECK(info->literal() == NULL); | |
6137 FunctionLiteral* result = NULL; | |
6138 // Ok to use Isolate here; this function is only called in the main thread. | |
6139 DCHECK(parsing_on_main_thread_); | |
6140 Isolate* isolate = info->isolate(); | |
6141 pre_parse_timer_ = isolate->counters()->pre_parse(); | |
6142 if (FLAG_trace_parse || allow_natives() || extension_ != NULL) { | |
6143 // If intrinsics are allowed, the Parser cannot operate independent of the | |
6144 // V8 heap because of Runtime. Tell the string table to internalize strings | |
6145 // and values right after they're created. | |
6146 ast_value_factory()->Internalize(isolate); | |
6147 } | |
6148 | |
6149 if (info->is_lazy()) { | |
6150 DCHECK(!info->is_eval()); | |
6151 if (info->shared_info()->is_function()) { | |
6152 result = ParseLazy(isolate, info); | |
6153 } else { | |
6154 result = ParseProgram(isolate, info); | |
6155 } | |
6156 } else { | |
6157 SetCachedData(info); | |
6158 result = ParseProgram(isolate, info); | |
6159 } | |
6160 info->set_literal(result); | |
6161 | |
6162 Internalize(isolate, info->script(), result == NULL); | |
6163 DCHECK(ast_value_factory()->IsInternalized()); | |
6164 return (result != NULL); | |
6165 } | |
6166 | |
6167 | |
6168 void Parser::ParseOnBackground(ParseInfo* info) { | |
6169 parsing_on_main_thread_ = false; | |
6170 | |
6171 DCHECK(info->literal() == NULL); | |
6172 FunctionLiteral* result = NULL; | |
6173 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone()); | |
6174 | |
6175 CompleteParserRecorder recorder; | |
6176 if (produce_cached_parse_data()) log_ = &recorder; | |
6177 | |
6178 DCHECK(info->source_stream() != NULL); | |
6179 ExternalStreamingStream stream(info->source_stream(), | |
6180 info->source_stream_encoding()); | |
6181 scanner_.Initialize(&stream); | |
6182 DCHECK(info->context().is_null() || info->context()->IsNativeContext()); | |
6183 | |
6184 // When streaming, we don't know the length of the source until we have parsed | |
6185 // it. The raw data can be UTF-8, so we wouldn't know the source length until | |
6186 // we have decoded it anyway even if we knew the raw data length (which we | |
6187 // don't). We work around this by storing all the scopes which need their end | |
6188 // position set at the end of the script (the top scope and possible eval | |
6189 // scopes) and set their end position after we know the script length. | |
6190 result = DoParseProgram(info); | |
6191 | |
6192 info->set_literal(result); | |
6193 | |
6194 // We cannot internalize on a background thread; a foreground task will take | |
6195 // care of calling Parser::Internalize just before compilation. | |
6196 | |
6197 if (produce_cached_parse_data()) { | |
6198 if (result != NULL) *info->cached_data() = recorder.GetScriptData(); | |
6199 log_ = NULL; | |
6200 } | |
6201 } | |
6202 | |
6203 | |
6204 ParserTraits::TemplateLiteralState Parser::OpenTemplateLiteral(int pos) { | |
6205 return new (zone()) ParserTraits::TemplateLiteral(zone(), pos); | |
6206 } | |
6207 | |
6208 | |
6209 void Parser::AddTemplateSpan(TemplateLiteralState* state, bool tail) { | |
6210 int pos = scanner()->location().beg_pos; | |
6211 int end = scanner()->location().end_pos - (tail ? 1 : 2); | |
6212 const AstRawString* tv = scanner()->CurrentSymbol(ast_value_factory()); | |
6213 const AstRawString* trv = scanner()->CurrentRawSymbol(ast_value_factory()); | |
6214 Literal* cooked = factory()->NewStringLiteral(tv, pos); | |
6215 Literal* raw = factory()->NewStringLiteral(trv, pos); | |
6216 (*state)->AddTemplateSpan(cooked, raw, end, zone()); | |
6217 } | |
6218 | |
6219 | |
6220 void Parser::AddTemplateExpression(TemplateLiteralState* state, | |
6221 Expression* expression) { | |
6222 (*state)->AddExpression(expression, zone()); | |
6223 } | |
6224 | |
6225 | |
6226 Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start, | |
6227 Expression* tag) { | |
6228 TemplateLiteral* lit = *state; | |
6229 int pos = lit->position(); | |
6230 const ZoneList<Expression*>* cooked_strings = lit->cooked(); | |
6231 const ZoneList<Expression*>* raw_strings = lit->raw(); | |
6232 const ZoneList<Expression*>* expressions = lit->expressions(); | |
6233 DCHECK_EQ(cooked_strings->length(), raw_strings->length()); | |
6234 DCHECK_EQ(cooked_strings->length(), expressions->length() + 1); | |
6235 | |
6236 if (!tag) { | |
6237 // Build tree of BinaryOps to simplify code-generation | |
6238 Expression* expr = cooked_strings->at(0); | |
6239 int i = 0; | |
6240 while (i < expressions->length()) { | |
6241 Expression* sub = expressions->at(i++); | |
6242 Expression* cooked_str = cooked_strings->at(i); | |
6243 | |
6244 // Let middle be ToString(sub). | |
6245 ZoneList<Expression*>* args = | |
6246 new (zone()) ZoneList<Expression*>(1, zone()); | |
6247 args->Add(sub, zone()); | |
6248 Expression* middle = factory()->NewCallRuntime(Runtime::kInlineToString, | |
6249 args, sub->position()); | |
6250 | |
6251 expr = factory()->NewBinaryOperation( | |
6252 Token::ADD, factory()->NewBinaryOperation( | |
6253 Token::ADD, expr, middle, expr->position()), | |
6254 cooked_str, sub->position()); | |
6255 } | |
6256 return expr; | |
6257 } else { | |
6258 uint32_t hash = ComputeTemplateLiteralHash(lit); | |
6259 | |
6260 int cooked_idx = function_state_->NextMaterializedLiteralIndex(); | |
6261 int raw_idx = function_state_->NextMaterializedLiteralIndex(); | |
6262 | |
6263 // $getTemplateCallSite | |
6264 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(4, zone()); | |
6265 args->Add(factory()->NewArrayLiteral( | |
6266 const_cast<ZoneList<Expression*>*>(cooked_strings), | |
6267 cooked_idx, is_strong(language_mode()), pos), | |
6268 zone()); | |
6269 args->Add( | |
6270 factory()->NewArrayLiteral( | |
6271 const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx, | |
6272 is_strong(language_mode()), pos), | |
6273 zone()); | |
6274 | |
6275 // Ensure hash is suitable as a Smi value | |
6276 Smi* hash_obj = Smi::cast(Internals::IntToSmi(static_cast<int>(hash))); | |
6277 args->Add(factory()->NewSmiLiteral(hash_obj->value(), pos), zone()); | |
6278 | |
6279 this->CheckPossibleEvalCall(tag, scope_); | |
6280 Expression* call_site = factory()->NewCallRuntime( | |
6281 Context::GET_TEMPLATE_CALL_SITE_INDEX, args, start); | |
6282 | |
6283 // Call TagFn | |
6284 ZoneList<Expression*>* call_args = | |
6285 new (zone()) ZoneList<Expression*>(expressions->length() + 1, zone()); | |
6286 call_args->Add(call_site, zone()); | |
6287 call_args->AddAll(*expressions, zone()); | |
6288 return factory()->NewCall(tag, call_args, pos); | |
6289 } | |
6290 } | |
6291 | |
6292 | |
6293 uint32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) { | |
6294 const ZoneList<Expression*>* raw_strings = lit->raw(); | |
6295 int total = raw_strings->length(); | |
6296 DCHECK(total); | |
6297 | |
6298 uint32_t running_hash = 0; | |
6299 | |
6300 for (int index = 0; index < total; ++index) { | |
6301 if (index) { | |
6302 running_hash = StringHasher::ComputeRunningHashOneByte( | |
6303 running_hash, "${}", 3); | |
6304 } | |
6305 | |
6306 const AstRawString* raw_string = | |
6307 raw_strings->at(index)->AsLiteral()->raw_value()->AsString(); | |
6308 if (raw_string->is_one_byte()) { | |
6309 const char* data = reinterpret_cast<const char*>(raw_string->raw_data()); | |
6310 running_hash = StringHasher::ComputeRunningHashOneByte( | |
6311 running_hash, data, raw_string->length()); | |
6312 } else { | |
6313 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); | |
6314 running_hash = StringHasher::ComputeRunningHash(running_hash, data, | |
6315 raw_string->length()); | |
6316 } | |
6317 } | |
6318 | |
6319 return running_hash; | |
6320 } | |
6321 | |
6322 | |
6323 ZoneList<v8::internal::Expression*>* Parser::PrepareSpreadArguments( | |
6324 ZoneList<v8::internal::Expression*>* list) { | |
6325 ZoneList<v8::internal::Expression*>* args = | |
6326 new (zone()) ZoneList<v8::internal::Expression*>(1, zone()); | |
6327 if (list->length() == 1) { | |
6328 // Spread-call with single spread argument produces an InternalArray | |
6329 // containing the values from the array. | |
6330 // | |
6331 // Function is called or constructed with the produced array of arguments | |
6332 // | |
6333 // EG: Apply(Func, Spread(spread0)) | |
6334 ZoneList<Expression*>* spread_list = | |
6335 new (zone()) ZoneList<Expression*>(0, zone()); | |
6336 spread_list->Add(list->at(0)->AsSpread()->expression(), zone()); | |
6337 args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX, | |
6338 spread_list, RelocInfo::kNoPosition), | |
6339 zone()); | |
6340 return args; | |
6341 } else { | |
6342 // Spread-call with multiple arguments produces array literals for each | |
6343 // sequences of unspread arguments, and converts each spread iterable to | |
6344 // an Internal array. Finally, all of these produced arrays are flattened | |
6345 // into a single InternalArray, containing the arguments for the call. | |
6346 // | |
6347 // EG: Apply(Func, Flatten([unspread0, unspread1], Spread(spread0), | |
6348 // Spread(spread1), [unspread2, unspread3])) | |
6349 int i = 0; | |
6350 int n = list->length(); | |
6351 while (i < n) { | |
6352 if (!list->at(i)->IsSpread()) { | |
6353 ZoneList<v8::internal::Expression*>* unspread = | |
6354 new (zone()) ZoneList<v8::internal::Expression*>(1, zone()); | |
6355 | |
6356 // Push array of unspread parameters | |
6357 while (i < n && !list->at(i)->IsSpread()) { | |
6358 unspread->Add(list->at(i++), zone()); | |
6359 } | |
6360 int literal_index = function_state_->NextMaterializedLiteralIndex(); | |
6361 args->Add(factory()->NewArrayLiteral(unspread, literal_index, | |
6362 is_strong(language_mode()), | |
6363 RelocInfo::kNoPosition), | |
6364 zone()); | |
6365 | |
6366 if (i == n) break; | |
6367 } | |
6368 | |
6369 // Push eagerly spread argument | |
6370 ZoneList<v8::internal::Expression*>* spread_list = | |
6371 new (zone()) ZoneList<v8::internal::Expression*>(1, zone()); | |
6372 spread_list->Add(list->at(i++)->AsSpread()->expression(), zone()); | |
6373 args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX, | |
6374 spread_list, RelocInfo::kNoPosition), | |
6375 zone()); | |
6376 } | |
6377 | |
6378 list = new (zone()) ZoneList<v8::internal::Expression*>(1, zone()); | |
6379 list->Add(factory()->NewCallRuntime(Context::SPREAD_ARGUMENTS_INDEX, args, | |
6380 RelocInfo::kNoPosition), | |
6381 zone()); | |
6382 return list; | |
6383 } | |
6384 UNREACHABLE(); | |
6385 } | |
6386 | |
6387 | |
6388 Expression* Parser::SpreadCall(Expression* function, | |
6389 ZoneList<v8::internal::Expression*>* args, | |
6390 int pos) { | |
6391 if (function->IsSuperCallReference()) { | |
6392 // Super calls | |
6393 // %reflect_construct(%GetPrototype(<this-function>), args, new.target)) | |
6394 ZoneList<Expression*>* tmp = new (zone()) ZoneList<Expression*>(1, zone()); | |
6395 tmp->Add(function->AsSuperCallReference()->this_function_var(), zone()); | |
6396 Expression* get_prototype = | |
6397 factory()->NewCallRuntime(Runtime::kGetPrototype, tmp, pos); | |
6398 args->InsertAt(0, get_prototype, zone()); | |
6399 args->Add(function->AsSuperCallReference()->new_target_var(), zone()); | |
6400 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, | |
6401 pos); | |
6402 } else { | |
6403 if (function->IsProperty()) { | |
6404 // Method calls | |
6405 if (function->AsProperty()->IsSuperAccess()) { | |
6406 Expression* home = | |
6407 ThisExpression(scope_, factory(), RelocInfo::kNoPosition); | |
6408 args->InsertAt(0, function, zone()); | |
6409 args->InsertAt(1, home, zone()); | |
6410 } else { | |
6411 Variable* temp = | |
6412 scope_->NewTemporary(ast_value_factory()->empty_string()); | |
6413 VariableProxy* obj = factory()->NewVariableProxy(temp); | |
6414 Assignment* assign_obj = factory()->NewAssignment( | |
6415 Token::ASSIGN, obj, function->AsProperty()->obj(), | |
6416 RelocInfo::kNoPosition); | |
6417 function = factory()->NewProperty( | |
6418 assign_obj, function->AsProperty()->key(), RelocInfo::kNoPosition); | |
6419 args->InsertAt(0, function, zone()); | |
6420 obj = factory()->NewVariableProxy(temp); | |
6421 args->InsertAt(1, obj, zone()); | |
6422 } | |
6423 } else { | |
6424 // Non-method calls | |
6425 args->InsertAt(0, function, zone()); | |
6426 args->InsertAt(1, factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), | |
6427 zone()); | |
6428 } | |
6429 return factory()->NewCallRuntime(Context::REFLECT_APPLY_INDEX, args, pos); | |
6430 } | |
6431 } | |
6432 | |
6433 | |
6434 Expression* Parser::SpreadCallNew(Expression* function, | |
6435 ZoneList<v8::internal::Expression*>* args, | |
6436 int pos) { | |
6437 args->InsertAt(0, function, zone()); | |
6438 | |
6439 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos); | |
6440 } | |
6441 | |
6442 | |
6443 void Parser::SetLanguageMode(Scope* scope, LanguageMode mode) { | |
6444 v8::Isolate::UseCounterFeature feature; | |
6445 if (is_sloppy(mode)) | |
6446 feature = v8::Isolate::kSloppyMode; | |
6447 else if (is_strong(mode)) | |
6448 feature = v8::Isolate::kStrongMode; | |
6449 else if (is_strict(mode)) | |
6450 feature = v8::Isolate::kStrictMode; | |
6451 else | |
6452 UNREACHABLE(); | |
6453 ++use_counts_[feature]; | |
6454 scope->SetLanguageMode(mode); | |
6455 } | |
6456 | |
6457 | |
6458 void Parser::RaiseLanguageMode(LanguageMode mode) { | |
6459 SetLanguageMode(scope_, | |
6460 static_cast<LanguageMode>(scope_->language_mode() | mode)); | |
6461 } | |
6462 | |
6463 } // namespace internal | |
6464 } // namespace v8 | |
OLD | NEW |