OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/parsing/parser.h" | 5 #include "src/parsing/parser.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
9 #include "src/ast/ast-literal-reindexer.h" | 9 #include "src/ast/ast-literal-reindexer.h" |
10 #include "src/ast/scopeinfo.h" | 10 #include "src/ast/scopeinfo.h" |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 } | 94 } |
95 | 95 |
96 | 96 |
97 RegExpBuilder::RegExpBuilder(Zone* zone) | 97 RegExpBuilder::RegExpBuilder(Zone* zone) |
98 : zone_(zone), | 98 : zone_(zone), |
99 pending_empty_(false), | 99 pending_empty_(false), |
100 characters_(NULL), | 100 characters_(NULL), |
101 terms_(), | 101 terms_(), |
102 alternatives_() | 102 alternatives_() |
103 #ifdef DEBUG | 103 #ifdef DEBUG |
104 , last_added_(ADD_NONE) | 104 , |
| 105 last_added_(ADD_NONE) |
105 #endif | 106 #endif |
106 {} | 107 { |
| 108 } |
107 | 109 |
108 | 110 |
109 void RegExpBuilder::FlushCharacters() { | 111 void RegExpBuilder::FlushCharacters() { |
110 pending_empty_ = false; | 112 pending_empty_ = false; |
111 if (characters_ != NULL) { | 113 if (characters_ != NULL) { |
112 RegExpTree* atom = new(zone()) RegExpAtom(characters_->ToConstVector()); | 114 RegExpTree* atom = new (zone()) RegExpAtom(characters_->ToConstVector()); |
113 characters_ = NULL; | 115 characters_ = NULL; |
114 text_.Add(atom, zone()); | 116 text_.Add(atom, zone()); |
115 LAST(ADD_ATOM); | 117 LAST(ADD_ATOM); |
116 } | 118 } |
117 } | 119 } |
118 | 120 |
119 | 121 |
120 void RegExpBuilder::FlushText() { | 122 void RegExpBuilder::FlushText() { |
121 FlushCharacters(); | 123 FlushCharacters(); |
122 int num_text = text_.length(); | 124 int num_text = text_.length(); |
123 if (num_text == 0) { | 125 if (num_text == 0) { |
124 return; | 126 return; |
125 } else if (num_text == 1) { | 127 } else if (num_text == 1) { |
126 terms_.Add(text_.last(), zone()); | 128 terms_.Add(text_.last(), zone()); |
127 } else { | 129 } else { |
128 RegExpText* text = new(zone()) RegExpText(zone()); | 130 RegExpText* text = new (zone()) RegExpText(zone()); |
129 for (int i = 0; i < num_text; i++) | 131 for (int i = 0; i < num_text; i++) text_.Get(i)->AppendToText(text, zone()); |
130 text_.Get(i)->AppendToText(text, zone()); | |
131 terms_.Add(text, zone()); | 132 terms_.Add(text, zone()); |
132 } | 133 } |
133 text_.Clear(); | 134 text_.Clear(); |
134 } | 135 } |
135 | 136 |
136 | 137 |
137 void RegExpBuilder::AddCharacter(uc16 c) { | 138 void RegExpBuilder::AddCharacter(uc16 c) { |
138 pending_empty_ = false; | 139 pending_empty_ = false; |
139 if (characters_ == NULL) { | 140 if (characters_ == NULL) { |
140 characters_ = new(zone()) ZoneList<uc16>(4, zone()); | 141 characters_ = new (zone()) ZoneList<uc16>(4, zone()); |
141 } | 142 } |
142 characters_->Add(c, zone()); | 143 characters_->Add(c, zone()); |
143 LAST(ADD_CHAR); | 144 LAST(ADD_CHAR); |
144 } | 145 } |
145 | 146 |
146 | 147 |
147 void RegExpBuilder::AddEmpty() { | 148 void RegExpBuilder::AddEmpty() { pending_empty_ = true; } |
148 pending_empty_ = true; | |
149 } | |
150 | 149 |
151 | 150 |
152 void RegExpBuilder::AddAtom(RegExpTree* term) { | 151 void RegExpBuilder::AddAtom(RegExpTree* term) { |
153 if (term->IsEmpty()) { | 152 if (term->IsEmpty()) { |
154 AddEmpty(); | 153 AddEmpty(); |
155 return; | 154 return; |
156 } | 155 } |
157 if (term->IsTextElement()) { | 156 if (term->IsTextElement()) { |
158 FlushCharacters(); | 157 FlushCharacters(); |
159 text_.Add(term, zone()); | 158 text_.Add(term, zone()); |
160 } else { | 159 } else { |
161 FlushText(); | 160 FlushText(); |
162 terms_.Add(term, zone()); | 161 terms_.Add(term, zone()); |
163 } | 162 } |
164 LAST(ADD_ATOM); | 163 LAST(ADD_ATOM); |
165 } | 164 } |
166 | 165 |
167 | 166 |
168 void RegExpBuilder::AddAssertion(RegExpTree* assert) { | 167 void RegExpBuilder::AddAssertion(RegExpTree* assert) { |
169 FlushText(); | 168 FlushText(); |
170 terms_.Add(assert, zone()); | 169 terms_.Add(assert, zone()); |
171 LAST(ADD_ASSERT); | 170 LAST(ADD_ASSERT); |
172 } | 171 } |
173 | 172 |
174 | 173 |
175 void RegExpBuilder::NewAlternative() { | 174 void RegExpBuilder::NewAlternative() { FlushTerms(); } |
176 FlushTerms(); | |
177 } | |
178 | 175 |
179 | 176 |
180 void RegExpBuilder::FlushTerms() { | 177 void RegExpBuilder::FlushTerms() { |
181 FlushText(); | 178 FlushText(); |
182 int num_terms = terms_.length(); | 179 int num_terms = terms_.length(); |
183 RegExpTree* alternative; | 180 RegExpTree* alternative; |
184 if (num_terms == 0) { | 181 if (num_terms == 0) { |
185 alternative = new (zone()) RegExpEmpty(); | 182 alternative = new (zone()) RegExpEmpty(); |
186 } else if (num_terms == 1) { | 183 } else if (num_terms == 1) { |
187 alternative = terms_.last(); | 184 alternative = terms_.last(); |
188 } else { | 185 } else { |
189 alternative = new(zone()) RegExpAlternative(terms_.GetList(zone())); | 186 alternative = new (zone()) RegExpAlternative(terms_.GetList(zone())); |
190 } | 187 } |
191 alternatives_.Add(alternative, zone()); | 188 alternatives_.Add(alternative, zone()); |
192 terms_.Clear(); | 189 terms_.Clear(); |
193 LAST(ADD_NONE); | 190 LAST(ADD_NONE); |
194 } | 191 } |
195 | 192 |
196 | 193 |
197 RegExpTree* RegExpBuilder::ToRegExp() { | 194 RegExpTree* RegExpBuilder::ToRegExp() { |
198 FlushTerms(); | 195 FlushTerms(); |
199 int num_alternatives = alternatives_.length(); | 196 int num_alternatives = alternatives_.length(); |
200 if (num_alternatives == 0) return new (zone()) RegExpEmpty(); | 197 if (num_alternatives == 0) return new (zone()) RegExpEmpty(); |
201 if (num_alternatives == 1) return alternatives_.last(); | 198 if (num_alternatives == 1) return alternatives_.last(); |
202 return new(zone()) RegExpDisjunction(alternatives_.GetList(zone())); | 199 return new (zone()) RegExpDisjunction(alternatives_.GetList(zone())); |
203 } | 200 } |
204 | 201 |
205 | 202 |
206 void RegExpBuilder::AddQuantifierToAtom( | 203 void RegExpBuilder::AddQuantifierToAtom( |
207 int min, int max, RegExpQuantifier::QuantifierType quantifier_type) { | 204 int min, int max, RegExpQuantifier::QuantifierType quantifier_type) { |
208 if (pending_empty_) { | 205 if (pending_empty_) { |
209 pending_empty_ = false; | 206 pending_empty_ = false; |
210 return; | 207 return; |
211 } | 208 } |
212 RegExpTree* atom; | 209 RegExpTree* atom; |
213 if (characters_ != NULL) { | 210 if (characters_ != NULL) { |
214 DCHECK(last_added_ == ADD_CHAR); | 211 DCHECK(last_added_ == ADD_CHAR); |
215 // Last atom was character. | 212 // Last atom was character. |
216 Vector<const uc16> char_vector = characters_->ToConstVector(); | 213 Vector<const uc16> char_vector = characters_->ToConstVector(); |
217 int num_chars = char_vector.length(); | 214 int num_chars = char_vector.length(); |
218 if (num_chars > 1) { | 215 if (num_chars > 1) { |
219 Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1); | 216 Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1); |
220 text_.Add(new(zone()) RegExpAtom(prefix), zone()); | 217 text_.Add(new (zone()) RegExpAtom(prefix), zone()); |
221 char_vector = char_vector.SubVector(num_chars - 1, num_chars); | 218 char_vector = char_vector.SubVector(num_chars - 1, num_chars); |
222 } | 219 } |
223 characters_ = NULL; | 220 characters_ = NULL; |
224 atom = new(zone()) RegExpAtom(char_vector); | 221 atom = new (zone()) RegExpAtom(char_vector); |
225 FlushText(); | 222 FlushText(); |
226 } else if (text_.length() > 0) { | 223 } else if (text_.length() > 0) { |
227 DCHECK(last_added_ == ADD_ATOM); | 224 DCHECK(last_added_ == ADD_ATOM); |
228 atom = text_.RemoveLast(); | 225 atom = text_.RemoveLast(); |
229 FlushText(); | 226 FlushText(); |
230 } else if (terms_.length() > 0) { | 227 } else if (terms_.length() > 0) { |
231 DCHECK(last_added_ == ADD_ATOM); | 228 DCHECK(last_added_ == ADD_ATOM); |
232 atom = terms_.RemoveLast(); | 229 atom = terms_.RemoveLast(); |
233 if (atom->max_match() == 0) { | 230 if (atom->max_match() == 0) { |
234 // Guaranteed to only match an empty string. | 231 // Guaranteed to only match an empty string. |
235 LAST(ADD_TERM); | 232 LAST(ADD_TERM); |
236 if (min == 0) { | 233 if (min == 0) { |
237 return; | 234 return; |
238 } | 235 } |
239 terms_.Add(atom, zone()); | 236 terms_.Add(atom, zone()); |
240 return; | 237 return; |
241 } | 238 } |
242 } else { | 239 } else { |
243 // Only call immediately after adding an atom or character! | 240 // Only call immediately after adding an atom or character! |
244 UNREACHABLE(); | 241 UNREACHABLE(); |
245 return; | 242 return; |
246 } | 243 } |
247 terms_.Add( | 244 terms_.Add(new (zone()) RegExpQuantifier(min, max, quantifier_type, atom), |
248 new(zone()) RegExpQuantifier(min, max, quantifier_type, atom), zone()); | 245 zone()); |
249 LAST(ADD_TERM); | 246 LAST(ADD_TERM); |
250 } | 247 } |
251 | 248 |
252 | 249 |
253 FunctionEntry ParseData::GetFunctionEntry(int start) { | 250 FunctionEntry ParseData::GetFunctionEntry(int start) { |
254 // The current pre-data entry must be a FunctionEntry with the given | 251 // The current pre-data entry must be a FunctionEntry with the given |
255 // start position. | 252 // start position. |
256 if ((function_index_ + FunctionEntry::kSize <= Length()) && | 253 if ((function_index_ + FunctionEntry::kSize <= Length()) && |
257 (static_cast<int>(Data()[function_index_]) == start)) { | 254 (static_cast<int>(Data()[function_index_]) == start)) { |
258 int index = function_index_; | 255 int index = function_index_; |
(...skipping 20 matching lines...) Expand all Loading... |
279 int data_length = Length(); | 276 int data_length = Length(); |
280 if (data_length < PreparseDataConstants::kHeaderSize) return false; | 277 if (data_length < PreparseDataConstants::kHeaderSize) return false; |
281 if (Magic() != PreparseDataConstants::kMagicNumber) return false; | 278 if (Magic() != PreparseDataConstants::kMagicNumber) return false; |
282 if (Version() != PreparseDataConstants::kCurrentVersion) return false; | 279 if (Version() != PreparseDataConstants::kCurrentVersion) return false; |
283 if (HasError()) return false; | 280 if (HasError()) return false; |
284 // Check that the space allocated for function entries is sane. | 281 // Check that the space allocated for function entries is sane. |
285 int functions_size = FunctionsSize(); | 282 int functions_size = FunctionsSize(); |
286 if (functions_size < 0) return false; | 283 if (functions_size < 0) return false; |
287 if (functions_size % FunctionEntry::kSize != 0) return false; | 284 if (functions_size % FunctionEntry::kSize != 0) return false; |
288 // Check that the total size has room for header and function entries. | 285 // Check that the total size has room for header and function entries. |
289 int minimum_size = | 286 int minimum_size = PreparseDataConstants::kHeaderSize + functions_size; |
290 PreparseDataConstants::kHeaderSize + functions_size; | |
291 if (data_length < minimum_size) return false; | 287 if (data_length < minimum_size) return false; |
292 return true; | 288 return true; |
293 } | 289 } |
294 | 290 |
295 | 291 |
296 void ParseData::Initialize() { | 292 void ParseData::Initialize() { |
297 // Prepares state for use. | 293 // Prepares state for use. |
298 int data_length = Length(); | 294 int data_length = Length(); |
299 if (data_length >= PreparseDataConstants::kHeaderSize) { | 295 if (data_length >= PreparseDataConstants::kHeaderSize) { |
300 function_index_ = PreparseDataConstants::kHeaderSize; | 296 function_index_ = PreparseDataConstants::kHeaderSize; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 // 'continue' statement targets). Upon construction, a new target is | 398 // 'continue' statement targets). Upon construction, a new target is |
403 // added; it is removed upon destruction. | 399 // added; it is removed upon destruction. |
404 | 400 |
405 class Target BASE_EMBEDDED { | 401 class Target BASE_EMBEDDED { |
406 public: | 402 public: |
407 Target(Target** variable, BreakableStatement* statement) | 403 Target(Target** variable, BreakableStatement* statement) |
408 : variable_(variable), statement_(statement), previous_(*variable) { | 404 : variable_(variable), statement_(statement), previous_(*variable) { |
409 *variable = this; | 405 *variable = this; |
410 } | 406 } |
411 | 407 |
412 ~Target() { | 408 ~Target() { *variable_ = previous_; } |
413 *variable_ = previous_; | |
414 } | |
415 | 409 |
416 Target* previous() { return previous_; } | 410 Target* previous() { return previous_; } |
417 BreakableStatement* statement() { return statement_; } | 411 BreakableStatement* statement() { return statement_; } |
418 | 412 |
419 private: | 413 private: |
420 Target** variable_; | 414 Target** variable_; |
421 BreakableStatement* statement_; | 415 BreakableStatement* statement_; |
422 Target* previous_; | 416 Target* previous_; |
423 }; | 417 }; |
424 | 418 |
425 | 419 |
426 class TargetScope BASE_EMBEDDED { | 420 class TargetScope BASE_EMBEDDED { |
427 public: | 421 public: |
428 explicit TargetScope(Target** variable) | 422 explicit TargetScope(Target** variable) |
429 : variable_(variable), previous_(*variable) { | 423 : variable_(variable), previous_(*variable) { |
430 *variable = NULL; | 424 *variable = NULL; |
431 } | 425 } |
432 | 426 |
433 ~TargetScope() { | 427 ~TargetScope() { *variable_ = previous_; } |
434 *variable_ = previous_; | |
435 } | |
436 | 428 |
437 private: | 429 private: |
438 Target** variable_; | 430 Target** variable_; |
439 Target* previous_; | 431 Target* previous_; |
440 }; | 432 }; |
441 | 433 |
442 | 434 |
443 // ---------------------------------------------------------------------------- | 435 // ---------------------------------------------------------------------------- |
444 // The CHECK_OK macro is a convenient macro to enforce error | 436 // The CHECK_OK macro is a convenient macro to enforce error |
445 // handling for functions that may fail (by returning !*ok). | 437 // handling for functions that may fail (by returning !*ok). |
446 // | 438 // |
447 // CAUTION: This macro appends extra statements after a call, | 439 // CAUTION: This macro appends extra statements after a call, |
448 // thus it must never be used where only a single statement | 440 // thus it must never be used where only a single statement |
449 // is correct (e.g. an if statement branch w/o braces)! | 441 // is correct (e.g. an if statement branch w/o braces)! |
450 | 442 |
451 #define CHECK_OK ok); \ | 443 #define CHECK_OK ok); \ |
452 if (!*ok) return NULL; \ | 444 if (!*ok) return NULL; \ |
453 ((void)0 | 445 ((void)0 |
454 #define DUMMY ) // to make indentation work | 446 #define DUMMY ) // to make indentation work |
455 #undef DUMMY | 447 #undef DUMMY |
456 | 448 |
457 #define CHECK_FAILED /**/); \ | 449 #define CHECK_FAILED /**/); \ |
458 if (failed_) return NULL; \ | 450 if (failed_) return NULL; \ |
459 ((void)0 | 451 ((void)0 |
460 #define DUMMY ) // to make indentation work | 452 #define DUMMY ) // to make indentation work |
461 #undef DUMMY | 453 #undef DUMMY |
462 | 454 |
463 // ---------------------------------------------------------------------------- | 455 // ---------------------------------------------------------------------------- |
464 // Implementation of Parser | 456 // Implementation of Parser |
465 | 457 |
466 bool ParserTraits::IsEval(const AstRawString* identifier) const { | 458 bool ParserTraits::IsEval(const AstRawString* identifier) const { |
467 return identifier == parser_->ast_value_factory()->eval_string(); | 459 return identifier == parser_->ast_value_factory()->eval_string(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 | 510 |
519 void ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left, | 511 void ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left, |
520 Expression* right) { | 512 Expression* right) { |
521 DCHECK(left != NULL); | 513 DCHECK(left != NULL); |
522 if (left->IsProperty() && right->IsFunctionLiteral()) { | 514 if (left->IsProperty() && right->IsFunctionLiteral()) { |
523 right->AsFunctionLiteral()->set_pretenure(); | 515 right->AsFunctionLiteral()->set_pretenure(); |
524 } | 516 } |
525 } | 517 } |
526 | 518 |
527 | 519 |
528 void ParserTraits::CheckPossibleEvalCall(Expression* expression, | 520 void ParserTraits::CheckPossibleEvalCall(Expression* expression, Scope* scope) { |
529 Scope* scope) { | |
530 VariableProxy* callee = expression->AsVariableProxy(); | 521 VariableProxy* callee = expression->AsVariableProxy(); |
531 if (callee != NULL && | 522 if (callee != NULL && |
532 callee->raw_name() == parser_->ast_value_factory()->eval_string()) { | 523 callee->raw_name() == parser_->ast_value_factory()->eval_string()) { |
533 scope->DeclarationScope()->RecordEvalCall(); | 524 scope->DeclarationScope()->RecordEvalCall(); |
534 scope->RecordEvalCall(); | 525 scope->RecordEvalCall(); |
535 } | 526 } |
536 } | 527 } |
537 | 528 |
538 | 529 |
539 Expression* ParserTraits::MarkExpressionAsAssigned(Expression* expression) { | 530 Expression* ParserTraits::MarkExpressionAsAssigned(Expression* expression) { |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
629 } | 620 } |
630 } | 621 } |
631 } | 622 } |
632 // Desugar '+foo' => 'foo*1' | 623 // Desugar '+foo' => 'foo*1' |
633 if (op == Token::ADD) { | 624 if (op == Token::ADD) { |
634 return factory->NewBinaryOperation( | 625 return factory->NewBinaryOperation( |
635 Token::MUL, expression, factory->NewNumberLiteral(1, pos, true), pos); | 626 Token::MUL, expression, factory->NewNumberLiteral(1, pos, true), pos); |
636 } | 627 } |
637 // The same idea for '-foo' => 'foo*(-1)'. | 628 // The same idea for '-foo' => 'foo*(-1)'. |
638 if (op == Token::SUB) { | 629 if (op == Token::SUB) { |
639 return factory->NewBinaryOperation( | 630 return factory->NewBinaryOperation(Token::MUL, expression, |
640 Token::MUL, expression, factory->NewNumberLiteral(-1, pos), pos); | 631 factory->NewNumberLiteral(-1, pos), pos); |
641 } | 632 } |
642 // ...and one more time for '~foo' => 'foo^(~0)'. | 633 // ...and one more time for '~foo' => 'foo^(~0)'. |
643 if (op == Token::BIT_NOT) { | 634 if (op == Token::BIT_NOT) { |
644 return factory->NewBinaryOperation( | 635 return factory->NewBinaryOperation(Token::BIT_XOR, expression, |
645 Token::BIT_XOR, expression, factory->NewNumberLiteral(~0, pos), pos); | 636 factory->NewNumberLiteral(~0, pos), pos); |
646 } | 637 } |
647 return factory->NewUnaryOperation(op, expression, pos); | 638 return factory->NewUnaryOperation(op, expression, pos); |
648 } | 639 } |
649 | 640 |
650 | 641 |
651 Expression* ParserTraits::NewThrowReferenceError( | 642 Expression* ParserTraits::NewThrowReferenceError( |
652 MessageTemplate::Template message, int pos) { | 643 MessageTemplate::Template message, int pos) { |
653 return NewThrowError(Runtime::kNewReferenceError, message, | 644 return NewThrowError(Runtime::kNewReferenceError, message, |
654 parser_->ast_value_factory()->empty_string(), pos); | 645 parser_->ast_value_factory()->empty_string(), pos); |
655 } | 646 } |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1044 | 1035 |
1045 // Enter 'scope' with the given parsing mode. | 1036 // Enter 'scope' with the given parsing mode. |
1046 ParsingModeScope parsing_mode_scope(this, parsing_mode); | 1037 ParsingModeScope parsing_mode_scope(this, parsing_mode); |
1047 AstNodeFactory function_factory(ast_value_factory()); | 1038 AstNodeFactory function_factory(ast_value_factory()); |
1048 FunctionState function_state(&function_state_, &scope_, scope, | 1039 FunctionState function_state(&function_state_, &scope_, scope, |
1049 kNormalFunction, &function_factory); | 1040 kNormalFunction, &function_factory); |
1050 | 1041 |
1051 // Don't count the mode in the use counters--give the program a chance | 1042 // Don't count the mode in the use counters--give the program a chance |
1052 // to enable script/module-wide strict/strong mode below. | 1043 // to enable script/module-wide strict/strong mode below. |
1053 scope_->SetLanguageMode(info->language_mode()); | 1044 scope_->SetLanguageMode(info->language_mode()); |
1054 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); | 1045 ZoneList<Statement*>* body = new (zone()) ZoneList<Statement*>(16, zone()); |
1055 bool ok = true; | 1046 bool ok = true; |
1056 int beg_pos = scanner()->location().beg_pos; | 1047 int beg_pos = scanner()->location().beg_pos; |
1057 if (info->is_module()) { | 1048 if (info->is_module()) { |
1058 ParseModuleItemList(body, &ok); | 1049 ParseModuleItemList(body, &ok); |
1059 } else { | 1050 } else { |
1060 ParseStatementList(body, Token::EOS, &ok); | 1051 ParseStatementList(body, Token::EOS, &ok); |
1061 } | 1052 } |
1062 | 1053 |
1063 // The parser will peek but not consume EOS. Our scope logically goes all | 1054 // The parser will peek but not consume EOS. Our scope logically goes all |
1064 // the way to the EOS, though. | 1055 // the way to the EOS, though. |
1065 scope->set_end_position(scanner()->peek_location().beg_pos); | 1056 scope->set_end_position(scanner()->peek_location().beg_pos); |
1066 | 1057 |
1067 if (ok && is_strict(language_mode())) { | 1058 if (ok && is_strict(language_mode())) { |
1068 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); | 1059 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); |
1069 } | 1060 } |
1070 if (ok && is_sloppy(language_mode()) && allow_harmony_sloppy_function()) { | 1061 if (ok && is_sloppy(language_mode()) && allow_harmony_sloppy_function()) { |
1071 // TODO(littledan): Function bindings on the global object that modify | 1062 // TODO(littledan): Function bindings on the global object that modify |
1072 // pre-existing bindings should be made writable, enumerable and | 1063 // pre-existing bindings should be made writable, enumerable and |
1073 // nonconfigurable if possible, whereas this code will leave attributes | 1064 // nonconfigurable if possible, whereas this code will leave attributes |
1074 // unchanged if the property already exists. | 1065 // unchanged if the property already exists. |
1075 InsertSloppyBlockFunctionVarBindings(scope, &ok); | 1066 InsertSloppyBlockFunctionVarBindings(scope, &ok); |
1076 } | 1067 } |
1077 if (ok && (is_strict(language_mode()) || allow_harmony_sloppy() || | 1068 if (ok && (is_strict(language_mode()) || allow_harmony_sloppy() || |
1078 allow_harmony_destructuring_bind())) { | 1069 allow_harmony_destructuring_bind())) { |
1079 CheckConflictingVarDeclarations(scope_, &ok); | 1070 CheckConflictingVarDeclarations(scope_, &ok); |
1080 } | 1071 } |
1081 | 1072 |
1082 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { | 1073 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { |
1083 if (body->length() != 1 || | 1074 if (body->length() != 1 || !body->at(0)->IsExpressionStatement() || |
1084 !body->at(0)->IsExpressionStatement() || | 1075 !body->at(0) |
1085 !body->at(0)->AsExpressionStatement()-> | 1076 ->AsExpressionStatement() |
1086 expression()->IsFunctionLiteral()) { | 1077 ->expression() |
| 1078 ->IsFunctionLiteral()) { |
1087 ReportMessage(MessageTemplate::kSingleFunctionLiteral); | 1079 ReportMessage(MessageTemplate::kSingleFunctionLiteral); |
1088 ok = false; | 1080 ok = false; |
1089 } | 1081 } |
1090 } | 1082 } |
1091 | 1083 |
1092 if (ok) { | 1084 if (ok) { |
1093 result = factory()->NewFunctionLiteral( | 1085 result = factory()->NewFunctionLiteral( |
1094 ast_value_factory()->empty_string(), ast_value_factory(), scope_, | 1086 ast_value_factory()->empty_string(), ast_value_factory(), scope_, |
1095 body, function_state.materialized_literal_count(), | 1087 body, function_state.materialized_literal_count(), |
1096 function_state.expected_property_count(), 0, | 1088 function_state.expected_property_count(), 0, |
(...skipping 23 matching lines...) Expand all Loading... |
1120 timer.Start(); | 1112 timer.Start(); |
1121 } | 1113 } |
1122 Handle<SharedFunctionInfo> shared_info = info->shared_info(); | 1114 Handle<SharedFunctionInfo> shared_info = info->shared_info(); |
1123 | 1115 |
1124 // Initialize parser state. | 1116 // Initialize parser state. |
1125 source = String::Flatten(source); | 1117 source = String::Flatten(source); |
1126 FunctionLiteral* result; | 1118 FunctionLiteral* result; |
1127 if (source->IsExternalTwoByteString()) { | 1119 if (source->IsExternalTwoByteString()) { |
1128 ExternalTwoByteStringUtf16CharacterStream stream( | 1120 ExternalTwoByteStringUtf16CharacterStream stream( |
1129 Handle<ExternalTwoByteString>::cast(source), | 1121 Handle<ExternalTwoByteString>::cast(source), |
1130 shared_info->start_position(), | 1122 shared_info->start_position(), shared_info->end_position()); |
1131 shared_info->end_position()); | |
1132 result = ParseLazy(isolate, info, &stream); | 1123 result = ParseLazy(isolate, info, &stream); |
1133 } else { | 1124 } else { |
1134 GenericStringUtf16CharacterStream stream(source, | 1125 GenericStringUtf16CharacterStream stream( |
1135 shared_info->start_position(), | 1126 source, shared_info->start_position(), shared_info->end_position()); |
1136 shared_info->end_position()); | |
1137 result = ParseLazy(isolate, info, &stream); | 1127 result = ParseLazy(isolate, info, &stream); |
1138 } | 1128 } |
1139 | 1129 |
1140 if (FLAG_trace_parse && result != NULL) { | 1130 if (FLAG_trace_parse && result != NULL) { |
1141 double ms = timer.Elapsed().InMillisecondsF(); | 1131 double ms = timer.Elapsed().InMillisecondsF(); |
1142 base::SmartArrayPointer<char> name_chars = | 1132 base::SmartArrayPointer<char> name_chars = |
1143 result->debug_name()->ToCString(); | 1133 result->debug_name()->ToCString(); |
1144 PrintF("[parsing function: %s - took %0.3f ms]\n", name_chars.get(), ms); | 1134 PrintF("[parsing function: %s - took %0.3f ms]\n", name_chars.get(), ms); |
1145 } | 1135 } |
1146 return result; | 1136 return result; |
(...skipping 29 matching lines...) Expand all Loading... |
1176 scope = Scope::DeserializeScopeChain(isolate, zone(), | 1166 scope = Scope::DeserializeScopeChain(isolate, zone(), |
1177 info->closure()->context(), scope); | 1167 info->closure()->context(), scope); |
1178 } | 1168 } |
1179 original_scope_ = scope; | 1169 original_scope_ = scope; |
1180 AstNodeFactory function_factory(ast_value_factory()); | 1170 AstNodeFactory function_factory(ast_value_factory()); |
1181 FunctionState function_state(&function_state_, &scope_, scope, | 1171 FunctionState function_state(&function_state_, &scope_, scope, |
1182 shared_info->kind(), &function_factory); | 1172 shared_info->kind(), &function_factory); |
1183 DCHECK(is_sloppy(scope->language_mode()) || | 1173 DCHECK(is_sloppy(scope->language_mode()) || |
1184 is_strict(info->language_mode())); | 1174 is_strict(info->language_mode())); |
1185 DCHECK(info->language_mode() == shared_info->language_mode()); | 1175 DCHECK(info->language_mode() == shared_info->language_mode()); |
1186 FunctionLiteral::FunctionType function_type = shared_info->is_expression() | 1176 FunctionLiteral::FunctionType function_type = |
1187 ? (shared_info->is_anonymous() | 1177 shared_info->is_expression() |
1188 ? FunctionLiteral::ANONYMOUS_EXPRESSION | 1178 ? (shared_info->is_anonymous() |
1189 : FunctionLiteral::NAMED_EXPRESSION) | 1179 ? FunctionLiteral::ANONYMOUS_EXPRESSION |
1190 : FunctionLiteral::DECLARATION; | 1180 : FunctionLiteral::NAMED_EXPRESSION) |
| 1181 : FunctionLiteral::DECLARATION; |
1191 bool ok = true; | 1182 bool ok = true; |
1192 | 1183 |
1193 if (shared_info->is_arrow()) { | 1184 if (shared_info->is_arrow()) { |
1194 Scope* scope = | 1185 Scope* scope = |
1195 NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction); | 1186 NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction); |
1196 SetLanguageMode(scope, shared_info->language_mode()); | 1187 SetLanguageMode(scope, shared_info->language_mode()); |
1197 scope->set_start_position(shared_info->start_position()); | 1188 scope->set_start_position(shared_info->start_position()); |
1198 ExpressionClassifier formals_classifier; | 1189 ExpressionClassifier formals_classifier; |
1199 ParserFormalParameters formals(scope); | 1190 ParserFormalParameters formals(scope); |
1200 Checkpoint checkpoint(this); | 1191 Checkpoint checkpoint(this); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1271 // StatementList :: | 1262 // StatementList :: |
1272 // (StatementListItem)* <end_token> | 1263 // (StatementListItem)* <end_token> |
1273 | 1264 |
1274 // Allocate a target stack to use for this set of source | 1265 // Allocate a target stack to use for this set of source |
1275 // elements. This way, all scripts and functions get their own | 1266 // elements. This way, all scripts and functions get their own |
1276 // target stack thus avoiding illegal breaks and continues across | 1267 // target stack thus avoiding illegal breaks and continues across |
1277 // functions. | 1268 // functions. |
1278 TargetScope scope(&this->target_stack_); | 1269 TargetScope scope(&this->target_stack_); |
1279 | 1270 |
1280 DCHECK(body != NULL); | 1271 DCHECK(body != NULL); |
1281 bool directive_prologue = true; // Parsing directive prologue. | 1272 bool directive_prologue = true; // Parsing directive prologue. |
1282 | 1273 |
1283 while (peek() != end_token) { | 1274 while (peek() != end_token) { |
1284 if (directive_prologue && peek() != Token::STRING) { | 1275 if (directive_prologue && peek() != Token::STRING) { |
1285 directive_prologue = false; | 1276 directive_prologue = false; |
1286 } | 1277 } |
1287 | 1278 |
1288 Scanner::Location token_loc = scanner()->peek_location(); | 1279 Scanner::Location token_loc = scanner()->peek_location(); |
1289 Scanner::Location old_this_loc = function_state_->this_location(); | 1280 Scanner::Location old_this_loc = function_state_->this_location(); |
1290 Scanner::Location old_super_loc = function_state_->super_location(); | 1281 Scanner::Location old_super_loc = function_state_->super_location(); |
1291 Statement* stat = ParseStatementListItem(CHECK_OK); | 1282 Statement* stat = ParseStatementListItem(CHECK_OK); |
(...skipping 10 matching lines...) Expand all Loading... |
1302 } | 1293 } |
1303 if (super_loc.beg_pos != old_super_loc.beg_pos && | 1294 if (super_loc.beg_pos != old_super_loc.beg_pos && |
1304 super_loc.beg_pos != token_loc.beg_pos) { | 1295 super_loc.beg_pos != token_loc.beg_pos) { |
1305 ReportMessageAt(super_loc, MessageTemplate::kStrongConstructorSuper); | 1296 ReportMessageAt(super_loc, MessageTemplate::kStrongConstructorSuper); |
1306 *ok = false; | 1297 *ok = false; |
1307 return nullptr; | 1298 return nullptr; |
1308 } | 1299 } |
1309 } | 1300 } |
1310 | 1301 |
1311 if (stat == NULL || stat->IsEmpty()) { | 1302 if (stat == NULL || stat->IsEmpty()) { |
1312 directive_prologue = false; // End of directive prologue. | 1303 directive_prologue = false; // End of directive prologue. |
1313 continue; | 1304 continue; |
1314 } | 1305 } |
1315 | 1306 |
1316 if (directive_prologue) { | 1307 if (directive_prologue) { |
1317 // A shot at a directive. | 1308 // A shot at a directive. |
1318 ExpressionStatement* e_stat; | 1309 ExpressionStatement* e_stat; |
1319 Literal* literal; | 1310 Literal* literal; |
1320 // Still processing directive prologue? | 1311 // Still processing directive prologue? |
1321 if ((e_stat = stat->AsExpressionStatement()) != NULL && | 1312 if ((e_stat = stat->AsExpressionStatement()) != NULL && |
1322 (literal = e_stat->expression()->AsLiteral()) != NULL && | 1313 (literal = e_stat->expression()->AsLiteral()) != NULL && |
(...skipping 908 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2231 ZoneList<const AstRawString*>* names, bool* ok) { | 2222 ZoneList<const AstRawString*>* names, bool* ok) { |
2232 // FunctionDeclaration :: | 2223 // FunctionDeclaration :: |
2233 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' | 2224 // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' |
2234 // GeneratorDeclaration :: | 2225 // GeneratorDeclaration :: |
2235 // 'function' '*' Identifier '(' FormalParameterListopt ')' | 2226 // 'function' '*' Identifier '(' FormalParameterListopt ')' |
2236 // '{' FunctionBody '}' | 2227 // '{' FunctionBody '}' |
2237 Expect(Token::FUNCTION, CHECK_OK); | 2228 Expect(Token::FUNCTION, CHECK_OK); |
2238 int pos = position(); | 2229 int pos = position(); |
2239 bool is_generator = Check(Token::MUL); | 2230 bool is_generator = Check(Token::MUL); |
2240 bool is_strict_reserved = false; | 2231 bool is_strict_reserved = false; |
2241 const AstRawString* name = ParseIdentifierOrStrictReservedWord( | 2232 const AstRawString* name = |
2242 &is_strict_reserved, CHECK_OK); | 2233 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
2243 | 2234 |
2244 if (fni_ != NULL) { | 2235 if (fni_ != NULL) { |
2245 fni_->Enter(); | 2236 fni_->Enter(); |
2246 fni_->PushEnclosingName(name); | 2237 fni_->PushEnclosingName(name); |
2247 } | 2238 } |
2248 FunctionLiteral* fun = ParseFunctionLiteral( | 2239 FunctionLiteral* fun = ParseFunctionLiteral( |
2249 name, scanner()->location(), | 2240 name, scanner()->location(), |
2250 is_strict_reserved ? kFunctionNameIsStrictReserved | 2241 is_strict_reserved ? kFunctionNameIsStrictReserved |
2251 : kFunctionNameValidityUnknown, | 2242 : kFunctionNameValidityUnknown, |
2252 is_generator ? FunctionKind::kGeneratorFunction | 2243 is_generator ? FunctionKind::kGeneratorFunction |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2349 } | 2340 } |
2350 | 2341 |
2351 | 2342 |
2352 Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) { | 2343 Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) { |
2353 // The harmony mode uses block elements instead of statements. | 2344 // The harmony mode uses block elements instead of statements. |
2354 // | 2345 // |
2355 // Block :: | 2346 // Block :: |
2356 // '{' StatementList '}' | 2347 // '{' StatementList '}' |
2357 | 2348 |
2358 // Construct block expecting 16 statements. | 2349 // Construct block expecting 16 statements. |
2359 Block* body = | 2350 Block* body = factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition); |
2360 factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition); | |
2361 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); | 2351 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); |
2362 | 2352 |
2363 // Parse the statements and collect escaping labels. | 2353 // Parse the statements and collect escaping labels. |
2364 Expect(Token::LBRACE, CHECK_OK); | 2354 Expect(Token::LBRACE, CHECK_OK); |
2365 block_scope->set_start_position(scanner()->location().beg_pos); | 2355 block_scope->set_start_position(scanner()->location().beg_pos); |
2366 { BlockState block_state(&scope_, block_scope); | 2356 { |
| 2357 BlockState block_state(&scope_, block_scope); |
2367 Target target(&this->target_stack_, body); | 2358 Target target(&this->target_stack_, body); |
2368 | 2359 |
2369 while (peek() != Token::RBRACE) { | 2360 while (peek() != Token::RBRACE) { |
2370 Statement* stat = ParseStatementListItem(CHECK_OK); | 2361 Statement* stat = ParseStatementListItem(CHECK_OK); |
2371 if (stat && !stat->IsEmpty()) { | 2362 if (stat && !stat->IsEmpty()) { |
2372 body->statements()->Add(stat, zone()); | 2363 body->statements()->Add(stat, zone()); |
2373 } | 2364 } |
2374 } | 2365 } |
2375 } | 2366 } |
2376 Expect(Token::RBRACE, CHECK_OK); | 2367 Expect(Token::RBRACE, CHECK_OK); |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2585 | 2576 |
2586 parsing_result->bindings_loc = | 2577 parsing_result->bindings_loc = |
2587 Scanner::Location(bindings_start, scanner()->location().end_pos); | 2578 Scanner::Location(bindings_start, scanner()->location().end_pos); |
2588 } | 2579 } |
2589 | 2580 |
2590 | 2581 |
2591 static bool ContainsLabel(ZoneList<const AstRawString*>* labels, | 2582 static bool ContainsLabel(ZoneList<const AstRawString*>* labels, |
2592 const AstRawString* label) { | 2583 const AstRawString* label) { |
2593 DCHECK(label != NULL); | 2584 DCHECK(label != NULL); |
2594 if (labels != NULL) { | 2585 if (labels != NULL) { |
2595 for (int i = labels->length(); i-- > 0; ) { | 2586 for (int i = labels->length(); i-- > 0;) { |
2596 if (labels->at(i) == label) { | 2587 if (labels->at(i) == label) { |
2597 return true; | 2588 return true; |
2598 } | 2589 } |
2599 } | 2590 } |
2600 } | 2591 } |
2601 return false; | 2592 return false; |
2602 } | 2593 } |
2603 | 2594 |
2604 | 2595 |
2605 Statement* Parser::ParseExpressionOrLabelledStatement( | 2596 Statement* Parser::ParseExpressionOrLabelledStatement( |
(...skipping 11 matching lines...) Expand all Loading... |
2617 case Token::FUNCTION: | 2608 case Token::FUNCTION: |
2618 case Token::LBRACE: | 2609 case Token::LBRACE: |
2619 UNREACHABLE(); // Always handled by the callers. | 2610 UNREACHABLE(); // Always handled by the callers. |
2620 case Token::CLASS: | 2611 case Token::CLASS: |
2621 ReportUnexpectedToken(Next()); | 2612 ReportUnexpectedToken(Next()); |
2622 *ok = false; | 2613 *ok = false; |
2623 return nullptr; | 2614 return nullptr; |
2624 | 2615 |
2625 case Token::THIS: | 2616 case Token::THIS: |
2626 if (!FLAG_strong_this) break; | 2617 if (!FLAG_strong_this) break; |
2627 // Fall through. | 2618 // Fall through. |
2628 case Token::SUPER: | 2619 case Token::SUPER: |
2629 if (is_strong(language_mode()) && | 2620 if (is_strong(language_mode()) && |
2630 IsClassConstructor(function_state_->kind())) { | 2621 IsClassConstructor(function_state_->kind())) { |
2631 bool is_this = peek() == Token::THIS; | 2622 bool is_this = peek() == Token::THIS; |
2632 Expression* expr; | 2623 Expression* expr; |
2633 ExpressionClassifier classifier; | 2624 ExpressionClassifier classifier; |
2634 if (is_this) { | 2625 if (is_this) { |
2635 expr = ParseStrongInitializationExpression(&classifier, CHECK_OK); | 2626 expr = ParseStrongInitializationExpression(&classifier, CHECK_OK); |
2636 } else { | 2627 } else { |
2637 expr = ParseStrongSuperCallExpression(&classifier, CHECK_OK); | 2628 expr = ParseStrongSuperCallExpression(&classifier, CHECK_OK); |
(...skipping 20 matching lines...) Expand all Loading... |
2658 } | 2649 } |
2659 break; | 2650 break; |
2660 | 2651 |
2661 default: | 2652 default: |
2662 break; | 2653 break; |
2663 } | 2654 } |
2664 | 2655 |
2665 bool starts_with_idenfifier = peek_any_identifier(); | 2656 bool starts_with_idenfifier = peek_any_identifier(); |
2666 Expression* expr = ParseExpression(true, CHECK_OK); | 2657 Expression* expr = ParseExpression(true, CHECK_OK); |
2667 if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL && | 2658 if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL && |
2668 expr->AsVariableProxy() != NULL && | 2659 expr->AsVariableProxy() != NULL && !expr->AsVariableProxy()->is_this()) { |
2669 !expr->AsVariableProxy()->is_this()) { | |
2670 // Expression is a single identifier, and not, e.g., a parenthesized | 2660 // Expression is a single identifier, and not, e.g., a parenthesized |
2671 // identifier. | 2661 // identifier. |
2672 VariableProxy* var = expr->AsVariableProxy(); | 2662 VariableProxy* var = expr->AsVariableProxy(); |
2673 const AstRawString* label = var->raw_name(); | 2663 const AstRawString* label = var->raw_name(); |
2674 // TODO(1240780): We don't check for redeclaration of labels | 2664 // TODO(1240780): We don't check for redeclaration of labels |
2675 // during preparsing since keeping track of the set of active | 2665 // during preparsing since keeping track of the set of active |
2676 // labels requires nontrivial changes to the way scopes are | 2666 // labels requires nontrivial changes to the way scopes are |
2677 // structured. However, these are probably changes we want to | 2667 // structured. However, these are probably changes we want to |
2678 // make later anyway so we should go back and fix this then. | 2668 // make later anyway so we should go back and fix this then. |
2679 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) { | 2669 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) { |
2680 ParserTraits::ReportMessage(MessageTemplate::kLabelRedeclaration, label); | 2670 ParserTraits::ReportMessage(MessageTemplate::kLabelRedeclaration, label); |
2681 *ok = false; | 2671 *ok = false; |
2682 return NULL; | 2672 return NULL; |
2683 } | 2673 } |
2684 if (labels == NULL) { | 2674 if (labels == NULL) { |
2685 labels = new(zone()) ZoneList<const AstRawString*>(4, zone()); | 2675 labels = new (zone()) ZoneList<const AstRawString*>(4, zone()); |
2686 } | 2676 } |
2687 labels->Add(label, zone()); | 2677 labels->Add(label, zone()); |
2688 // Remove the "ghost" variable that turned out to be a label | 2678 // 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 | 2679 // from the top scope. This way, we don't try to resolve it |
2690 // during the scope processing. | 2680 // during the scope processing. |
2691 scope_->RemoveUnresolved(var); | 2681 scope_->RemoveUnresolved(var); |
2692 Expect(Token::COLON, CHECK_OK); | 2682 Expect(Token::COLON, CHECK_OK); |
2693 return ParseStatement(labels, ok); | 2683 return ParseStatement(labels, ok); |
2694 } | 2684 } |
2695 | 2685 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2731 Expression* condition = ParseExpression(true, CHECK_OK); | 2721 Expression* condition = ParseExpression(true, CHECK_OK); |
2732 Expect(Token::RPAREN, CHECK_OK); | 2722 Expect(Token::RPAREN, CHECK_OK); |
2733 Statement* then_statement = ParseSubStatement(labels, CHECK_OK); | 2723 Statement* then_statement = ParseSubStatement(labels, CHECK_OK); |
2734 Statement* else_statement = NULL; | 2724 Statement* else_statement = NULL; |
2735 if (peek() == Token::ELSE) { | 2725 if (peek() == Token::ELSE) { |
2736 Next(); | 2726 Next(); |
2737 else_statement = ParseSubStatement(labels, CHECK_OK); | 2727 else_statement = ParseSubStatement(labels, CHECK_OK); |
2738 } else { | 2728 } else { |
2739 else_statement = factory()->NewEmptyStatement(RelocInfo::kNoPosition); | 2729 else_statement = factory()->NewEmptyStatement(RelocInfo::kNoPosition); |
2740 } | 2730 } |
2741 return factory()->NewIfStatement( | 2731 return factory()->NewIfStatement(condition, then_statement, else_statement, |
2742 condition, then_statement, else_statement, pos); | 2732 pos); |
2743 } | 2733 } |
2744 | 2734 |
2745 | 2735 |
2746 Statement* Parser::ParseContinueStatement(bool* ok) { | 2736 Statement* Parser::ParseContinueStatement(bool* ok) { |
2747 // ContinueStatement :: | 2737 // ContinueStatement :: |
2748 // 'continue' Identifier? ';' | 2738 // 'continue' Identifier? ';' |
2749 | 2739 |
2750 int pos = peek_position(); | 2740 int pos = peek_position(); |
2751 Expect(Token::CONTINUE, CHECK_OK); | 2741 Expect(Token::CONTINUE, CHECK_OK); |
2752 const AstRawString* label = NULL; | 2742 const AstRawString* label = NULL; |
2753 Token::Value tok = peek(); | 2743 Token::Value tok = peek(); |
2754 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | 2744 if (!scanner()->HasAnyLineTerminatorBeforeNext() && tok != Token::SEMICOLON && |
2755 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { | 2745 tok != Token::RBRACE && tok != Token::EOS) { |
2756 // ECMA allows "eval" or "arguments" as labels even in strict mode. | 2746 // ECMA allows "eval" or "arguments" as labels even in strict mode. |
2757 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | 2747 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
2758 } | 2748 } |
2759 IterationStatement* target = LookupContinueTarget(label, CHECK_OK); | 2749 IterationStatement* target = LookupContinueTarget(label, CHECK_OK); |
2760 if (target == NULL) { | 2750 if (target == NULL) { |
2761 // Illegal continue statement. | 2751 // Illegal continue statement. |
2762 MessageTemplate::Template message = MessageTemplate::kIllegalContinue; | 2752 MessageTemplate::Template message = MessageTemplate::kIllegalContinue; |
2763 if (label != NULL) { | 2753 if (label != NULL) { |
2764 message = MessageTemplate::kUnknownLabel; | 2754 message = MessageTemplate::kUnknownLabel; |
2765 } | 2755 } |
2766 ParserTraits::ReportMessage(message, label); | 2756 ParserTraits::ReportMessage(message, label); |
2767 *ok = false; | 2757 *ok = false; |
2768 return NULL; | 2758 return NULL; |
2769 } | 2759 } |
2770 ExpectSemicolon(CHECK_OK); | 2760 ExpectSemicolon(CHECK_OK); |
2771 return factory()->NewContinueStatement(target, pos); | 2761 return factory()->NewContinueStatement(target, pos); |
2772 } | 2762 } |
2773 | 2763 |
2774 | 2764 |
2775 Statement* Parser::ParseBreakStatement(ZoneList<const AstRawString*>* labels, | 2765 Statement* Parser::ParseBreakStatement(ZoneList<const AstRawString*>* labels, |
2776 bool* ok) { | 2766 bool* ok) { |
2777 // BreakStatement :: | 2767 // BreakStatement :: |
2778 // 'break' Identifier? ';' | 2768 // 'break' Identifier? ';' |
2779 | 2769 |
2780 int pos = peek_position(); | 2770 int pos = peek_position(); |
2781 Expect(Token::BREAK, CHECK_OK); | 2771 Expect(Token::BREAK, CHECK_OK); |
2782 const AstRawString* label = NULL; | 2772 const AstRawString* label = NULL; |
2783 Token::Value tok = peek(); | 2773 Token::Value tok = peek(); |
2784 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | 2774 if (!scanner()->HasAnyLineTerminatorBeforeNext() && tok != Token::SEMICOLON && |
2785 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { | 2775 tok != Token::RBRACE && tok != Token::EOS) { |
2786 // ECMA allows "eval" or "arguments" as labels even in strict mode. | 2776 // ECMA allows "eval" or "arguments" as labels even in strict mode. |
2787 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | 2777 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
2788 } | 2778 } |
2789 // Parse labeled break statements that target themselves into | 2779 // Parse labeled break statements that target themselves into |
2790 // empty statements, e.g. 'l1: l2: l3: break l2;' | 2780 // empty statements, e.g. 'l1: l2: l3: break l2;' |
2791 if (label != NULL && ContainsLabel(labels, label)) { | 2781 if (label != NULL && ContainsLabel(labels, label)) { |
2792 ExpectSemicolon(CHECK_OK); | 2782 ExpectSemicolon(CHECK_OK); |
2793 return factory()->NewEmptyStatement(pos); | 2783 return factory()->NewEmptyStatement(pos); |
2794 } | 2784 } |
2795 BreakableStatement* target = NULL; | 2785 BreakableStatement* target = NULL; |
(...skipping 20 matching lines...) Expand all Loading... |
2816 // Consume the return token. It is necessary to do that before | 2806 // Consume the return token. It is necessary to do that before |
2817 // reporting any errors on it, because of the way errors are | 2807 // reporting any errors on it, because of the way errors are |
2818 // reported (underlining). | 2808 // reported (underlining). |
2819 Expect(Token::RETURN, CHECK_OK); | 2809 Expect(Token::RETURN, CHECK_OK); |
2820 Scanner::Location loc = scanner()->location(); | 2810 Scanner::Location loc = scanner()->location(); |
2821 function_state_->set_return_location(loc); | 2811 function_state_->set_return_location(loc); |
2822 | 2812 |
2823 Token::Value tok = peek(); | 2813 Token::Value tok = peek(); |
2824 Statement* result; | 2814 Statement* result; |
2825 Expression* return_value; | 2815 Expression* return_value; |
2826 if (scanner()->HasAnyLineTerminatorBeforeNext() || | 2816 if (scanner()->HasAnyLineTerminatorBeforeNext() || tok == Token::SEMICOLON || |
2827 tok == Token::SEMICOLON || | 2817 tok == Token::RBRACE || tok == Token::EOS) { |
2828 tok == Token::RBRACE || | |
2829 tok == Token::EOS) { | |
2830 if (IsSubclassConstructor(function_state_->kind())) { | 2818 if (IsSubclassConstructor(function_state_->kind())) { |
2831 return_value = ThisExpression(scope_, factory(), loc.beg_pos); | 2819 return_value = ThisExpression(scope_, factory(), loc.beg_pos); |
2832 } else { | 2820 } else { |
2833 return_value = GetLiteralUndefined(position()); | 2821 return_value = GetLiteralUndefined(position()); |
2834 } | 2822 } |
2835 } else { | 2823 } else { |
2836 if (is_strong(language_mode()) && | 2824 if (is_strong(language_mode()) && |
2837 IsClassConstructor(function_state_->kind())) { | 2825 IsClassConstructor(function_state_->kind())) { |
2838 int pos = peek_position(); | 2826 int pos = peek_position(); |
2839 ReportMessageAt(Scanner::Location(pos, pos + 1), | 2827 ReportMessageAt(Scanner::Location(pos, pos + 1), |
2840 MessageTemplate::kStrongConstructorReturnValue); | 2828 MessageTemplate::kStrongConstructorReturnValue); |
2841 *ok = false; | 2829 *ok = false; |
2842 return NULL; | 2830 return NULL; |
2843 } | 2831 } |
2844 | 2832 |
2845 int pos = peek_position(); | 2833 int pos = peek_position(); |
2846 return_value = ParseExpression(true, CHECK_OK); | 2834 return_value = ParseExpression(true, CHECK_OK); |
2847 | 2835 |
2848 if (IsSubclassConstructor(function_state_->kind())) { | 2836 if (IsSubclassConstructor(function_state_->kind())) { |
2849 // For subclass constructors we need to return this in case of undefined | 2837 // For subclass constructors we need to return this in case of undefined |
2850 // and throw an exception in case of a non object. | 2838 // and throw an exception in case of a non object. |
2851 // | 2839 // |
2852 // return expr; | 2840 // return expr; |
2853 // | 2841 // |
2854 // Is rewritten as: | 2842 // Is rewritten as: |
2855 // | 2843 // |
2856 // return (temp = expr) === undefined ? this : | 2844 // return (temp = expr) === undefined ? this : |
2857 // %_IsSpecObject(temp) ? temp : throw new TypeError(...); | 2845 // %_IsSpecObject(temp) ? temp : throw new TypeError(...); |
2858 Variable* temp = scope_->NewTemporary( | 2846 Variable* temp = |
2859 ast_value_factory()->empty_string()); | 2847 scope_->NewTemporary(ast_value_factory()->empty_string()); |
2860 Assignment* assign = factory()->NewAssignment( | 2848 Assignment* assign = factory()->NewAssignment( |
2861 Token::ASSIGN, factory()->NewVariableProxy(temp), return_value, pos); | 2849 Token::ASSIGN, factory()->NewVariableProxy(temp), return_value, pos); |
2862 | 2850 |
2863 Expression* throw_expression = | 2851 Expression* throw_expression = |
2864 NewThrowTypeError(MessageTemplate::kDerivedConstructorReturn, | 2852 NewThrowTypeError(MessageTemplate::kDerivedConstructorReturn, |
2865 ast_value_factory()->empty_string(), pos); | 2853 ast_value_factory()->empty_string(), pos); |
2866 | 2854 |
2867 // %_IsSpecObject(temp) | 2855 // %_IsSpecObject(temp) |
2868 ZoneList<Expression*>* is_spec_object_args = | 2856 ZoneList<Expression*>* is_spec_object_args = |
2869 new (zone()) ZoneList<Expression*>(1, zone()); | 2857 new (zone()) ZoneList<Expression*>(1, zone()); |
(...skipping 15 matching lines...) Expand all Loading... |
2885 return_value = factory()->NewConditional( | 2873 return_value = factory()->NewConditional( |
2886 is_undefined, ThisExpression(scope_, factory(), pos), | 2874 is_undefined, ThisExpression(scope_, factory(), pos), |
2887 is_object_conditional, pos); | 2875 is_object_conditional, pos); |
2888 } | 2876 } |
2889 } | 2877 } |
2890 ExpectSemicolon(CHECK_OK); | 2878 ExpectSemicolon(CHECK_OK); |
2891 | 2879 |
2892 if (is_generator()) { | 2880 if (is_generator()) { |
2893 Expression* generator = factory()->NewVariableProxy( | 2881 Expression* generator = factory()->NewVariableProxy( |
2894 function_state_->generator_object_variable()); | 2882 function_state_->generator_object_variable()); |
2895 Expression* yield = factory()->NewYield( | 2883 Expression* yield = factory()->NewYield(generator, return_value, |
2896 generator, return_value, Yield::kFinal, loc.beg_pos); | 2884 Yield::kFinal, loc.beg_pos); |
2897 result = factory()->NewExpressionStatement(yield, loc.beg_pos); | 2885 result = factory()->NewExpressionStatement(yield, loc.beg_pos); |
2898 } else { | 2886 } else { |
2899 result = factory()->NewReturnStatement(return_value, loc.beg_pos); | 2887 result = factory()->NewReturnStatement(return_value, loc.beg_pos); |
2900 } | 2888 } |
2901 | 2889 |
2902 Scope* decl_scope = scope_->DeclarationScope(); | 2890 Scope* decl_scope = scope_->DeclarationScope(); |
2903 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) { | 2891 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) { |
2904 ReportMessageAt(loc, MessageTemplate::kIllegalReturn); | 2892 ReportMessageAt(loc, MessageTemplate::kIllegalReturn); |
2905 *ok = false; | 2893 *ok = false; |
2906 return NULL; | 2894 return NULL; |
(...skipping 16 matching lines...) Expand all Loading... |
2923 return NULL; | 2911 return NULL; |
2924 } | 2912 } |
2925 | 2913 |
2926 Expect(Token::LPAREN, CHECK_OK); | 2914 Expect(Token::LPAREN, CHECK_OK); |
2927 Expression* expr = ParseExpression(true, CHECK_OK); | 2915 Expression* expr = ParseExpression(true, CHECK_OK); |
2928 Expect(Token::RPAREN, CHECK_OK); | 2916 Expect(Token::RPAREN, CHECK_OK); |
2929 | 2917 |
2930 scope_->DeclarationScope()->RecordWithStatement(); | 2918 scope_->DeclarationScope()->RecordWithStatement(); |
2931 Scope* with_scope = NewScope(scope_, WITH_SCOPE); | 2919 Scope* with_scope = NewScope(scope_, WITH_SCOPE); |
2932 Block* body; | 2920 Block* body; |
2933 { BlockState block_state(&scope_, with_scope); | 2921 { |
| 2922 BlockState block_state(&scope_, with_scope); |
2934 with_scope->set_start_position(scanner()->peek_location().beg_pos); | 2923 with_scope->set_start_position(scanner()->peek_location().beg_pos); |
2935 | 2924 |
2936 // The body of the with statement must be enclosed in an additional | 2925 // The body of the with statement must be enclosed in an additional |
2937 // lexical scope in case the body is a FunctionDeclaration. | 2926 // lexical scope in case the body is a FunctionDeclaration. |
2938 body = factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition); | 2927 body = factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition); |
2939 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); | 2928 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); |
2940 block_scope->set_start_position(scanner()->location().beg_pos); | 2929 block_scope->set_start_position(scanner()->location().beg_pos); |
2941 { | 2930 { |
2942 BlockState block_state(&scope_, block_scope); | 2931 BlockState block_state(&scope_, block_scope); |
2943 Target target(&this->target_stack_, body); | 2932 Target target(&this->target_stack_, body); |
(...skipping 24 matching lines...) Expand all Loading... |
2968 if (*default_seen_ptr) { | 2957 if (*default_seen_ptr) { |
2969 ReportMessage(MessageTemplate::kMultipleDefaultsInSwitch); | 2958 ReportMessage(MessageTemplate::kMultipleDefaultsInSwitch); |
2970 *ok = false; | 2959 *ok = false; |
2971 return NULL; | 2960 return NULL; |
2972 } | 2961 } |
2973 *default_seen_ptr = true; | 2962 *default_seen_ptr = true; |
2974 } | 2963 } |
2975 Expect(Token::COLON, CHECK_OK); | 2964 Expect(Token::COLON, CHECK_OK); |
2976 int pos = position(); | 2965 int pos = position(); |
2977 ZoneList<Statement*>* statements = | 2966 ZoneList<Statement*>* statements = |
2978 new(zone()) ZoneList<Statement*>(5, zone()); | 2967 new (zone()) ZoneList<Statement*>(5, zone()); |
2979 Statement* stat = NULL; | 2968 Statement* stat = NULL; |
2980 while (peek() != Token::CASE && | 2969 while (peek() != Token::CASE && peek() != Token::DEFAULT && |
2981 peek() != Token::DEFAULT && | |
2982 peek() != Token::RBRACE) { | 2970 peek() != Token::RBRACE) { |
2983 stat = ParseStatementListItem(CHECK_OK); | 2971 stat = ParseStatementListItem(CHECK_OK); |
2984 statements->Add(stat, zone()); | 2972 statements->Add(stat, zone()); |
2985 } | 2973 } |
2986 if (is_strong(language_mode()) && stat != NULL && !stat->IsJump() && | 2974 if (is_strong(language_mode()) && stat != NULL && !stat->IsJump() && |
2987 peek() != Token::RBRACE) { | 2975 peek() != Token::RBRACE) { |
2988 ReportMessageAt(scanner()->location(), | 2976 ReportMessageAt(scanner()->location(), |
2989 MessageTemplate::kStrongSwitchFallthrough); | 2977 MessageTemplate::kStrongSwitchFallthrough); |
2990 *ok = false; | 2978 *ok = false; |
2991 return NULL; | 2979 return NULL; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3080 Expect(Token::THROW, CHECK_OK); | 3068 Expect(Token::THROW, CHECK_OK); |
3081 int pos = position(); | 3069 int pos = position(); |
3082 if (scanner()->HasAnyLineTerminatorBeforeNext()) { | 3070 if (scanner()->HasAnyLineTerminatorBeforeNext()) { |
3083 ReportMessage(MessageTemplate::kNewlineAfterThrow); | 3071 ReportMessage(MessageTemplate::kNewlineAfterThrow); |
3084 *ok = false; | 3072 *ok = false; |
3085 return NULL; | 3073 return NULL; |
3086 } | 3074 } |
3087 Expression* exception = ParseExpression(true, CHECK_OK); | 3075 Expression* exception = ParseExpression(true, CHECK_OK); |
3088 ExpectSemicolon(CHECK_OK); | 3076 ExpectSemicolon(CHECK_OK); |
3089 | 3077 |
3090 return factory()->NewExpressionStatement( | 3078 return factory()->NewExpressionStatement(factory()->NewThrow(exception, pos), |
3091 factory()->NewThrow(exception, pos), pos); | 3079 pos); |
3092 } | 3080 } |
3093 | 3081 |
3094 | 3082 |
3095 TryStatement* Parser::ParseTryStatement(bool* ok) { | 3083 TryStatement* Parser::ParseTryStatement(bool* ok) { |
3096 // TryStatement :: | 3084 // TryStatement :: |
3097 // 'try' Block Catch | 3085 // 'try' Block Catch |
3098 // 'try' Block Finally | 3086 // 'try' Block Finally |
3099 // 'try' Block Catch Finally | 3087 // 'try' Block Catch Finally |
3100 // | 3088 // |
3101 // Catch :: | 3089 // Catch :: |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3313 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos); | 3301 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos); |
3314 | 3302 |
3315 return factory()->NewBinaryOperation( | 3303 return factory()->NewBinaryOperation( |
3316 Token::AND, | 3304 Token::AND, |
3317 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos), | 3305 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos), |
3318 throw_call, pos); | 3306 throw_call, pos); |
3319 } | 3307 } |
3320 | 3308 |
3321 | 3309 |
3322 void Parser::InitializeForEachStatement(ForEachStatement* stmt, | 3310 void Parser::InitializeForEachStatement(ForEachStatement* stmt, |
3323 Expression* each, | 3311 Expression* each, Expression* subject, |
3324 Expression* subject, | |
3325 Statement* body) { | 3312 Statement* body) { |
3326 ForOfStatement* for_of = stmt->AsForOfStatement(); | 3313 ForOfStatement* for_of = stmt->AsForOfStatement(); |
3327 | 3314 |
3328 if (for_of != NULL) { | 3315 if (for_of != NULL) { |
3329 Variable* iterator = scope_->NewTemporary( | 3316 Variable* iterator = |
3330 ast_value_factory()->dot_iterator_string()); | 3317 scope_->NewTemporary(ast_value_factory()->dot_iterator_string()); |
3331 Variable* result = scope_->NewTemporary( | 3318 Variable* result = |
3332 ast_value_factory()->dot_result_string()); | 3319 scope_->NewTemporary(ast_value_factory()->dot_result_string()); |
3333 | 3320 |
3334 Expression* assign_iterator; | 3321 Expression* assign_iterator; |
3335 Expression* next_result; | 3322 Expression* next_result; |
3336 Expression* result_done; | 3323 Expression* result_done; |
3337 Expression* assign_each; | 3324 Expression* assign_each; |
3338 | 3325 |
3339 // iterator = subject[Symbol.iterator]() | 3326 // iterator = subject[Symbol.iterator]() |
3340 assign_iterator = factory()->NewAssignment( | 3327 assign_iterator = factory()->NewAssignment( |
3341 Token::ASSIGN, factory()->NewVariableProxy(iterator), | 3328 Token::ASSIGN, factory()->NewVariableProxy(iterator), |
3342 GetIterator(subject, factory()), subject->position()); | 3329 GetIterator(subject, factory()), subject->position()); |
3343 | 3330 |
3344 // !%_IsSpecObject(result = iterator.next()) && | 3331 // !%_IsSpecObject(result = iterator.next()) && |
3345 // %ThrowIteratorResultNotAnObject(result) | 3332 // %ThrowIteratorResultNotAnObject(result) |
3346 { | 3333 { |
3347 // result = iterator.next() | 3334 // result = iterator.next() |
3348 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); | 3335 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); |
3349 next_result = | 3336 next_result = |
3350 BuildIteratorNextResult(iterator_proxy, result, subject->position()); | 3337 BuildIteratorNextResult(iterator_proxy, result, subject->position()); |
3351 } | 3338 } |
3352 | 3339 |
3353 // result.done | 3340 // result.done |
3354 { | 3341 { |
3355 Expression* done_literal = factory()->NewStringLiteral( | 3342 Expression* done_literal = factory()->NewStringLiteral( |
3356 ast_value_factory()->done_string(), RelocInfo::kNoPosition); | 3343 ast_value_factory()->done_string(), RelocInfo::kNoPosition); |
3357 Expression* result_proxy = factory()->NewVariableProxy(result); | 3344 Expression* result_proxy = factory()->NewVariableProxy(result); |
3358 result_done = factory()->NewProperty( | 3345 result_done = factory()->NewProperty(result_proxy, done_literal, |
3359 result_proxy, done_literal, RelocInfo::kNoPosition); | 3346 RelocInfo::kNoPosition); |
3360 } | 3347 } |
3361 | 3348 |
3362 // each = result.value | 3349 // each = result.value |
3363 { | 3350 { |
3364 Expression* value_literal = factory()->NewStringLiteral( | 3351 Expression* value_literal = factory()->NewStringLiteral( |
3365 ast_value_factory()->value_string(), RelocInfo::kNoPosition); | 3352 ast_value_factory()->value_string(), RelocInfo::kNoPosition); |
3366 Expression* result_proxy = factory()->NewVariableProxy(result); | 3353 Expression* result_proxy = factory()->NewVariableProxy(result); |
3367 Expression* result_value = factory()->NewProperty( | 3354 Expression* result_value = factory()->NewProperty( |
3368 result_proxy, value_literal, RelocInfo::kNoPosition); | 3355 result_proxy, value_literal, RelocInfo::kNoPosition); |
3369 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value, | 3356 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value, |
3370 RelocInfo::kNoPosition); | 3357 RelocInfo::kNoPosition); |
3371 } | 3358 } |
3372 | 3359 |
3373 for_of->Initialize(each, subject, body, | 3360 for_of->Initialize(each, subject, body, assign_iterator, next_result, |
3374 assign_iterator, | 3361 result_done, assign_each); |
3375 next_result, | |
3376 result_done, | |
3377 assign_each); | |
3378 } else { | 3362 } else { |
3379 stmt->Initialize(each, subject, body); | 3363 stmt->Initialize(each, subject, body); |
3380 } | 3364 } |
3381 } | 3365 } |
3382 | 3366 |
3383 | 3367 |
3384 Statement* Parser::DesugarLexicalBindingsInForStatement( | 3368 Statement* Parser::DesugarLexicalBindingsInForStatement( |
3385 Scope* inner_scope, bool is_const, ZoneList<const AstRawString*>* names, | 3369 Scope* inner_scope, bool is_const, ZoneList<const AstRawString*>* names, |
3386 ForStatement* loop, Statement* init, Expression* cond, Statement* next, | 3370 ForStatement* loop, Statement* init, Expression* cond, Statement* next, |
3387 Statement* body, bool* ok) { | 3371 Statement* body, bool* ok) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3435 const AstRawString* temp_name = ast_value_factory()->dot_for_string(); | 3419 const AstRawString* temp_name = ast_value_factory()->dot_for_string(); |
3436 | 3420 |
3437 // For each lexical variable x: | 3421 // For each lexical variable x: |
3438 // make statement: temp_x = x. | 3422 // make statement: temp_x = x. |
3439 for (int i = 0; i < names->length(); i++) { | 3423 for (int i = 0; i < names->length(); i++) { |
3440 VariableProxy* proxy = NewUnresolved(names->at(i), LET); | 3424 VariableProxy* proxy = NewUnresolved(names->at(i), LET); |
3441 Variable* temp = scope_->NewTemporary(temp_name); | 3425 Variable* temp = scope_->NewTemporary(temp_name); |
3442 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); | 3426 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); |
3443 Assignment* assignment = factory()->NewAssignment( | 3427 Assignment* assignment = factory()->NewAssignment( |
3444 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition); | 3428 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition); |
3445 Statement* assignment_statement = factory()->NewExpressionStatement( | 3429 Statement* assignment_statement = |
3446 assignment, RelocInfo::kNoPosition); | 3430 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
3447 outer_block->statements()->Add(assignment_statement, zone()); | 3431 outer_block->statements()->Add(assignment_statement, zone()); |
3448 temps.Add(temp, zone()); | 3432 temps.Add(temp, zone()); |
3449 } | 3433 } |
3450 | 3434 |
3451 Variable* first = NULL; | 3435 Variable* first = NULL; |
3452 // Make statement: first = 1. | 3436 // Make statement: first = 1. |
3453 if (next) { | 3437 if (next) { |
3454 first = scope_->NewTemporary(temp_name); | 3438 first = scope_->NewTemporary(temp_name); |
3455 VariableProxy* first_proxy = factory()->NewVariableProxy(first); | 3439 VariableProxy* first_proxy = factory()->NewVariableProxy(first); |
3456 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); | 3440 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3715 // { | 3699 // { |
3716 // <let x' be a temporary variable> | 3700 // <let x' be a temporary variable> |
3717 // for (x' in/of e) { | 3701 // for (x' in/of e) { |
3718 // let/const/var x; | 3702 // let/const/var x; |
3719 // x = x'; | 3703 // x = x'; |
3720 // b; | 3704 // b; |
3721 // } | 3705 // } |
3722 // let x; // for TDZ | 3706 // let x; // for TDZ |
3723 // } | 3707 // } |
3724 | 3708 |
3725 Variable* temp = scope_->NewTemporary( | 3709 Variable* temp = |
3726 ast_value_factory()->dot_for_string()); | 3710 scope_->NewTemporary(ast_value_factory()->dot_for_string()); |
3727 ForEachStatement* loop = | 3711 ForEachStatement* loop = |
3728 factory()->NewForEachStatement(mode, labels, stmt_pos); | 3712 factory()->NewForEachStatement(mode, labels, stmt_pos); |
3729 Target target(&this->target_stack_, loop); | 3713 Target target(&this->target_stack_, loop); |
3730 | 3714 |
3731 Expression* enumerable = ParseExpression(true, CHECK_OK); | 3715 Expression* enumerable = ParseExpression(true, CHECK_OK); |
3732 | 3716 |
3733 Expect(Token::RPAREN, CHECK_OK); | 3717 Expect(Token::RPAREN, CHECK_OK); |
3734 | 3718 |
3735 Scope* body_scope = NewScope(scope_, BLOCK_SCOPE); | 3719 Scope* body_scope = NewScope(scope_, BLOCK_SCOPE); |
3736 body_scope->set_start_position(scanner()->location().beg_pos); | 3720 body_scope->set_start_position(scanner()->location().beg_pos); |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3897 Expression* exp = ParseExpression(true, CHECK_OK); | 3881 Expression* exp = ParseExpression(true, CHECK_OK); |
3898 next = factory()->NewExpressionStatement(exp, exp->position()); | 3882 next = factory()->NewExpressionStatement(exp, exp->position()); |
3899 } | 3883 } |
3900 Expect(Token::RPAREN, CHECK_OK); | 3884 Expect(Token::RPAREN, CHECK_OK); |
3901 | 3885 |
3902 Statement* body = ParseSubStatement(NULL, CHECK_OK); | 3886 Statement* body = ParseSubStatement(NULL, CHECK_OK); |
3903 | 3887 |
3904 Statement* result = NULL; | 3888 Statement* result = NULL; |
3905 if (lexical_bindings.length() > 0) { | 3889 if (lexical_bindings.length() > 0) { |
3906 scope_ = for_scope; | 3890 scope_ = for_scope; |
3907 result = DesugarLexicalBindingsInForStatement( | 3891 result = DesugarLexicalBindingsInForStatement(inner_scope, is_const, |
3908 inner_scope, is_const, &lexical_bindings, loop, init, cond, | 3892 &lexical_bindings, loop, init, |
3909 next, body, CHECK_OK); | 3893 cond, next, body, CHECK_OK); |
3910 scope_ = saved_scope; | 3894 scope_ = saved_scope; |
3911 for_scope->set_end_position(scanner()->location().end_pos); | 3895 for_scope->set_end_position(scanner()->location().end_pos); |
3912 } else { | 3896 } else { |
3913 scope_ = saved_scope; | 3897 scope_ = saved_scope; |
3914 for_scope->set_end_position(scanner()->location().end_pos); | 3898 for_scope->set_end_position(scanner()->location().end_pos); |
3915 for_scope = for_scope->FinalizeBlockScope(); | 3899 for_scope = for_scope->FinalizeBlockScope(); |
3916 if (for_scope) { | 3900 if (for_scope) { |
3917 // Rewrite a for statement of the form | 3901 // Rewrite a for statement of the form |
3918 // for (const x = i; c; n) b | 3902 // for (const x = i; c; n) b |
3919 // | 3903 // |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4098 if (!Rewriter::Rewrite(this, expr, ast_value_factory())) { | 4082 if (!Rewriter::Rewrite(this, expr, ast_value_factory())) { |
4099 *ok = false; | 4083 *ok = false; |
4100 return nullptr; | 4084 return nullptr; |
4101 } | 4085 } |
4102 return expr; | 4086 return expr; |
4103 } | 4087 } |
4104 | 4088 |
4105 | 4089 |
4106 void ParserTraits::ParseArrowFunctionFormalParameterList( | 4090 void ParserTraits::ParseArrowFunctionFormalParameterList( |
4107 ParserFormalParameters* parameters, Expression* expr, | 4091 ParserFormalParameters* parameters, Expression* expr, |
4108 const Scanner::Location& params_loc, | 4092 const Scanner::Location& params_loc, Scanner::Location* duplicate_loc, |
4109 Scanner::Location* duplicate_loc, bool* ok) { | 4093 bool* ok) { |
4110 if (expr->IsEmptyParentheses()) return; | 4094 if (expr->IsEmptyParentheses()) return; |
4111 | 4095 |
4112 ParseArrowFunctionFormalParameters(parameters, expr, params_loc, ok); | 4096 ParseArrowFunctionFormalParameters(parameters, expr, params_loc, ok); |
4113 if (!*ok) return; | 4097 if (!*ok) return; |
4114 | 4098 |
4115 ExpressionClassifier classifier; | 4099 ExpressionClassifier classifier; |
4116 if (!parameters->is_simple) { | 4100 if (!parameters->is_simple) { |
4117 classifier.RecordNonSimpleParameter(); | 4101 classifier.RecordNonSimpleParameter(); |
4118 } | 4102 } |
4119 for (int i = 0; i < parameters->Arity(); ++i) { | 4103 for (int i = 0; i < parameters->Arity(); ++i) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4154 LanguageMode language_mode, bool* ok) { | 4138 LanguageMode language_mode, bool* ok) { |
4155 // Function :: | 4139 // Function :: |
4156 // '(' FormalParameterList? ')' '{' FunctionBody '}' | 4140 // '(' FormalParameterList? ')' '{' FunctionBody '}' |
4157 // | 4141 // |
4158 // Getter :: | 4142 // Getter :: |
4159 // '(' ')' '{' FunctionBody '}' | 4143 // '(' ')' '{' FunctionBody '}' |
4160 // | 4144 // |
4161 // Setter :: | 4145 // Setter :: |
4162 // '(' PropertySetParameterList ')' '{' FunctionBody '}' | 4146 // '(' PropertySetParameterList ')' '{' FunctionBody '}' |
4163 | 4147 |
4164 int pos = function_token_pos == RelocInfo::kNoPosition | 4148 int pos = function_token_pos == RelocInfo::kNoPosition ? peek_position() |
4165 ? peek_position() : function_token_pos; | 4149 : function_token_pos; |
4166 | 4150 |
4167 bool is_generator = IsGeneratorFunction(kind); | 4151 bool is_generator = IsGeneratorFunction(kind); |
4168 | 4152 |
4169 // Anonymous functions were passed either the empty symbol or a null | 4153 // 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 | 4154 // handle as the function name. Remember if we were passed a non-empty |
4171 // handle to decide whether to invoke function name inference. | 4155 // handle to decide whether to invoke function name inference. |
4172 bool should_infer_name = function_name == NULL; | 4156 bool should_infer_name = function_name == NULL; |
4173 | 4157 |
4174 // We want a non-null handle as the function name. | 4158 // We want a non-null handle as the function name. |
4175 if (should_infer_name) { | 4159 if (should_infer_name) { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4246 | 4230 |
4247 Expect(Token::LPAREN, CHECK_OK); | 4231 Expect(Token::LPAREN, CHECK_OK); |
4248 int start_position = scanner()->location().beg_pos; | 4232 int start_position = scanner()->location().beg_pos; |
4249 scope_->set_start_position(start_position); | 4233 scope_->set_start_position(start_position); |
4250 ParserFormalParameters formals(scope); | 4234 ParserFormalParameters formals(scope); |
4251 ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK); | 4235 ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK); |
4252 arity = formals.Arity(); | 4236 arity = formals.Arity(); |
4253 Expect(Token::RPAREN, CHECK_OK); | 4237 Expect(Token::RPAREN, CHECK_OK); |
4254 int formals_end_position = scanner()->location().end_pos; | 4238 int formals_end_position = scanner()->location().end_pos; |
4255 | 4239 |
4256 CheckArityRestrictions(arity, arity_restriction, | 4240 CheckArityRestrictions(arity, arity_restriction, formals.has_rest, |
4257 formals.has_rest, start_position, | 4241 start_position, formals_end_position, CHECK_OK); |
4258 formals_end_position, CHECK_OK); | |
4259 Expect(Token::LBRACE, CHECK_OK); | 4242 Expect(Token::LBRACE, CHECK_OK); |
4260 | 4243 |
4261 // Determine if the function can be parsed lazily. Lazy parsing is different | 4244 // 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. | 4245 // from lazy compilation; we need to parse more eagerly than we compile. |
4263 | 4246 |
4264 // We can only parse lazily if we also compile lazily. The heuristics for | 4247 // We can only parse lazily if we also compile lazily. The heuristics for |
4265 // lazy compilation are: | 4248 // lazy compilation are: |
4266 // - It must not have been prohibited by the caller to Parse (some callers | 4249 // - It must not have been prohibited by the caller to Parse (some callers |
4267 // need a full AST). | 4250 // need a full AST). |
4268 // - The outer scope must allow lazy compilation of inner functions. | 4251 // - The outer scope must allow lazy compilation of inner functions. |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4555 Expression* initial_value = | 4538 Expression* initial_value = |
4556 factory()->NewVariableProxy(parameters.scope->parameter(i)); | 4539 factory()->NewVariableProxy(parameters.scope->parameter(i)); |
4557 if (parameter.initializer != nullptr) { | 4540 if (parameter.initializer != nullptr) { |
4558 // IS_UNDEFINED($param) ? initializer : $param | 4541 // IS_UNDEFINED($param) ? initializer : $param |
4559 DCHECK(!parameter.is_rest); | 4542 DCHECK(!parameter.is_rest); |
4560 auto condition = factory()->NewCompareOperation( | 4543 auto condition = factory()->NewCompareOperation( |
4561 Token::EQ_STRICT, | 4544 Token::EQ_STRICT, |
4562 factory()->NewVariableProxy(parameters.scope->parameter(i)), | 4545 factory()->NewVariableProxy(parameters.scope->parameter(i)), |
4563 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), | 4546 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), |
4564 RelocInfo::kNoPosition); | 4547 RelocInfo::kNoPosition); |
4565 initial_value = factory()->NewConditional( | 4548 initial_value = |
4566 condition, parameter.initializer, initial_value, | 4549 factory()->NewConditional(condition, parameter.initializer, |
4567 RelocInfo::kNoPosition); | 4550 initial_value, RelocInfo::kNoPosition); |
4568 descriptor.initialization_pos = parameter.initializer->position(); | 4551 descriptor.initialization_pos = parameter.initializer->position(); |
4569 initializer_position = parameter.initializer_end_position; | 4552 initializer_position = parameter.initializer_end_position; |
4570 } else if (parameter.is_rest) { | 4553 } else if (parameter.is_rest) { |
4571 // $rest = []; | 4554 // $rest = []; |
4572 // for (var $argument_index = $rest_index; | 4555 // for (var $argument_index = $rest_index; |
4573 // $argument_index < %_ArgumentsLength(); | 4556 // $argument_index < %_ArgumentsLength(); |
4574 // ++$argument_index) { | 4557 // ++$argument_index) { |
4575 // %AppendElement($rest, %_Arguments($argument_index)); | 4558 // %AppendElement($rest, %_Arguments($argument_index)); |
4576 // } | 4559 // } |
4577 // let <param> = $rest; | 4560 // let <param> = $rest; |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4676 } | 4659 } |
4677 | 4660 |
4678 | 4661 |
4679 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( | 4662 ZoneList<Statement*>* Parser::ParseEagerFunctionBody( |
4680 const AstRawString* function_name, int pos, | 4663 const AstRawString* function_name, int pos, |
4681 const ParserFormalParameters& parameters, FunctionKind kind, | 4664 const ParserFormalParameters& parameters, FunctionKind kind, |
4682 FunctionLiteral::FunctionType function_type, bool* ok) { | 4665 FunctionLiteral::FunctionType function_type, bool* ok) { |
4683 // Everything inside an eagerly parsed function will be parsed eagerly | 4666 // Everything inside an eagerly parsed function will be parsed eagerly |
4684 // (see comment above). | 4667 // (see comment above). |
4685 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); | 4668 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); |
4686 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); | 4669 ZoneList<Statement*>* result = new (zone()) ZoneList<Statement*>(8, zone()); |
4687 | 4670 |
4688 static const int kFunctionNameAssignmentIndex = 0; | 4671 static const int kFunctionNameAssignmentIndex = 0; |
4689 if (function_type == FunctionLiteral::NAMED_EXPRESSION) { | 4672 if (function_type == FunctionLiteral::NAMED_EXPRESSION) { |
4690 DCHECK(function_name != NULL); | 4673 DCHECK(function_name != NULL); |
4691 // If we have a named function expression, we add a local variable | 4674 // 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 | 4675 // declaration to the body of the function with the name of the |
4693 // function and let it refer to the function itself (closure). | 4676 // function and let it refer to the function itself (closure). |
4694 // Not having parsed the function body, the language mode may still change, | 4677 // 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. | 4678 // so we reserve a spot and create the actual const assignment later. |
4696 DCHECK_EQ(kFunctionNameAssignmentIndex, result->length()); | 4679 DCHECK_EQ(kFunctionNameAssignmentIndex, result->length()); |
(...skipping 11 matching lines...) Expand all Loading... |
4708 inner_block->set_scope(inner_scope); | 4691 inner_block->set_scope(inner_scope); |
4709 body = inner_block->statements(); | 4692 body = inner_block->statements(); |
4710 } | 4693 } |
4711 | 4694 |
4712 { | 4695 { |
4713 BlockState block_state(&scope_, inner_scope); | 4696 BlockState block_state(&scope_, inner_scope); |
4714 | 4697 |
4715 // For generators, allocate and yield an iterator on function entry. | 4698 // For generators, allocate and yield an iterator on function entry. |
4716 if (IsGeneratorFunction(kind)) { | 4699 if (IsGeneratorFunction(kind)) { |
4717 ZoneList<Expression*>* arguments = | 4700 ZoneList<Expression*>* arguments = |
4718 new(zone()) ZoneList<Expression*>(0, zone()); | 4701 new (zone()) ZoneList<Expression*>(0, zone()); |
4719 CallRuntime* allocation = factory()->NewCallRuntime( | 4702 CallRuntime* allocation = factory()->NewCallRuntime( |
4720 Runtime::kCreateJSGeneratorObject, arguments, pos); | 4703 Runtime::kCreateJSGeneratorObject, arguments, pos); |
4721 VariableProxy* init_proxy = factory()->NewVariableProxy( | 4704 VariableProxy* init_proxy = factory()->NewVariableProxy( |
4722 function_state_->generator_object_variable()); | 4705 function_state_->generator_object_variable()); |
4723 Assignment* assignment = factory()->NewAssignment( | 4706 Assignment* assignment = factory()->NewAssignment( |
4724 Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition); | 4707 Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition); |
4725 VariableProxy* get_proxy = factory()->NewVariableProxy( | 4708 VariableProxy* get_proxy = factory()->NewVariableProxy( |
4726 function_state_->generator_object_variable()); | 4709 function_state_->generator_object_variable()); |
4727 Yield* yield = factory()->NewYield( | 4710 Yield* yield = factory()->NewYield(get_proxy, assignment, Yield::kInitial, |
4728 get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition); | 4711 RelocInfo::kNoPosition); |
4729 body->Add(factory()->NewExpressionStatement( | 4712 body->Add( |
4730 yield, RelocInfo::kNoPosition), zone()); | 4713 factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition), |
| 4714 zone()); |
4731 } | 4715 } |
4732 | 4716 |
4733 ParseStatementList(body, Token::RBRACE, CHECK_OK); | 4717 ParseStatementList(body, Token::RBRACE, CHECK_OK); |
4734 | 4718 |
4735 if (IsGeneratorFunction(kind)) { | 4719 if (IsGeneratorFunction(kind)) { |
4736 VariableProxy* get_proxy = factory()->NewVariableProxy( | 4720 VariableProxy* get_proxy = factory()->NewVariableProxy( |
4737 function_state_->generator_object_variable()); | 4721 function_state_->generator_object_variable()); |
4738 Expression* undefined = | 4722 Expression* undefined = |
4739 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition); | 4723 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition); |
4740 Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal, | 4724 Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal, |
4741 RelocInfo::kNoPosition); | 4725 RelocInfo::kNoPosition); |
4742 body->Add(factory()->NewExpressionStatement( | 4726 body->Add( |
4743 yield, RelocInfo::kNoPosition), zone()); | 4727 factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition), |
| 4728 zone()); |
4744 } | 4729 } |
4745 | 4730 |
4746 if (IsSubclassConstructor(kind)) { | 4731 if (IsSubclassConstructor(kind)) { |
4747 body->Add( | 4732 body->Add( |
4748 factory()->NewReturnStatement( | 4733 factory()->NewReturnStatement( |
4749 this->ThisExpression(scope_, factory(), RelocInfo::kNoPosition), | 4734 this->ThisExpression(scope_, factory(), RelocInfo::kNoPosition), |
4750 RelocInfo::kNoPosition), | 4735 RelocInfo::kNoPosition), |
4751 zone()); | 4736 zone()); |
4752 } | 4737 } |
4753 } | 4738 } |
4754 | 4739 |
4755 Expect(Token::RBRACE, CHECK_OK); | 4740 Expect(Token::RBRACE, CHECK_OK); |
4756 scope_->set_end_position(scanner()->location().end_pos); | 4741 scope_->set_end_position(scanner()->location().end_pos); |
4757 | 4742 |
4758 if (!parameters.is_simple) { | 4743 if (!parameters.is_simple) { |
4759 DCHECK_NOT_NULL(inner_scope); | 4744 DCHECK_NOT_NULL(inner_scope); |
4760 DCHECK_EQ(body, inner_block->statements()); | 4745 DCHECK_EQ(body, inner_block->statements()); |
4761 SetLanguageMode(scope_, inner_scope->language_mode()); | 4746 SetLanguageMode(scope_, inner_scope->language_mode()); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4939 } | 4924 } |
4940 | 4925 |
4941 | 4926 |
4942 Expression* Parser::ParseV8Intrinsic(bool* ok) { | 4927 Expression* Parser::ParseV8Intrinsic(bool* ok) { |
4943 // CallRuntime :: | 4928 // CallRuntime :: |
4944 // '%' Identifier Arguments | 4929 // '%' Identifier Arguments |
4945 | 4930 |
4946 int pos = peek_position(); | 4931 int pos = peek_position(); |
4947 Expect(Token::MOD, CHECK_OK); | 4932 Expect(Token::MOD, CHECK_OK); |
4948 // Allow "eval" or "arguments" for backward compatibility. | 4933 // Allow "eval" or "arguments" for backward compatibility. |
4949 const AstRawString* name = ParseIdentifier(kAllowRestrictedIdentifiers, | 4934 const AstRawString* name = |
4950 CHECK_OK); | 4935 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
4951 Scanner::Location spread_pos; | 4936 Scanner::Location spread_pos; |
4952 ExpressionClassifier classifier; | 4937 ExpressionClassifier classifier; |
4953 ZoneList<Expression*>* args = | 4938 ZoneList<Expression*>* args = |
4954 ParseArguments(&spread_pos, &classifier, CHECK_OK); | 4939 ParseArguments(&spread_pos, &classifier, CHECK_OK); |
4955 ValidateExpression(&classifier, CHECK_OK); | 4940 ValidateExpression(&classifier, CHECK_OK); |
4956 | 4941 |
4957 DCHECK(!spread_pos.IsValid()); | 4942 DCHECK(!spread_pos.IsValid()); |
4958 | 4943 |
4959 if (extension_ != NULL) { | 4944 if (extension_ != NULL) { |
4960 // The extension structures are only accessible while parsing the | 4945 // The extension structures are only accessible while parsing the |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5010 return factory()->NewUndefinedLiteral(position); | 4995 return factory()->NewUndefinedLiteral(position); |
5011 } | 4996 } |
5012 | 4997 |
5013 | 4998 |
5014 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { | 4999 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { |
5015 Declaration* decl = scope->CheckConflictingVarDeclarations(); | 5000 Declaration* decl = scope->CheckConflictingVarDeclarations(); |
5016 if (decl != NULL) { | 5001 if (decl != NULL) { |
5017 // In ES6, conflicting variable bindings are early errors. | 5002 // In ES6, conflicting variable bindings are early errors. |
5018 const AstRawString* name = decl->proxy()->raw_name(); | 5003 const AstRawString* name = decl->proxy()->raw_name(); |
5019 int position = decl->proxy()->position(); | 5004 int position = decl->proxy()->position(); |
5020 Scanner::Location location = position == RelocInfo::kNoPosition | 5005 Scanner::Location location = |
5021 ? Scanner::Location::invalid() | 5006 position == RelocInfo::kNoPosition |
5022 : Scanner::Location(position, position + 1); | 5007 ? Scanner::Location::invalid() |
| 5008 : Scanner::Location(position, position + 1); |
5023 ParserTraits::ReportMessageAt(location, MessageTemplate::kVarRedeclaration, | 5009 ParserTraits::ReportMessageAt(location, MessageTemplate::kVarRedeclaration, |
5024 name); | 5010 name); |
5025 *ok = false; | 5011 *ok = false; |
5026 } | 5012 } |
5027 } | 5013 } |
5028 | 5014 |
5029 | 5015 |
5030 void Parser::InsertShadowingVarBindingInitializers(Block* inner_block) { | 5016 void Parser::InsertShadowingVarBindingInitializers(Block* inner_block) { |
5031 // For each var-binding that shadows a parameter, insert an assignment | 5017 // For each var-binding that shadows a parameter, insert an assignment |
5032 // initializing the variable with the parameter. | 5018 // initializing the variable with the parameter. |
5033 Scope* inner_scope = inner_block->scope(); | 5019 Scope* inner_scope = inner_block->scope(); |
5034 DCHECK(inner_scope->is_declaration_scope()); | 5020 DCHECK(inner_scope->is_declaration_scope()); |
5035 Scope* function_scope = inner_scope->outer_scope(); | 5021 Scope* function_scope = inner_scope->outer_scope(); |
5036 DCHECK(function_scope->is_function_scope()); | 5022 DCHECK(function_scope->is_function_scope()); |
5037 ZoneList<Declaration*>* decls = inner_scope->declarations(); | 5023 ZoneList<Declaration*>* decls = inner_scope->declarations(); |
5038 for (int i = 0; i < decls->length(); ++i) { | 5024 for (int i = 0; i < decls->length(); ++i) { |
5039 Declaration* decl = decls->at(i); | 5025 Declaration* decl = decls->at(i); |
5040 if (decl->mode() != VAR || !decl->IsVariableDeclaration()) continue; | 5026 if (decl->mode() != VAR || !decl->IsVariableDeclaration()) continue; |
5041 const AstRawString* name = decl->proxy()->raw_name(); | 5027 const AstRawString* name = decl->proxy()->raw_name(); |
5042 Variable* parameter = function_scope->LookupLocal(name); | 5028 Variable* parameter = function_scope->LookupLocal(name); |
5043 if (parameter == nullptr) continue; | 5029 if (parameter == nullptr) continue; |
5044 VariableProxy* to = inner_scope->NewUnresolved(factory(), name); | 5030 VariableProxy* to = inner_scope->NewUnresolved(factory(), name); |
5045 VariableProxy* from = factory()->NewVariableProxy(parameter); | 5031 VariableProxy* from = factory()->NewVariableProxy(parameter); |
5046 Expression* assignment = factory()->NewAssignment( | 5032 Expression* assignment = factory()->NewAssignment(Token::ASSIGN, to, from, |
5047 Token::ASSIGN, to, from, RelocInfo::kNoPosition); | 5033 RelocInfo::kNoPosition); |
5048 Statement* statement = factory()->NewExpressionStatement( | 5034 Statement* statement = |
5049 assignment, RelocInfo::kNoPosition); | 5035 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
5050 inner_block->statements()->InsertAt(0, statement, zone()); | 5036 inner_block->statements()->InsertAt(0, statement, zone()); |
5051 } | 5037 } |
5052 } | 5038 } |
5053 | 5039 |
5054 | 5040 |
5055 void Parser::InsertSloppyBlockFunctionVarBindings(Scope* scope, bool* ok) { | 5041 void Parser::InsertSloppyBlockFunctionVarBindings(Scope* scope, bool* ok) { |
5056 // For each variable which is used as a function declaration in a sloppy | 5042 // For each variable which is used as a function declaration in a sloppy |
5057 // block, | 5043 // block, |
5058 DCHECK(scope->is_declaration_scope()); | 5044 DCHECK(scope->is_declaration_scope()); |
5059 SloppyBlockFunctionMap* map = scope->sloppy_block_function_map(); | 5045 SloppyBlockFunctionMap* map = scope->sloppy_block_function_map(); |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5230 Advance(); | 5216 Advance(); |
5231 } | 5217 } |
5232 | 5218 |
5233 | 5219 |
5234 void RegExpParser::Advance(int dist) { | 5220 void RegExpParser::Advance(int dist) { |
5235 next_pos_ += dist - 1; | 5221 next_pos_ += dist - 1; |
5236 Advance(); | 5222 Advance(); |
5237 } | 5223 } |
5238 | 5224 |
5239 | 5225 |
5240 bool RegExpParser::simple() { | 5226 bool RegExpParser::simple() { return simple_; } |
5241 return simple_; | |
5242 } | |
5243 | 5227 |
5244 | 5228 |
5245 bool RegExpParser::IsSyntaxCharacter(uc32 c) { | 5229 bool RegExpParser::IsSyntaxCharacter(uc32 c) { |
5246 return c == '^' || c == '$' || c == '\\' || c == '.' || c == '*' || | 5230 return c == '^' || c == '$' || c == '\\' || c == '.' || c == '*' || |
5247 c == '+' || c == '?' || c == '(' || c == ')' || c == '[' || c == ']' || | 5231 c == '+' || c == '?' || c == '(' || c == ')' || c == '[' || c == ']' || |
5248 c == '{' || c == '}' || c == '|'; | 5232 c == '{' || c == '}' || c == '|'; |
5249 } | 5233 } |
5250 | 5234 |
5251 | 5235 |
5252 RegExpTree* RegExpParser::ReportError(Vector<const char> message) { | 5236 RegExpTree* RegExpParser::ReportError(Vector<const char> message) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5285 // Atom Quantifier | 5269 // Atom Quantifier |
5286 RegExpTree* RegExpParser::ParseDisjunction() { | 5270 RegExpTree* RegExpParser::ParseDisjunction() { |
5287 // Used to store current state while parsing subexpressions. | 5271 // Used to store current state while parsing subexpressions. |
5288 RegExpParserState initial_state(NULL, INITIAL, RegExpLookaround::LOOKAHEAD, 0, | 5272 RegExpParserState initial_state(NULL, INITIAL, RegExpLookaround::LOOKAHEAD, 0, |
5289 zone()); | 5273 zone()); |
5290 RegExpParserState* state = &initial_state; | 5274 RegExpParserState* state = &initial_state; |
5291 // Cache the builder in a local variable for quick access. | 5275 // Cache the builder in a local variable for quick access. |
5292 RegExpBuilder* builder = initial_state.builder(); | 5276 RegExpBuilder* builder = initial_state.builder(); |
5293 while (true) { | 5277 while (true) { |
5294 switch (current()) { | 5278 switch (current()) { |
5295 case kEndMarker: | 5279 case kEndMarker: |
5296 if (state->IsSubexpression()) { | 5280 if (state->IsSubexpression()) { |
5297 // Inside a parenthesized group when hitting end of input. | 5281 // Inside a parenthesized group when hitting end of input. |
5298 ReportError(CStrVector("Unterminated group") CHECK_FAILED); | 5282 ReportError(CStrVector("Unterminated group") CHECK_FAILED); |
5299 } | 5283 } |
5300 DCHECK_EQ(INITIAL, state->group_type()); | 5284 DCHECK_EQ(INITIAL, state->group_type()); |
5301 // Parsing completed successfully. | 5285 // Parsing completed successfully. |
5302 return builder->ToRegExp(); | 5286 return builder->ToRegExp(); |
5303 case ')': { | 5287 case ')': { |
5304 if (!state->IsSubexpression()) { | 5288 if (!state->IsSubexpression()) { |
5305 ReportError(CStrVector("Unmatched ')'") CHECK_FAILED); | 5289 ReportError(CStrVector("Unmatched ')'") CHECK_FAILED); |
5306 } | 5290 } |
5307 DCHECK_NE(INITIAL, state->group_type()); | 5291 DCHECK_NE(INITIAL, state->group_type()); |
5308 | 5292 |
5309 Advance(); | 5293 Advance(); |
5310 // End disjunction parsing and convert builder content to new single | 5294 // End disjunction parsing and convert builder content to new single |
5311 // regexp atom. | 5295 // regexp atom. |
5312 RegExpTree* body = builder->ToRegExp(); | 5296 RegExpTree* body = builder->ToRegExp(); |
5313 | 5297 |
5314 int end_capture_index = captures_started(); | 5298 int end_capture_index = captures_started(); |
5315 | 5299 |
5316 int capture_index = state->capture_index(); | 5300 int capture_index = state->capture_index(); |
5317 SubexpressionType group_type = state->group_type(); | 5301 SubexpressionType group_type = state->group_type(); |
5318 | 5302 |
5319 // Build result of subexpression. | 5303 // Build result of subexpression. |
5320 if (group_type == CAPTURE) { | 5304 if (group_type == CAPTURE) { |
5321 RegExpCapture* capture = GetCapture(capture_index); | 5305 RegExpCapture* capture = GetCapture(capture_index); |
5322 capture->set_body(body); | 5306 capture->set_body(body); |
5323 body = capture; | 5307 body = capture; |
5324 } else if (group_type != GROUPING) { | 5308 } else if (group_type != GROUPING) { |
5325 DCHECK(group_type == POSITIVE_LOOKAROUND || | 5309 DCHECK(group_type == POSITIVE_LOOKAROUND || |
5326 group_type == NEGATIVE_LOOKAROUND); | 5310 group_type == NEGATIVE_LOOKAROUND); |
5327 bool is_positive = (group_type == POSITIVE_LOOKAROUND); | 5311 bool is_positive = (group_type == POSITIVE_LOOKAROUND); |
5328 body = new (zone()) RegExpLookaround( | 5312 body = new (zone()) RegExpLookaround( |
5329 body, is_positive, end_capture_index - capture_index, capture_index, | 5313 body, is_positive, end_capture_index - capture_index, |
5330 state->lookaround_type()); | 5314 capture_index, state->lookaround_type()); |
5331 } | 5315 } |
5332 | 5316 |
5333 // Restore previous state. | 5317 // Restore previous state. |
5334 state = state->previous_state(); | 5318 state = state->previous_state(); |
5335 builder = state->builder(); | 5319 builder = state->builder(); |
5336 | 5320 |
5337 builder->AddAtom(body); | 5321 builder->AddAtom(body); |
5338 // For compatability with JSC and ES3, we allow quantifiers after | 5322 // For compatability with JSC and ES3, we allow quantifiers after |
5339 // lookaheads, and break in all cases. | 5323 // lookaheads, and break in all cases. |
5340 break; | 5324 break; |
5341 } | 5325 } |
5342 case '|': { | 5326 case '|': { |
5343 Advance(); | 5327 Advance(); |
5344 builder->NewAlternative(); | 5328 builder->NewAlternative(); |
5345 continue; | 5329 continue; |
5346 } | 5330 } |
5347 case '*': | 5331 case '*': |
5348 case '+': | 5332 case '+': |
5349 case '?': | 5333 case '?': |
5350 return ReportError(CStrVector("Nothing to repeat")); | 5334 return ReportError(CStrVector("Nothing to repeat")); |
5351 case '^': { | 5335 case '^': { |
5352 Advance(); | 5336 Advance(); |
5353 if (multiline_) { | 5337 if (multiline_) { |
5354 builder->AddAssertion( | 5338 builder->AddAssertion( |
5355 new(zone()) RegExpAssertion(RegExpAssertion::START_OF_LINE)); | 5339 new (zone()) RegExpAssertion(RegExpAssertion::START_OF_LINE)); |
5356 } else { | 5340 } else { |
5357 builder->AddAssertion( | 5341 builder->AddAssertion( |
5358 new(zone()) RegExpAssertion(RegExpAssertion::START_OF_INPUT)); | 5342 new (zone()) RegExpAssertion(RegExpAssertion::START_OF_INPUT)); |
5359 set_contains_anchor(); | 5343 set_contains_anchor(); |
5360 } | 5344 } |
5361 continue; | 5345 continue; |
5362 } | 5346 } |
5363 case '$': { | 5347 case '$': { |
5364 Advance(); | 5348 Advance(); |
5365 RegExpAssertion::AssertionType assertion_type = | 5349 RegExpAssertion::AssertionType assertion_type = |
5366 multiline_ ? RegExpAssertion::END_OF_LINE : | 5350 multiline_ ? RegExpAssertion::END_OF_LINE |
5367 RegExpAssertion::END_OF_INPUT; | 5351 : RegExpAssertion::END_OF_INPUT; |
5368 builder->AddAssertion(new(zone()) RegExpAssertion(assertion_type)); | 5352 builder->AddAssertion(new (zone()) RegExpAssertion(assertion_type)); |
5369 continue; | 5353 continue; |
5370 } | 5354 } |
5371 case '.': { | 5355 case '.': { |
5372 Advance(); | 5356 Advance(); |
5373 // everything except \x0a, \x0d, \u2028 and \u2029 | 5357 // everything except \x0a, \x0d, \u2028 and \u2029 |
5374 ZoneList<CharacterRange>* ranges = | 5358 ZoneList<CharacterRange>* ranges = |
5375 new(zone()) ZoneList<CharacterRange>(2, zone()); | 5359 new (zone()) ZoneList<CharacterRange>(2, zone()); |
5376 CharacterRange::AddClassEscape('.', ranges, zone()); | 5360 CharacterRange::AddClassEscape('.', ranges, zone()); |
5377 RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false); | 5361 RegExpTree* atom = new (zone()) RegExpCharacterClass(ranges, false); |
5378 builder->AddAtom(atom); | 5362 builder->AddAtom(atom); |
5379 break; | 5363 break; |
5380 } | 5364 } |
5381 case '(': { | 5365 case '(': { |
5382 SubexpressionType subexpr_type = CAPTURE; | 5366 SubexpressionType subexpr_type = CAPTURE; |
5383 RegExpLookaround::Type lookaround_type = state->lookaround_type(); | 5367 RegExpLookaround::Type lookaround_type = state->lookaround_type(); |
5384 Advance(); | 5368 Advance(); |
5385 if (current() == '?') { | 5369 if (current() == '?') { |
| 5370 switch (Next()) { |
| 5371 case ':': |
| 5372 subexpr_type = GROUPING; |
| 5373 break; |
| 5374 case '=': |
| 5375 lookaround_type = RegExpLookaround::LOOKAHEAD; |
| 5376 subexpr_type = POSITIVE_LOOKAROUND; |
| 5377 break; |
| 5378 case '!': |
| 5379 lookaround_type = RegExpLookaround::LOOKAHEAD; |
| 5380 subexpr_type = NEGATIVE_LOOKAROUND; |
| 5381 break; |
| 5382 case '<': |
| 5383 if (FLAG_harmony_regexp_lookbehind) { |
| 5384 Advance(); |
| 5385 lookaround_type = RegExpLookaround::LOOKBEHIND; |
| 5386 if (Next() == '=') { |
| 5387 subexpr_type = POSITIVE_LOOKAROUND; |
| 5388 break; |
| 5389 } else if (Next() == '!') { |
| 5390 subexpr_type = NEGATIVE_LOOKAROUND; |
| 5391 break; |
| 5392 } |
| 5393 } |
| 5394 // Fall through. |
| 5395 default: |
| 5396 ReportError(CStrVector("Invalid group") CHECK_FAILED); |
| 5397 break; |
| 5398 } |
| 5399 Advance(2); |
| 5400 } else { |
| 5401 if (captures_started_ >= kMaxCaptures) { |
| 5402 ReportError(CStrVector("Too many captures") CHECK_FAILED); |
| 5403 } |
| 5404 captures_started_++; |
| 5405 } |
| 5406 // Store current state and begin new disjunction parsing. |
| 5407 state = new (zone()) RegExpParserState( |
| 5408 state, subexpr_type, lookaround_type, captures_started_, zone()); |
| 5409 builder = state->builder(); |
| 5410 continue; |
| 5411 } |
| 5412 case '[': { |
| 5413 RegExpTree* atom = ParseCharacterClass(CHECK_FAILED); |
| 5414 builder->AddAtom(atom); |
| 5415 break; |
| 5416 } |
| 5417 // Atom :: |
| 5418 // \ AtomEscape |
| 5419 case '\\': |
5386 switch (Next()) { | 5420 switch (Next()) { |
5387 case ':': | 5421 case kEndMarker: |
5388 subexpr_type = GROUPING; | 5422 return ReportError(CStrVector("\\ at end of pattern")); |
5389 break; | 5423 case 'b': |
5390 case '=': | 5424 Advance(2); |
5391 lookaround_type = RegExpLookaround::LOOKAHEAD; | 5425 builder->AddAssertion( |
5392 subexpr_type = POSITIVE_LOOKAROUND; | 5426 new (zone()) RegExpAssertion(RegExpAssertion::BOUNDARY)); |
5393 break; | 5427 continue; |
5394 case '!': | 5428 case 'B': |
5395 lookaround_type = RegExpLookaround::LOOKAHEAD; | 5429 Advance(2); |
5396 subexpr_type = NEGATIVE_LOOKAROUND; | 5430 builder->AddAssertion( |
5397 break; | 5431 new (zone()) RegExpAssertion(RegExpAssertion::NON_BOUNDARY)); |
5398 case '<': | 5432 continue; |
5399 if (FLAG_harmony_regexp_lookbehind) { | 5433 // AtomEscape :: |
| 5434 // CharacterClassEscape |
| 5435 // |
| 5436 // CharacterClassEscape :: one of |
| 5437 // d D s S w W |
| 5438 case 'd': |
| 5439 case 'D': |
| 5440 case 's': |
| 5441 case 'S': |
| 5442 case 'w': |
| 5443 case 'W': { |
| 5444 uc32 c = Next(); |
| 5445 Advance(2); |
| 5446 ZoneList<CharacterRange>* ranges = |
| 5447 new (zone()) ZoneList<CharacterRange>(2, zone()); |
| 5448 CharacterRange::AddClassEscape(c, ranges, zone()); |
| 5449 RegExpTree* atom = new (zone()) RegExpCharacterClass(ranges, false); |
| 5450 builder->AddAtom(atom); |
| 5451 break; |
| 5452 } |
| 5453 case '1': |
| 5454 case '2': |
| 5455 case '3': |
| 5456 case '4': |
| 5457 case '5': |
| 5458 case '6': |
| 5459 case '7': |
| 5460 case '8': |
| 5461 case '9': { |
| 5462 int index = 0; |
| 5463 if (ParseBackReferenceIndex(&index)) { |
| 5464 if (state->IsInsideCaptureGroup(index)) { |
| 5465 // The backreference is inside the capture group it refers to. |
| 5466 // Nothing can possibly have been captured yet. |
| 5467 builder->AddEmpty(); |
| 5468 } else { |
| 5469 RegExpCapture* capture = GetCapture(index); |
| 5470 RegExpTree* atom = new (zone()) RegExpBackReference(capture); |
| 5471 builder->AddAtom(atom); |
| 5472 } |
| 5473 break; |
| 5474 } |
| 5475 uc32 first_digit = Next(); |
| 5476 if (first_digit == '8' || first_digit == '9') { |
| 5477 // If the 'u' flag is present, only syntax characters can be |
| 5478 // escaped, |
| 5479 // no other identity escapes are allowed. If the 'u' flag is not |
| 5480 // present, all identity escapes are allowed. |
| 5481 if (!FLAG_harmony_unicode_regexps || !unicode_) { |
| 5482 builder->AddCharacter(first_digit); |
| 5483 Advance(2); |
| 5484 } else { |
| 5485 return ReportError(CStrVector("Invalid escape")); |
| 5486 } |
| 5487 break; |
| 5488 } |
| 5489 } |
| 5490 // FALLTHROUGH |
| 5491 case '0': { |
| 5492 Advance(); |
| 5493 uc32 octal = ParseOctalLiteral(); |
| 5494 builder->AddCharacter(octal); |
| 5495 break; |
| 5496 } |
| 5497 // ControlEscape :: one of |
| 5498 // f n r t v |
| 5499 case 'f': |
| 5500 Advance(2); |
| 5501 builder->AddCharacter('\f'); |
| 5502 break; |
| 5503 case 'n': |
| 5504 Advance(2); |
| 5505 builder->AddCharacter('\n'); |
| 5506 break; |
| 5507 case 'r': |
| 5508 Advance(2); |
| 5509 builder->AddCharacter('\r'); |
| 5510 break; |
| 5511 case 't': |
| 5512 Advance(2); |
| 5513 builder->AddCharacter('\t'); |
| 5514 break; |
| 5515 case 'v': |
| 5516 Advance(2); |
| 5517 builder->AddCharacter('\v'); |
| 5518 break; |
| 5519 case 'c': { |
| 5520 Advance(); |
| 5521 uc32 controlLetter = Next(); |
| 5522 // Special case if it is an ASCII letter. |
| 5523 // Convert lower case letters to uppercase. |
| 5524 uc32 letter = controlLetter & ~('a' ^ 'A'); |
| 5525 if (letter < 'A' || 'Z' < letter) { |
| 5526 // controlLetter is not in range 'A'-'Z' or 'a'-'z'. |
| 5527 // This is outside the specification. We match JSC in |
| 5528 // reading the backslash as a literal character instead |
| 5529 // of as starting an escape. |
| 5530 builder->AddCharacter('\\'); |
| 5531 } else { |
| 5532 Advance(2); |
| 5533 builder->AddCharacter(controlLetter & 0x1f); |
| 5534 } |
| 5535 break; |
| 5536 } |
| 5537 case 'x': { |
| 5538 Advance(2); |
| 5539 uc32 value; |
| 5540 if (ParseHexEscape(2, &value)) { |
| 5541 builder->AddCharacter(value); |
| 5542 } else if (!FLAG_harmony_unicode_regexps || !unicode_) { |
| 5543 builder->AddCharacter('x'); |
| 5544 } else { |
| 5545 // If the 'u' flag is present, invalid escapes are not treated as |
| 5546 // identity escapes. |
| 5547 return ReportError(CStrVector("Invalid escape")); |
| 5548 } |
| 5549 break; |
| 5550 } |
| 5551 case 'u': { |
| 5552 Advance(2); |
| 5553 uc32 value; |
| 5554 if (ParseUnicodeEscape(&value)) { |
| 5555 builder->AddCharacter(value); |
| 5556 } else if (!FLAG_harmony_unicode_regexps || !unicode_) { |
| 5557 builder->AddCharacter('u'); |
| 5558 } else { |
| 5559 // If the 'u' flag is present, invalid escapes are not treated as |
| 5560 // identity escapes. |
| 5561 return ReportError(CStrVector("Invalid unicode escape")); |
| 5562 } |
| 5563 break; |
| 5564 } |
| 5565 default: |
| 5566 Advance(); |
| 5567 // If the 'u' flag is present, only syntax characters can be |
| 5568 // escaped, no |
| 5569 // other identity escapes are allowed. If the 'u' flag is not |
| 5570 // present, |
| 5571 // all identity escapes are allowed. |
| 5572 if (!FLAG_harmony_unicode_regexps || !unicode_ || |
| 5573 IsSyntaxCharacter(current())) { |
| 5574 builder->AddCharacter(current()); |
5400 Advance(); | 5575 Advance(); |
5401 lookaround_type = RegExpLookaround::LOOKBEHIND; | 5576 } else { |
5402 if (Next() == '=') { | 5577 return ReportError(CStrVector("Invalid escape")); |
5403 subexpr_type = POSITIVE_LOOKAROUND; | 5578 } |
5404 break; | 5579 break; |
5405 } else if (Next() == '!') { | 5580 } |
5406 subexpr_type = NEGATIVE_LOOKAROUND; | 5581 break; |
5407 break; | 5582 case '{': { |
5408 } | 5583 int dummy; |
5409 } | 5584 if (ParseIntervalQuantifier(&dummy, &dummy)) { |
5410 // Fall through. | 5585 ReportError(CStrVector("Nothing to repeat") CHECK_FAILED); |
5411 default: | 5586 } |
5412 ReportError(CStrVector("Invalid group") CHECK_FAILED); | 5587 // fallthrough |
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 } | 5588 } |
5568 default: | 5589 default: |
5569 Advance(); | 5590 builder->AddCharacter(current()); |
5570 // If the 'u' flag is present, only syntax characters can be escaped, no | 5591 Advance(); |
5571 // other identity escapes are allowed. If the 'u' flag is not present, | 5592 break; |
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()) | 5593 } // end switch(current()) |
5595 | 5594 |
5596 int min; | 5595 int min; |
5597 int max; | 5596 int max; |
5598 switch (current()) { | 5597 switch (current()) { |
5599 // QuantifierPrefix :: | 5598 // QuantifierPrefix :: |
5600 // * | 5599 // * |
5601 // + | 5600 // + |
5602 // ? | 5601 // ? |
5603 // { | 5602 // { |
5604 case '*': | 5603 case '*': |
5605 min = 0; | 5604 min = 0; |
5606 max = RegExpTree::kInfinity; | 5605 max = RegExpTree::kInfinity; |
5607 Advance(); | 5606 Advance(); |
5608 break; | 5607 break; |
5609 case '+': | 5608 case '+': |
5610 min = 1; | 5609 min = 1; |
5611 max = RegExpTree::kInfinity; | 5610 max = RegExpTree::kInfinity; |
5612 Advance(); | 5611 Advance(); |
5613 break; | 5612 break; |
5614 case '?': | 5613 case '?': |
5615 min = 0; | 5614 min = 0; |
5616 max = 1; | 5615 max = 1; |
5617 Advance(); | 5616 Advance(); |
5618 break; | 5617 break; |
5619 case '{': | 5618 case '{': |
5620 if (ParseIntervalQuantifier(&min, &max)) { | 5619 if (ParseIntervalQuantifier(&min, &max)) { |
5621 if (max < min) { | 5620 if (max < min) { |
5622 ReportError(CStrVector("numbers out of order in {} quantifier.") | 5621 ReportError(CStrVector("numbers out of order in {} quantifier.") |
5623 CHECK_FAILED); | 5622 CHECK_FAILED); |
5624 } | 5623 } |
5625 break; | 5624 break; |
5626 } else { | 5625 } else { |
5627 continue; | 5626 continue; |
5628 } | 5627 } |
5629 default: | 5628 default: |
5630 continue; | 5629 continue; |
5631 } | 5630 } |
5632 RegExpQuantifier::QuantifierType quantifier_type = RegExpQuantifier::GREEDY; | 5631 RegExpQuantifier::QuantifierType quantifier_type = RegExpQuantifier::GREEDY; |
5633 if (current() == '?') { | 5632 if (current() == '?') { |
5634 quantifier_type = RegExpQuantifier::NON_GREEDY; | 5633 quantifier_type = RegExpQuantifier::NON_GREEDY; |
5635 Advance(); | 5634 Advance(); |
5636 } else if (FLAG_regexp_possessive_quantifier && current() == '+') { | 5635 } else if (FLAG_regexp_possessive_quantifier && current() == '+') { |
5637 // FLAG_regexp_possessive_quantifier is a debug-only flag. | 5636 // FLAG_regexp_possessive_quantifier is a debug-only flag. |
5638 quantifier_type = RegExpQuantifier::POSSESSIVE; | 5637 quantifier_type = RegExpQuantifier::POSSESSIVE; |
5639 Advance(); | 5638 Advance(); |
5640 } | 5639 } |
5641 builder->AddQuantifierToAtom(min, max, quantifier_type); | 5640 builder->AddQuantifierToAtom(min, max, quantifier_type); |
5642 } | 5641 } |
5643 } | 5642 } |
5644 | 5643 |
5645 | 5644 |
5646 #ifdef DEBUG | 5645 #ifdef DEBUG |
5647 // Currently only used in an DCHECK. | 5646 // Currently only used in an DCHECK. |
5648 static bool IsSpecialClassEscape(uc32 c) { | 5647 static bool IsSpecialClassEscape(uc32 c) { |
5649 switch (c) { | 5648 switch (c) { |
5650 case 'd': case 'D': | 5649 case 'd': |
5651 case 's': case 'S': | 5650 case 'D': |
5652 case 'w': case 'W': | 5651 case 's': |
| 5652 case 'S': |
| 5653 case 'w': |
| 5654 case 'W': |
5653 return true; | 5655 return true; |
5654 default: | 5656 default: |
5655 return false; | 5657 return false; |
5656 } | 5658 } |
5657 } | 5659 } |
5658 #endif | 5660 #endif |
5659 | 5661 |
5660 | 5662 |
5661 // In order to know whether an escape is a backreference or not we have to scan | 5663 // 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 | 5664 // the entire regexp and find the number of capturing parentheses. However we |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5929 return '\t'; | 5931 return '\t'; |
5930 case 'v': | 5932 case 'v': |
5931 Advance(); | 5933 Advance(); |
5932 return '\v'; | 5934 return '\v'; |
5933 case 'c': { | 5935 case 'c': { |
5934 uc32 controlLetter = Next(); | 5936 uc32 controlLetter = Next(); |
5935 uc32 letter = controlLetter & ~('A' ^ 'a'); | 5937 uc32 letter = controlLetter & ~('A' ^ 'a'); |
5936 // For compatibility with JSC, inside a character class | 5938 // For compatibility with JSC, inside a character class |
5937 // we also accept digits and underscore as control characters. | 5939 // we also accept digits and underscore as control characters. |
5938 if ((controlLetter >= '0' && controlLetter <= '9') || | 5940 if ((controlLetter >= '0' && controlLetter <= '9') || |
5939 controlLetter == '_' || | 5941 controlLetter == '_' || (letter >= 'A' && letter <= 'Z')) { |
5940 (letter >= 'A' && letter <= 'Z')) { | |
5941 Advance(2); | 5942 Advance(2); |
5942 // Control letters mapped to ASCII control characters in the range | 5943 // Control letters mapped to ASCII control characters in the range |
5943 // 0x00-0x1f. | 5944 // 0x00-0x1f. |
5944 return controlLetter & 0x1f; | 5945 return controlLetter & 0x1f; |
5945 } | 5946 } |
5946 // We match JSC in reading the backslash as a literal | 5947 // We match JSC in reading the backslash as a literal |
5947 // character instead of as starting an escape. | 5948 // character instead of as starting an escape. |
5948 return '\\'; | 5949 return '\\'; |
5949 } | 5950 } |
5950 case '0': case '1': case '2': case '3': case '4': case '5': | 5951 case '0': |
5951 case '6': case '7': | 5952 case '1': |
| 5953 case '2': |
| 5954 case '3': |
| 5955 case '4': |
| 5956 case '5': |
| 5957 case '6': |
| 5958 case '7': |
5952 // For compatibility, we interpret a decimal escape that isn't | 5959 // For compatibility, we interpret a decimal escape that isn't |
5953 // a back reference (and therefore either \0 or not valid according | 5960 // a back reference (and therefore either \0 or not valid according |
5954 // to the specification) as a 1..3 digit octal character code. | 5961 // to the specification) as a 1..3 digit octal character code. |
5955 return ParseOctalLiteral(); | 5962 return ParseOctalLiteral(); |
5956 case 'x': { | 5963 case 'x': { |
5957 Advance(); | 5964 Advance(); |
5958 uc32 value; | 5965 uc32 value; |
5959 if (ParseHexEscape(2, &value)) { | 5966 if (ParseHexEscape(2, &value)) { |
5960 return value; | 5967 return value; |
5961 } | 5968 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5999 } | 6006 } |
6000 return 0; | 6007 return 0; |
6001 } | 6008 } |
6002 | 6009 |
6003 | 6010 |
6004 CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) { | 6011 CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) { |
6005 DCHECK_EQ(0, *char_class); | 6012 DCHECK_EQ(0, *char_class); |
6006 uc32 first = current(); | 6013 uc32 first = current(); |
6007 if (first == '\\') { | 6014 if (first == '\\') { |
6008 switch (Next()) { | 6015 switch (Next()) { |
6009 case 'w': case 'W': case 'd': case 'D': case 's': case 'S': { | 6016 case 'w': |
| 6017 case 'W': |
| 6018 case 'd': |
| 6019 case 'D': |
| 6020 case 's': |
| 6021 case 'S': { |
6010 *char_class = Next(); | 6022 *char_class = Next(); |
6011 Advance(2); | 6023 Advance(2); |
6012 return CharacterRange::Singleton(0); // Return dummy value. | 6024 return CharacterRange::Singleton(0); // Return dummy value. |
6013 } | 6025 } |
6014 case kEndMarker: | 6026 case kEndMarker: |
6015 return ReportError(CStrVector("\\ at end of pattern")); | 6027 return ReportError(CStrVector("\\ at end of pattern")); |
6016 default: | 6028 default: |
6017 uc32 c = ParseClassCharacterEscape(CHECK_FAILED); | 6029 uc32 c = ParseClassCharacterEscape(CHECK_FAILED); |
6018 return CharacterRange::Singleton(c); | 6030 return CharacterRange::Singleton(c); |
6019 } | 6031 } |
6020 } else { | 6032 } else { |
6021 Advance(); | 6033 Advance(); |
6022 return CharacterRange::Singleton(first); | 6034 return CharacterRange::Singleton(first); |
6023 } | 6035 } |
6024 } | 6036 } |
6025 | 6037 |
6026 | 6038 |
6027 static const uc16 kNoCharClass = 0; | 6039 static const uc16 kNoCharClass = 0; |
6028 | 6040 |
6029 // Adds range or pre-defined character class to character ranges. | 6041 // Adds range or pre-defined character class to character ranges. |
6030 // If char_class is not kInvalidClass, it's interpreted as a class | 6042 // If char_class is not kInvalidClass, it's interpreted as a class |
6031 // escape (i.e., 's' means whitespace, from '\s'). | 6043 // escape (i.e., 's' means whitespace, from '\s'). |
6032 static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges, | 6044 static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges, |
6033 uc16 char_class, | 6045 uc16 char_class, CharacterRange range, |
6034 CharacterRange range, | |
6035 Zone* zone) { | 6046 Zone* zone) { |
6036 if (char_class != kNoCharClass) { | 6047 if (char_class != kNoCharClass) { |
6037 CharacterRange::AddClassEscape(char_class, ranges, zone); | 6048 CharacterRange::AddClassEscape(char_class, ranges, zone); |
6038 } else { | 6049 } else { |
6039 ranges->Add(range, zone); | 6050 ranges->Add(range, zone); |
6040 } | 6051 } |
6041 } | 6052 } |
6042 | 6053 |
6043 | 6054 |
6044 RegExpTree* RegExpParser::ParseCharacterClass() { | 6055 RegExpTree* RegExpParser::ParseCharacterClass() { |
6045 static const char* kUnterminated = "Unterminated character class"; | 6056 static const char* kUnterminated = "Unterminated character class"; |
6046 static const char* kRangeOutOfOrder = "Range out of order in character class"; | 6057 static const char* kRangeOutOfOrder = "Range out of order in character class"; |
6047 | 6058 |
6048 DCHECK_EQ(current(), '['); | 6059 DCHECK_EQ(current(), '['); |
6049 Advance(); | 6060 Advance(); |
6050 bool is_negated = false; | 6061 bool is_negated = false; |
6051 if (current() == '^') { | 6062 if (current() == '^') { |
6052 is_negated = true; | 6063 is_negated = true; |
6053 Advance(); | 6064 Advance(); |
6054 } | 6065 } |
6055 ZoneList<CharacterRange>* ranges = | 6066 ZoneList<CharacterRange>* ranges = |
6056 new(zone()) ZoneList<CharacterRange>(2, zone()); | 6067 new (zone()) ZoneList<CharacterRange>(2, zone()); |
6057 while (has_more() && current() != ']') { | 6068 while (has_more() && current() != ']') { |
6058 uc16 char_class = kNoCharClass; | 6069 uc16 char_class = kNoCharClass; |
6059 CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED); | 6070 CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED); |
6060 if (current() == '-') { | 6071 if (current() == '-') { |
6061 Advance(); | 6072 Advance(); |
6062 if (current() == kEndMarker) { | 6073 if (current() == kEndMarker) { |
6063 // If we reach the end we break out of the loop and let the | 6074 // If we reach the end we break out of the loop and let the |
6064 // following code report an error. | 6075 // following code report an error. |
6065 break; | 6076 break; |
6066 } else if (current() == ']') { | 6077 } else if (current() == ']') { |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6242 Expression* cooked_str = cooked_strings->at(i); | 6253 Expression* cooked_str = cooked_strings->at(i); |
6243 | 6254 |
6244 // Let middle be ToString(sub). | 6255 // Let middle be ToString(sub). |
6245 ZoneList<Expression*>* args = | 6256 ZoneList<Expression*>* args = |
6246 new (zone()) ZoneList<Expression*>(1, zone()); | 6257 new (zone()) ZoneList<Expression*>(1, zone()); |
6247 args->Add(sub, zone()); | 6258 args->Add(sub, zone()); |
6248 Expression* middle = factory()->NewCallRuntime(Runtime::kInlineToString, | 6259 Expression* middle = factory()->NewCallRuntime(Runtime::kInlineToString, |
6249 args, sub->position()); | 6260 args, sub->position()); |
6250 | 6261 |
6251 expr = factory()->NewBinaryOperation( | 6262 expr = factory()->NewBinaryOperation( |
6252 Token::ADD, factory()->NewBinaryOperation( | 6263 Token::ADD, factory()->NewBinaryOperation(Token::ADD, expr, middle, |
6253 Token::ADD, expr, middle, expr->position()), | 6264 expr->position()), |
6254 cooked_str, sub->position()); | 6265 cooked_str, sub->position()); |
6255 } | 6266 } |
6256 return expr; | 6267 return expr; |
6257 } else { | 6268 } else { |
6258 uint32_t hash = ComputeTemplateLiteralHash(lit); | 6269 uint32_t hash = ComputeTemplateLiteralHash(lit); |
6259 | 6270 |
6260 int cooked_idx = function_state_->NextMaterializedLiteralIndex(); | 6271 int cooked_idx = function_state_->NextMaterializedLiteralIndex(); |
6261 int raw_idx = function_state_->NextMaterializedLiteralIndex(); | 6272 int raw_idx = function_state_->NextMaterializedLiteralIndex(); |
6262 | 6273 |
6263 // $getTemplateCallSite | 6274 // $getTemplateCallSite |
6264 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(4, zone()); | 6275 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(4, zone()); |
6265 args->Add(factory()->NewArrayLiteral( | 6276 args->Add(factory()->NewArrayLiteral( |
6266 const_cast<ZoneList<Expression*>*>(cooked_strings), | 6277 const_cast<ZoneList<Expression*>*>(cooked_strings), |
6267 cooked_idx, is_strong(language_mode()), pos), | 6278 cooked_idx, is_strong(language_mode()), pos), |
6268 zone()); | 6279 zone()); |
6269 args->Add( | 6280 args->Add(factory()->NewArrayLiteral( |
6270 factory()->NewArrayLiteral( | 6281 const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx, |
6271 const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx, | 6282 is_strong(language_mode()), pos), |
6272 is_strong(language_mode()), pos), | 6283 zone()); |
6273 zone()); | |
6274 | 6284 |
6275 // Ensure hash is suitable as a Smi value | 6285 // Ensure hash is suitable as a Smi value |
6276 Smi* hash_obj = Smi::cast(Internals::IntToSmi(static_cast<int>(hash))); | 6286 Smi* hash_obj = Smi::cast(Internals::IntToSmi(static_cast<int>(hash))); |
6277 args->Add(factory()->NewSmiLiteral(hash_obj->value(), pos), zone()); | 6287 args->Add(factory()->NewSmiLiteral(hash_obj->value(), pos), zone()); |
6278 | 6288 |
6279 this->CheckPossibleEvalCall(tag, scope_); | 6289 this->CheckPossibleEvalCall(tag, scope_); |
6280 Expression* call_site = factory()->NewCallRuntime( | 6290 Expression* call_site = factory()->NewCallRuntime( |
6281 Context::GET_TEMPLATE_CALL_SITE_INDEX, args, start); | 6291 Context::GET_TEMPLATE_CALL_SITE_INDEX, args, start); |
6282 | 6292 |
6283 // Call TagFn | 6293 // Call TagFn |
6284 ZoneList<Expression*>* call_args = | 6294 ZoneList<Expression*>* call_args = |
6285 new (zone()) ZoneList<Expression*>(expressions->length() + 1, zone()); | 6295 new (zone()) ZoneList<Expression*>(expressions->length() + 1, zone()); |
6286 call_args->Add(call_site, zone()); | 6296 call_args->Add(call_site, zone()); |
6287 call_args->AddAll(*expressions, zone()); | 6297 call_args->AddAll(*expressions, zone()); |
6288 return factory()->NewCall(tag, call_args, pos); | 6298 return factory()->NewCall(tag, call_args, pos); |
6289 } | 6299 } |
6290 } | 6300 } |
6291 | 6301 |
6292 | 6302 |
6293 uint32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) { | 6303 uint32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) { |
6294 const ZoneList<Expression*>* raw_strings = lit->raw(); | 6304 const ZoneList<Expression*>* raw_strings = lit->raw(); |
6295 int total = raw_strings->length(); | 6305 int total = raw_strings->length(); |
6296 DCHECK(total); | 6306 DCHECK(total); |
6297 | 6307 |
6298 uint32_t running_hash = 0; | 6308 uint32_t running_hash = 0; |
6299 | 6309 |
6300 for (int index = 0; index < total; ++index) { | 6310 for (int index = 0; index < total; ++index) { |
6301 if (index) { | 6311 if (index) { |
6302 running_hash = StringHasher::ComputeRunningHashOneByte( | 6312 running_hash = |
6303 running_hash, "${}", 3); | 6313 StringHasher::ComputeRunningHashOneByte(running_hash, "${}", 3); |
6304 } | 6314 } |
6305 | 6315 |
6306 const AstRawString* raw_string = | 6316 const AstRawString* raw_string = |
6307 raw_strings->at(index)->AsLiteral()->raw_value()->AsString(); | 6317 raw_strings->at(index)->AsLiteral()->raw_value()->AsString(); |
6308 if (raw_string->is_one_byte()) { | 6318 if (raw_string->is_one_byte()) { |
6309 const char* data = reinterpret_cast<const char*>(raw_string->raw_data()); | 6319 const char* data = reinterpret_cast<const char*>(raw_string->raw_data()); |
6310 running_hash = StringHasher::ComputeRunningHashOneByte( | 6320 running_hash = StringHasher::ComputeRunningHashOneByte( |
6311 running_hash, data, raw_string->length()); | 6321 running_hash, data, raw_string->length()); |
6312 } else { | 6322 } else { |
6313 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); | 6323 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6455 } | 6465 } |
6456 | 6466 |
6457 | 6467 |
6458 void Parser::RaiseLanguageMode(LanguageMode mode) { | 6468 void Parser::RaiseLanguageMode(LanguageMode mode) { |
6459 SetLanguageMode(scope_, | 6469 SetLanguageMode(scope_, |
6460 static_cast<LanguageMode>(scope_->language_mode() | mode)); | 6470 static_cast<LanguageMode>(scope_->language_mode() | mode)); |
6461 } | 6471 } |
6462 | 6472 |
6463 } // namespace internal | 6473 } // namespace internal |
6464 } // namespace v8 | 6474 } // namespace v8 |
OLD | NEW |