blob: fa2893b64b906f835ac312b5d8617e38284d0971 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/parsing/parser.h"
6
7#include "src/api.h"
8#include "src/ast/ast.h"
Ben Murdoch097c5b22016-05-18 11:27:45 +01009#include "src/ast/ast-expression-rewriter.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010#include "src/ast/ast-expression-visitor.h"
11#include "src/ast/ast-literal-reindexer.h"
12#include "src/ast/scopeinfo.h"
13#include "src/bailout-reason.h"
14#include "src/base/platform/platform.h"
15#include "src/bootstrapper.h"
16#include "src/char-predicates-inl.h"
17#include "src/codegen.h"
18#include "src/compiler.h"
19#include "src/messages.h"
20#include "src/parsing/parameter-initializer-rewriter.h"
21#include "src/parsing/parser-base.h"
22#include "src/parsing/rewriter.h"
23#include "src/parsing/scanner-character-streams.h"
24#include "src/runtime/runtime.h"
25#include "src/string-stream.h"
Ben Murdoch097c5b22016-05-18 11:27:45 +010026#include "src/tracing/trace-event.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000027
28namespace v8 {
29namespace internal {
30
31ScriptData::ScriptData(const byte* data, int length)
32 : owns_data_(false), rejected_(false), data_(data), length_(length) {
33 if (!IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment)) {
34 byte* copy = NewArray<byte>(length);
35 DCHECK(IsAligned(reinterpret_cast<intptr_t>(copy), kPointerAlignment));
36 CopyBytes(copy, data, length);
37 data_ = copy;
38 AcquireDataOwnership();
39 }
40}
41
42
43ParseInfo::ParseInfo(Zone* zone)
44 : zone_(zone),
45 flags_(0),
46 source_stream_(nullptr),
47 source_stream_encoding_(ScriptCompiler::StreamedSource::ONE_BYTE),
48 extension_(nullptr),
49 compile_options_(ScriptCompiler::kNoCompileOptions),
50 script_scope_(nullptr),
51 unicode_cache_(nullptr),
52 stack_limit_(0),
53 hash_seed_(0),
54 cached_data_(nullptr),
55 ast_value_factory_(nullptr),
56 literal_(nullptr),
57 scope_(nullptr) {}
58
59
60ParseInfo::ParseInfo(Zone* zone, Handle<JSFunction> function)
61 : ParseInfo(zone, Handle<SharedFunctionInfo>(function->shared())) {
62 set_closure(function);
63 set_context(Handle<Context>(function->context()));
64}
65
66
67ParseInfo::ParseInfo(Zone* zone, Handle<SharedFunctionInfo> shared)
68 : ParseInfo(zone) {
69 isolate_ = shared->GetIsolate();
70
71 set_lazy();
72 set_hash_seed(isolate_->heap()->HashSeed());
73 set_stack_limit(isolate_->stack_guard()->real_climit());
74 set_unicode_cache(isolate_->unicode_cache());
75 set_language_mode(shared->language_mode());
76 set_shared_info(shared);
77
78 Handle<Script> script(Script::cast(shared->script()));
79 set_script(script);
80 if (!script.is_null() && script->type() == Script::TYPE_NATIVE) {
81 set_native();
82 }
83}
84
85
86ParseInfo::ParseInfo(Zone* zone, Handle<Script> script) : ParseInfo(zone) {
87 isolate_ = script->GetIsolate();
88
89 set_hash_seed(isolate_->heap()->HashSeed());
90 set_stack_limit(isolate_->stack_guard()->real_climit());
91 set_unicode_cache(isolate_->unicode_cache());
92 set_script(script);
93
94 if (script->type() == Script::TYPE_NATIVE) {
95 set_native();
96 }
97}
98
99
100FunctionEntry ParseData::GetFunctionEntry(int start) {
101 // The current pre-data entry must be a FunctionEntry with the given
102 // start position.
103 if ((function_index_ + FunctionEntry::kSize <= Length()) &&
104 (static_cast<int>(Data()[function_index_]) == start)) {
105 int index = function_index_;
106 function_index_ += FunctionEntry::kSize;
107 Vector<unsigned> subvector(&(Data()[index]), FunctionEntry::kSize);
108 return FunctionEntry(subvector);
109 }
110 return FunctionEntry();
111}
112
113
114int ParseData::FunctionCount() {
115 int functions_size = FunctionsSize();
116 if (functions_size < 0) return 0;
117 if (functions_size % FunctionEntry::kSize != 0) return 0;
118 return functions_size / FunctionEntry::kSize;
119}
120
121
122bool ParseData::IsSane() {
123 if (!IsAligned(script_data_->length(), sizeof(unsigned))) return false;
124 // Check that the header data is valid and doesn't specify
125 // point to positions outside the store.
126 int data_length = Length();
127 if (data_length < PreparseDataConstants::kHeaderSize) return false;
128 if (Magic() != PreparseDataConstants::kMagicNumber) return false;
129 if (Version() != PreparseDataConstants::kCurrentVersion) return false;
130 if (HasError()) return false;
131 // Check that the space allocated for function entries is sane.
132 int functions_size = FunctionsSize();
133 if (functions_size < 0) return false;
134 if (functions_size % FunctionEntry::kSize != 0) return false;
135 // Check that the total size has room for header and function entries.
136 int minimum_size =
137 PreparseDataConstants::kHeaderSize + functions_size;
138 if (data_length < minimum_size) return false;
139 return true;
140}
141
142
143void ParseData::Initialize() {
144 // Prepares state for use.
145 int data_length = Length();
146 if (data_length >= PreparseDataConstants::kHeaderSize) {
147 function_index_ = PreparseDataConstants::kHeaderSize;
148 }
149}
150
151
152bool ParseData::HasError() {
153 return Data()[PreparseDataConstants::kHasErrorOffset];
154}
155
156
157unsigned ParseData::Magic() {
158 return Data()[PreparseDataConstants::kMagicOffset];
159}
160
161
162unsigned ParseData::Version() {
163 return Data()[PreparseDataConstants::kVersionOffset];
164}
165
166
167int ParseData::FunctionsSize() {
168 return static_cast<int>(Data()[PreparseDataConstants::kFunctionsSizeOffset]);
169}
170
171
172void Parser::SetCachedData(ParseInfo* info) {
173 if (compile_options_ == ScriptCompiler::kNoCompileOptions) {
174 cached_parse_data_ = NULL;
175 } else {
176 DCHECK(info->cached_data() != NULL);
177 if (compile_options_ == ScriptCompiler::kConsumeParserCache) {
178 cached_parse_data_ = ParseData::FromCachedData(*info->cached_data());
179 }
180 }
181}
182
Ben Murdoch097c5b22016-05-18 11:27:45 +0100183FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name,
184 bool call_super, Scope* scope,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000185 int pos, int end_pos,
186 LanguageMode language_mode) {
187 int materialized_literal_count = -1;
188 int expected_property_count = -1;
189 int parameter_count = 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100190 if (name == nullptr) name = ast_value_factory()->empty_string();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000191
192 FunctionKind kind = call_super ? FunctionKind::kDefaultSubclassConstructor
193 : FunctionKind::kDefaultBaseConstructor;
194 Scope* function_scope = NewScope(scope, FUNCTION_SCOPE, kind);
195 SetLanguageMode(function_scope,
196 static_cast<LanguageMode>(language_mode | STRICT));
197 // Set start and end position to the same value
198 function_scope->set_start_position(pos);
199 function_scope->set_end_position(pos);
200 ZoneList<Statement*>* body = NULL;
201
202 {
203 AstNodeFactory function_factory(ast_value_factory());
204 FunctionState function_state(&function_state_, &scope_, function_scope,
205 kind, &function_factory);
206
207 body = new (zone()) ZoneList<Statement*>(call_super ? 2 : 1, zone());
208 if (call_super) {
209 // $super_constructor = %_GetSuperConstructor(<this-function>)
210 // %reflect_construct($super_constructor, arguments, new.target)
211 ZoneList<Expression*>* args =
212 new (zone()) ZoneList<Expression*>(2, zone());
213 VariableProxy* this_function_proxy = scope_->NewUnresolved(
214 factory(), ast_value_factory()->this_function_string(),
215 Variable::NORMAL, pos);
216 ZoneList<Expression*>* tmp =
217 new (zone()) ZoneList<Expression*>(1, zone());
218 tmp->Add(this_function_proxy, zone());
219 Expression* super_constructor = factory()->NewCallRuntime(
220 Runtime::kInlineGetSuperConstructor, tmp, pos);
221 args->Add(super_constructor, zone());
222 VariableProxy* arguments_proxy = scope_->NewUnresolved(
223 factory(), ast_value_factory()->arguments_string(), Variable::NORMAL,
224 pos);
225 args->Add(arguments_proxy, zone());
226 VariableProxy* new_target_proxy = scope_->NewUnresolved(
227 factory(), ast_value_factory()->new_target_string(), Variable::NORMAL,
228 pos);
229 args->Add(new_target_proxy, zone());
230 CallRuntime* call = factory()->NewCallRuntime(
231 Context::REFLECT_CONSTRUCT_INDEX, args, pos);
232 body->Add(factory()->NewReturnStatement(call, pos), zone());
233 }
234
235 materialized_literal_count = function_state.materialized_literal_count();
236 expected_property_count = function_state.expected_property_count();
237 }
238
239 FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
240 name, function_scope, body, materialized_literal_count,
241 expected_property_count, parameter_count,
242 FunctionLiteral::kNoDuplicateParameters,
243 FunctionLiteral::kAnonymousExpression,
244 FunctionLiteral::kShouldLazyCompile, kind, pos);
245
246 return function_literal;
247}
248
249
250// ----------------------------------------------------------------------------
251// Target is a support class to facilitate manipulation of the
252// Parser's target_stack_ (the stack of potential 'break' and
253// 'continue' statement targets). Upon construction, a new target is
254// added; it is removed upon destruction.
255
256class Target BASE_EMBEDDED {
257 public:
258 Target(Target** variable, BreakableStatement* statement)
259 : variable_(variable), statement_(statement), previous_(*variable) {
260 *variable = this;
261 }
262
263 ~Target() {
264 *variable_ = previous_;
265 }
266
267 Target* previous() { return previous_; }
268 BreakableStatement* statement() { return statement_; }
269
270 private:
271 Target** variable_;
272 BreakableStatement* statement_;
273 Target* previous_;
274};
275
276
277class TargetScope BASE_EMBEDDED {
278 public:
279 explicit TargetScope(Target** variable)
280 : variable_(variable), previous_(*variable) {
281 *variable = NULL;
282 }
283
284 ~TargetScope() {
285 *variable_ = previous_;
286 }
287
288 private:
289 Target** variable_;
290 Target* previous_;
291};
292
293
294// ----------------------------------------------------------------------------
295// The CHECK_OK macro is a convenient macro to enforce error
296// handling for functions that may fail (by returning !*ok).
297//
298// CAUTION: This macro appends extra statements after a call,
299// thus it must never be used where only a single statement
300// is correct (e.g. an if statement branch w/o braces)!
301
302#define CHECK_OK ok); \
303 if (!*ok) return NULL; \
304 ((void)0
305#define DUMMY ) // to make indentation work
306#undef DUMMY
307
308#define CHECK_FAILED /**/); \
309 if (failed_) return NULL; \
310 ((void)0
311#define DUMMY ) // to make indentation work
312#undef DUMMY
313
314// ----------------------------------------------------------------------------
315// Implementation of Parser
316
317bool ParserTraits::IsEval(const AstRawString* identifier) const {
318 return identifier == parser_->ast_value_factory()->eval_string();
319}
320
321
322bool ParserTraits::IsArguments(const AstRawString* identifier) const {
323 return identifier == parser_->ast_value_factory()->arguments_string();
324}
325
326
327bool ParserTraits::IsEvalOrArguments(const AstRawString* identifier) const {
328 return IsEval(identifier) || IsArguments(identifier);
329}
330
331bool ParserTraits::IsUndefined(const AstRawString* identifier) const {
332 return identifier == parser_->ast_value_factory()->undefined_string();
333}
334
335bool ParserTraits::IsPrototype(const AstRawString* identifier) const {
336 return identifier == parser_->ast_value_factory()->prototype_string();
337}
338
339
340bool ParserTraits::IsConstructor(const AstRawString* identifier) const {
341 return identifier == parser_->ast_value_factory()->constructor_string();
342}
343
344
345bool ParserTraits::IsThisProperty(Expression* expression) {
346 DCHECK(expression != NULL);
347 Property* property = expression->AsProperty();
348 return property != NULL && property->obj()->IsVariableProxy() &&
349 property->obj()->AsVariableProxy()->is_this();
350}
351
352
353bool ParserTraits::IsIdentifier(Expression* expression) {
354 VariableProxy* operand = expression->AsVariableProxy();
355 return operand != NULL && !operand->is_this();
356}
357
358
359void ParserTraits::PushPropertyName(FuncNameInferrer* fni,
360 Expression* expression) {
361 if (expression->IsPropertyName()) {
362 fni->PushLiteralName(expression->AsLiteral()->AsRawPropertyName());
363 } else {
364 fni->PushLiteralName(
365 parser_->ast_value_factory()->anonymous_function_string());
366 }
367}
368
369
370void ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left,
371 Expression* right) {
372 DCHECK(left != NULL);
373 if (left->IsProperty() && right->IsFunctionLiteral()) {
374 right->AsFunctionLiteral()->set_pretenure();
375 }
376}
377
378
379Expression* ParserTraits::MarkExpressionAsAssigned(Expression* expression) {
380 VariableProxy* proxy =
381 expression != NULL ? expression->AsVariableProxy() : NULL;
382 if (proxy != NULL) proxy->set_is_assigned();
383 return expression;
384}
385
386
387bool ParserTraits::ShortcutNumericLiteralBinaryExpression(
388 Expression** x, Expression* y, Token::Value op, int pos,
389 AstNodeFactory* factory) {
390 if ((*x)->AsLiteral() && (*x)->AsLiteral()->raw_value()->IsNumber() &&
391 y->AsLiteral() && y->AsLiteral()->raw_value()->IsNumber()) {
392 double x_val = (*x)->AsLiteral()->raw_value()->AsNumber();
393 double y_val = y->AsLiteral()->raw_value()->AsNumber();
394 bool x_has_dot = (*x)->AsLiteral()->raw_value()->ContainsDot();
395 bool y_has_dot = y->AsLiteral()->raw_value()->ContainsDot();
396 bool has_dot = x_has_dot || y_has_dot;
397 switch (op) {
398 case Token::ADD:
399 *x = factory->NewNumberLiteral(x_val + y_val, pos, has_dot);
400 return true;
401 case Token::SUB:
402 *x = factory->NewNumberLiteral(x_val - y_val, pos, has_dot);
403 return true;
404 case Token::MUL:
405 *x = factory->NewNumberLiteral(x_val * y_val, pos, has_dot);
406 return true;
407 case Token::DIV:
408 *x = factory->NewNumberLiteral(x_val / y_val, pos, has_dot);
409 return true;
410 case Token::BIT_OR: {
411 int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
412 *x = factory->NewNumberLiteral(value, pos, has_dot);
413 return true;
414 }
415 case Token::BIT_AND: {
416 int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
417 *x = factory->NewNumberLiteral(value, pos, has_dot);
418 return true;
419 }
420 case Token::BIT_XOR: {
421 int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
422 *x = factory->NewNumberLiteral(value, pos, has_dot);
423 return true;
424 }
425 case Token::SHL: {
426 int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
427 *x = factory->NewNumberLiteral(value, pos, has_dot);
428 return true;
429 }
430 case Token::SHR: {
431 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
432 uint32_t value = DoubleToUint32(x_val) >> shift;
433 *x = factory->NewNumberLiteral(value, pos, has_dot);
434 return true;
435 }
436 case Token::SAR: {
437 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
438 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
439 *x = factory->NewNumberLiteral(value, pos, has_dot);
440 return true;
441 }
Ben Murdochda12d292016-06-02 14:46:10 +0100442 case Token::EXP: {
443 double value = Pow(x_val, y_val);
444 int int_value = static_cast<int>(value);
445 *x = factory->NewNumberLiteral(
446 int_value == value && value != -0.0 ? int_value : value, pos,
447 has_dot);
448 return true;
449 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000450 default:
451 break;
452 }
453 }
454 return false;
455}
456
457
458Expression* ParserTraits::BuildUnaryExpression(Expression* expression,
459 Token::Value op, int pos,
460 AstNodeFactory* factory) {
461 DCHECK(expression != NULL);
462 if (expression->IsLiteral()) {
463 const AstValue* literal = expression->AsLiteral()->raw_value();
464 if (op == Token::NOT) {
465 // Convert the literal to a boolean condition and negate it.
466 bool condition = literal->BooleanValue();
467 return factory->NewBooleanLiteral(!condition, pos);
468 } else if (literal->IsNumber()) {
469 // Compute some expressions involving only number literals.
470 double value = literal->AsNumber();
471 bool has_dot = literal->ContainsDot();
472 switch (op) {
473 case Token::ADD:
474 return expression;
475 case Token::SUB:
476 return factory->NewNumberLiteral(-value, pos, has_dot);
477 case Token::BIT_NOT:
478 return factory->NewNumberLiteral(~DoubleToInt32(value), pos, has_dot);
479 default:
480 break;
481 }
482 }
483 }
484 // Desugar '+foo' => 'foo*1'
485 if (op == Token::ADD) {
486 return factory->NewBinaryOperation(
487 Token::MUL, expression, factory->NewNumberLiteral(1, pos, true), pos);
488 }
489 // The same idea for '-foo' => 'foo*(-1)'.
490 if (op == Token::SUB) {
491 return factory->NewBinaryOperation(
492 Token::MUL, expression, factory->NewNumberLiteral(-1, pos), pos);
493 }
494 // ...and one more time for '~foo' => 'foo^(~0)'.
495 if (op == Token::BIT_NOT) {
496 return factory->NewBinaryOperation(
497 Token::BIT_XOR, expression, factory->NewNumberLiteral(~0, pos), pos);
498 }
499 return factory->NewUnaryOperation(op, expression, pos);
500}
501
Ben Murdochda12d292016-06-02 14:46:10 +0100502Expression* ParserTraits::BuildIteratorResult(Expression* value, bool done) {
503 int pos = RelocInfo::kNoPosition;
504 AstNodeFactory* factory = parser_->factory();
505 Zone* zone = parser_->zone();
506
507 if (value == nullptr) value = factory->NewUndefinedLiteral(pos);
508
509 auto args = new (zone) ZoneList<Expression*>(2, zone);
510 args->Add(value, zone);
511 args->Add(factory->NewBooleanLiteral(done, pos), zone);
512
513 return factory->NewCallRuntime(Runtime::kInlineCreateIterResultObject, args,
514 pos);
515}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000516
517Expression* ParserTraits::NewThrowReferenceError(
518 MessageTemplate::Template message, int pos) {
519 return NewThrowError(Runtime::kNewReferenceError, message,
520 parser_->ast_value_factory()->empty_string(), pos);
521}
522
523
524Expression* ParserTraits::NewThrowSyntaxError(MessageTemplate::Template message,
525 const AstRawString* arg,
526 int pos) {
527 return NewThrowError(Runtime::kNewSyntaxError, message, arg, pos);
528}
529
530
531Expression* ParserTraits::NewThrowTypeError(MessageTemplate::Template message,
532 const AstRawString* arg, int pos) {
533 return NewThrowError(Runtime::kNewTypeError, message, arg, pos);
534}
535
536
537Expression* ParserTraits::NewThrowError(Runtime::FunctionId id,
538 MessageTemplate::Template message,
539 const AstRawString* arg, int pos) {
540 Zone* zone = parser_->zone();
541 ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(2, zone);
542 args->Add(parser_->factory()->NewSmiLiteral(message, pos), zone);
543 args->Add(parser_->factory()->NewStringLiteral(arg, pos), zone);
544 CallRuntime* call_constructor =
545 parser_->factory()->NewCallRuntime(id, args, pos);
546 return parser_->factory()->NewThrow(call_constructor, pos);
547}
548
549
550void ParserTraits::ReportMessageAt(Scanner::Location source_location,
551 MessageTemplate::Template message,
552 const char* arg, ParseErrorType error_type) {
553 if (parser_->stack_overflow()) {
554 // Suppress the error message (syntax error or such) in the presence of a
555 // stack overflow. The isolate allows only one pending exception at at time
556 // and we want to report the stack overflow later.
557 return;
558 }
559 parser_->pending_error_handler_.ReportMessageAt(source_location.beg_pos,
560 source_location.end_pos,
561 message, arg, error_type);
562}
563
564
565void ParserTraits::ReportMessage(MessageTemplate::Template message,
566 const char* arg, ParseErrorType error_type) {
567 Scanner::Location source_location = parser_->scanner()->location();
568 ReportMessageAt(source_location, message, arg, error_type);
569}
570
571
572void ParserTraits::ReportMessage(MessageTemplate::Template message,
573 const AstRawString* arg,
574 ParseErrorType error_type) {
575 Scanner::Location source_location = parser_->scanner()->location();
576 ReportMessageAt(source_location, message, arg, error_type);
577}
578
579
580void ParserTraits::ReportMessageAt(Scanner::Location source_location,
581 MessageTemplate::Template message,
582 const AstRawString* arg,
583 ParseErrorType error_type) {
584 if (parser_->stack_overflow()) {
585 // Suppress the error message (syntax error or such) in the presence of a
586 // stack overflow. The isolate allows only one pending exception at at time
587 // and we want to report the stack overflow later.
588 return;
589 }
590 parser_->pending_error_handler_.ReportMessageAt(source_location.beg_pos,
591 source_location.end_pos,
592 message, arg, error_type);
593}
594
595
596const AstRawString* ParserTraits::GetSymbol(Scanner* scanner) {
597 const AstRawString* result =
598 parser_->scanner()->CurrentSymbol(parser_->ast_value_factory());
599 DCHECK(result != NULL);
600 return result;
601}
602
603
604const AstRawString* ParserTraits::GetNumberAsSymbol(Scanner* scanner) {
605 double double_value = parser_->scanner()->DoubleValue();
606 char array[100];
607 const char* string =
608 DoubleToCString(double_value, Vector<char>(array, arraysize(array)));
609 return parser_->ast_value_factory()->GetOneByteString(string);
610}
611
612
613const AstRawString* ParserTraits::GetNextSymbol(Scanner* scanner) {
614 return parser_->scanner()->NextSymbol(parser_->ast_value_factory());
615}
616
617
618Expression* ParserTraits::ThisExpression(Scope* scope, AstNodeFactory* factory,
619 int pos) {
620 return scope->NewUnresolved(factory,
621 parser_->ast_value_factory()->this_string(),
622 Variable::THIS, pos, pos + 4);
623}
624
625
626Expression* ParserTraits::SuperPropertyReference(Scope* scope,
627 AstNodeFactory* factory,
628 int pos) {
629 // this_function[home_object_symbol]
630 VariableProxy* this_function_proxy = scope->NewUnresolved(
631 factory, parser_->ast_value_factory()->this_function_string(),
632 Variable::NORMAL, pos);
633 Expression* home_object_symbol_literal =
634 factory->NewSymbolLiteral("home_object_symbol", RelocInfo::kNoPosition);
635 Expression* home_object = factory->NewProperty(
636 this_function_proxy, home_object_symbol_literal, pos);
637 return factory->NewSuperPropertyReference(
638 ThisExpression(scope, factory, pos)->AsVariableProxy(), home_object, pos);
639}
640
641
642Expression* ParserTraits::SuperCallReference(Scope* scope,
643 AstNodeFactory* factory, int pos) {
644 VariableProxy* new_target_proxy = scope->NewUnresolved(
645 factory, parser_->ast_value_factory()->new_target_string(),
646 Variable::NORMAL, pos);
647 VariableProxy* this_function_proxy = scope->NewUnresolved(
648 factory, parser_->ast_value_factory()->this_function_string(),
649 Variable::NORMAL, pos);
650 return factory->NewSuperCallReference(
651 ThisExpression(scope, factory, pos)->AsVariableProxy(), new_target_proxy,
652 this_function_proxy, pos);
653}
654
655
656Expression* ParserTraits::NewTargetExpression(Scope* scope,
657 AstNodeFactory* factory,
658 int pos) {
659 static const int kNewTargetStringLength = 10;
660 auto proxy = scope->NewUnresolved(
661 factory, parser_->ast_value_factory()->new_target_string(),
662 Variable::NORMAL, pos, pos + kNewTargetStringLength);
663 proxy->set_is_new_target();
664 return proxy;
665}
666
667
Ben Murdoch097c5b22016-05-18 11:27:45 +0100668Expression* ParserTraits::FunctionSentExpression(Scope* scope,
669 AstNodeFactory* factory,
670 int pos) {
671 // We desugar function.sent into %GeneratorGetInput(generator).
672 Zone* zone = parser_->zone();
673 ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(1, zone);
674 VariableProxy* generator = factory->NewVariableProxy(
675 parser_->function_state_->generator_object_variable());
676 args->Add(generator, zone);
677 return factory->NewCallRuntime(Runtime::kGeneratorGetInput, args, pos);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000678}
679
680
681Literal* ParserTraits::ExpressionFromLiteral(Token::Value token, int pos,
682 Scanner* scanner,
683 AstNodeFactory* factory) {
684 switch (token) {
685 case Token::NULL_LITERAL:
686 return factory->NewNullLiteral(pos);
687 case Token::TRUE_LITERAL:
688 return factory->NewBooleanLiteral(true, pos);
689 case Token::FALSE_LITERAL:
690 return factory->NewBooleanLiteral(false, pos);
691 case Token::SMI: {
692 int value = scanner->smi_value();
693 return factory->NewSmiLiteral(value, pos);
694 }
695 case Token::NUMBER: {
696 bool has_dot = scanner->ContainsDot();
697 double value = scanner->DoubleValue();
698 return factory->NewNumberLiteral(value, pos, has_dot);
699 }
700 default:
701 DCHECK(false);
702 }
703 return NULL;
704}
705
706
707Expression* ParserTraits::ExpressionFromIdentifier(const AstRawString* name,
708 int start_position,
709 int end_position,
710 Scope* scope,
711 AstNodeFactory* factory) {
712 if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name);
713 return scope->NewUnresolved(factory, name, Variable::NORMAL, start_position,
714 end_position);
715}
716
717
718Expression* ParserTraits::ExpressionFromString(int pos, Scanner* scanner,
719 AstNodeFactory* factory) {
720 const AstRawString* symbol = GetSymbol(scanner);
721 if (parser_->fni_ != NULL) parser_->fni_->PushLiteralName(symbol);
722 return factory->NewStringLiteral(symbol, pos);
723}
724
725
726Expression* ParserTraits::GetIterator(Expression* iterable,
727 AstNodeFactory* factory, int pos) {
728 Expression* iterator_symbol_literal =
729 factory->NewSymbolLiteral("iterator_symbol", RelocInfo::kNoPosition);
730 Expression* prop =
731 factory->NewProperty(iterable, iterator_symbol_literal, pos);
732 Zone* zone = parser_->zone();
733 ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(0, zone);
734 return factory->NewCall(prop, args, pos);
735}
736
737
738Literal* ParserTraits::GetLiteralTheHole(int position,
739 AstNodeFactory* factory) {
740 return factory->NewTheHoleLiteral(RelocInfo::kNoPosition);
741}
742
743
744Expression* ParserTraits::ParseV8Intrinsic(bool* ok) {
745 return parser_->ParseV8Intrinsic(ok);
746}
747
748
749FunctionLiteral* ParserTraits::ParseFunctionLiteral(
750 const AstRawString* name, Scanner::Location function_name_location,
751 FunctionNameValidity function_name_validity, FunctionKind kind,
752 int function_token_position, FunctionLiteral::FunctionType type,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000753 LanguageMode language_mode, bool* ok) {
754 return parser_->ParseFunctionLiteral(
755 name, function_name_location, function_name_validity, kind,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100756 function_token_position, type, language_mode, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000757}
758
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000759ClassLiteral* ParserTraits::ParseClassLiteral(
Ben Murdochda12d292016-06-02 14:46:10 +0100760 Type::ExpressionClassifier* classifier, const AstRawString* name,
761 Scanner::Location class_name_location, bool name_is_strict_reserved,
762 int pos, bool* ok) {
763 return parser_->ParseClassLiteral(classifier, name, class_name_location,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000764 name_is_strict_reserved, pos, ok);
765}
766
Ben Murdochda12d292016-06-02 14:46:10 +0100767void ParserTraits::MarkTailPosition(Expression* expression) {
768 expression->MarkTail();
769}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000770
771Parser::Parser(ParseInfo* info)
772 : ParserBase<ParserTraits>(info->zone(), &scanner_, info->stack_limit(),
773 info->extension(), info->ast_value_factory(),
774 NULL, this),
775 scanner_(info->unicode_cache()),
776 reusable_preparser_(NULL),
777 original_scope_(NULL),
778 target_stack_(NULL),
779 compile_options_(info->compile_options()),
780 cached_parse_data_(NULL),
781 total_preparse_skipped_(0),
782 pre_parse_timer_(NULL),
783 parsing_on_main_thread_(true) {
784 // Even though we were passed ParseInfo, we should not store it in
785 // Parser - this makes sure that Isolate is not accidentally accessed via
786 // ParseInfo during background parsing.
787 DCHECK(!info->script().is_null() || info->source_stream() != NULL);
788 set_allow_lazy(info->allow_lazy_parsing());
789 set_allow_natives(FLAG_allow_natives_syntax || info->is_native());
Ben Murdochda12d292016-06-02 14:46:10 +0100790 set_allow_tailcalls(FLAG_harmony_tailcalls && !info->is_native() &&
791 info->isolate()->is_tail_call_elimination_enabled());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000792 set_allow_harmony_sloppy(FLAG_harmony_sloppy);
793 set_allow_harmony_sloppy_function(FLAG_harmony_sloppy_function);
794 set_allow_harmony_sloppy_let(FLAG_harmony_sloppy_let);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000795 set_allow_harmony_do_expressions(FLAG_harmony_do_expressions);
796 set_allow_harmony_function_name(FLAG_harmony_function_name);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100797 set_allow_harmony_function_sent(FLAG_harmony_function_sent);
Ben Murdochda12d292016-06-02 14:46:10 +0100798 set_allow_harmony_restrictive_declarations(
799 FLAG_harmony_restrictive_declarations);
800 set_allow_harmony_exponentiation_operator(
801 FLAG_harmony_exponentiation_operator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000802 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
803 ++feature) {
804 use_counts_[feature] = 0;
805 }
806 if (info->ast_value_factory() == NULL) {
807 // info takes ownership of AstValueFactory.
808 info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed()));
809 info->set_ast_value_factory_owned();
810 ast_value_factory_ = info->ast_value_factory();
811 }
812}
813
814
815FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {
816 // TODO(bmeurer): We temporarily need to pass allow_nesting = true here,
817 // see comment for HistogramTimerScope class.
818
819 // It's OK to use the Isolate & counters here, since this function is only
820 // called in the main thread.
821 DCHECK(parsing_on_main_thread_);
822
823 HistogramTimerScope timer_scope(isolate->counters()->parse(), true);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100824 TRACE_EVENT0("v8", "V8.Parse");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000825 Handle<String> source(String::cast(info->script()->source()));
826 isolate->counters()->total_parse_size()->Increment(source->length());
827 base::ElapsedTimer timer;
828 if (FLAG_trace_parse) {
829 timer.Start();
830 }
831 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
832
833 // Initialize parser state.
834 CompleteParserRecorder recorder;
835
836 if (produce_cached_parse_data()) {
837 log_ = &recorder;
838 } else if (consume_cached_parse_data()) {
839 cached_parse_data_->Initialize();
840 }
841
842 source = String::Flatten(source);
843 FunctionLiteral* result;
844
845 if (source->IsExternalTwoByteString()) {
846 // Notice that the stream is destroyed at the end of the branch block.
847 // The last line of the blocks can't be moved outside, even though they're
848 // identical calls.
849 ExternalTwoByteStringUtf16CharacterStream stream(
850 Handle<ExternalTwoByteString>::cast(source), 0, source->length());
851 scanner_.Initialize(&stream);
852 result = DoParseProgram(info);
853 } else {
854 GenericStringUtf16CharacterStream stream(source, 0, source->length());
855 scanner_.Initialize(&stream);
856 result = DoParseProgram(info);
857 }
858 if (result != NULL) {
859 DCHECK_EQ(scanner_.peek_location().beg_pos, source->length());
860 }
861 HandleSourceURLComments(isolate, info->script());
862
863 if (FLAG_trace_parse && result != NULL) {
864 double ms = timer.Elapsed().InMillisecondsF();
865 if (info->is_eval()) {
866 PrintF("[parsing eval");
867 } else if (info->script()->name()->IsString()) {
868 String* name = String::cast(info->script()->name());
869 base::SmartArrayPointer<char> name_chars = name->ToCString();
870 PrintF("[parsing script: %s", name_chars.get());
871 } else {
872 PrintF("[parsing script");
873 }
874 PrintF(" - took %0.3f ms]\n", ms);
875 }
876 if (produce_cached_parse_data()) {
877 if (result != NULL) *info->cached_data() = recorder.GetScriptData();
878 log_ = NULL;
879 }
880 return result;
881}
882
883
884FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
885 // Note that this function can be called from the main thread or from a
886 // background thread. We should not access anything Isolate / heap dependent
887 // via ParseInfo, and also not pass it forward.
888 DCHECK(scope_ == NULL);
889 DCHECK(target_stack_ == NULL);
890
891 Mode parsing_mode = FLAG_lazy && allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY;
892 if (allow_natives() || extension_ != NULL) parsing_mode = PARSE_EAGERLY;
893
894 FunctionLiteral* result = NULL;
895 {
896 // TODO(wingo): Add an outer SCRIPT_SCOPE corresponding to the native
897 // context, which will have the "this" binding for script scopes.
898 Scope* scope = NewScope(scope_, SCRIPT_SCOPE);
899 info->set_script_scope(scope);
900 if (!info->context().is_null() && !info->context()->IsNativeContext()) {
901 scope = Scope::DeserializeScopeChain(info->isolate(), zone(),
902 *info->context(), scope);
903 // The Scope is backed up by ScopeInfo (which is in the V8 heap); this
904 // means the Parser cannot operate independent of the V8 heap. Tell the
905 // string table to internalize strings and values right after they're
906 // created. This kind of parsing can only be done in the main thread.
907 DCHECK(parsing_on_main_thread_);
908 ast_value_factory()->Internalize(info->isolate());
909 }
910 original_scope_ = scope;
911 if (info->is_eval()) {
912 if (!scope->is_script_scope() || is_strict(info->language_mode())) {
913 parsing_mode = PARSE_EAGERLY;
914 }
915 scope = NewScope(scope, EVAL_SCOPE);
916 } else if (info->is_module()) {
917 scope = NewScope(scope, MODULE_SCOPE);
918 }
919
920 scope->set_start_position(0);
921
922 // Enter 'scope' with the given parsing mode.
923 ParsingModeScope parsing_mode_scope(this, parsing_mode);
924 AstNodeFactory function_factory(ast_value_factory());
925 FunctionState function_state(&function_state_, &scope_, scope,
926 kNormalFunction, &function_factory);
927
928 // Don't count the mode in the use counters--give the program a chance
Ben Murdochda12d292016-06-02 14:46:10 +0100929 // to enable script/module-wide strict mode below.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000930 scope_->SetLanguageMode(info->language_mode());
931 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
932 bool ok = true;
933 int beg_pos = scanner()->location().beg_pos;
934 if (info->is_module()) {
935 ParseModuleItemList(body, &ok);
936 } else {
937 ParseStatementList(body, Token::EOS, &ok);
938 }
939
940 // The parser will peek but not consume EOS. Our scope logically goes all
941 // the way to the EOS, though.
942 scope->set_end_position(scanner()->peek_location().beg_pos);
943
944 if (ok && is_strict(language_mode())) {
945 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
946 }
947 if (ok && is_sloppy(language_mode()) && allow_harmony_sloppy_function()) {
948 // TODO(littledan): Function bindings on the global object that modify
949 // pre-existing bindings should be made writable, enumerable and
950 // nonconfigurable if possible, whereas this code will leave attributes
951 // unchanged if the property already exists.
952 InsertSloppyBlockFunctionVarBindings(scope, &ok);
953 }
Ben Murdochda12d292016-06-02 14:46:10 +0100954 if (ok) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000955 CheckConflictingVarDeclarations(scope_, &ok);
956 }
957
958 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) {
959 if (body->length() != 1 ||
960 !body->at(0)->IsExpressionStatement() ||
961 !body->at(0)->AsExpressionStatement()->
962 expression()->IsFunctionLiteral()) {
963 ReportMessage(MessageTemplate::kSingleFunctionLiteral);
964 ok = false;
965 }
966 }
967
968 if (ok) {
969 ParserTraits::RewriteDestructuringAssignments();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100970 result = factory()->NewScriptOrEvalFunctionLiteral(
971 scope_, body, function_state.materialized_literal_count(),
972 function_state.expected_property_count());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000973 }
974 }
975
976 // Make sure the target stack is empty.
977 DCHECK(target_stack_ == NULL);
978
979 return result;
980}
981
982
983FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info) {
984 // It's OK to use the Isolate & counters here, since this function is only
985 // called in the main thread.
986 DCHECK(parsing_on_main_thread_);
987 HistogramTimerScope timer_scope(isolate->counters()->parse_lazy());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100988 TRACE_EVENT0("v8", "V8.ParseLazy");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000989 Handle<String> source(String::cast(info->script()->source()));
990 isolate->counters()->total_parse_size()->Increment(source->length());
991 base::ElapsedTimer timer;
992 if (FLAG_trace_parse) {
993 timer.Start();
994 }
995 Handle<SharedFunctionInfo> shared_info = info->shared_info();
996
997 // Initialize parser state.
998 source = String::Flatten(source);
999 FunctionLiteral* result;
1000 if (source->IsExternalTwoByteString()) {
1001 ExternalTwoByteStringUtf16CharacterStream stream(
1002 Handle<ExternalTwoByteString>::cast(source),
1003 shared_info->start_position(),
1004 shared_info->end_position());
1005 result = ParseLazy(isolate, info, &stream);
1006 } else {
1007 GenericStringUtf16CharacterStream stream(source,
1008 shared_info->start_position(),
1009 shared_info->end_position());
1010 result = ParseLazy(isolate, info, &stream);
1011 }
1012
1013 if (FLAG_trace_parse && result != NULL) {
1014 double ms = timer.Elapsed().InMillisecondsF();
1015 base::SmartArrayPointer<char> name_chars =
1016 result->debug_name()->ToCString();
1017 PrintF("[parsing function: %s - took %0.3f ms]\n", name_chars.get(), ms);
1018 }
1019 return result;
1020}
1021
Ben Murdoch097c5b22016-05-18 11:27:45 +01001022static FunctionLiteral::FunctionType ComputeFunctionType(
1023 Handle<SharedFunctionInfo> shared_info) {
1024 if (shared_info->is_declaration()) {
1025 return FunctionLiteral::kDeclaration;
1026 } else if (shared_info->is_named_expression()) {
1027 return FunctionLiteral::kNamedExpression;
1028 } else if (IsConciseMethod(shared_info->kind()) ||
1029 IsAccessorFunction(shared_info->kind())) {
1030 return FunctionLiteral::kAccessorOrMethod;
1031 }
1032 return FunctionLiteral::kAnonymousExpression;
1033}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001034
1035FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
1036 Utf16CharacterStream* source) {
1037 Handle<SharedFunctionInfo> shared_info = info->shared_info();
1038 scanner_.Initialize(source);
1039 DCHECK(scope_ == NULL);
1040 DCHECK(target_stack_ == NULL);
1041
1042 Handle<String> name(String::cast(shared_info->name()));
1043 DCHECK(ast_value_factory());
1044 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
1045 const AstRawString* raw_name = ast_value_factory()->GetString(name);
1046 fni_->PushEnclosingName(raw_name);
1047
1048 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
1049
1050 // Place holder for the result.
1051 FunctionLiteral* result = NULL;
1052
1053 {
1054 // Parse the function literal.
1055 Scope* scope = NewScope(scope_, SCRIPT_SCOPE);
1056 info->set_script_scope(scope);
1057 if (!info->closure().is_null()) {
1058 // Ok to use Isolate here, since lazy function parsing is only done in the
1059 // main thread.
1060 DCHECK(parsing_on_main_thread_);
1061 scope = Scope::DeserializeScopeChain(isolate, zone(),
1062 info->closure()->context(), scope);
1063 }
1064 original_scope_ = scope;
1065 AstNodeFactory function_factory(ast_value_factory());
1066 FunctionState function_state(&function_state_, &scope_, scope,
1067 shared_info->kind(), &function_factory);
1068 DCHECK(is_sloppy(scope->language_mode()) ||
1069 is_strict(info->language_mode()));
1070 DCHECK(info->language_mode() == shared_info->language_mode());
1071 FunctionLiteral::FunctionType function_type =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001072 ComputeFunctionType(shared_info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001073 bool ok = true;
1074
1075 if (shared_info->is_arrow()) {
1076 // TODO(adamk): We should construct this scope from the ScopeInfo.
1077 Scope* scope =
1078 NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction);
1079
1080 // These two bits only need to be explicitly set because we're
1081 // not passing the ScopeInfo to the Scope constructor.
1082 // TODO(adamk): Remove these calls once the above NewScope call
1083 // passes the ScopeInfo.
1084 if (shared_info->scope_info()->CallsEval()) {
1085 scope->RecordEvalCall();
1086 }
1087 SetLanguageMode(scope, shared_info->language_mode());
1088
1089 scope->set_start_position(shared_info->start_position());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001090 ExpressionClassifier formals_classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001091 ParserFormalParameters formals(scope);
1092 Checkpoint checkpoint(this);
1093 {
1094 // Parsing patterns as variable reference expression creates
1095 // NewUnresolved references in current scope. Entrer arrow function
1096 // scope for formal parameter parsing.
1097 BlockState block_state(&scope_, scope);
1098 if (Check(Token::LPAREN)) {
1099 // '(' StrictFormalParameters ')'
1100 ParseFormalParameterList(&formals, &formals_classifier, &ok);
1101 if (ok) ok = Check(Token::RPAREN);
1102 } else {
1103 // BindingIdentifier
1104 ParseFormalParameter(&formals, &formals_classifier, &ok);
1105 if (ok) {
1106 DeclareFormalParameter(formals.scope, formals.at(0),
1107 &formals_classifier);
1108 }
1109 }
1110 }
1111
1112 if (ok) {
1113 checkpoint.Restore(&formals.materialized_literals_count);
1114 // Pass `accept_IN=true` to ParseArrowFunctionLiteral --- This should
1115 // not be observable, or else the preparser would have failed.
1116 Expression* expression =
1117 ParseArrowFunctionLiteral(true, formals, formals_classifier, &ok);
1118 if (ok) {
1119 // Scanning must end at the same position that was recorded
1120 // previously. If not, parsing has been interrupted due to a stack
1121 // overflow, at which point the partially parsed arrow function
1122 // concise body happens to be a valid expression. This is a problem
1123 // only for arrow functions with single expression bodies, since there
1124 // is no end token such as "}" for normal functions.
1125 if (scanner()->location().end_pos == shared_info->end_position()) {
1126 // The pre-parser saw an arrow function here, so the full parser
1127 // must produce a FunctionLiteral.
1128 DCHECK(expression->IsFunctionLiteral());
1129 result = expression->AsFunctionLiteral();
1130 } else {
1131 ok = false;
1132 }
1133 }
1134 }
1135 } else if (shared_info->is_default_constructor()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001136 result = DefaultConstructor(
1137 raw_name, IsSubclassConstructor(shared_info->kind()), scope,
1138 shared_info->start_position(), shared_info->end_position(),
1139 shared_info->language_mode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001140 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001141 result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(),
1142 kSkipFunctionNameCheck, shared_info->kind(),
1143 RelocInfo::kNoPosition, function_type,
1144 shared_info->language_mode(), &ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001145 }
1146 // Make sure the results agree.
1147 DCHECK(ok == (result != NULL));
1148 }
1149
1150 // Make sure the target stack is empty.
1151 DCHECK(target_stack_ == NULL);
1152
1153 if (result != NULL) {
1154 Handle<String> inferred_name(shared_info->inferred_name());
1155 result->set_inferred_name(inferred_name);
1156 }
1157 return result;
1158}
1159
1160
1161void* Parser::ParseStatementList(ZoneList<Statement*>* body, int end_token,
1162 bool* ok) {
1163 // StatementList ::
1164 // (StatementListItem)* <end_token>
1165
1166 // Allocate a target stack to use for this set of source
1167 // elements. This way, all scripts and functions get their own
1168 // target stack thus avoiding illegal breaks and continues across
1169 // functions.
1170 TargetScope scope(&this->target_stack_);
1171
1172 DCHECK(body != NULL);
1173 bool directive_prologue = true; // Parsing directive prologue.
1174
1175 while (peek() != end_token) {
1176 if (directive_prologue && peek() != Token::STRING) {
1177 directive_prologue = false;
1178 }
1179
1180 Scanner::Location token_loc = scanner()->peek_location();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001181 Statement* stat = ParseStatementListItem(CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001182 if (stat == NULL || stat->IsEmpty()) {
1183 directive_prologue = false; // End of directive prologue.
1184 continue;
1185 }
1186
1187 if (directive_prologue) {
1188 // A shot at a directive.
1189 ExpressionStatement* e_stat;
1190 Literal* literal;
1191 // Still processing directive prologue?
1192 if ((e_stat = stat->AsExpressionStatement()) != NULL &&
1193 (literal = e_stat->expression()->AsLiteral()) != NULL &&
1194 literal->raw_value()->IsString()) {
Ben Murdochda12d292016-06-02 14:46:10 +01001195 // Check "use strict" directive (ES5 14.1), "use asm" directive.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001196 bool use_strict_found =
1197 literal->raw_value()->AsString() ==
1198 ast_value_factory()->use_strict_string() &&
1199 token_loc.end_pos - token_loc.beg_pos ==
1200 ast_value_factory()->use_strict_string()->length() + 2;
Ben Murdochda12d292016-06-02 14:46:10 +01001201 if (use_strict_found) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001202 if (is_sloppy(scope_->language_mode())) {
1203 RaiseLanguageMode(STRICT);
1204 }
1205
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001206 if (!scope_->HasSimpleParameters()) {
1207 // TC39 deemed "use strict" directives to be an error when occurring
1208 // in the body of a function with non-simple parameter list, on
1209 // 29/7/2015. https://goo.gl/ueA7Ln
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001210 const AstRawString* string = literal->raw_value()->AsString();
1211 ParserTraits::ReportMessageAt(
1212 token_loc, MessageTemplate::kIllegalLanguageModeDirective,
1213 string);
1214 *ok = false;
1215 return nullptr;
1216 }
1217 // Because declarations in strict eval code don't leak into the scope
1218 // of the eval call, it is likely that functions declared in strict
1219 // eval code will be used within the eval code, so lazy parsing is
1220 // probably not a win.
1221 if (scope_->is_eval_scope()) mode_ = PARSE_EAGERLY;
1222 } else if (literal->raw_value()->AsString() ==
1223 ast_value_factory()->use_asm_string() &&
1224 token_loc.end_pos - token_loc.beg_pos ==
1225 ast_value_factory()->use_asm_string()->length() + 2) {
1226 // Store the usage count; The actual use counter on the isolate is
1227 // incremented after parsing is done.
1228 ++use_counts_[v8::Isolate::kUseAsm];
1229 scope_->SetAsmModule();
1230 } else {
1231 // Should not change mode, but will increment UseCounter
1232 // if appropriate. Ditto usages below.
1233 RaiseLanguageMode(SLOPPY);
1234 }
1235 } else {
1236 // End of the directive prologue.
1237 directive_prologue = false;
1238 RaiseLanguageMode(SLOPPY);
1239 }
1240 } else {
1241 RaiseLanguageMode(SLOPPY);
1242 }
1243
1244 body->Add(stat, zone());
1245 }
1246
1247 return 0;
1248}
1249
1250
1251Statement* Parser::ParseStatementListItem(bool* ok) {
1252 // (Ecma 262 6th Edition, 13.1):
1253 // StatementListItem:
1254 // Statement
1255 // Declaration
1256
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001257 switch (peek()) {
1258 case Token::FUNCTION:
1259 return ParseFunctionDeclaration(NULL, ok);
1260 case Token::CLASS:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001261 Consume(Token::CLASS);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001262 return ParseClassDeclaration(NULL, ok);
1263 case Token::CONST:
1264 if (allow_const()) {
1265 return ParseVariableStatement(kStatementListItem, NULL, ok);
1266 }
1267 break;
1268 case Token::VAR:
1269 return ParseVariableStatement(kStatementListItem, NULL, ok);
1270 case Token::LET:
1271 if (IsNextLetKeyword()) {
1272 return ParseVariableStatement(kStatementListItem, NULL, ok);
1273 }
1274 break;
1275 default:
1276 break;
1277 }
Ben Murdochda12d292016-06-02 14:46:10 +01001278 return ParseStatement(NULL, kAllowLabelledFunctionStatement, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001279}
1280
1281
1282Statement* Parser::ParseModuleItem(bool* ok) {
1283 // (Ecma 262 6th Edition, 15.2):
1284 // ModuleItem :
1285 // ImportDeclaration
1286 // ExportDeclaration
1287 // StatementListItem
1288
1289 switch (peek()) {
1290 case Token::IMPORT:
1291 return ParseImportDeclaration(ok);
1292 case Token::EXPORT:
1293 return ParseExportDeclaration(ok);
1294 default:
1295 return ParseStatementListItem(ok);
1296 }
1297}
1298
1299
1300void* Parser::ParseModuleItemList(ZoneList<Statement*>* body, bool* ok) {
1301 // (Ecma 262 6th Edition, 15.2):
1302 // Module :
1303 // ModuleBody?
1304 //
1305 // ModuleBody :
1306 // ModuleItem*
1307
1308 DCHECK(scope_->is_module_scope());
1309 RaiseLanguageMode(STRICT);
1310
1311 while (peek() != Token::EOS) {
1312 Statement* stat = ParseModuleItem(CHECK_OK);
1313 if (stat && !stat->IsEmpty()) {
1314 body->Add(stat, zone());
1315 }
1316 }
1317
1318 // Check that all exports are bound.
1319 ModuleDescriptor* descriptor = scope_->module();
1320 for (ModuleDescriptor::Iterator it = descriptor->iterator(); !it.done();
1321 it.Advance()) {
1322 if (scope_->LookupLocal(it.local_name()) == NULL) {
1323 // TODO(adamk): Pass both local_name and export_name once ParserTraits
1324 // supports multiple arg error messages.
1325 // Also try to report this at a better location.
1326 ParserTraits::ReportMessage(MessageTemplate::kModuleExportUndefined,
1327 it.local_name());
1328 *ok = false;
1329 return NULL;
1330 }
1331 }
1332
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001333 return NULL;
1334}
1335
1336
1337const AstRawString* Parser::ParseModuleSpecifier(bool* ok) {
1338 // ModuleSpecifier :
1339 // StringLiteral
1340
1341 Expect(Token::STRING, CHECK_OK);
1342 return GetSymbol(scanner());
1343}
1344
1345
1346void* Parser::ParseExportClause(ZoneList<const AstRawString*>* export_names,
1347 ZoneList<Scanner::Location>* export_locations,
1348 ZoneList<const AstRawString*>* local_names,
1349 Scanner::Location* reserved_loc, bool* ok) {
1350 // ExportClause :
1351 // '{' '}'
1352 // '{' ExportsList '}'
1353 // '{' ExportsList ',' '}'
1354 //
1355 // ExportsList :
1356 // ExportSpecifier
1357 // ExportsList ',' ExportSpecifier
1358 //
1359 // ExportSpecifier :
1360 // IdentifierName
1361 // IdentifierName 'as' IdentifierName
1362
1363 Expect(Token::LBRACE, CHECK_OK);
1364
1365 Token::Value name_tok;
1366 while ((name_tok = peek()) != Token::RBRACE) {
1367 // Keep track of the first reserved word encountered in case our
1368 // caller needs to report an error.
1369 if (!reserved_loc->IsValid() &&
1370 !Token::IsIdentifier(name_tok, STRICT, false)) {
1371 *reserved_loc = scanner()->location();
1372 }
1373 const AstRawString* local_name = ParseIdentifierName(CHECK_OK);
1374 const AstRawString* export_name = NULL;
1375 if (CheckContextualKeyword(CStrVector("as"))) {
1376 export_name = ParseIdentifierName(CHECK_OK);
1377 }
1378 if (export_name == NULL) {
1379 export_name = local_name;
1380 }
1381 export_names->Add(export_name, zone());
1382 local_names->Add(local_name, zone());
1383 export_locations->Add(scanner()->location(), zone());
1384 if (peek() == Token::RBRACE) break;
1385 Expect(Token::COMMA, CHECK_OK);
1386 }
1387
1388 Expect(Token::RBRACE, CHECK_OK);
1389
1390 return 0;
1391}
1392
1393
1394ZoneList<ImportDeclaration*>* Parser::ParseNamedImports(int pos, bool* ok) {
1395 // NamedImports :
1396 // '{' '}'
1397 // '{' ImportsList '}'
1398 // '{' ImportsList ',' '}'
1399 //
1400 // ImportsList :
1401 // ImportSpecifier
1402 // ImportsList ',' ImportSpecifier
1403 //
1404 // ImportSpecifier :
1405 // BindingIdentifier
1406 // IdentifierName 'as' BindingIdentifier
1407
1408 Expect(Token::LBRACE, CHECK_OK);
1409
1410 ZoneList<ImportDeclaration*>* result =
1411 new (zone()) ZoneList<ImportDeclaration*>(1, zone());
1412 while (peek() != Token::RBRACE) {
1413 const AstRawString* import_name = ParseIdentifierName(CHECK_OK);
1414 const AstRawString* local_name = import_name;
1415 // In the presence of 'as', the left-side of the 'as' can
1416 // be any IdentifierName. But without 'as', it must be a valid
1417 // BindingIdentifier.
1418 if (CheckContextualKeyword(CStrVector("as"))) {
1419 local_name = ParseIdentifierName(CHECK_OK);
1420 }
1421 if (!Token::IsIdentifier(scanner()->current_token(), STRICT, false)) {
1422 *ok = false;
1423 ReportMessage(MessageTemplate::kUnexpectedReserved);
1424 return NULL;
1425 } else if (IsEvalOrArguments(local_name)) {
1426 *ok = false;
1427 ReportMessage(MessageTemplate::kStrictEvalArguments);
1428 return NULL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001429 }
1430 VariableProxy* proxy = NewUnresolved(local_name, IMPORT);
1431 ImportDeclaration* declaration =
1432 factory()->NewImportDeclaration(proxy, import_name, NULL, scope_, pos);
1433 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
1434 result->Add(declaration, zone());
1435 if (peek() == Token::RBRACE) break;
1436 Expect(Token::COMMA, CHECK_OK);
1437 }
1438
1439 Expect(Token::RBRACE, CHECK_OK);
1440
1441 return result;
1442}
1443
1444
1445Statement* Parser::ParseImportDeclaration(bool* ok) {
1446 // ImportDeclaration :
1447 // 'import' ImportClause 'from' ModuleSpecifier ';'
1448 // 'import' ModuleSpecifier ';'
1449 //
1450 // ImportClause :
1451 // NameSpaceImport
1452 // NamedImports
1453 // ImportedDefaultBinding
1454 // ImportedDefaultBinding ',' NameSpaceImport
1455 // ImportedDefaultBinding ',' NamedImports
1456 //
1457 // NameSpaceImport :
1458 // '*' 'as' ImportedBinding
1459
1460 int pos = peek_position();
1461 Expect(Token::IMPORT, CHECK_OK);
1462
1463 Token::Value tok = peek();
1464
1465 // 'import' ModuleSpecifier ';'
1466 if (tok == Token::STRING) {
1467 const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
1468 scope_->module()->AddModuleRequest(module_specifier, zone());
1469 ExpectSemicolon(CHECK_OK);
1470 return factory()->NewEmptyStatement(pos);
1471 }
1472
1473 // Parse ImportedDefaultBinding if present.
1474 ImportDeclaration* import_default_declaration = NULL;
1475 if (tok != Token::MUL && tok != Token::LBRACE) {
1476 const AstRawString* local_name =
1477 ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK);
1478 VariableProxy* proxy = NewUnresolved(local_name, IMPORT);
1479 import_default_declaration = factory()->NewImportDeclaration(
1480 proxy, ast_value_factory()->default_string(), NULL, scope_, pos);
1481 Declare(import_default_declaration, DeclarationDescriptor::NORMAL, true,
1482 CHECK_OK);
1483 }
1484
1485 const AstRawString* module_instance_binding = NULL;
1486 ZoneList<ImportDeclaration*>* named_declarations = NULL;
1487 if (import_default_declaration == NULL || Check(Token::COMMA)) {
1488 switch (peek()) {
1489 case Token::MUL: {
1490 Consume(Token::MUL);
1491 ExpectContextualKeyword(CStrVector("as"), CHECK_OK);
1492 module_instance_binding =
1493 ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK);
1494 // TODO(ES6): Add an appropriate declaration.
1495 break;
1496 }
1497
1498 case Token::LBRACE:
1499 named_declarations = ParseNamedImports(pos, CHECK_OK);
1500 break;
1501
1502 default:
1503 *ok = false;
1504 ReportUnexpectedToken(scanner()->current_token());
1505 return NULL;
1506 }
1507 }
1508
1509 ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
1510 const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
1511 scope_->module()->AddModuleRequest(module_specifier, zone());
1512
1513 if (module_instance_binding != NULL) {
1514 // TODO(ES6): Set the module specifier for the module namespace binding.
1515 }
1516
1517 if (import_default_declaration != NULL) {
1518 import_default_declaration->set_module_specifier(module_specifier);
1519 }
1520
1521 if (named_declarations != NULL) {
1522 for (int i = 0; i < named_declarations->length(); ++i) {
1523 named_declarations->at(i)->set_module_specifier(module_specifier);
1524 }
1525 }
1526
1527 ExpectSemicolon(CHECK_OK);
1528 return factory()->NewEmptyStatement(pos);
1529}
1530
1531
1532Statement* Parser::ParseExportDefault(bool* ok) {
1533 // Supports the following productions, starting after the 'default' token:
1534 // 'export' 'default' FunctionDeclaration
1535 // 'export' 'default' ClassDeclaration
1536 // 'export' 'default' AssignmentExpression[In] ';'
1537
1538 Expect(Token::DEFAULT, CHECK_OK);
1539 Scanner::Location default_loc = scanner()->location();
1540
Ben Murdoch097c5b22016-05-18 11:27:45 +01001541 const AstRawString* default_string = ast_value_factory()->default_string();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001542 ZoneList<const AstRawString*> names(1, zone());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001543 Statement* result = nullptr;
1544 Expression* default_export = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001545 switch (peek()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001546 case Token::FUNCTION: {
1547 Consume(Token::FUNCTION);
1548 int pos = position();
1549 bool is_generator = Check(Token::MUL);
1550 if (peek() == Token::LPAREN) {
1551 // FunctionDeclaration[+Default] ::
1552 // 'function' '(' FormalParameters ')' '{' FunctionBody '}'
1553 //
1554 // GeneratorDeclaration[+Default] ::
1555 // 'function' '*' '(' FormalParameters ')' '{' FunctionBody '}'
1556 default_export = ParseFunctionLiteral(
1557 default_string, Scanner::Location::invalid(),
1558 kSkipFunctionNameCheck,
1559 is_generator ? FunctionKind::kGeneratorFunction
1560 : FunctionKind::kNormalFunction,
1561 pos, FunctionLiteral::kDeclaration, language_mode(), CHECK_OK);
1562 result = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
1563 } else {
1564 result = ParseFunctionDeclaration(pos, is_generator, &names, CHECK_OK);
1565 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001566 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001567 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001568
1569 case Token::CLASS:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001570 Consume(Token::CLASS);
1571 if (peek() == Token::EXTENDS || peek() == Token::LBRACE) {
1572 // ClassDeclaration[+Default] ::
1573 // 'class' ('extends' LeftHandExpression)? '{' ClassBody '}'
Ben Murdochda12d292016-06-02 14:46:10 +01001574 default_export = ParseClassLiteral(nullptr, default_string,
1575 Scanner::Location::invalid(), false,
1576 position(), CHECK_OK);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001577 result = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
1578 } else {
1579 result = ParseClassDeclaration(&names, CHECK_OK);
1580 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001581 break;
1582
1583 default: {
1584 int pos = peek_position();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001585 ExpressionClassifier classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001586 Expression* expr = ParseAssignmentExpression(true, &classifier, CHECK_OK);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001587 RewriteNonPattern(&classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001588
1589 ExpectSemicolon(CHECK_OK);
1590 result = factory()->NewExpressionStatement(expr, pos);
1591 break;
1592 }
1593 }
1594
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001595 DCHECK_LE(names.length(), 1);
1596 if (names.length() == 1) {
1597 scope_->module()->AddLocalExport(default_string, names.first(), zone(), ok);
1598 if (!*ok) {
1599 ParserTraits::ReportMessageAt(
1600 default_loc, MessageTemplate::kDuplicateExport, default_string);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001601 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001602 }
1603 } else {
1604 // TODO(ES6): Assign result to a const binding with the name "*default*"
1605 // and add an export entry with "*default*" as the local name.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001606 USE(default_export);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001607 }
1608
1609 return result;
1610}
1611
1612
1613Statement* Parser::ParseExportDeclaration(bool* ok) {
1614 // ExportDeclaration:
1615 // 'export' '*' 'from' ModuleSpecifier ';'
1616 // 'export' ExportClause ('from' ModuleSpecifier)? ';'
1617 // 'export' VariableStatement
1618 // 'export' Declaration
1619 // 'export' 'default' ... (handled in ParseExportDefault)
1620
1621 int pos = peek_position();
1622 Expect(Token::EXPORT, CHECK_OK);
1623
1624 Statement* result = NULL;
1625 ZoneList<const AstRawString*> names(1, zone());
1626 switch (peek()) {
1627 case Token::DEFAULT:
1628 return ParseExportDefault(ok);
1629
1630 case Token::MUL: {
1631 Consume(Token::MUL);
1632 ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
1633 const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
1634 scope_->module()->AddModuleRequest(module_specifier, zone());
1635 // TODO(ES6): scope_->module()->AddStarExport(...)
1636 ExpectSemicolon(CHECK_OK);
1637 return factory()->NewEmptyStatement(pos);
1638 }
1639
1640 case Token::LBRACE: {
1641 // There are two cases here:
1642 //
1643 // 'export' ExportClause ';'
1644 // and
1645 // 'export' ExportClause FromClause ';'
1646 //
1647 // In the first case, the exported identifiers in ExportClause must
1648 // not be reserved words, while in the latter they may be. We
1649 // pass in a location that gets filled with the first reserved word
1650 // encountered, and then throw a SyntaxError if we are in the
1651 // non-FromClause case.
1652 Scanner::Location reserved_loc = Scanner::Location::invalid();
1653 ZoneList<const AstRawString*> export_names(1, zone());
1654 ZoneList<Scanner::Location> export_locations(1, zone());
1655 ZoneList<const AstRawString*> local_names(1, zone());
1656 ParseExportClause(&export_names, &export_locations, &local_names,
1657 &reserved_loc, CHECK_OK);
1658 const AstRawString* indirect_export_module_specifier = NULL;
1659 if (CheckContextualKeyword(CStrVector("from"))) {
1660 indirect_export_module_specifier = ParseModuleSpecifier(CHECK_OK);
1661 } else if (reserved_loc.IsValid()) {
1662 // No FromClause, so reserved words are invalid in ExportClause.
1663 *ok = false;
1664 ReportMessageAt(reserved_loc, MessageTemplate::kUnexpectedReserved);
1665 return NULL;
1666 }
1667 ExpectSemicolon(CHECK_OK);
1668 const int length = export_names.length();
1669 DCHECK_EQ(length, local_names.length());
1670 DCHECK_EQ(length, export_locations.length());
1671 if (indirect_export_module_specifier == NULL) {
1672 for (int i = 0; i < length; ++i) {
1673 scope_->module()->AddLocalExport(export_names[i], local_names[i],
1674 zone(), ok);
1675 if (!*ok) {
1676 ParserTraits::ReportMessageAt(export_locations[i],
1677 MessageTemplate::kDuplicateExport,
1678 export_names[i]);
1679 return NULL;
1680 }
1681 }
1682 } else {
1683 scope_->module()->AddModuleRequest(indirect_export_module_specifier,
1684 zone());
1685 for (int i = 0; i < length; ++i) {
1686 // TODO(ES6): scope_->module()->AddIndirectExport(...);(
1687 }
1688 }
1689 return factory()->NewEmptyStatement(pos);
1690 }
1691
1692 case Token::FUNCTION:
1693 result = ParseFunctionDeclaration(&names, CHECK_OK);
1694 break;
1695
1696 case Token::CLASS:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001697 Consume(Token::CLASS);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001698 result = ParseClassDeclaration(&names, CHECK_OK);
1699 break;
1700
1701 case Token::VAR:
1702 case Token::LET:
1703 case Token::CONST:
1704 result = ParseVariableStatement(kStatementListItem, &names, CHECK_OK);
1705 break;
1706
1707 default:
1708 *ok = false;
1709 ReportUnexpectedToken(scanner()->current_token());
1710 return NULL;
1711 }
1712
1713 // Extract declared names into export declarations.
1714 ModuleDescriptor* descriptor = scope_->module();
1715 for (int i = 0; i < names.length(); ++i) {
1716 descriptor->AddLocalExport(names[i], names[i], zone(), ok);
1717 if (!*ok) {
1718 // TODO(adamk): Possibly report this error at the right place.
1719 ParserTraits::ReportMessage(MessageTemplate::kDuplicateExport, names[i]);
1720 return NULL;
1721 }
1722 }
1723
1724 DCHECK_NOT_NULL(result);
1725 return result;
1726}
1727
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001728Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels,
Ben Murdochda12d292016-06-02 14:46:10 +01001729 AllowLabelledFunctionStatement allow_function,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001730 bool* ok) {
1731 // Statement ::
1732 // EmptyStatement
1733 // ...
1734
1735 if (peek() == Token::SEMICOLON) {
1736 Next();
1737 return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
1738 }
Ben Murdochda12d292016-06-02 14:46:10 +01001739 return ParseSubStatement(labels, allow_function, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001740}
1741
Ben Murdochda12d292016-06-02 14:46:10 +01001742Statement* Parser::ParseSubStatement(
1743 ZoneList<const AstRawString*>* labels,
1744 AllowLabelledFunctionStatement allow_function, bool* ok) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001745 // Statement ::
1746 // Block
1747 // VariableStatement
1748 // EmptyStatement
1749 // ExpressionStatement
1750 // IfStatement
1751 // IterationStatement
1752 // ContinueStatement
1753 // BreakStatement
1754 // ReturnStatement
1755 // WithStatement
1756 // LabelledStatement
1757 // SwitchStatement
1758 // ThrowStatement
1759 // TryStatement
1760 // DebuggerStatement
1761
1762 // Note: Since labels can only be used by 'break' and 'continue'
1763 // statements, which themselves are only valid within blocks,
1764 // iterations or 'switch' statements (i.e., BreakableStatements),
1765 // labels can be simply ignored in all other cases; except for
1766 // trivial labeled break statements 'label: break label' which is
1767 // parsed into an empty statement.
1768 switch (peek()) {
1769 case Token::LBRACE:
1770 return ParseBlock(labels, ok);
1771
1772 case Token::SEMICOLON:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001773 Next();
1774 return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
1775
1776 case Token::IF:
1777 return ParseIfStatement(labels, ok);
1778
1779 case Token::DO:
1780 return ParseDoWhileStatement(labels, ok);
1781
1782 case Token::WHILE:
1783 return ParseWhileStatement(labels, ok);
1784
1785 case Token::FOR:
1786 return ParseForStatement(labels, ok);
1787
1788 case Token::CONTINUE:
1789 case Token::BREAK:
1790 case Token::RETURN:
1791 case Token::THROW:
1792 case Token::TRY: {
1793 // These statements must have their labels preserved in an enclosing
1794 // block
1795 if (labels == NULL) {
1796 return ParseStatementAsUnlabelled(labels, ok);
1797 } else {
1798 Block* result =
1799 factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition);
1800 Target target(&this->target_stack_, result);
1801 Statement* statement = ParseStatementAsUnlabelled(labels, CHECK_OK);
1802 if (result) result->statements()->Add(statement, zone());
1803 return result;
1804 }
1805 }
1806
1807 case Token::WITH:
1808 return ParseWithStatement(labels, ok);
1809
1810 case Token::SWITCH:
1811 return ParseSwitchStatement(labels, ok);
1812
Ben Murdochda12d292016-06-02 14:46:10 +01001813 case Token::FUNCTION:
1814 // FunctionDeclaration only allowed as a StatementListItem, not in
1815 // an arbitrary Statement position. Exceptions such as
1816 // ES#sec-functiondeclarations-in-ifstatement-statement-clauses
1817 // are handled by calling ParseScopedStatement rather than
1818 // ParseSubStatement directly.
1819 ReportMessageAt(scanner()->peek_location(),
1820 is_strict(language_mode())
1821 ? MessageTemplate::kStrictFunction
1822 : MessageTemplate::kSloppyFunction);
1823 *ok = false;
1824 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001825
1826 case Token::DEBUGGER:
1827 return ParseDebuggerStatement(ok);
1828
1829 case Token::VAR:
1830 return ParseVariableStatement(kStatement, NULL, ok);
1831
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001832 default:
Ben Murdochda12d292016-06-02 14:46:10 +01001833 return ParseExpressionOrLabelledStatement(labels, allow_function, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001834 }
1835}
1836
1837Statement* Parser::ParseStatementAsUnlabelled(
1838 ZoneList<const AstRawString*>* labels, bool* ok) {
1839 switch (peek()) {
1840 case Token::CONTINUE:
1841 return ParseContinueStatement(ok);
1842
1843 case Token::BREAK:
1844 return ParseBreakStatement(labels, ok);
1845
1846 case Token::RETURN:
1847 return ParseReturnStatement(ok);
1848
1849 case Token::THROW:
1850 return ParseThrowStatement(ok);
1851
1852 case Token::TRY:
1853 return ParseTryStatement(ok);
1854
1855 default:
1856 UNREACHABLE();
1857 return NULL;
1858 }
1859}
1860
1861
1862VariableProxy* Parser::NewUnresolved(const AstRawString* name,
1863 VariableMode mode) {
1864 // If we are inside a function, a declaration of a var/const variable is a
1865 // truly local variable, and the scope of the variable is always the function
1866 // scope.
1867 // Let/const variables in harmony mode are always added to the immediately
1868 // enclosing scope.
1869 Scope* scope =
1870 IsLexicalVariableMode(mode) ? scope_ : scope_->DeclarationScope();
1871 return scope->NewUnresolved(factory(), name, Variable::NORMAL,
1872 scanner()->location().beg_pos,
1873 scanner()->location().end_pos);
1874}
1875
1876
1877Variable* Parser::Declare(Declaration* declaration,
1878 DeclarationDescriptor::Kind declaration_kind,
1879 bool resolve, bool* ok, Scope* scope) {
1880 VariableProxy* proxy = declaration->proxy();
1881 DCHECK(proxy->raw_name() != NULL);
1882 const AstRawString* name = proxy->raw_name();
1883 VariableMode mode = declaration->mode();
1884 bool is_function_declaration = declaration->IsFunctionDeclaration();
1885 if (scope == nullptr) scope = scope_;
1886 Scope* declaration_scope =
1887 IsLexicalVariableMode(mode) ? scope : scope->DeclarationScope();
1888 Variable* var = NULL;
1889
1890 // If a suitable scope exists, then we can statically declare this
1891 // variable and also set its mode. In any case, a Declaration node
1892 // will be added to the scope so that the declaration can be added
1893 // to the corresponding activation frame at runtime if necessary.
1894 // For instance, var declarations inside a sloppy eval scope need
1895 // to be added to the calling function context. Similarly, strict
1896 // mode eval scope and lexical eval bindings do not leak variable
1897 // declarations to the caller's scope so we declare all locals, too.
1898 if (declaration_scope->is_function_scope() ||
1899 declaration_scope->is_block_scope() ||
1900 declaration_scope->is_module_scope() ||
1901 declaration_scope->is_script_scope() ||
1902 (declaration_scope->is_eval_scope() &&
1903 (is_strict(declaration_scope->language_mode()) ||
1904 IsLexicalVariableMode(mode)))) {
1905 // Declare the variable in the declaration scope.
1906 var = declaration_scope->LookupLocal(name);
1907 if (var == NULL) {
1908 // Declare the name.
1909 Variable::Kind kind = Variable::NORMAL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001910 if (is_function_declaration) {
1911 kind = Variable::FUNCTION;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001912 }
1913 var = declaration_scope->DeclareLocal(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001914 name, mode, declaration->initialization(), kind, kNotAssigned);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001915 } else if ((IsLexicalVariableMode(mode) ||
1916 IsLexicalVariableMode(var->mode())) &&
1917 // Lexical bindings may appear for some parameters in sloppy
1918 // mode even with --harmony-sloppy off.
1919 (is_strict(language_mode()) || allow_harmony_sloppy())) {
1920 // Allow duplicate function decls for web compat, see bug 4693.
1921 if (is_sloppy(language_mode()) && is_function_declaration &&
1922 var->is_function()) {
1923 DCHECK(IsLexicalVariableMode(mode) &&
1924 IsLexicalVariableMode(var->mode()));
1925 ++use_counts_[v8::Isolate::kSloppyModeBlockScopedFunctionRedefinition];
1926 } else {
1927 // The name was declared in this scope before; check for conflicting
1928 // re-declarations. We have a conflict if either of the declarations
1929 // is not a var (in script scope, we also have to ignore legacy const
1930 // for compatibility). There is similar code in runtime.cc in the
1931 // Declare functions. The function CheckConflictingVarDeclarations
1932 // checks for var and let bindings from different scopes whereas this
1933 // is a check for conflicting declarations within the same scope. This
1934 // check also covers the special case
1935 //
1936 // function () { let x; { var x; } }
1937 //
1938 // because the var declaration is hoisted to the function scope where
1939 // 'x' is already bound.
1940 DCHECK(IsDeclaredVariableMode(var->mode()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001941 // In harmony we treat re-declarations as early errors. See
1942 // ES5 16 for a definition of early errors.
1943 if (declaration_kind == DeclarationDescriptor::NORMAL) {
1944 ParserTraits::ReportMessage(MessageTemplate::kVarRedeclaration, name);
1945 } else {
1946 ParserTraits::ReportMessage(MessageTemplate::kParamDupe);
1947 }
1948 *ok = false;
1949 return nullptr;
1950 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001951 } else if (mode == VAR) {
1952 var->set_maybe_assigned();
1953 }
1954 } else if (declaration_scope->is_eval_scope() &&
1955 is_sloppy(declaration_scope->language_mode()) &&
1956 !IsLexicalVariableMode(mode)) {
1957 // In a var binding in a sloppy direct eval, pollute the enclosing scope
1958 // with this new binding by doing the following:
1959 // The proxy is bound to a lookup variable to force a dynamic declaration
1960 // using the DeclareLookupSlot runtime function.
1961 Variable::Kind kind = Variable::NORMAL;
1962 // TODO(sigurds) figure out if kNotAssigned is OK here
1963 var = new (zone()) Variable(declaration_scope, name, mode, kind,
1964 declaration->initialization(), kNotAssigned);
1965 var->AllocateTo(VariableLocation::LOOKUP, -1);
1966 var->SetFromEval();
1967 resolve = true;
1968 }
1969
1970
1971 // We add a declaration node for every declaration. The compiler
1972 // will only generate code if necessary. In particular, declarations
1973 // for inner local variables that do not represent functions won't
1974 // result in any generated code.
1975 //
1976 // Note that we always add an unresolved proxy even if it's not
1977 // used, simply because we don't know in this method (w/o extra
1978 // parameters) if the proxy is needed or not. The proxy will be
1979 // bound during variable resolution time unless it was pre-bound
1980 // below.
1981 //
1982 // WARNING: This will lead to multiple declaration nodes for the
1983 // same variable if it is declared several times. This is not a
1984 // semantic issue as long as we keep the source order, but it may be
1985 // a performance issue since it may lead to repeated
1986 // RuntimeHidden_DeclareLookupSlot calls.
1987 declaration_scope->AddDeclaration(declaration);
1988
1989 if (mode == CONST_LEGACY && declaration_scope->is_script_scope()) {
1990 // For global const variables we bind the proxy to a variable.
1991 DCHECK(resolve); // should be set by all callers
1992 Variable::Kind kind = Variable::NORMAL;
1993 var = new (zone()) Variable(declaration_scope, name, mode, kind,
1994 kNeedsInitialization, kNotAssigned);
1995 }
1996
1997 // If requested and we have a local variable, bind the proxy to the variable
1998 // at parse-time. This is used for functions (and consts) declared inside
1999 // statements: the corresponding function (or const) variable must be in the
2000 // function scope and not a statement-local scope, e.g. as provided with a
2001 // 'with' statement:
2002 //
2003 // with (obj) {
2004 // function f() {}
2005 // }
2006 //
2007 // which is translated into:
2008 //
2009 // with (obj) {
2010 // // in this case this is not: 'var f; f = function () {};'
2011 // var f = function () {};
2012 // }
2013 //
2014 // Note that if 'f' is accessed from inside the 'with' statement, it
2015 // will be allocated in the context (because we must be able to look
2016 // it up dynamically) but it will also be accessed statically, i.e.,
2017 // with a context slot index and a context chain length for this
2018 // initialization code. Thus, inside the 'with' statement, we need
2019 // both access to the static and the dynamic context chain; the
2020 // runtime needs to provide both.
2021 if (resolve && var != NULL) {
2022 proxy->BindTo(var);
2023 }
2024 return var;
2025}
2026
2027
2028// Language extension which is only enabled for source files loaded
2029// through the API's extension mechanism. A native function
2030// declaration is resolved by looking up the function through a
2031// callback provided by the extension.
2032Statement* Parser::ParseNativeDeclaration(bool* ok) {
2033 int pos = peek_position();
2034 Expect(Token::FUNCTION, CHECK_OK);
2035 // Allow "eval" or "arguments" for backward compatibility.
2036 const AstRawString* name =
2037 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
2038 Expect(Token::LPAREN, CHECK_OK);
2039 bool done = (peek() == Token::RPAREN);
2040 while (!done) {
2041 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
2042 done = (peek() == Token::RPAREN);
2043 if (!done) {
2044 Expect(Token::COMMA, CHECK_OK);
2045 }
2046 }
2047 Expect(Token::RPAREN, CHECK_OK);
2048 Expect(Token::SEMICOLON, CHECK_OK);
2049
2050 // Make sure that the function containing the native declaration
2051 // isn't lazily compiled. The extension structures are only
2052 // accessible while parsing the first time not when reparsing
2053 // because of lazy compilation.
2054 // TODO(adamk): Should this be ClosureScope()?
2055 scope_->DeclarationScope()->ForceEagerCompilation();
2056
2057 // TODO(1240846): It's weird that native function declarations are
2058 // introduced dynamically when we meet their declarations, whereas
2059 // other functions are set up when entering the surrounding scope.
2060 VariableProxy* proxy = NewUnresolved(name, VAR);
2061 Declaration* declaration =
2062 factory()->NewVariableDeclaration(proxy, VAR, scope_, pos);
2063 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
2064 NativeFunctionLiteral* lit = factory()->NewNativeFunctionLiteral(
2065 name, extension_, RelocInfo::kNoPosition);
2066 return factory()->NewExpressionStatement(
2067 factory()->NewAssignment(Token::INIT, proxy, lit, RelocInfo::kNoPosition),
2068 pos);
2069}
2070
2071
2072Statement* Parser::ParseFunctionDeclaration(
2073 ZoneList<const AstRawString*>* names, bool* ok) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002074 Expect(Token::FUNCTION, CHECK_OK);
2075 int pos = position();
2076 bool is_generator = Check(Token::MUL);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002077 return ParseFunctionDeclaration(pos, is_generator, names, ok);
2078}
2079
2080
2081Statement* Parser::ParseFunctionDeclaration(
2082 int pos, bool is_generator, ZoneList<const AstRawString*>* names,
2083 bool* ok) {
2084 // FunctionDeclaration ::
2085 // 'function' Identifier '(' FormalParameters ')' '{' FunctionBody '}'
2086 // GeneratorDeclaration ::
2087 // 'function' '*' Identifier '(' FormalParameters ')' '{' FunctionBody '}'
2088 //
2089 // 'function' and '*' (if present) have been consumed by the caller.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002090 bool is_strict_reserved = false;
2091 const AstRawString* name = ParseIdentifierOrStrictReservedWord(
2092 &is_strict_reserved, CHECK_OK);
2093
2094 FuncNameInferrer::State fni_state(fni_);
2095 if (fni_ != NULL) fni_->PushEnclosingName(name);
2096 FunctionLiteral* fun = ParseFunctionLiteral(
2097 name, scanner()->location(),
2098 is_strict_reserved ? kFunctionNameIsStrictReserved
2099 : kFunctionNameValidityUnknown,
2100 is_generator ? FunctionKind::kGeneratorFunction
2101 : FunctionKind::kNormalFunction,
Ben Murdoch097c5b22016-05-18 11:27:45 +01002102 pos, FunctionLiteral::kDeclaration, language_mode(), CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002103
2104 // Even if we're not at the top-level of the global or a function
2105 // scope, we treat it as such and introduce the function with its
2106 // initial value upon entering the corresponding scope.
2107 // In ES6, a function behaves as a lexical binding, except in
2108 // a script scope, or the initial scope of eval or another function.
2109 VariableMode mode =
Ben Murdochda12d292016-06-02 14:46:10 +01002110 (is_strict(language_mode()) || allow_harmony_sloppy_function()) &&
2111 !scope_->is_declaration_scope()
2112 ? LET
2113 : VAR;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002114 VariableProxy* proxy = NewUnresolved(name, mode);
2115 Declaration* declaration =
2116 factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);
2117 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
2118 if (names) names->Add(name, zone());
2119 EmptyStatement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
2120 if (is_sloppy(language_mode()) && allow_harmony_sloppy_function() &&
2121 !scope_->is_declaration_scope()) {
2122 SloppyBlockFunctionStatement* delegate =
2123 factory()->NewSloppyBlockFunctionStatement(empty, scope_);
2124 scope_->DeclarationScope()->sloppy_block_function_map()->Declare(name,
2125 delegate);
2126 return delegate;
2127 }
2128 return empty;
2129}
2130
2131
2132Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
2133 bool* ok) {
2134 // ClassDeclaration ::
2135 // 'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}'
2136 //
Ben Murdoch097c5b22016-05-18 11:27:45 +01002137 // 'class' is expected to be consumed by the caller.
2138 //
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002139 // A ClassDeclaration
2140 //
2141 // class C { ... }
2142 //
2143 // has the same semantics as:
2144 //
2145 // let C = class C { ... };
2146 //
2147 // so rewrite it as such.
2148
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002149 if (!allow_harmony_sloppy() && is_sloppy(language_mode())) {
2150 ReportMessage(MessageTemplate::kSloppyLexical);
2151 *ok = false;
2152 return NULL;
2153 }
2154
2155 int pos = position();
2156 bool is_strict_reserved = false;
2157 const AstRawString* name =
2158 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
Ben Murdochda12d292016-06-02 14:46:10 +01002159 ClassLiteral* value = ParseClassLiteral(nullptr, name, scanner()->location(),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002160 is_strict_reserved, pos, CHECK_OK);
2161
Ben Murdochda12d292016-06-02 14:46:10 +01002162 VariableProxy* proxy = NewUnresolved(name, LET);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002163 Declaration* declaration =
Ben Murdochda12d292016-06-02 14:46:10 +01002164 factory()->NewVariableDeclaration(proxy, LET, scope_, pos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002165 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002166 proxy->var()->set_initializer_position(position());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002167 Assignment* assignment =
2168 factory()->NewAssignment(Token::INIT, proxy, value, pos);
2169 Statement* assignment_statement =
2170 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
2171 if (names) names->Add(name, zone());
2172 return assignment_statement;
2173}
2174
2175
2176Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels,
2177 bool finalize_block_scope, bool* ok) {
2178 // The harmony mode uses block elements instead of statements.
2179 //
2180 // Block ::
2181 // '{' StatementList '}'
2182
2183 // Construct block expecting 16 statements.
2184 Block* body =
2185 factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition);
2186 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
2187
2188 // Parse the statements and collect escaping labels.
2189 Expect(Token::LBRACE, CHECK_OK);
2190 block_scope->set_start_position(scanner()->location().beg_pos);
2191 { BlockState block_state(&scope_, block_scope);
2192 Target target(&this->target_stack_, body);
2193
2194 while (peek() != Token::RBRACE) {
2195 Statement* stat = ParseStatementListItem(CHECK_OK);
2196 if (stat && !stat->IsEmpty()) {
2197 body->statements()->Add(stat, zone());
2198 }
2199 }
2200 }
2201 Expect(Token::RBRACE, CHECK_OK);
2202 block_scope->set_end_position(scanner()->location().end_pos);
2203 if (finalize_block_scope) {
2204 block_scope = block_scope->FinalizeBlockScope();
2205 }
2206 body->set_scope(block_scope);
2207 return body;
2208}
2209
2210
2211Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) {
2212 return ParseBlock(labels, true, ok);
2213}
2214
2215
2216Block* Parser::DeclarationParsingResult::BuildInitializationBlock(
2217 ZoneList<const AstRawString*>* names, bool* ok) {
2218 Block* result = descriptor.parser->factory()->NewBlock(
2219 NULL, 1, true, descriptor.declaration_pos);
2220 for (auto declaration : declarations) {
2221 PatternRewriter::DeclareAndInitializeVariables(
2222 result, &descriptor, &declaration, names, CHECK_OK);
2223 }
2224 return result;
2225}
2226
2227
2228Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
2229 ZoneList<const AstRawString*>* names,
2230 bool* ok) {
2231 // VariableStatement ::
2232 // VariableDeclarations ';'
2233
2234 // The scope of a var/const declared variable anywhere inside a function
2235 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
2236 // transform a source-level var/const declaration into a (Function)
2237 // Scope declaration, and rewrite the source-level initialization into an
2238 // assignment statement. We use a block to collect multiple assignments.
2239 //
2240 // We mark the block as initializer block because we don't want the
2241 // rewriter to add a '.result' assignment to such a block (to get compliant
2242 // behavior for code such as print(eval('var x = 7')), and for cosmetic
2243 // reasons when pretty-printing. Also, unless an assignment (initialization)
2244 // is inside an initializer block, it is ignored.
2245
2246 DeclarationParsingResult parsing_result;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002247 Block* result =
2248 ParseVariableDeclarations(var_context, &parsing_result, names, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002249 ExpectSemicolon(CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002250 return result;
2251}
2252
Ben Murdoch097c5b22016-05-18 11:27:45 +01002253Block* Parser::ParseVariableDeclarations(
2254 VariableDeclarationContext var_context,
2255 DeclarationParsingResult* parsing_result,
2256 ZoneList<const AstRawString*>* names, bool* ok) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002257 // VariableDeclarations ::
2258 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
2259 //
2260 // The ES6 Draft Rev3 specifies the following grammar for const declarations
2261 //
2262 // ConstDeclaration ::
2263 // const ConstBinding (',' ConstBinding)* ';'
2264 // ConstBinding ::
2265 // Identifier '=' AssignmentExpression
2266 //
2267 // TODO(ES6):
2268 // ConstBinding ::
2269 // BindingPattern '=' AssignmentExpression
2270
2271 parsing_result->descriptor.parser = this;
2272 parsing_result->descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
2273 parsing_result->descriptor.declaration_pos = peek_position();
2274 parsing_result->descriptor.initialization_pos = peek_position();
2275 parsing_result->descriptor.mode = VAR;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002276
2277 Block* init_block = nullptr;
2278 if (var_context != kForStatement) {
2279 init_block = factory()->NewBlock(
2280 NULL, 1, true, parsing_result->descriptor.declaration_pos);
2281 }
2282
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002283 if (peek() == Token::VAR) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002284 Consume(Token::VAR);
2285 } else if (peek() == Token::CONST && allow_const()) {
2286 Consume(Token::CONST);
Ben Murdochda12d292016-06-02 14:46:10 +01002287 DCHECK(is_strict(language_mode()) || allow_harmony_sloppy());
2288 DCHECK(var_context != kStatement);
2289 parsing_result->descriptor.mode = CONST;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002290 } else if (peek() == Token::LET && allow_let()) {
2291 Consume(Token::LET);
2292 DCHECK(var_context != kStatement);
2293 parsing_result->descriptor.mode = LET;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002294 } else {
2295 UNREACHABLE(); // by current callers
2296 }
2297
2298 parsing_result->descriptor.scope = scope_;
2299 parsing_result->descriptor.hoist_scope = nullptr;
2300
2301
2302 bool first_declaration = true;
2303 int bindings_start = peek_position();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002304 do {
2305 FuncNameInferrer::State fni_state(fni_);
2306
2307 // Parse name.
2308 if (!first_declaration) Consume(Token::COMMA);
2309
2310 Expression* pattern;
2311 int decl_pos = peek_position();
2312 {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002313 ExpressionClassifier pattern_classifier(this);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002314 pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
2315 ValidateBindingPattern(&pattern_classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002316 if (IsLexicalVariableMode(parsing_result->descriptor.mode)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002317 ValidateLetPattern(&pattern_classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002318 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002319 }
2320
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002321 Scanner::Location variable_loc = scanner()->location();
2322 const AstRawString* single_name =
2323 pattern->IsVariableProxy() ? pattern->AsVariableProxy()->raw_name()
2324 : nullptr;
2325 if (single_name != nullptr) {
2326 if (fni_ != NULL) fni_->PushVariableName(single_name);
2327 }
2328
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002329 Expression* value = NULL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002330 int initializer_position = RelocInfo::kNoPosition;
2331 if (Check(Token::ASSIGN)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002332 ExpressionClassifier classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002333 value = ParseAssignmentExpression(var_context != kForStatement,
Ben Murdoch097c5b22016-05-18 11:27:45 +01002334 &classifier, CHECK_OK);
2335 RewriteNonPattern(&classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002336 variable_loc.end_pos = scanner()->location().end_pos;
2337
2338 if (!parsing_result->first_initializer_loc.IsValid()) {
2339 parsing_result->first_initializer_loc = variable_loc;
2340 }
2341
2342 // Don't infer if it is "a = function(){...}();"-like expression.
2343 if (single_name) {
2344 if (fni_ != NULL && value->AsCall() == NULL &&
2345 value->AsCallNew() == NULL) {
2346 fni_->Infer();
2347 } else {
2348 fni_->RemoveLastFunction();
2349 }
2350 }
2351
Ben Murdoch097c5b22016-05-18 11:27:45 +01002352 if (allow_harmony_function_name()) {
2353 ParserTraits::SetFunctionNameFromIdentifierRef(value, pattern);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002354 }
2355
2356 // End position of the initializer is after the assignment expression.
2357 initializer_position = scanner()->location().end_pos;
2358 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002359 // Initializers may be either required or implied unless this is a
2360 // for-in/of iteration variable.
2361 if (var_context != kForStatement || !PeekInOrOf()) {
2362 // ES6 'const' and binding patterns require initializers.
2363 if (parsing_result->descriptor.mode == CONST ||
2364 !pattern->IsVariableProxy()) {
2365 ParserTraits::ReportMessageAt(
2366 Scanner::Location(decl_pos, scanner()->location().end_pos),
2367 MessageTemplate::kDeclarationMissingInitializer,
2368 !pattern->IsVariableProxy() ? "destructuring" : "const");
2369 *ok = false;
2370 return nullptr;
2371 }
2372
2373 // 'let x' and (legacy) 'const x' initialize 'x' to undefined.
2374 if (parsing_result->descriptor.mode == LET ||
2375 parsing_result->descriptor.mode == CONST_LEGACY) {
2376 value = GetLiteralUndefined(position());
2377 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002378 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002379
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002380 // End position of the initializer is after the variable.
2381 initializer_position = position();
2382 }
2383
Ben Murdoch097c5b22016-05-18 11:27:45 +01002384 DeclarationParsingResult::Declaration decl(pattern, initializer_position,
2385 value);
2386 if (var_context == kForStatement) {
2387 // Save the declaration for further handling in ParseForStatement.
2388 parsing_result->declarations.Add(decl);
2389 } else {
2390 // Immediately declare the variable otherwise. This avoids O(N^2)
2391 // behavior (where N is the number of variables in a single
2392 // declaration) in the PatternRewriter having to do with removing
2393 // and adding VariableProxies to the Scope (see bug 4699).
2394 DCHECK_NOT_NULL(init_block);
2395 PatternRewriter::DeclareAndInitializeVariables(
2396 init_block, &parsing_result->descriptor, &decl, names, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002397 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002398 first_declaration = false;
2399 } while (peek() == Token::COMMA);
2400
2401 parsing_result->bindings_loc =
2402 Scanner::Location(bindings_start, scanner()->location().end_pos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002403
2404 DCHECK(*ok);
2405 return init_block;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002406}
2407
2408
2409static bool ContainsLabel(ZoneList<const AstRawString*>* labels,
2410 const AstRawString* label) {
2411 DCHECK(label != NULL);
2412 if (labels != NULL) {
2413 for (int i = labels->length(); i-- > 0; ) {
2414 if (labels->at(i) == label) {
2415 return true;
2416 }
2417 }
2418 }
2419 return false;
2420}
2421
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002422Statement* Parser::ParseExpressionOrLabelledStatement(
Ben Murdochda12d292016-06-02 14:46:10 +01002423 ZoneList<const AstRawString*>* labels,
2424 AllowLabelledFunctionStatement allow_function, bool* ok) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002425 // ExpressionStatement | LabelledStatement ::
2426 // Expression ';'
2427 // Identifier ':' Statement
2428 //
2429 // ExpressionStatement[Yield] :
2430 // [lookahead ∉ {{, function, class, let [}] Expression[In, ?Yield] ;
2431
2432 int pos = peek_position();
2433
2434 switch (peek()) {
2435 case Token::FUNCTION:
2436 case Token::LBRACE:
2437 UNREACHABLE(); // Always handled by the callers.
2438 case Token::CLASS:
2439 ReportUnexpectedToken(Next());
2440 *ok = false;
2441 return nullptr;
2442
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002443 default:
2444 break;
2445 }
2446
2447 bool starts_with_idenfifier = peek_any_identifier();
2448 Expression* expr = ParseExpression(true, CHECK_OK);
2449 if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL &&
2450 expr->AsVariableProxy() != NULL &&
2451 !expr->AsVariableProxy()->is_this()) {
2452 // Expression is a single identifier, and not, e.g., a parenthesized
2453 // identifier.
2454 VariableProxy* var = expr->AsVariableProxy();
2455 const AstRawString* label = var->raw_name();
2456 // TODO(1240780): We don't check for redeclaration of labels
2457 // during preparsing since keeping track of the set of active
2458 // labels requires nontrivial changes to the way scopes are
2459 // structured. However, these are probably changes we want to
2460 // make later anyway so we should go back and fix this then.
2461 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
2462 ParserTraits::ReportMessage(MessageTemplate::kLabelRedeclaration, label);
2463 *ok = false;
2464 return NULL;
2465 }
2466 if (labels == NULL) {
2467 labels = new(zone()) ZoneList<const AstRawString*>(4, zone());
2468 }
2469 labels->Add(label, zone());
2470 // Remove the "ghost" variable that turned out to be a label
2471 // from the top scope. This way, we don't try to resolve it
2472 // during the scope processing.
2473 scope_->RemoveUnresolved(var);
2474 Expect(Token::COLON, CHECK_OK);
Ben Murdochda12d292016-06-02 14:46:10 +01002475 // ES#sec-labelled-function-declarations Labelled Function Declarations
2476 if (peek() == Token::FUNCTION && is_sloppy(language_mode())) {
2477 if (allow_function == kAllowLabelledFunctionStatement) {
2478 return ParseFunctionDeclaration(labels, ok);
2479 } else {
2480 return ParseScopedStatement(labels, true, ok);
2481 }
2482 }
2483 return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002484 }
2485
2486 // If we have an extension, we allow a native function declaration.
2487 // A native function declaration starts with "native function" with
2488 // no line-terminator between the two words.
2489 if (extension_ != NULL && peek() == Token::FUNCTION &&
2490 !scanner()->HasAnyLineTerminatorBeforeNext() && expr != NULL &&
2491 expr->AsVariableProxy() != NULL &&
2492 expr->AsVariableProxy()->raw_name() ==
2493 ast_value_factory()->native_string() &&
2494 !scanner()->literal_contains_escapes()) {
2495 return ParseNativeDeclaration(ok);
2496 }
2497
2498 // Parsed expression statement, followed by semicolon.
2499 // Detect attempts at 'let' declarations in sloppy mode.
2500 if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER &&
2501 expr->AsVariableProxy() != NULL &&
2502 expr->AsVariableProxy()->raw_name() ==
2503 ast_value_factory()->let_string()) {
2504 ReportMessage(MessageTemplate::kSloppyLexical, NULL);
2505 *ok = false;
2506 return NULL;
2507 }
2508 ExpectSemicolon(CHECK_OK);
2509 return factory()->NewExpressionStatement(expr, pos);
2510}
2511
2512
2513IfStatement* Parser::ParseIfStatement(ZoneList<const AstRawString*>* labels,
2514 bool* ok) {
2515 // IfStatement ::
2516 // 'if' '(' Expression ')' Statement ('else' Statement)?
2517
2518 int pos = peek_position();
2519 Expect(Token::IF, CHECK_OK);
2520 Expect(Token::LPAREN, CHECK_OK);
2521 Expression* condition = ParseExpression(true, CHECK_OK);
2522 Expect(Token::RPAREN, CHECK_OK);
Ben Murdochda12d292016-06-02 14:46:10 +01002523 Statement* then_statement = ParseScopedStatement(labels, false, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002524 Statement* else_statement = NULL;
2525 if (peek() == Token::ELSE) {
2526 Next();
Ben Murdochda12d292016-06-02 14:46:10 +01002527 else_statement = ParseScopedStatement(labels, false, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002528 } else {
2529 else_statement = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
2530 }
2531 return factory()->NewIfStatement(
2532 condition, then_statement, else_statement, pos);
2533}
2534
2535
2536Statement* Parser::ParseContinueStatement(bool* ok) {
2537 // ContinueStatement ::
2538 // 'continue' Identifier? ';'
2539
2540 int pos = peek_position();
2541 Expect(Token::CONTINUE, CHECK_OK);
2542 const AstRawString* label = NULL;
2543 Token::Value tok = peek();
2544 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
2545 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
2546 // ECMA allows "eval" or "arguments" as labels even in strict mode.
2547 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
2548 }
2549 IterationStatement* target = LookupContinueTarget(label, CHECK_OK);
2550 if (target == NULL) {
2551 // Illegal continue statement.
2552 MessageTemplate::Template message = MessageTemplate::kIllegalContinue;
2553 if (label != NULL) {
2554 message = MessageTemplate::kUnknownLabel;
2555 }
2556 ParserTraits::ReportMessage(message, label);
2557 *ok = false;
2558 return NULL;
2559 }
2560 ExpectSemicolon(CHECK_OK);
2561 return factory()->NewContinueStatement(target, pos);
2562}
2563
2564
2565Statement* Parser::ParseBreakStatement(ZoneList<const AstRawString*>* labels,
2566 bool* ok) {
2567 // BreakStatement ::
2568 // 'break' Identifier? ';'
2569
2570 int pos = peek_position();
2571 Expect(Token::BREAK, CHECK_OK);
2572 const AstRawString* label = NULL;
2573 Token::Value tok = peek();
2574 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
2575 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
2576 // ECMA allows "eval" or "arguments" as labels even in strict mode.
2577 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
2578 }
2579 // Parse labeled break statements that target themselves into
2580 // empty statements, e.g. 'l1: l2: l3: break l2;'
2581 if (label != NULL && ContainsLabel(labels, label)) {
2582 ExpectSemicolon(CHECK_OK);
2583 return factory()->NewEmptyStatement(pos);
2584 }
2585 BreakableStatement* target = NULL;
2586 target = LookupBreakTarget(label, CHECK_OK);
2587 if (target == NULL) {
2588 // Illegal break statement.
2589 MessageTemplate::Template message = MessageTemplate::kIllegalBreak;
2590 if (label != NULL) {
2591 message = MessageTemplate::kUnknownLabel;
2592 }
2593 ParserTraits::ReportMessage(message, label);
2594 *ok = false;
2595 return NULL;
2596 }
2597 ExpectSemicolon(CHECK_OK);
2598 return factory()->NewBreakStatement(target, pos);
2599}
2600
2601
2602Statement* Parser::ParseReturnStatement(bool* ok) {
2603 // ReturnStatement ::
2604 // 'return' Expression? ';'
2605
2606 // Consume the return token. It is necessary to do that before
2607 // reporting any errors on it, because of the way errors are
2608 // reported (underlining).
2609 Expect(Token::RETURN, CHECK_OK);
2610 Scanner::Location loc = scanner()->location();
2611 function_state_->set_return_location(loc);
2612
2613 Token::Value tok = peek();
2614 Statement* result;
2615 Expression* return_value;
2616 if (scanner()->HasAnyLineTerminatorBeforeNext() ||
2617 tok == Token::SEMICOLON ||
2618 tok == Token::RBRACE ||
2619 tok == Token::EOS) {
2620 if (IsSubclassConstructor(function_state_->kind())) {
2621 return_value = ThisExpression(scope_, factory(), loc.beg_pos);
2622 } else {
2623 return_value = GetLiteralUndefined(position());
2624 }
2625 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002626 int pos = peek_position();
2627 return_value = ParseExpression(true, CHECK_OK);
2628
2629 if (IsSubclassConstructor(function_state_->kind())) {
2630 // For subclass constructors we need to return this in case of undefined
Ben Murdoch097c5b22016-05-18 11:27:45 +01002631 // return a Smi (transformed into an exception in the ConstructStub)
2632 // for a non object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002633 //
2634 // return expr;
2635 //
2636 // Is rewritten as:
2637 //
2638 // return (temp = expr) === undefined ? this :
Ben Murdoch097c5b22016-05-18 11:27:45 +01002639 // %_IsJSReceiver(temp) ? temp : 1;
2640
2641 // temp = expr
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002642 Variable* temp = scope_->NewTemporary(
2643 ast_value_factory()->empty_string());
2644 Assignment* assign = factory()->NewAssignment(
2645 Token::ASSIGN, factory()->NewVariableProxy(temp), return_value, pos);
2646
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002647 // %_IsJSReceiver(temp)
2648 ZoneList<Expression*>* is_spec_object_args =
2649 new (zone()) ZoneList<Expression*>(1, zone());
2650 is_spec_object_args->Add(factory()->NewVariableProxy(temp), zone());
2651 Expression* is_spec_object_call = factory()->NewCallRuntime(
2652 Runtime::kInlineIsJSReceiver, is_spec_object_args, pos);
2653
2654 // %_IsJSReceiver(temp) ? temp : throw_expression
2655 Expression* is_object_conditional = factory()->NewConditional(
2656 is_spec_object_call, factory()->NewVariableProxy(temp),
Ben Murdoch097c5b22016-05-18 11:27:45 +01002657 factory()->NewSmiLiteral(1, pos), pos);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002658
2659 // temp === undefined
2660 Expression* is_undefined = factory()->NewCompareOperation(
2661 Token::EQ_STRICT, assign,
2662 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), pos);
2663
2664 // is_undefined ? this : is_object_conditional
2665 return_value = factory()->NewConditional(
2666 is_undefined, ThisExpression(scope_, factory(), pos),
2667 is_object_conditional, pos);
2668 }
2669
Ben Murdoch097c5b22016-05-18 11:27:45 +01002670 // ES6 14.6.1 Static Semantics: IsInTailPosition
Ben Murdochda12d292016-06-02 14:46:10 +01002671 if (allow_tailcalls() && !is_sloppy(language_mode())) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002672 function_state_->AddExpressionInTailPosition(return_value);
2673 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002674 }
2675 ExpectSemicolon(CHECK_OK);
2676
2677 if (is_generator()) {
Ben Murdochda12d292016-06-02 14:46:10 +01002678 return_value = BuildIteratorResult(return_value, true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002679 }
2680
Ben Murdochda12d292016-06-02 14:46:10 +01002681 result = factory()->NewReturnStatement(return_value, loc.beg_pos);
2682
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002683 Scope* decl_scope = scope_->DeclarationScope();
2684 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) {
2685 ReportMessageAt(loc, MessageTemplate::kIllegalReturn);
2686 *ok = false;
2687 return NULL;
2688 }
2689 return result;
2690}
2691
2692
2693Statement* Parser::ParseWithStatement(ZoneList<const AstRawString*>* labels,
2694 bool* ok) {
2695 // WithStatement ::
2696 // 'with' '(' Expression ')' Statement
2697
2698 Expect(Token::WITH, CHECK_OK);
2699 int pos = position();
2700
2701 if (is_strict(language_mode())) {
2702 ReportMessage(MessageTemplate::kStrictWith);
2703 *ok = false;
2704 return NULL;
2705 }
2706
2707 Expect(Token::LPAREN, CHECK_OK);
2708 Expression* expr = ParseExpression(true, CHECK_OK);
2709 Expect(Token::RPAREN, CHECK_OK);
2710
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002711 Scope* with_scope = NewScope(scope_, WITH_SCOPE);
Ben Murdochda12d292016-06-02 14:46:10 +01002712 Statement* body;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002713 { BlockState block_state(&scope_, with_scope);
2714 with_scope->set_start_position(scanner()->peek_location().beg_pos);
Ben Murdochda12d292016-06-02 14:46:10 +01002715 body = ParseScopedStatement(labels, true, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002716 with_scope->set_end_position(scanner()->location().end_pos);
2717 }
2718 return factory()->NewWithStatement(with_scope, expr, body, pos);
2719}
2720
2721
2722CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
2723 // CaseClause ::
2724 // 'case' Expression ':' StatementList
2725 // 'default' ':' StatementList
2726
2727 Expression* label = NULL; // NULL expression indicates default case
2728 if (peek() == Token::CASE) {
2729 Expect(Token::CASE, CHECK_OK);
2730 label = ParseExpression(true, CHECK_OK);
2731 } else {
2732 Expect(Token::DEFAULT, CHECK_OK);
2733 if (*default_seen_ptr) {
2734 ReportMessage(MessageTemplate::kMultipleDefaultsInSwitch);
2735 *ok = false;
2736 return NULL;
2737 }
2738 *default_seen_ptr = true;
2739 }
2740 Expect(Token::COLON, CHECK_OK);
2741 int pos = position();
2742 ZoneList<Statement*>* statements =
2743 new(zone()) ZoneList<Statement*>(5, zone());
2744 Statement* stat = NULL;
2745 while (peek() != Token::CASE &&
2746 peek() != Token::DEFAULT &&
2747 peek() != Token::RBRACE) {
2748 stat = ParseStatementListItem(CHECK_OK);
2749 statements->Add(stat, zone());
2750 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002751 return factory()->NewCaseClause(label, statements, pos);
2752}
2753
2754
2755Statement* Parser::ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
2756 bool* ok) {
2757 // SwitchStatement ::
2758 // 'switch' '(' Expression ')' '{' CaseClause* '}'
2759 // In order to get the CaseClauses to execute in their own lexical scope,
2760 // but without requiring downstream code to have special scope handling
2761 // code for switch statements, desugar into blocks as follows:
2762 // { // To group the statements--harmless to evaluate Expression in scope
2763 // .tag_variable = Expression;
2764 // { // To give CaseClauses a scope
2765 // switch (.tag_variable) { CaseClause* }
2766 // }
2767 // }
2768
2769 Block* switch_block =
2770 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
2771 int switch_pos = peek_position();
2772
2773 Expect(Token::SWITCH, CHECK_OK);
2774 Expect(Token::LPAREN, CHECK_OK);
2775 Expression* tag = ParseExpression(true, CHECK_OK);
2776 Expect(Token::RPAREN, CHECK_OK);
2777
2778 Variable* tag_variable =
2779 scope_->NewTemporary(ast_value_factory()->dot_switch_tag_string());
2780 Assignment* tag_assign = factory()->NewAssignment(
2781 Token::ASSIGN, factory()->NewVariableProxy(tag_variable), tag,
2782 tag->position());
2783 Statement* tag_statement =
2784 factory()->NewExpressionStatement(tag_assign, RelocInfo::kNoPosition);
2785 switch_block->statements()->Add(tag_statement, zone());
2786
2787 // make statement: undefined;
2788 // This is needed so the tag isn't returned as the value, in case the switch
2789 // statements don't have a value.
2790 switch_block->statements()->Add(
2791 factory()->NewExpressionStatement(
2792 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
2793 RelocInfo::kNoPosition),
2794 zone());
2795
2796 Block* cases_block =
2797 factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
2798 Scope* cases_scope = NewScope(scope_, BLOCK_SCOPE);
2799 cases_scope->SetNonlinear();
2800
2801 SwitchStatement* switch_statement =
2802 factory()->NewSwitchStatement(labels, switch_pos);
2803
2804 cases_scope->set_start_position(scanner()->location().beg_pos);
2805 {
2806 BlockState cases_block_state(&scope_, cases_scope);
2807 Target target(&this->target_stack_, switch_statement);
2808
2809 Expression* tag_read = factory()->NewVariableProxy(tag_variable);
2810
2811 bool default_seen = false;
2812 ZoneList<CaseClause*>* cases =
2813 new (zone()) ZoneList<CaseClause*>(4, zone());
2814 Expect(Token::LBRACE, CHECK_OK);
2815 while (peek() != Token::RBRACE) {
2816 CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
2817 cases->Add(clause, zone());
2818 }
2819 switch_statement->Initialize(tag_read, cases);
2820 cases_block->statements()->Add(switch_statement, zone());
2821 }
2822 Expect(Token::RBRACE, CHECK_OK);
2823
2824 cases_scope->set_end_position(scanner()->location().end_pos);
2825 cases_scope = cases_scope->FinalizeBlockScope();
2826 cases_block->set_scope(cases_scope);
2827
2828 switch_block->statements()->Add(cases_block, zone());
2829
2830 return switch_block;
2831}
2832
2833
2834Statement* Parser::ParseThrowStatement(bool* ok) {
2835 // ThrowStatement ::
2836 // 'throw' Expression ';'
2837
2838 Expect(Token::THROW, CHECK_OK);
2839 int pos = position();
2840 if (scanner()->HasAnyLineTerminatorBeforeNext()) {
2841 ReportMessage(MessageTemplate::kNewlineAfterThrow);
2842 *ok = false;
2843 return NULL;
2844 }
2845 Expression* exception = ParseExpression(true, CHECK_OK);
2846 ExpectSemicolon(CHECK_OK);
2847
2848 return factory()->NewExpressionStatement(
2849 factory()->NewThrow(exception, pos), pos);
2850}
2851
Ben Murdoch097c5b22016-05-18 11:27:45 +01002852class Parser::DontCollectExpressionsInTailPositionScope {
2853 public:
2854 DontCollectExpressionsInTailPositionScope(
2855 Parser::FunctionState* function_state)
2856 : function_state_(function_state),
2857 old_value_(function_state->collect_expressions_in_tail_position()) {
2858 function_state->set_collect_expressions_in_tail_position(false);
2859 }
2860 ~DontCollectExpressionsInTailPositionScope() {
2861 function_state_->set_collect_expressions_in_tail_position(old_value_);
2862 }
2863
2864 private:
2865 Parser::FunctionState* function_state_;
2866 bool old_value_;
2867};
2868
2869// Collects all return expressions at tail call position in this scope
2870// to a separate list.
2871class Parser::CollectExpressionsInTailPositionToListScope {
2872 public:
2873 CollectExpressionsInTailPositionToListScope(
2874 Parser::FunctionState* function_state, List<Expression*>* list)
2875 : function_state_(function_state), list_(list) {
2876 function_state->expressions_in_tail_position().Swap(list_);
2877 }
2878 ~CollectExpressionsInTailPositionToListScope() {
2879 function_state_->expressions_in_tail_position().Swap(list_);
2880 }
2881
2882 private:
2883 Parser::FunctionState* function_state_;
2884 List<Expression*>* list_;
2885};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002886
2887TryStatement* Parser::ParseTryStatement(bool* ok) {
2888 // TryStatement ::
2889 // 'try' Block Catch
2890 // 'try' Block Finally
2891 // 'try' Block Catch Finally
2892 //
2893 // Catch ::
2894 // 'catch' '(' Identifier ')' Block
2895 //
2896 // Finally ::
2897 // 'finally' Block
2898
2899 Expect(Token::TRY, CHECK_OK);
2900 int pos = position();
2901
Ben Murdoch097c5b22016-05-18 11:27:45 +01002902 Block* try_block;
2903 {
2904 DontCollectExpressionsInTailPositionScope no_tail_calls(function_state_);
2905 try_block = ParseBlock(NULL, CHECK_OK);
2906 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002907
2908 Token::Value tok = peek();
2909 if (tok != Token::CATCH && tok != Token::FINALLY) {
2910 ReportMessage(MessageTemplate::kNoCatchOrFinally);
2911 *ok = false;
2912 return NULL;
2913 }
2914
2915 Scope* catch_scope = NULL;
2916 Variable* catch_variable = NULL;
2917 Block* catch_block = NULL;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002918 List<Expression*> expressions_in_tail_position_in_catch_block;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002919 if (tok == Token::CATCH) {
2920 Consume(Token::CATCH);
2921
2922 Expect(Token::LPAREN, CHECK_OK);
2923 catch_scope = NewScope(scope_, CATCH_SCOPE);
2924 catch_scope->set_start_position(scanner()->location().beg_pos);
2925
Ben Murdoch097c5b22016-05-18 11:27:45 +01002926 ExpressionClassifier pattern_classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002927 Expression* pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
2928 ValidateBindingPattern(&pattern_classifier, CHECK_OK);
2929
2930 const AstRawString* name = ast_value_factory()->dot_catch_string();
2931 bool is_simple = pattern->IsVariableProxy();
2932 if (is_simple) {
2933 auto proxy = pattern->AsVariableProxy();
2934 scope_->RemoveUnresolved(proxy);
2935 name = proxy->raw_name();
2936 }
2937
2938 catch_variable = catch_scope->DeclareLocal(name, VAR, kCreatedInitialized,
2939 Variable::NORMAL);
2940
2941 Expect(Token::RPAREN, CHECK_OK);
2942
2943 {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002944 CollectExpressionsInTailPositionToListScope
2945 collect_expressions_in_tail_position_scope(
2946 function_state_, &expressions_in_tail_position_in_catch_block);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002947 BlockState block_state(&scope_, catch_scope);
2948
2949 // TODO(adamk): Make a version of ParseBlock that takes a scope and
2950 // a block.
2951 catch_block =
2952 factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition);
2953 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
2954
2955 block_scope->set_start_position(scanner()->location().beg_pos);
2956 {
2957 BlockState block_state(&scope_, block_scope);
2958 Target target(&this->target_stack_, catch_block);
2959
2960 if (!is_simple) {
2961 DeclarationDescriptor descriptor;
2962 descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
2963 descriptor.parser = this;
2964 descriptor.scope = scope_;
2965 descriptor.hoist_scope = nullptr;
2966 descriptor.mode = LET;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002967 descriptor.declaration_pos = pattern->position();
2968 descriptor.initialization_pos = pattern->position();
2969
2970 DeclarationParsingResult::Declaration decl(
2971 pattern, pattern->position(),
2972 factory()->NewVariableProxy(catch_variable));
2973
Ben Murdochda12d292016-06-02 14:46:10 +01002974 Block* init_block =
2975 factory()->NewBlock(nullptr, 8, true, RelocInfo::kNoPosition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002976 PatternRewriter::DeclareAndInitializeVariables(
Ben Murdochda12d292016-06-02 14:46:10 +01002977 init_block, &descriptor, &decl, nullptr, CHECK_OK);
2978 catch_block->statements()->Add(init_block, zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002979 }
2980
2981 Expect(Token::LBRACE, CHECK_OK);
2982 while (peek() != Token::RBRACE) {
2983 Statement* stat = ParseStatementListItem(CHECK_OK);
2984 if (stat && !stat->IsEmpty()) {
2985 catch_block->statements()->Add(stat, zone());
2986 }
2987 }
2988 Consume(Token::RBRACE);
2989 }
2990 block_scope->set_end_position(scanner()->location().end_pos);
2991 block_scope = block_scope->FinalizeBlockScope();
2992 catch_block->set_scope(block_scope);
2993 }
2994
2995 catch_scope->set_end_position(scanner()->location().end_pos);
2996 tok = peek();
2997 }
2998
2999 Block* finally_block = NULL;
3000 DCHECK(tok == Token::FINALLY || catch_block != NULL);
3001 if (tok == Token::FINALLY) {
3002 Consume(Token::FINALLY);
3003 finally_block = ParseBlock(NULL, CHECK_OK);
3004 }
3005
3006 // Simplify the AST nodes by converting:
3007 // 'try B0 catch B1 finally B2'
3008 // to:
3009 // 'try { try B0 catch B1 } finally B2'
3010
3011 if (catch_block != NULL && finally_block != NULL) {
3012 // If we have both, create an inner try/catch.
3013 DCHECK(catch_scope != NULL && catch_variable != NULL);
3014 TryCatchStatement* statement =
3015 factory()->NewTryCatchStatement(try_block, catch_scope, catch_variable,
3016 catch_block, RelocInfo::kNoPosition);
3017 try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
3018 try_block->statements()->Add(statement, zone());
3019 catch_block = NULL; // Clear to indicate it's been handled.
3020 }
3021
3022 TryStatement* result = NULL;
3023 if (catch_block != NULL) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003024 // For a try-catch construct append return expressions from the catch block
3025 // to the list of return expressions.
3026 function_state_->expressions_in_tail_position().AddAll(
3027 expressions_in_tail_position_in_catch_block);
3028
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003029 DCHECK(finally_block == NULL);
3030 DCHECK(catch_scope != NULL && catch_variable != NULL);
3031 result = factory()->NewTryCatchStatement(try_block, catch_scope,
3032 catch_variable, catch_block, pos);
3033 } else {
3034 DCHECK(finally_block != NULL);
3035 result = factory()->NewTryFinallyStatement(try_block, finally_block, pos);
3036 }
3037
3038 return result;
3039}
3040
3041
3042DoWhileStatement* Parser::ParseDoWhileStatement(
3043 ZoneList<const AstRawString*>* labels, bool* ok) {
3044 // DoStatement ::
3045 // 'do' Statement 'while' '(' Expression ')' ';'
3046
3047 DoWhileStatement* loop =
3048 factory()->NewDoWhileStatement(labels, peek_position());
3049 Target target(&this->target_stack_, loop);
3050
3051 Expect(Token::DO, CHECK_OK);
Ben Murdochda12d292016-06-02 14:46:10 +01003052 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003053 Expect(Token::WHILE, CHECK_OK);
3054 Expect(Token::LPAREN, CHECK_OK);
3055
3056 Expression* cond = ParseExpression(true, CHECK_OK);
3057 Expect(Token::RPAREN, CHECK_OK);
3058
3059 // Allow do-statements to be terminated with and without
3060 // semi-colons. This allows code such as 'do;while(0)return' to
3061 // parse, which would not be the case if we had used the
3062 // ExpectSemicolon() functionality here.
3063 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
3064
3065 if (loop != NULL) loop->Initialize(cond, body);
3066 return loop;
3067}
3068
3069
3070WhileStatement* Parser::ParseWhileStatement(
3071 ZoneList<const AstRawString*>* labels, bool* ok) {
3072 // WhileStatement ::
3073 // 'while' '(' Expression ')' Statement
3074
3075 WhileStatement* loop = factory()->NewWhileStatement(labels, peek_position());
3076 Target target(&this->target_stack_, loop);
3077
3078 Expect(Token::WHILE, CHECK_OK);
3079 Expect(Token::LPAREN, CHECK_OK);
3080 Expression* cond = ParseExpression(true, CHECK_OK);
3081 Expect(Token::RPAREN, CHECK_OK);
Ben Murdochda12d292016-06-02 14:46:10 +01003082 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003083
3084 if (loop != NULL) loop->Initialize(cond, body);
3085 return loop;
3086}
3087
3088
3089// !%_IsJSReceiver(result = iterator.next()) &&
3090// %ThrowIteratorResultNotAnObject(result)
3091Expression* Parser::BuildIteratorNextResult(Expression* iterator,
3092 Variable* result, int pos) {
3093 Expression* next_literal = factory()->NewStringLiteral(
3094 ast_value_factory()->next_string(), RelocInfo::kNoPosition);
3095 Expression* next_property =
3096 factory()->NewProperty(iterator, next_literal, RelocInfo::kNoPosition);
3097 ZoneList<Expression*>* next_arguments =
3098 new (zone()) ZoneList<Expression*>(0, zone());
3099 Expression* next_call =
3100 factory()->NewCall(next_property, next_arguments, pos);
3101 Expression* result_proxy = factory()->NewVariableProxy(result);
3102 Expression* left =
3103 factory()->NewAssignment(Token::ASSIGN, result_proxy, next_call, pos);
3104
3105 // %_IsJSReceiver(...)
3106 ZoneList<Expression*>* is_spec_object_args =
3107 new (zone()) ZoneList<Expression*>(1, zone());
3108 is_spec_object_args->Add(left, zone());
3109 Expression* is_spec_object_call = factory()->NewCallRuntime(
3110 Runtime::kInlineIsJSReceiver, is_spec_object_args, pos);
3111
3112 // %ThrowIteratorResultNotAnObject(result)
3113 Expression* result_proxy_again = factory()->NewVariableProxy(result);
3114 ZoneList<Expression*>* throw_arguments =
3115 new (zone()) ZoneList<Expression*>(1, zone());
3116 throw_arguments->Add(result_proxy_again, zone());
3117 Expression* throw_call = factory()->NewCallRuntime(
3118 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos);
3119
3120 return factory()->NewBinaryOperation(
3121 Token::AND,
3122 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos),
3123 throw_call, pos);
3124}
3125
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003126void Parser::InitializeForEachStatement(ForEachStatement* stmt,
3127 Expression* each, Expression* subject,
Ben Murdochda12d292016-06-02 14:46:10 +01003128 Statement* body) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003129 ForOfStatement* for_of = stmt->AsForOfStatement();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003130 if (for_of != NULL) {
Ben Murdochda12d292016-06-02 14:46:10 +01003131 InitializeForOfStatement(for_of, each, subject, body,
3132 RelocInfo::kNoPosition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003133 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01003134 if (each->IsArrayLiteral() || each->IsObjectLiteral()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003135 Variable* temp =
3136 scope_->NewTemporary(ast_value_factory()->empty_string());
3137 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
3138 Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment(
3139 this, factory()->NewAssignment(Token::ASSIGN, each, temp_proxy,
3140 RelocInfo::kNoPosition),
3141 scope_);
3142 auto block =
3143 factory()->NewBlock(nullptr, 2, false, RelocInfo::kNoPosition);
3144 block->statements()->Add(factory()->NewExpressionStatement(
3145 assign_each, RelocInfo::kNoPosition),
3146 zone());
3147 block->statements()->Add(body, zone());
3148 body = block;
3149 each = factory()->NewVariableProxy(temp);
3150 }
3151 stmt->Initialize(each, subject, body);
3152 }
3153}
3154
Ben Murdochda12d292016-06-02 14:46:10 +01003155void Parser::InitializeForOfStatement(ForOfStatement* for_of, Expression* each,
3156 Expression* iterable, Statement* body,
3157 int iterable_pos) {
3158 Variable* iterator =
3159 scope_->NewTemporary(ast_value_factory()->dot_iterator_string());
3160 Variable* result =
3161 scope_->NewTemporary(ast_value_factory()->dot_result_string());
3162
3163 Expression* assign_iterator;
3164 Expression* next_result;
3165 Expression* result_done;
3166 Expression* assign_each;
3167
3168 // Hackily disambiguate o from o.next and o [Symbol.iterator]().
3169 // TODO(verwaest): Come up with a better solution.
3170 int get_iterator_pos = iterable_pos != RelocInfo::kNoPosition
3171 ? iterable_pos
3172 : iterable->position() - 2;
3173 int next_result_pos = iterable_pos != RelocInfo::kNoPosition
3174 ? iterable_pos
3175 : iterable->position() - 1;
3176
3177 // iterator = iterable[Symbol.iterator]()
3178 assign_iterator = factory()->NewAssignment(
3179 Token::ASSIGN, factory()->NewVariableProxy(iterator),
3180 GetIterator(iterable, factory(), get_iterator_pos), iterable->position());
3181
3182 // !%_IsJSReceiver(result = iterator.next()) &&
3183 // %ThrowIteratorResultNotAnObject(result)
3184 {
3185 // result = iterator.next()
3186 Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
3187 next_result =
3188 BuildIteratorNextResult(iterator_proxy, result, next_result_pos);
3189 }
3190
3191 // result.done
3192 {
3193 Expression* done_literal = factory()->NewStringLiteral(
3194 ast_value_factory()->done_string(), RelocInfo::kNoPosition);
3195 Expression* result_proxy = factory()->NewVariableProxy(result);
3196 result_done = factory()->NewProperty(result_proxy, done_literal,
3197 RelocInfo::kNoPosition);
3198 }
3199
3200 // each = result.value
3201 {
3202 Expression* value_literal = factory()->NewStringLiteral(
3203 ast_value_factory()->value_string(), RelocInfo::kNoPosition);
3204 Expression* result_proxy = factory()->NewVariableProxy(result);
3205 Expression* result_value = factory()->NewProperty(
3206 result_proxy, value_literal, RelocInfo::kNoPosition);
3207 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value,
3208 RelocInfo::kNoPosition);
3209 if (each->IsArrayLiteral() || each->IsObjectLiteral()) {
3210 assign_each = PatternRewriter::RewriteDestructuringAssignment(
3211 this, assign_each->AsAssignment(), scope_);
3212 }
3213 }
3214
3215 for_of->Initialize(each, iterable, body, iterator, assign_iterator,
3216 next_result, result_done, assign_each);
3217}
3218
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003219Statement* Parser::DesugarLexicalBindingsInForStatement(
Ben Murdoch097c5b22016-05-18 11:27:45 +01003220 Scope* inner_scope, VariableMode mode, ZoneList<const AstRawString*>* names,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003221 ForStatement* loop, Statement* init, Expression* cond, Statement* next,
3222 Statement* body, bool* ok) {
3223 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are
3224 // copied into a new environment. Moreover, the "next" statement must be
3225 // evaluated not in the environment of the just completed iteration but in
3226 // that of the upcoming one. We achieve this with the following desugaring.
3227 // Extra care is needed to preserve the completion value of the original loop.
3228 //
3229 // We are given a for statement of the form
3230 //
3231 // labels: for (let/const x = i; cond; next) body
3232 //
3233 // and rewrite it as follows. Here we write {{ ... }} for init-blocks, ie.,
3234 // blocks whose ignore_completion_value_ flag is set.
3235 //
3236 // {
3237 // let/const x = i;
3238 // temp_x = x;
3239 // first = 1;
3240 // undefined;
3241 // outer: for (;;) {
3242 // let/const x = temp_x;
3243 // {{ if (first == 1) {
3244 // first = 0;
3245 // } else {
3246 // next;
3247 // }
3248 // flag = 1;
3249 // if (!cond) break;
3250 // }}
3251 // labels: for (; flag == 1; flag = 0, temp_x = x) {
3252 // body
3253 // }
3254 // {{ if (flag == 1) // Body used break.
3255 // break;
3256 // }}
3257 // }
3258 // }
3259
3260 DCHECK(names->length() > 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003261 ZoneList<Variable*> temps(names->length(), zone());
3262
3263 Block* outer_block = factory()->NewBlock(NULL, names->length() + 4, false,
3264 RelocInfo::kNoPosition);
3265
3266 // Add statement: let/const x = i.
3267 outer_block->statements()->Add(init, zone());
3268
3269 const AstRawString* temp_name = ast_value_factory()->dot_for_string();
3270
3271 // For each lexical variable x:
3272 // make statement: temp_x = x.
3273 for (int i = 0; i < names->length(); i++) {
3274 VariableProxy* proxy = NewUnresolved(names->at(i), LET);
3275 Variable* temp = scope_->NewTemporary(temp_name);
3276 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
3277 Assignment* assignment = factory()->NewAssignment(
3278 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition);
3279 Statement* assignment_statement = factory()->NewExpressionStatement(
3280 assignment, RelocInfo::kNoPosition);
3281 outer_block->statements()->Add(assignment_statement, zone());
3282 temps.Add(temp, zone());
3283 }
3284
3285 Variable* first = NULL;
3286 // Make statement: first = 1.
3287 if (next) {
3288 first = scope_->NewTemporary(temp_name);
3289 VariableProxy* first_proxy = factory()->NewVariableProxy(first);
3290 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
3291 Assignment* assignment = factory()->NewAssignment(
3292 Token::ASSIGN, first_proxy, const1, RelocInfo::kNoPosition);
3293 Statement* assignment_statement =
3294 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
3295 outer_block->statements()->Add(assignment_statement, zone());
3296 }
3297
3298 // make statement: undefined;
3299 outer_block->statements()->Add(
3300 factory()->NewExpressionStatement(
3301 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
3302 RelocInfo::kNoPosition),
3303 zone());
3304
3305 // Make statement: outer: for (;;)
3306 // Note that we don't actually create the label, or set this loop up as an
3307 // explicit break target, instead handing it directly to those nodes that
3308 // need to know about it. This should be safe because we don't run any code
3309 // in this function that looks up break targets.
3310 ForStatement* outer_loop =
3311 factory()->NewForStatement(NULL, RelocInfo::kNoPosition);
3312 outer_block->statements()->Add(outer_loop, zone());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003313 outer_block->set_scope(scope_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003314
3315 Block* inner_block =
3316 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003317 {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003318 BlockState block_state(&scope_, inner_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003319
Ben Murdoch097c5b22016-05-18 11:27:45 +01003320 Block* ignore_completion_block = factory()->NewBlock(
3321 NULL, names->length() + 3, true, RelocInfo::kNoPosition);
3322 ZoneList<Variable*> inner_vars(names->length(), zone());
3323 // For each let variable x:
3324 // make statement: let/const x = temp_x.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003325 for (int i = 0; i < names->length(); i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003326 VariableProxy* proxy = NewUnresolved(names->at(i), mode);
3327 Declaration* declaration = factory()->NewVariableDeclaration(
3328 proxy, mode, scope_, RelocInfo::kNoPosition);
3329 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
3330 inner_vars.Add(declaration->proxy()->var(), zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003331 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003332 Assignment* assignment = factory()->NewAssignment(
Ben Murdoch097c5b22016-05-18 11:27:45 +01003333 Token::INIT, proxy, temp_proxy, RelocInfo::kNoPosition);
3334 Statement* assignment_statement =
3335 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
3336 DCHECK(init->position() != RelocInfo::kNoPosition);
3337 proxy->var()->set_initializer_position(init->position());
3338 ignore_completion_block->statements()->Add(assignment_statement, zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003339 }
3340
Ben Murdoch097c5b22016-05-18 11:27:45 +01003341 // Make statement: if (first == 1) { first = 0; } else { next; }
3342 if (next) {
3343 DCHECK(first);
3344 Expression* compare = NULL;
3345 // Make compare expression: first == 1.
3346 {
3347 Expression* const1 =
3348 factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
3349 VariableProxy* first_proxy = factory()->NewVariableProxy(first);
3350 compare = factory()->NewCompareOperation(Token::EQ, first_proxy, const1,
3351 RelocInfo::kNoPosition);
3352 }
3353 Statement* clear_first = NULL;
3354 // Make statement: first = 0.
3355 {
3356 VariableProxy* first_proxy = factory()->NewVariableProxy(first);
3357 Expression* const0 =
3358 factory()->NewSmiLiteral(0, RelocInfo::kNoPosition);
3359 Assignment* assignment = factory()->NewAssignment(
3360 Token::ASSIGN, first_proxy, const0, RelocInfo::kNoPosition);
3361 clear_first = factory()->NewExpressionStatement(assignment,
3362 RelocInfo::kNoPosition);
3363 }
3364 Statement* clear_first_or_next = factory()->NewIfStatement(
3365 compare, clear_first, next, RelocInfo::kNoPosition);
3366 ignore_completion_block->statements()->Add(clear_first_or_next, zone());
3367 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003368
Ben Murdoch097c5b22016-05-18 11:27:45 +01003369 Variable* flag = scope_->NewTemporary(temp_name);
3370 // Make statement: flag = 1.
3371 {
3372 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
3373 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
3374 Assignment* assignment = factory()->NewAssignment(
3375 Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition);
3376 Statement* assignment_statement =
3377 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
3378 ignore_completion_block->statements()->Add(assignment_statement, zone());
3379 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003380
Ben Murdoch097c5b22016-05-18 11:27:45 +01003381 // Make statement: if (!cond) break.
3382 if (cond) {
3383 Statement* stop =
3384 factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition);
3385 Statement* noop = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
3386 ignore_completion_block->statements()->Add(
3387 factory()->NewIfStatement(cond, noop, stop, cond->position()),
3388 zone());
3389 }
3390
3391 inner_block->statements()->Add(ignore_completion_block, zone());
3392 // Make cond expression for main loop: flag == 1.
3393 Expression* flag_cond = NULL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003394 {
3395 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
3396 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003397 flag_cond = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
3398 RelocInfo::kNoPosition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003399 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003400
Ben Murdoch097c5b22016-05-18 11:27:45 +01003401 // Create chain of expressions "flag = 0, temp_x = x, ..."
3402 Statement* compound_next_statement = NULL;
3403 {
3404 Expression* compound_next = NULL;
3405 // Make expression: flag = 0.
3406 {
3407 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
3408 Expression* const0 =
3409 factory()->NewSmiLiteral(0, RelocInfo::kNoPosition);
3410 compound_next = factory()->NewAssignment(
3411 Token::ASSIGN, flag_proxy, const0, RelocInfo::kNoPosition);
3412 }
3413
3414 // Make the comma-separated list of temp_x = x assignments.
3415 int inner_var_proxy_pos = scanner()->location().beg_pos;
3416 for (int i = 0; i < names->length(); i++) {
3417 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
3418 VariableProxy* proxy =
3419 factory()->NewVariableProxy(inner_vars.at(i), inner_var_proxy_pos);
3420 Assignment* assignment = factory()->NewAssignment(
3421 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition);
3422 compound_next = factory()->NewBinaryOperation(
3423 Token::COMMA, compound_next, assignment, RelocInfo::kNoPosition);
3424 }
3425
3426 compound_next_statement = factory()->NewExpressionStatement(
3427 compound_next, RelocInfo::kNoPosition);
3428 }
3429
3430 // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x)
3431 // Note that we re-use the original loop node, which retains its labels
3432 // and ensures that any break or continue statements in body point to
3433 // the right place.
3434 loop->Initialize(NULL, flag_cond, compound_next_statement, body);
3435 inner_block->statements()->Add(loop, zone());
3436
3437 // Make statement: {{if (flag == 1) break;}}
3438 {
3439 Expression* compare = NULL;
3440 // Make compare expresion: flag == 1.
3441 {
3442 Expression* const1 =
3443 factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
3444 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
3445 compare = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
3446 RelocInfo::kNoPosition);
3447 }
3448 Statement* stop =
3449 factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition);
3450 Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
3451 Statement* if_flag_break = factory()->NewIfStatement(
3452 compare, stop, empty, RelocInfo::kNoPosition);
3453 Block* ignore_completion_block =
3454 factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
3455 ignore_completion_block->statements()->Add(if_flag_break, zone());
3456 inner_block->statements()->Add(ignore_completion_block, zone());
3457 }
3458
3459 inner_scope->set_end_position(scanner()->location().end_pos);
3460 inner_block->set_scope(inner_scope);
3461 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003462
3463 outer_loop->Initialize(NULL, NULL, NULL, inner_block);
3464 return outer_block;
3465}
3466
Ben Murdochda12d292016-06-02 14:46:10 +01003467Statement* Parser::ParseScopedStatement(ZoneList<const AstRawString*>* labels,
3468 bool legacy, bool* ok) {
3469 if (is_strict(language_mode()) || peek() != Token::FUNCTION ||
3470 (legacy && allow_harmony_restrictive_declarations())) {
3471 return ParseSubStatement(labels, kDisallowLabelledFunctionStatement, ok);
3472 } else {
3473 if (legacy) {
3474 ++use_counts_[v8::Isolate::kLegacyFunctionDeclaration];
3475 }
3476 // Make a block around the statement for a lexical binding
3477 // is introduced by a FunctionDeclaration.
3478 Scope* body_scope = NewScope(scope_, BLOCK_SCOPE);
3479 BlockState block_state(&scope_, body_scope);
3480 Block* block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
3481 Statement* body = ParseFunctionDeclaration(NULL, CHECK_OK);
3482 block->statements()->Add(body, zone());
3483 body_scope->set_end_position(scanner()->location().end_pos);
3484 body_scope = body_scope->FinalizeBlockScope();
3485 block->set_scope(body_scope);
3486 return block;
3487 }
3488}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003489
3490Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
3491 bool* ok) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003492 int stmt_pos = peek_position();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003493 Statement* init = NULL;
3494 ZoneList<const AstRawString*> lexical_bindings(1, zone());
3495
3496 // Create an in-between scope for let-bound iteration variables.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003497 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003498
3499 BlockState block_state(&scope_, for_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003500 Expect(Token::FOR, CHECK_OK);
3501 Expect(Token::LPAREN, CHECK_OK);
3502 for_scope->set_start_position(scanner()->location().beg_pos);
3503 bool is_let_identifier_expression = false;
3504 DeclarationParsingResult parsing_result;
3505 if (peek() != Token::SEMICOLON) {
3506 if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) ||
3507 (peek() == Token::LET && IsNextLetKeyword())) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003508 ParseVariableDeclarations(kForStatement, &parsing_result, nullptr,
3509 CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003510
Ben Murdochda12d292016-06-02 14:46:10 +01003511 ForEachStatement::VisitMode mode = ForEachStatement::ENUMERATE;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003512 int each_beg_pos = scanner()->location().beg_pos;
3513 int each_end_pos = scanner()->location().end_pos;
3514
Ben Murdoch097c5b22016-05-18 11:27:45 +01003515 if (CheckInOrOf(&mode, ok)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003516 if (!*ok) return nullptr;
Ben Murdoch097c5b22016-05-18 11:27:45 +01003517 if (parsing_result.declarations.length() != 1) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003518 ParserTraits::ReportMessageAt(
3519 parsing_result.bindings_loc,
Ben Murdoch097c5b22016-05-18 11:27:45 +01003520 MessageTemplate::kForInOfLoopMultiBindings,
3521 ForEachStatement::VisitModeString(mode));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003522 *ok = false;
3523 return nullptr;
3524 }
3525 DeclarationParsingResult::Declaration& decl =
3526 parsing_result.declarations[0];
3527 if (parsing_result.first_initializer_loc.IsValid() &&
3528 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE ||
3529 IsLexicalVariableMode(parsing_result.descriptor.mode) ||
3530 !decl.pattern->IsVariableProxy())) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003531 ParserTraits::ReportMessageAt(
3532 parsing_result.first_initializer_loc,
3533 MessageTemplate::kForInOfLoopInitializer,
3534 ForEachStatement::VisitModeString(mode));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003535 *ok = false;
3536 return nullptr;
3537 }
3538
3539 Block* init_block = nullptr;
3540
3541 // special case for legacy for (var/const x =.... in)
3542 if (!IsLexicalVariableMode(parsing_result.descriptor.mode) &&
3543 decl.pattern->IsVariableProxy() && decl.initializer != nullptr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003544 ++use_counts_[v8::Isolate::kForInInitializer];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003545 const AstRawString* name =
3546 decl.pattern->AsVariableProxy()->raw_name();
3547 VariableProxy* single_var = scope_->NewUnresolved(
3548 factory(), name, Variable::NORMAL, each_beg_pos, each_end_pos);
3549 init_block = factory()->NewBlock(
3550 nullptr, 2, true, parsing_result.descriptor.declaration_pos);
3551 init_block->statements()->Add(
3552 factory()->NewExpressionStatement(
3553 factory()->NewAssignment(Token::ASSIGN, single_var,
3554 decl.initializer,
3555 RelocInfo::kNoPosition),
3556 RelocInfo::kNoPosition),
3557 zone());
3558 }
3559
3560 // Rewrite a for-in/of statement of the form
3561 //
3562 // for (let/const/var x in/of e) b
3563 //
3564 // into
3565 //
3566 // {
3567 // <let x' be a temporary variable>
3568 // for (x' in/of e) {
3569 // let/const/var x;
3570 // x = x';
3571 // b;
3572 // }
3573 // let x; // for TDZ
3574 // }
3575
Ben Murdoch097c5b22016-05-18 11:27:45 +01003576 Variable* temp =
3577 scope_->NewTemporary(ast_value_factory()->dot_for_string());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003578 ForEachStatement* loop =
3579 factory()->NewForEachStatement(mode, labels, stmt_pos);
3580 Target target(&this->target_stack_, loop);
3581
Ben Murdoch097c5b22016-05-18 11:27:45 +01003582 Expression* enumerable;
3583 if (mode == ForEachStatement::ITERATE) {
3584 ExpressionClassifier classifier(this);
3585 enumerable = ParseAssignmentExpression(true, &classifier, CHECK_OK);
3586 RewriteNonPattern(&classifier, CHECK_OK);
3587 } else {
3588 enumerable = ParseExpression(true, CHECK_OK);
3589 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003590
3591 Expect(Token::RPAREN, CHECK_OK);
3592
3593 Scope* body_scope = NewScope(scope_, BLOCK_SCOPE);
3594 body_scope->set_start_position(scanner()->location().beg_pos);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003595
3596 Block* body_block =
3597 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
3598
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003599 {
Ben Murdochda12d292016-06-02 14:46:10 +01003600 DontCollectExpressionsInTailPositionScope no_tail_calls(
3601 function_state_);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003602 BlockState block_state(&scope_, body_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003603
Ben Murdochda12d292016-06-02 14:46:10 +01003604 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003605
3606 auto each_initialization_block =
3607 factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
3608 {
3609 auto descriptor = parsing_result.descriptor;
3610 descriptor.declaration_pos = RelocInfo::kNoPosition;
3611 descriptor.initialization_pos = RelocInfo::kNoPosition;
3612 decl.initializer = factory()->NewVariableProxy(temp);
3613
3614 PatternRewriter::DeclareAndInitializeVariables(
3615 each_initialization_block, &descriptor, &decl,
3616 IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings
3617 : nullptr,
3618 CHECK_OK);
3619 }
3620
3621 body_block->statements()->Add(each_initialization_block, zone());
3622 body_block->statements()->Add(body, zone());
3623 VariableProxy* temp_proxy =
3624 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos);
Ben Murdochda12d292016-06-02 14:46:10 +01003625 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003626 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003627 body_scope->set_end_position(scanner()->location().end_pos);
3628 body_scope = body_scope->FinalizeBlockScope();
Ben Murdoch097c5b22016-05-18 11:27:45 +01003629 body_block->set_scope(body_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003630
3631 // Create a TDZ for any lexically-bound names.
3632 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) {
3633 DCHECK_NULL(init_block);
3634
3635 init_block =
3636 factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition);
3637
3638 for (int i = 0; i < lexical_bindings.length(); ++i) {
3639 // TODO(adamk): This needs to be some sort of special
3640 // INTERNAL variable that's invisible to the debugger
3641 // but visible to everything else.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003642 VariableProxy* tdz_proxy =
3643 NewUnresolved(lexical_bindings[i], LET);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003644 Declaration* tdz_decl = factory()->NewVariableDeclaration(
3645 tdz_proxy, LET, scope_, RelocInfo::kNoPosition);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003646 Variable* tdz_var = Declare(
3647 tdz_decl, DeclarationDescriptor::NORMAL, true, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003648 tdz_var->set_initializer_position(position());
3649 }
3650 }
3651
Ben Murdoch097c5b22016-05-18 11:27:45 +01003652 Statement* final_loop = loop->IsForOfStatement()
3653 ? FinalizeForOfStatement(
3654 loop->AsForOfStatement(), RelocInfo::kNoPosition)
3655 : loop;
3656
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003657 for_scope->set_end_position(scanner()->location().end_pos);
3658 for_scope = for_scope->FinalizeBlockScope();
3659 // Parsed for-in loop w/ variable declarations.
3660 if (init_block != nullptr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003661 init_block->statements()->Add(final_loop, zone());
3662 init_block->set_scope(for_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003663 return init_block;
3664 } else {
3665 DCHECK_NULL(for_scope);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003666 return final_loop;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003667 }
3668 } else {
3669 init = parsing_result.BuildInitializationBlock(
3670 IsLexicalVariableMode(parsing_result.descriptor.mode)
3671 ? &lexical_bindings
3672 : nullptr,
3673 CHECK_OK);
3674 }
3675 } else {
3676 int lhs_beg_pos = peek_position();
Ben Murdoch097c5b22016-05-18 11:27:45 +01003677 ExpressionClassifier classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003678 Expression* expression = ParseExpression(false, &classifier, CHECK_OK);
3679 int lhs_end_pos = scanner()->location().end_pos;
Ben Murdochda12d292016-06-02 14:46:10 +01003680 ForEachStatement::VisitMode mode = ForEachStatement::ENUMERATE;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003681 is_let_identifier_expression =
3682 expression->IsVariableProxy() &&
3683 expression->AsVariableProxy()->raw_name() ==
3684 ast_value_factory()->let_string();
3685
3686 bool is_for_each = CheckInOrOf(&mode, ok);
3687 if (!*ok) return nullptr;
Ben Murdochda12d292016-06-02 14:46:10 +01003688 bool is_destructuring = is_for_each && (expression->IsArrayLiteral() ||
3689 expression->IsObjectLiteral());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003690
3691 if (is_destructuring) {
3692 ValidateAssignmentPattern(&classifier, CHECK_OK);
3693 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003694 RewriteNonPattern(&classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003695 }
3696
3697 if (is_for_each) {
3698 if (!is_destructuring) {
3699 expression = this->CheckAndRewriteReferenceExpression(
3700 expression, lhs_beg_pos, lhs_end_pos,
3701 MessageTemplate::kInvalidLhsInFor, kSyntaxError, CHECK_OK);
3702 }
3703
3704 ForEachStatement* loop =
3705 factory()->NewForEachStatement(mode, labels, stmt_pos);
3706 Target target(&this->target_stack_, loop);
3707
Ben Murdoch097c5b22016-05-18 11:27:45 +01003708 Expression* enumerable;
3709 if (mode == ForEachStatement::ITERATE) {
3710 ExpressionClassifier classifier(this);
3711 enumerable = ParseAssignmentExpression(true, &classifier, CHECK_OK);
3712 RewriteNonPattern(&classifier, CHECK_OK);
3713 } else {
3714 enumerable = ParseExpression(true, CHECK_OK);
3715 }
3716
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003717 Expect(Token::RPAREN, CHECK_OK);
3718
Ben Murdochda12d292016-06-02 14:46:10 +01003719 // For legacy compat reasons, give for loops similar treatment to
3720 // if statements in allowing a function declaration for a body
3721 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
3722 InitializeForEachStatement(loop, expression, enumerable, body);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003723
3724 Statement* final_loop = loop->IsForOfStatement()
3725 ? FinalizeForOfStatement(
3726 loop->AsForOfStatement(), RelocInfo::kNoPosition)
3727 : loop;
3728
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003729 for_scope->set_end_position(scanner()->location().end_pos);
3730 for_scope = for_scope->FinalizeBlockScope();
3731 DCHECK(for_scope == nullptr);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003732 return final_loop;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003733
3734 } else {
3735 init = factory()->NewExpressionStatement(expression, lhs_beg_pos);
3736 }
3737 }
3738 }
3739
3740 // Standard 'for' loop
3741 ForStatement* loop = factory()->NewForStatement(labels, stmt_pos);
3742 Target target(&this->target_stack_, loop);
3743
3744 // Parsed initializer at this point.
3745 // Detect attempts at 'let' declarations in sloppy mode.
3746 if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER &&
3747 is_sloppy(language_mode()) && is_let_identifier_expression) {
3748 ReportMessage(MessageTemplate::kSloppyLexical, NULL);
3749 *ok = false;
3750 return NULL;
3751 }
3752 Expect(Token::SEMICOLON, CHECK_OK);
3753
Ben Murdoch097c5b22016-05-18 11:27:45 +01003754 Expression* cond = NULL;
3755 Statement* next = NULL;
3756 Statement* body = NULL;
3757
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003758 // If there are let bindings, then condition and the next statement of the
3759 // for loop must be parsed in a new scope.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003760 Scope* inner_scope = scope_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003761 if (lexical_bindings.length() > 0) {
3762 inner_scope = NewScope(for_scope, BLOCK_SCOPE);
3763 inner_scope->set_start_position(scanner()->location().beg_pos);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003764 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01003765 {
3766 BlockState block_state(&scope_, inner_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003767
Ben Murdoch097c5b22016-05-18 11:27:45 +01003768 if (peek() != Token::SEMICOLON) {
3769 cond = ParseExpression(true, CHECK_OK);
3770 }
3771 Expect(Token::SEMICOLON, CHECK_OK);
3772
3773 if (peek() != Token::RPAREN) {
3774 Expression* exp = ParseExpression(true, CHECK_OK);
3775 next = factory()->NewExpressionStatement(exp, exp->position());
3776 }
3777 Expect(Token::RPAREN, CHECK_OK);
3778
Ben Murdochda12d292016-06-02 14:46:10 +01003779 body = ParseScopedStatement(NULL, true, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003780 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003781
3782 Statement* result = NULL;
3783 if (lexical_bindings.length() > 0) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003784 BlockState block_state(&scope_, for_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003785 result = DesugarLexicalBindingsInForStatement(
Ben Murdoch097c5b22016-05-18 11:27:45 +01003786 inner_scope, parsing_result.descriptor.mode, &lexical_bindings, loop,
3787 init, cond, next, body, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003788 for_scope->set_end_position(scanner()->location().end_pos);
3789 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003790 for_scope->set_end_position(scanner()->location().end_pos);
3791 for_scope = for_scope->FinalizeBlockScope();
3792 if (for_scope) {
3793 // Rewrite a for statement of the form
3794 // for (const x = i; c; n) b
3795 //
3796 // into
3797 //
3798 // {
3799 // const x = i;
3800 // for (; c; n) b
3801 // }
3802 //
3803 // or, desugar
3804 // for (; c; n) b
3805 // into
3806 // {
3807 // for (; c; n) b
3808 // }
3809 // just in case b introduces a lexical binding some other way, e.g., if b
3810 // is a FunctionDeclaration.
3811 Block* block =
3812 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
3813 if (init != nullptr) {
3814 block->statements()->Add(init, zone());
3815 }
3816 block->statements()->Add(loop, zone());
3817 block->set_scope(for_scope);
3818 loop->Initialize(NULL, cond, next, body);
3819 result = block;
3820 } else {
3821 loop->Initialize(init, cond, next, body);
3822 result = loop;
3823 }
3824 }
3825 return result;
3826}
3827
3828
3829DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
3830 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
3831 // contexts this is used as a statement which invokes the debugger as i a
3832 // break point is present.
3833 // DebuggerStatement ::
3834 // 'debugger' ';'
3835
3836 int pos = peek_position();
3837 Expect(Token::DEBUGGER, CHECK_OK);
3838 ExpectSemicolon(CHECK_OK);
3839 return factory()->NewDebuggerStatement(pos);
3840}
3841
3842
3843bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
3844 if (expression->IsLiteral()) return true;
3845 MaterializedLiteral* lit = expression->AsMaterializedLiteral();
3846 return lit != NULL && lit->is_simple();
3847}
3848
3849
3850Handle<FixedArray> CompileTimeValue::GetValue(Isolate* isolate,
3851 Expression* expression) {
3852 Factory* factory = isolate->factory();
3853 DCHECK(IsCompileTimeValue(expression));
3854 Handle<FixedArray> result = factory->NewFixedArray(2, TENURED);
3855 ObjectLiteral* object_literal = expression->AsObjectLiteral();
3856 if (object_literal != NULL) {
3857 DCHECK(object_literal->is_simple());
3858 if (object_literal->fast_elements()) {
3859 result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
3860 } else {
3861 result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
3862 }
3863 result->set(kElementsSlot, *object_literal->constant_properties());
3864 } else {
3865 ArrayLiteral* array_literal = expression->AsArrayLiteral();
3866 DCHECK(array_literal != NULL && array_literal->is_simple());
3867 result->set(kLiteralTypeSlot, Smi::FromInt(ARRAY_LITERAL));
3868 result->set(kElementsSlot, *array_literal->constant_elements());
3869 }
3870 return result;
3871}
3872
3873
3874CompileTimeValue::LiteralType CompileTimeValue::GetLiteralType(
3875 Handle<FixedArray> value) {
3876 Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot));
3877 return static_cast<LiteralType>(literal_type->value());
3878}
3879
3880
3881Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
3882 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3883}
3884
3885
3886void ParserTraits::ParseArrowFunctionFormalParameters(
3887 ParserFormalParameters* parameters, Expression* expr,
3888 const Scanner::Location& params_loc, bool* ok) {
3889 if (parameters->Arity() >= Code::kMaxArguments) {
3890 ReportMessageAt(params_loc, MessageTemplate::kMalformedArrowFunParamList);
3891 *ok = false;
3892 return;
3893 }
3894
3895 // ArrowFunctionFormals ::
3896 // Binary(Token::COMMA, NonTailArrowFunctionFormals, Tail)
3897 // Tail
3898 // NonTailArrowFunctionFormals ::
3899 // Binary(Token::COMMA, NonTailArrowFunctionFormals, VariableProxy)
3900 // VariableProxy
3901 // Tail ::
3902 // VariableProxy
3903 // Spread(VariableProxy)
3904 //
3905 // As we need to visit the parameters in left-to-right order, we recurse on
3906 // the left-hand side of comma expressions.
3907 //
3908 if (expr->IsBinaryOperation()) {
3909 BinaryOperation* binop = expr->AsBinaryOperation();
3910 // The classifier has already run, so we know that the expression is a valid
3911 // arrow function formals production.
3912 DCHECK_EQ(binop->op(), Token::COMMA);
3913 Expression* left = binop->left();
3914 Expression* right = binop->right();
3915 ParseArrowFunctionFormalParameters(parameters, left, params_loc, ok);
3916 if (!*ok) return;
3917 // LHS of comma expression should be unparenthesized.
3918 expr = right;
3919 }
3920
3921 // Only the right-most expression may be a rest parameter.
3922 DCHECK(!parameters->has_rest);
3923
3924 bool is_rest = expr->IsSpread();
3925 if (is_rest) {
3926 expr = expr->AsSpread()->expression();
3927 parameters->has_rest = true;
3928 }
3929 if (parameters->is_simple) {
3930 parameters->is_simple = !is_rest && expr->IsVariableProxy();
3931 }
3932
3933 Expression* initializer = nullptr;
3934 if (expr->IsVariableProxy()) {
3935 // When the formal parameter was originally seen, it was parsed as a
3936 // VariableProxy and recorded as unresolved in the scope. Here we undo that
3937 // parse-time side-effect for parameters that are single-names (not
3938 // patterns; for patterns that happens uniformly in
3939 // PatternRewriter::VisitVariableProxy).
3940 parser_->scope_->RemoveUnresolved(expr->AsVariableProxy());
3941 } else if (expr->IsAssignment()) {
3942 Assignment* assignment = expr->AsAssignment();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003943 DCHECK(!assignment->is_compound());
3944 initializer = assignment->value();
3945 expr = assignment->target();
3946
3947 // TODO(adamk): Only call this if necessary.
3948 RewriteParameterInitializerScope(parser_->stack_limit(), initializer,
3949 parser_->scope_, parameters->scope);
3950 }
3951
3952 // TODO(adamk): params_loc.end_pos is not the correct initializer position,
3953 // but it should be conservative enough to trigger hole checks for variables
3954 // referenced in the initializer (if any).
3955 AddFormalParameter(parameters, expr, initializer, params_loc.end_pos,
3956 is_rest);
3957}
3958
3959
3960DoExpression* Parser::ParseDoExpression(bool* ok) {
3961 // AssignmentExpression ::
3962 // do '{' StatementList '}'
3963 int pos = peek_position();
3964
3965 Expect(Token::DO, CHECK_OK);
3966 Variable* result =
3967 scope_->NewTemporary(ast_value_factory()->dot_result_string());
3968 Block* block = ParseBlock(nullptr, false, CHECK_OK);
3969 DoExpression* expr = factory()->NewDoExpression(block, result, pos);
3970 if (!Rewriter::Rewrite(this, expr, ast_value_factory())) {
3971 *ok = false;
3972 return nullptr;
3973 }
3974 block->set_scope(block->scope()->FinalizeBlockScope());
3975 return expr;
3976}
3977
3978
3979void ParserTraits::ParseArrowFunctionFormalParameterList(
3980 ParserFormalParameters* parameters, Expression* expr,
3981 const Scanner::Location& params_loc,
3982 Scanner::Location* duplicate_loc, bool* ok) {
3983 if (expr->IsEmptyParentheses()) return;
3984
3985 ParseArrowFunctionFormalParameters(parameters, expr, params_loc, ok);
3986 if (!*ok) return;
3987
Ben Murdoch097c5b22016-05-18 11:27:45 +01003988 Type::ExpressionClassifier classifier(parser_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003989 if (!parameters->is_simple) {
3990 classifier.RecordNonSimpleParameter();
3991 }
3992 for (int i = 0; i < parameters->Arity(); ++i) {
3993 auto parameter = parameters->at(i);
3994 DeclareFormalParameter(parameters->scope, parameter, &classifier);
3995 if (!duplicate_loc->IsValid()) {
3996 *duplicate_loc = classifier.duplicate_formal_parameter_error().location;
3997 }
3998 }
3999 DCHECK_EQ(parameters->is_simple, parameters->scope->has_simple_parameters());
4000}
4001
4002
4003void ParserTraits::ReindexLiterals(const ParserFormalParameters& parameters) {
4004 if (parser_->function_state_->materialized_literal_count() > 0) {
4005 AstLiteralReindexer reindexer;
4006
4007 for (const auto p : parameters.params) {
4008 if (p.pattern != nullptr) reindexer.Reindex(p.pattern);
4009 if (p.initializer != nullptr) reindexer.Reindex(p.initializer);
4010 }
4011
4012 DCHECK(reindexer.count() <=
4013 parser_->function_state_->materialized_literal_count());
4014 }
4015}
4016
4017
4018FunctionLiteral* Parser::ParseFunctionLiteral(
4019 const AstRawString* function_name, Scanner::Location function_name_location,
4020 FunctionNameValidity function_name_validity, FunctionKind kind,
4021 int function_token_pos, FunctionLiteral::FunctionType function_type,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004022 LanguageMode language_mode, bool* ok) {
4023 // Function ::
4024 // '(' FormalParameterList? ')' '{' FunctionBody '}'
4025 //
4026 // Getter ::
4027 // '(' ')' '{' FunctionBody '}'
4028 //
4029 // Setter ::
4030 // '(' PropertySetParameterList ')' '{' FunctionBody '}'
4031
4032 int pos = function_token_pos == RelocInfo::kNoPosition
4033 ? peek_position() : function_token_pos;
4034
4035 bool is_generator = IsGeneratorFunction(kind);
4036
4037 // Anonymous functions were passed either the empty symbol or a null
4038 // handle as the function name. Remember if we were passed a non-empty
4039 // handle to decide whether to invoke function name inference.
4040 bool should_infer_name = function_name == NULL;
4041
4042 // We want a non-null handle as the function name.
4043 if (should_infer_name) {
4044 function_name = ast_value_factory()->empty_string();
4045 }
4046
4047 // Function declarations are function scoped in normal mode, so they are
4048 // hoisted. In harmony block scoping mode they are block scoped, so they
4049 // are not hoisted.
4050 //
4051 // One tricky case are function declarations in a local sloppy-mode eval:
4052 // their declaration is hoisted, but they still see the local scope. E.g.,
4053 //
4054 // function() {
4055 // var x = 0
4056 // try { throw 1 } catch (x) { eval("function g() { return x }") }
4057 // return g()
4058 // }
4059 //
4060 // needs to return 1. To distinguish such cases, we need to detect
4061 // (1) whether a function stems from a sloppy eval, and
4062 // (2) whether it actually hoists across the eval.
4063 // Unfortunately, we do not represent sloppy eval scopes, so we do not have
4064 // either information available directly, especially not when lazily compiling
4065 // a function like 'g'. We hence rely on the following invariants:
4066 // - (1) is the case iff the innermost scope of the deserialized scope chain
4067 // under which we compile is _not_ a declaration scope. This holds because
4068 // in all normal cases, function declarations are fully hoisted to a
4069 // declaration scope and compiled relative to that.
4070 // - (2) is the case iff the current declaration scope is still the original
4071 // one relative to the deserialized scope chain. Otherwise we must be
4072 // compiling a function in an inner declaration scope in the eval, e.g. a
4073 // nested function, and hoisting works normally relative to that.
4074 Scope* declaration_scope = scope_->DeclarationScope();
4075 Scope* original_declaration_scope = original_scope_->DeclarationScope();
4076 Scope* scope = function_type == FunctionLiteral::kDeclaration &&
4077 is_sloppy(language_mode) &&
4078 !allow_harmony_sloppy_function() &&
4079 (original_scope_ == original_declaration_scope ||
4080 declaration_scope != original_declaration_scope)
4081 ? NewScope(declaration_scope, FUNCTION_SCOPE, kind)
4082 : NewScope(scope_, FUNCTION_SCOPE, kind);
4083 SetLanguageMode(scope, language_mode);
4084 ZoneList<Statement*>* body = NULL;
4085 int arity = -1;
4086 int materialized_literal_count = -1;
4087 int expected_property_count = -1;
4088 DuplicateFinder duplicate_finder(scanner()->unicode_cache());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004089 FunctionLiteral::EagerCompileHint eager_compile_hint =
4090 parenthesized_function_ ? FunctionLiteral::kShouldEagerCompile
4091 : FunctionLiteral::kShouldLazyCompile;
4092 bool should_be_used_once_hint = false;
Ben Murdoch097c5b22016-05-18 11:27:45 +01004093 bool has_duplicate_parameters;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004094 // Parse function.
4095 {
4096 AstNodeFactory function_factory(ast_value_factory());
4097 FunctionState function_state(&function_state_, &scope_, scope, kind,
4098 &function_factory);
4099 scope_->SetScopeName(function_name);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004100 ExpressionClassifier formals_classifier(this, &duplicate_finder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004101
4102 if (is_generator) {
4103 // For generators, allocating variables in contexts is currently a win
4104 // because it minimizes the work needed to suspend and resume an
Ben Murdochda12d292016-06-02 14:46:10 +01004105 // activation. The machine code produced for generators (by full-codegen)
4106 // relies on this forced context allocation, but not in an essential way.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004107 scope_->ForceContextAllocation();
4108
4109 // Calling a generator returns a generator object. That object is stored
4110 // in a temporary variable, a definition that is used by "yield"
4111 // expressions. This also marks the FunctionState as a generator.
4112 Variable* temp = scope_->NewTemporary(
4113 ast_value_factory()->dot_generator_object_string());
4114 function_state.set_generator_object_variable(temp);
4115 }
4116
4117 Expect(Token::LPAREN, CHECK_OK);
4118 int start_position = scanner()->location().beg_pos;
4119 scope_->set_start_position(start_position);
4120 ParserFormalParameters formals(scope);
4121 ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK);
4122 arity = formals.Arity();
4123 Expect(Token::RPAREN, CHECK_OK);
4124 int formals_end_position = scanner()->location().end_pos;
4125
Ben Murdoch097c5b22016-05-18 11:27:45 +01004126 CheckArityRestrictions(arity, kind, formals.has_rest, start_position,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004127 formals_end_position, CHECK_OK);
4128 Expect(Token::LBRACE, CHECK_OK);
4129
Ben Murdoch097c5b22016-05-18 11:27:45 +01004130 // Don't include the rest parameter into the function's formal parameter
4131 // count (esp. the SharedFunctionInfo::internal_formal_parameter_count,
4132 // which says whether we need to create an arguments adaptor frame).
4133 if (formals.has_rest) arity--;
4134
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004135 // Determine if the function can be parsed lazily. Lazy parsing is different
4136 // from lazy compilation; we need to parse more eagerly than we compile.
4137
4138 // We can only parse lazily if we also compile lazily. The heuristics for
4139 // lazy compilation are:
4140 // - It must not have been prohibited by the caller to Parse (some callers
4141 // need a full AST).
4142 // - The outer scope must allow lazy compilation of inner functions.
4143 // - The function mustn't be a function expression with an open parenthesis
4144 // before; we consider that a hint that the function will be called
4145 // immediately, and it would be a waste of time to make it lazily
4146 // compiled.
4147 // These are all things we can know at this point, without looking at the
4148 // function itself.
4149
4150 // In addition, we need to distinguish between these cases:
4151 // (function foo() {
4152 // bar = function() { return 1; }
4153 // })();
4154 // and
4155 // (function foo() {
4156 // var a = 1;
4157 // bar = function() { return a; }
4158 // })();
4159
4160 // Now foo will be parsed eagerly and compiled eagerly (optimization: assume
4161 // parenthesis before the function means that it will be called
4162 // immediately). The inner function *must* be parsed eagerly to resolve the
4163 // possible reference to the variable in foo's scope. However, it's possible
4164 // that it will be compiled lazily.
4165
4166 // To make this additional case work, both Parser and PreParser implement a
4167 // logic where only top-level functions will be parsed lazily.
4168 bool is_lazily_parsed = mode() == PARSE_LAZILY &&
4169 scope_->AllowsLazyParsing() &&
4170 !parenthesized_function_;
4171 parenthesized_function_ = false; // The bit was set for this function only.
4172
4173 // Eager or lazy parse?
4174 // If is_lazily_parsed, we'll parse lazy. If we can set a bookmark, we'll
4175 // pass it to SkipLazyFunctionBody, which may use it to abort lazy
4176 // parsing if it suspect that wasn't a good idea. If so, or if we didn't
4177 // try to lazy parse in the first place, we'll have to parse eagerly.
4178 Scanner::BookmarkScope bookmark(scanner());
4179 if (is_lazily_parsed) {
4180 Scanner::BookmarkScope* maybe_bookmark =
4181 bookmark.Set() ? &bookmark : nullptr;
4182 SkipLazyFunctionBody(&materialized_literal_count,
4183 &expected_property_count, /*CHECK_OK*/ ok,
4184 maybe_bookmark);
4185
4186 materialized_literal_count += formals.materialized_literals_count +
4187 function_state.materialized_literal_count();
4188
4189 if (bookmark.HasBeenReset()) {
4190 // Trigger eager (re-)parsing, just below this block.
4191 is_lazily_parsed = false;
4192
4193 // This is probably an initialization function. Inform the compiler it
4194 // should also eager-compile this function, and that we expect it to be
4195 // used once.
4196 eager_compile_hint = FunctionLiteral::kShouldEagerCompile;
4197 should_be_used_once_hint = true;
4198 }
4199 }
4200 if (!is_lazily_parsed) {
4201 // Determine whether the function body can be discarded after parsing.
4202 // The preconditions are:
4203 // - Lazy compilation has to be enabled.
4204 // - Neither V8 natives nor native function declarations can be allowed,
4205 // since parsing one would retroactively force the function to be
4206 // eagerly compiled.
4207 // - The invoker of this parser can't depend on the AST being eagerly
4208 // built (either because the function is about to be compiled, or
4209 // because the AST is going to be inspected for some reason).
4210 // - Because of the above, we can't be attempting to parse a
4211 // FunctionExpression; even without enclosing parentheses it might be
4212 // immediately invoked.
4213 // - The function literal shouldn't be hinted to eagerly compile.
4214 bool use_temp_zone =
4215 FLAG_lazy && !allow_natives() && extension_ == NULL && allow_lazy() &&
4216 function_type == FunctionLiteral::kDeclaration &&
4217 eager_compile_hint != FunctionLiteral::kShouldEagerCompile;
4218 // Open a new BodyScope, which sets our AstNodeFactory to allocate in the
4219 // new temporary zone if the preconditions are satisfied, and ensures that
4220 // the previous zone is always restored after parsing the body.
4221 // For the purpose of scope analysis, some ZoneObjects allocated by the
4222 // factory must persist after the function body is thrown away and
4223 // temp_zone is deallocated. These objects are instead allocated in a
4224 // parser-persistent zone (see parser_zone_ in AstNodeFactory).
4225 {
Ben Murdochda12d292016-06-02 14:46:10 +01004226 Zone temp_zone(zone()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004227 AstNodeFactory::BodyScope inner(factory(), &temp_zone, use_temp_zone);
4228
4229 body = ParseEagerFunctionBody(function_name, pos, formals, kind,
4230 function_type, CHECK_OK);
4231 }
4232 materialized_literal_count = function_state.materialized_literal_count();
4233 expected_property_count = function_state.expected_property_count();
4234 if (use_temp_zone) {
4235 // If the preconditions are correct the function body should never be
4236 // accessed, but do this anyway for better behaviour if they're wrong.
4237 body = NULL;
4238 }
4239 }
4240
4241 // Parsing the body may change the language mode in our scope.
4242 language_mode = scope->language_mode();
4243
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004244 // Validate name and parameter names. We can do this only after parsing the
4245 // function, since the function can declare itself strict.
4246 CheckFunctionName(language_mode, function_name, function_name_validity,
4247 function_name_location, CHECK_OK);
4248 const bool allow_duplicate_parameters =
4249 is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind);
4250 ValidateFormalParameters(&formals_classifier, language_mode,
4251 allow_duplicate_parameters, CHECK_OK);
4252
4253 if (is_strict(language_mode)) {
4254 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(),
4255 CHECK_OK);
4256 }
4257 if (is_sloppy(language_mode) && allow_harmony_sloppy_function()) {
4258 InsertSloppyBlockFunctionVarBindings(scope, CHECK_OK);
4259 }
Ben Murdochda12d292016-06-02 14:46:10 +01004260 CheckConflictingVarDeclarations(scope, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004261
4262 if (body) {
4263 // If body can be inspected, rewrite queued destructuring assignments
4264 ParserTraits::RewriteDestructuringAssignments();
4265 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01004266 has_duplicate_parameters =
4267 !formals_classifier.is_valid_formal_parameter_list_without_duplicates();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004268 }
4269
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004270 FunctionLiteral::ParameterFlag duplicate_parameters =
4271 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters
4272 : FunctionLiteral::kNoDuplicateParameters;
4273
4274 FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
4275 function_name, scope, body, materialized_literal_count,
4276 expected_property_count, arity, duplicate_parameters, function_type,
4277 eager_compile_hint, kind, pos);
4278 function_literal->set_function_token_position(function_token_pos);
4279 if (should_be_used_once_hint)
4280 function_literal->set_should_be_used_once_hint();
4281
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004282 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
4283 return function_literal;
4284}
4285
4286
4287void Parser::SkipLazyFunctionBody(int* materialized_literal_count,
4288 int* expected_property_count, bool* ok,
4289 Scanner::BookmarkScope* bookmark) {
4290 DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet());
4291 if (produce_cached_parse_data()) CHECK(log_);
4292
4293 int function_block_pos = position();
4294 if (consume_cached_parse_data() && !cached_parse_data_->rejected()) {
4295 // If we have cached data, we use it to skip parsing the function body. The
4296 // data contains the information we need to construct the lazy function.
4297 FunctionEntry entry =
4298 cached_parse_data_->GetFunctionEntry(function_block_pos);
4299 // Check that cached data is valid. If not, mark it as invalid (the embedder
4300 // handles it). Note that end position greater than end of stream is safe,
4301 // and hard to check.
4302 if (entry.is_valid() && entry.end_pos() > function_block_pos) {
4303 scanner()->SeekForward(entry.end_pos() - 1);
4304
4305 scope_->set_end_position(entry.end_pos());
4306 Expect(Token::RBRACE, ok);
4307 if (!*ok) {
4308 return;
4309 }
4310 total_preparse_skipped_ += scope_->end_position() - function_block_pos;
4311 *materialized_literal_count = entry.literal_count();
4312 *expected_property_count = entry.property_count();
4313 SetLanguageMode(scope_, entry.language_mode());
4314 if (entry.uses_super_property()) scope_->RecordSuperPropertyUsage();
4315 if (entry.calls_eval()) scope_->RecordEvalCall();
4316 return;
4317 }
4318 cached_parse_data_->Reject();
4319 }
4320 // With no cached data, we partially parse the function, without building an
4321 // AST. This gathers the data needed to build a lazy function.
4322 SingletonLogger logger;
4323 PreParser::PreParseResult result =
4324 ParseLazyFunctionBodyWithPreParser(&logger, bookmark);
4325 if (bookmark && bookmark->HasBeenReset()) {
4326 return; // Return immediately if pre-parser devided to abort parsing.
4327 }
4328 if (result == PreParser::kPreParseStackOverflow) {
4329 // Propagate stack overflow.
4330 set_stack_overflow();
4331 *ok = false;
4332 return;
4333 }
4334 if (logger.has_error()) {
4335 ParserTraits::ReportMessageAt(
4336 Scanner::Location(logger.start(), logger.end()), logger.message(),
4337 logger.argument_opt(), logger.error_type());
4338 *ok = false;
4339 return;
4340 }
4341 scope_->set_end_position(logger.end());
4342 Expect(Token::RBRACE, ok);
4343 if (!*ok) {
4344 return;
4345 }
4346 total_preparse_skipped_ += scope_->end_position() - function_block_pos;
4347 *materialized_literal_count = logger.literals();
4348 *expected_property_count = logger.properties();
4349 SetLanguageMode(scope_, logger.language_mode());
4350 if (logger.uses_super_property()) {
4351 scope_->RecordSuperPropertyUsage();
4352 }
4353 if (logger.calls_eval()) {
4354 scope_->RecordEvalCall();
4355 }
4356 if (produce_cached_parse_data()) {
4357 DCHECK(log_);
4358 // Position right after terminal '}'.
4359 int body_end = scanner()->location().end_pos;
4360 log_->LogFunction(function_block_pos, body_end, *materialized_literal_count,
4361 *expected_property_count, scope_->language_mode(),
4362 scope_->uses_super_property(), scope_->calls_eval());
4363 }
4364}
4365
4366
4367Statement* Parser::BuildAssertIsCoercible(Variable* var) {
4368 // if (var === null || var === undefined)
4369 // throw /* type error kNonCoercible) */;
4370
4371 Expression* condition = factory()->NewBinaryOperation(
4372 Token::OR, factory()->NewCompareOperation(
4373 Token::EQ_STRICT, factory()->NewVariableProxy(var),
4374 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
4375 RelocInfo::kNoPosition),
4376 factory()->NewCompareOperation(
4377 Token::EQ_STRICT, factory()->NewVariableProxy(var),
4378 factory()->NewNullLiteral(RelocInfo::kNoPosition),
4379 RelocInfo::kNoPosition),
4380 RelocInfo::kNoPosition);
4381 Expression* throw_type_error = this->NewThrowTypeError(
4382 MessageTemplate::kNonCoercible, ast_value_factory()->empty_string(),
4383 RelocInfo::kNoPosition);
4384 IfStatement* if_statement = factory()->NewIfStatement(
4385 condition, factory()->NewExpressionStatement(throw_type_error,
4386 RelocInfo::kNoPosition),
4387 factory()->NewEmptyStatement(RelocInfo::kNoPosition),
4388 RelocInfo::kNoPosition);
4389 return if_statement;
4390}
4391
4392
4393class InitializerRewriter : public AstExpressionVisitor {
4394 public:
4395 InitializerRewriter(uintptr_t stack_limit, Expression* root, Parser* parser,
4396 Scope* scope)
4397 : AstExpressionVisitor(stack_limit, root),
4398 parser_(parser),
4399 scope_(scope) {}
4400
4401 private:
Ben Murdoch097c5b22016-05-18 11:27:45 +01004402 void VisitExpression(Expression* expr) override {
4403 RewritableExpression* to_rewrite = expr->AsRewritableExpression();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004404 if (to_rewrite == nullptr || to_rewrite->is_rewritten()) return;
4405
4406 Parser::PatternRewriter::RewriteDestructuringAssignment(parser_, to_rewrite,
4407 scope_);
4408 }
4409
Ben Murdoch097c5b22016-05-18 11:27:45 +01004410 // Code in function literals does not need to be eagerly rewritten, it will be
4411 // rewritten when scheduled.
4412 void VisitFunctionLiteral(FunctionLiteral* expr) override {}
4413
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004414 private:
4415 Parser* parser_;
4416 Scope* scope_;
4417};
4418
4419
4420void Parser::RewriteParameterInitializer(Expression* expr, Scope* scope) {
4421 InitializerRewriter rewriter(stack_limit_, expr, this, scope);
4422 rewriter.Run();
4423}
4424
4425
4426Block* Parser::BuildParameterInitializationBlock(
4427 const ParserFormalParameters& parameters, bool* ok) {
4428 DCHECK(!parameters.is_simple);
4429 DCHECK(scope_->is_function_scope());
4430 Block* init_block =
4431 factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
4432 for (int i = 0; i < parameters.params.length(); ++i) {
4433 auto parameter = parameters.params[i];
4434 if (parameter.is_rest && parameter.pattern->IsVariableProxy()) break;
4435 DeclarationDescriptor descriptor;
4436 descriptor.declaration_kind = DeclarationDescriptor::PARAMETER;
4437 descriptor.parser = this;
4438 descriptor.scope = scope_;
4439 descriptor.hoist_scope = nullptr;
4440 descriptor.mode = LET;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004441 descriptor.declaration_pos = parameter.pattern->position();
4442 // The position that will be used by the AssignmentExpression
4443 // which copies from the temp parameter to the pattern.
4444 //
4445 // TODO(adamk): Should this be RelocInfo::kNoPosition, since
4446 // it's just copying from a temp var to the real param var?
4447 descriptor.initialization_pos = parameter.pattern->position();
4448 // The initializer position which will end up in,
4449 // Variable::initializer_position(), used for hole check elimination.
4450 int initializer_position = parameter.pattern->position();
4451 Expression* initial_value =
4452 factory()->NewVariableProxy(parameters.scope->parameter(i));
4453 if (parameter.initializer != nullptr) {
4454 // IS_UNDEFINED($param) ? initializer : $param
4455
4456 // Ensure initializer is rewritten
4457 RewriteParameterInitializer(parameter.initializer, scope_);
4458
4459 auto condition = factory()->NewCompareOperation(
4460 Token::EQ_STRICT,
4461 factory()->NewVariableProxy(parameters.scope->parameter(i)),
4462 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
4463 RelocInfo::kNoPosition);
4464 initial_value = factory()->NewConditional(
4465 condition, parameter.initializer, initial_value,
4466 RelocInfo::kNoPosition);
4467 descriptor.initialization_pos = parameter.initializer->position();
4468 initializer_position = parameter.initializer_end_position;
4469 }
4470
4471 Scope* param_scope = scope_;
4472 Block* param_block = init_block;
4473 if (!parameter.is_simple() && scope_->calls_sloppy_eval()) {
4474 param_scope = NewScope(scope_, BLOCK_SCOPE);
4475 param_scope->set_is_declaration_scope();
4476 param_scope->set_start_position(parameter.pattern->position());
4477 param_scope->set_end_position(RelocInfo::kNoPosition);
4478 param_scope->RecordEvalCall();
4479 param_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition);
4480 param_block->set_scope(param_scope);
4481 descriptor.hoist_scope = scope_;
4482 }
4483
4484 {
4485 BlockState block_state(&scope_, param_scope);
4486 DeclarationParsingResult::Declaration decl(
4487 parameter.pattern, initializer_position, initial_value);
4488 PatternRewriter::DeclareAndInitializeVariables(param_block, &descriptor,
4489 &decl, nullptr, CHECK_OK);
4490 }
4491
4492 if (!parameter.is_simple() && scope_->calls_sloppy_eval()) {
4493 param_scope = param_scope->FinalizeBlockScope();
4494 if (param_scope != nullptr) {
4495 CheckConflictingVarDeclarations(param_scope, CHECK_OK);
4496 }
4497 init_block->statements()->Add(param_block, zone());
4498 }
4499 }
4500 return init_block;
4501}
4502
4503
4504ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
4505 const AstRawString* function_name, int pos,
4506 const ParserFormalParameters& parameters, FunctionKind kind,
4507 FunctionLiteral::FunctionType function_type, bool* ok) {
4508 // Everything inside an eagerly parsed function will be parsed eagerly
4509 // (see comment above).
4510 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
4511 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone());
4512
4513 static const int kFunctionNameAssignmentIndex = 0;
4514 if (function_type == FunctionLiteral::kNamedExpression) {
4515 DCHECK(function_name != NULL);
4516 // If we have a named function expression, we add a local variable
4517 // declaration to the body of the function with the name of the
4518 // function and let it refer to the function itself (closure).
4519 // Not having parsed the function body, the language mode may still change,
4520 // so we reserve a spot and create the actual const assignment later.
4521 DCHECK_EQ(kFunctionNameAssignmentIndex, result->length());
4522 result->Add(NULL, zone());
4523 }
4524
4525 ZoneList<Statement*>* body = result;
4526 Scope* inner_scope = scope_;
4527 Block* inner_block = nullptr;
4528 if (!parameters.is_simple) {
4529 inner_scope = NewScope(scope_, BLOCK_SCOPE);
4530 inner_scope->set_is_declaration_scope();
4531 inner_scope->set_start_position(scanner()->location().beg_pos);
4532 inner_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition);
4533 inner_block->set_scope(inner_scope);
4534 body = inner_block->statements();
4535 }
4536
4537 {
4538 BlockState block_state(&scope_, inner_scope);
4539
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004540 if (IsGeneratorFunction(kind)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004541 // We produce:
4542 //
Ben Murdochda12d292016-06-02 14:46:10 +01004543 // try { InitialYield; ...body...; return {value: undefined, done: true} }
Ben Murdoch097c5b22016-05-18 11:27:45 +01004544 // finally { %GeneratorClose(generator) }
4545 //
4546 // - InitialYield yields the actual generator object.
Ben Murdochda12d292016-06-02 14:46:10 +01004547 // - Any return statement inside the body will have its argument wrapped
4548 // in a "done" iterator result object.
Ben Murdoch097c5b22016-05-18 11:27:45 +01004549 // - If the generator terminates for whatever reason, we must close it.
4550 // Hence the finally clause.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004551
Ben Murdoch097c5b22016-05-18 11:27:45 +01004552 Block* try_block =
4553 factory()->NewBlock(nullptr, 3, false, RelocInfo::kNoPosition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004554
Ben Murdoch097c5b22016-05-18 11:27:45 +01004555 {
4556 ZoneList<Expression*>* arguments =
4557 new (zone()) ZoneList<Expression*>(0, zone());
4558 CallRuntime* allocation = factory()->NewCallRuntime(
4559 Runtime::kCreateJSGeneratorObject, arguments, pos);
4560 VariableProxy* init_proxy = factory()->NewVariableProxy(
4561 function_state_->generator_object_variable());
4562 Assignment* assignment = factory()->NewAssignment(
4563 Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition);
4564 VariableProxy* get_proxy = factory()->NewVariableProxy(
4565 function_state_->generator_object_variable());
Ben Murdochda12d292016-06-02 14:46:10 +01004566 Yield* yield =
4567 factory()->NewYield(get_proxy, assignment, RelocInfo::kNoPosition);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004568 try_block->statements()->Add(
4569 factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition),
4570 zone());
4571 }
4572
4573 ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK);
4574
Ben Murdochda12d292016-06-02 14:46:10 +01004575 Statement* final_return = factory()->NewReturnStatement(
4576 BuildIteratorResult(nullptr, true), RelocInfo::kNoPosition);
4577 try_block->statements()->Add(final_return, zone());
Ben Murdoch097c5b22016-05-18 11:27:45 +01004578
4579 Block* finally_block =
4580 factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition);
4581 ZoneList<Expression*>* args =
4582 new (zone()) ZoneList<Expression*>(1, zone());
4583 VariableProxy* call_proxy = factory()->NewVariableProxy(
4584 function_state_->generator_object_variable());
4585 args->Add(call_proxy, zone());
4586 Expression* call = factory()->NewCallRuntime(
4587 Runtime::kGeneratorClose, args, RelocInfo::kNoPosition);
4588 finally_block->statements()->Add(
4589 factory()->NewExpressionStatement(call, RelocInfo::kNoPosition),
4590 zone());
4591
4592 body->Add(factory()->NewTryFinallyStatement(try_block, finally_block,
4593 RelocInfo::kNoPosition),
4594 zone());
4595 } else {
4596 ParseStatementList(body, Token::RBRACE, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004597 }
4598
4599 if (IsSubclassConstructor(kind)) {
4600 body->Add(
4601 factory()->NewReturnStatement(
4602 this->ThisExpression(scope_, factory(), RelocInfo::kNoPosition),
4603 RelocInfo::kNoPosition),
4604 zone());
4605 }
4606 }
4607
4608 Expect(Token::RBRACE, CHECK_OK);
4609 scope_->set_end_position(scanner()->location().end_pos);
4610
4611 if (!parameters.is_simple) {
4612 DCHECK_NOT_NULL(inner_scope);
4613 DCHECK_EQ(body, inner_block->statements());
4614 SetLanguageMode(scope_, inner_scope->language_mode());
4615 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK);
4616 DCHECK_NOT_NULL(init_block);
4617
4618 inner_scope->set_end_position(scanner()->location().end_pos);
4619 inner_scope = inner_scope->FinalizeBlockScope();
4620 if (inner_scope != nullptr) {
4621 CheckConflictingVarDeclarations(inner_scope, CHECK_OK);
4622 InsertShadowingVarBindingInitializers(inner_block);
4623 }
4624
4625 result->Add(init_block, zone());
4626 result->Add(inner_block, zone());
4627 }
4628
4629 if (function_type == FunctionLiteral::kNamedExpression) {
4630 // Now that we know the language mode, we can create the const assignment
4631 // in the previously reserved spot.
4632 // NOTE: We create a proxy and resolve it here so that in the
4633 // future we can change the AST to only refer to VariableProxies
4634 // instead of Variables and Proxies as is the case now.
4635 VariableMode fvar_mode = is_strict(language_mode()) ? CONST : CONST_LEGACY;
4636 Variable* fvar = new (zone())
4637 Variable(scope_, function_name, fvar_mode, Variable::NORMAL,
4638 kCreatedInitialized, kNotAssigned);
4639 VariableProxy* proxy = factory()->NewVariableProxy(fvar);
4640 VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
4641 proxy, fvar_mode, scope_, RelocInfo::kNoPosition);
4642 scope_->DeclareFunctionVar(fvar_declaration);
4643
4644 VariableProxy* fproxy = factory()->NewVariableProxy(fvar);
4645 result->Set(kFunctionNameAssignmentIndex,
4646 factory()->NewExpressionStatement(
4647 factory()->NewAssignment(Token::INIT, fproxy,
4648 factory()->NewThisFunction(pos),
4649 RelocInfo::kNoPosition),
4650 RelocInfo::kNoPosition));
4651 }
4652
Ben Murdoch097c5b22016-05-18 11:27:45 +01004653 // ES6 14.6.1 Static Semantics: IsInTailPosition
4654 // Mark collected return expressions that are in tail call position.
4655 const List<Expression*>& expressions_in_tail_position =
4656 function_state_->expressions_in_tail_position();
4657 for (int i = 0; i < expressions_in_tail_position.length(); ++i) {
Ben Murdochda12d292016-06-02 14:46:10 +01004658 MarkTailPosition(expressions_in_tail_position[i]);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004659 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004660 return result;
4661}
4662
4663
4664PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
4665 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) {
4666 // This function may be called on a background thread too; record only the
4667 // main thread preparse times.
4668 if (pre_parse_timer_ != NULL) {
4669 pre_parse_timer_->Start();
4670 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01004671 TRACE_EVENT0("v8", "V8.PreParse");
4672
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004673 DCHECK_EQ(Token::LBRACE, scanner()->current_token());
4674
4675 if (reusable_preparser_ == NULL) {
4676 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(),
4677 NULL, stack_limit_);
4678 reusable_preparser_->set_allow_lazy(true);
4679#define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name());
4680 SET_ALLOW(natives);
4681 SET_ALLOW(harmony_sloppy);
Ben Murdochda12d292016-06-02 14:46:10 +01004682 SET_ALLOW(harmony_sloppy_function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004683 SET_ALLOW(harmony_sloppy_let);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004684 SET_ALLOW(harmony_do_expressions);
4685 SET_ALLOW(harmony_function_name);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004686 SET_ALLOW(harmony_function_sent);
Ben Murdochda12d292016-06-02 14:46:10 +01004687 SET_ALLOW(harmony_exponentiation_operator);
4688 SET_ALLOW(harmony_restrictive_declarations);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004689#undef SET_ALLOW
4690 }
4691 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
4692 language_mode(), function_state_->kind(), scope_->has_simple_parameters(),
4693 logger, bookmark);
4694 if (pre_parse_timer_ != NULL) {
4695 pre_parse_timer_->Stop();
4696 }
4697 return result;
4698}
4699
Ben Murdochda12d292016-06-02 14:46:10 +01004700ClassLiteral* Parser::ParseClassLiteral(ExpressionClassifier* classifier,
4701 const AstRawString* name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004702 Scanner::Location class_name_location,
4703 bool name_is_strict_reserved, int pos,
4704 bool* ok) {
4705 // All parts of a ClassDeclaration and ClassExpression are strict code.
4706 if (name_is_strict_reserved) {
4707 ReportMessageAt(class_name_location,
4708 MessageTemplate::kUnexpectedStrictReserved);
4709 *ok = false;
4710 return NULL;
4711 }
4712 if (IsEvalOrArguments(name)) {
4713 ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments);
4714 *ok = false;
4715 return NULL;
4716 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004717
4718 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
4719 BlockState block_state(&scope_, block_scope);
4720 RaiseLanguageMode(STRICT);
4721 scope_->SetScopeName(name);
4722
4723 VariableProxy* proxy = NULL;
4724 if (name != NULL) {
4725 proxy = NewUnresolved(name, CONST);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004726 Declaration* declaration =
4727 factory()->NewVariableDeclaration(proxy, CONST, block_scope, pos);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004728 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
4729 }
4730
4731 Expression* extends = NULL;
4732 if (Check(Token::EXTENDS)) {
4733 block_scope->set_start_position(scanner()->location().end_pos);
Ben Murdochda12d292016-06-02 14:46:10 +01004734 ExpressionClassifier extends_classifier(this);
4735 extends = ParseLeftHandSideExpression(&extends_classifier, CHECK_OK);
4736 RewriteNonPattern(&extends_classifier, CHECK_OK);
4737 if (classifier != nullptr) {
4738 classifier->Accumulate(&extends_classifier,
4739 ExpressionClassifier::ExpressionProductions);
4740 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004741 } else {
4742 block_scope->set_start_position(scanner()->location().end_pos);
4743 }
4744
4745
4746 ClassLiteralChecker checker(this);
4747 ZoneList<ObjectLiteral::Property*>* properties = NewPropertyList(4, zone());
4748 FunctionLiteral* constructor = NULL;
4749 bool has_seen_constructor = false;
4750
4751 Expect(Token::LBRACE, CHECK_OK);
4752
4753 const bool has_extends = extends != nullptr;
4754 while (peek() != Token::RBRACE) {
4755 if (Check(Token::SEMICOLON)) continue;
4756 FuncNameInferrer::State fni_state(fni_);
4757 const bool in_class = true;
4758 const bool is_static = false;
4759 bool is_computed_name = false; // Classes do not care about computed
4760 // property names here.
Ben Murdochda12d292016-06-02 14:46:10 +01004761 ExpressionClassifier property_classifier(this);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004762 const AstRawString* property_name = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004763 ObjectLiteral::Property* property = ParsePropertyDefinition(
4764 &checker, in_class, has_extends, is_static, &is_computed_name,
Ben Murdochda12d292016-06-02 14:46:10 +01004765 &has_seen_constructor, &property_classifier, &property_name, CHECK_OK);
4766 RewriteNonPattern(&property_classifier, CHECK_OK);
4767 if (classifier != nullptr) {
4768 classifier->Accumulate(&property_classifier,
4769 ExpressionClassifier::ExpressionProductions);
4770 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004771
4772 if (has_seen_constructor && constructor == NULL) {
4773 constructor = GetPropertyValue(property)->AsFunctionLiteral();
4774 DCHECK_NOT_NULL(constructor);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004775 constructor->set_raw_name(
4776 name != nullptr ? name : ast_value_factory()->empty_string());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004777 } else {
4778 properties->Add(property, zone());
4779 }
4780
4781 if (fni_ != NULL) fni_->Infer();
4782
Ben Murdoch097c5b22016-05-18 11:27:45 +01004783 if (allow_harmony_function_name() &&
4784 property_name != ast_value_factory()->constructor_string()) {
4785 SetFunctionNameFromPropertyName(property, property_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004786 }
4787 }
4788
4789 Expect(Token::RBRACE, CHECK_OK);
4790 int end_pos = scanner()->location().end_pos;
4791
4792 if (constructor == NULL) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004793 constructor = DefaultConstructor(name, extends != NULL, block_scope, pos,
4794 end_pos, block_scope->language_mode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004795 }
4796
Ben Murdochda12d292016-06-02 14:46:10 +01004797 // Note that we do not finalize this block scope because it is
4798 // used as a sentinel value indicating an anonymous class.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004799 block_scope->set_end_position(end_pos);
4800
4801 if (name != NULL) {
4802 DCHECK_NOT_NULL(proxy);
4803 proxy->var()->set_initializer_position(end_pos);
4804 }
4805
Ben Murdoch097c5b22016-05-18 11:27:45 +01004806 return factory()->NewClassLiteral(block_scope, proxy, extends, constructor,
4807 properties, pos, end_pos);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004808}
4809
4810
4811Expression* Parser::ParseV8Intrinsic(bool* ok) {
4812 // CallRuntime ::
4813 // '%' Identifier Arguments
4814
4815 int pos = peek_position();
4816 Expect(Token::MOD, CHECK_OK);
4817 // Allow "eval" or "arguments" for backward compatibility.
4818 const AstRawString* name = ParseIdentifier(kAllowRestrictedIdentifiers,
4819 CHECK_OK);
4820 Scanner::Location spread_pos;
Ben Murdoch097c5b22016-05-18 11:27:45 +01004821 ExpressionClassifier classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004822 ZoneList<Expression*>* args =
4823 ParseArguments(&spread_pos, &classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004824
4825 DCHECK(!spread_pos.IsValid());
4826
4827 if (extension_ != NULL) {
4828 // The extension structures are only accessible while parsing the
4829 // very first time not when reparsing because of lazy compilation.
4830 scope_->DeclarationScope()->ForceEagerCompilation();
4831 }
4832
4833 const Runtime::Function* function = Runtime::FunctionForName(name->string());
4834
4835 if (function != NULL) {
4836 // Check for possible name clash.
4837 DCHECK_EQ(Context::kNotFound,
4838 Context::IntrinsicIndexForName(name->string()));
4839 // Check for built-in IS_VAR macro.
4840 if (function->function_id == Runtime::kIS_VAR) {
4841 DCHECK_EQ(Runtime::RUNTIME, function->intrinsic_type);
4842 // %IS_VAR(x) evaluates to x if x is a variable,
4843 // leads to a parse error otherwise. Could be implemented as an
4844 // inline function %_IS_VAR(x) to eliminate this special case.
4845 if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
4846 return args->at(0);
4847 } else {
4848 ReportMessage(MessageTemplate::kNotIsvar);
4849 *ok = false;
4850 return NULL;
4851 }
4852 }
4853
4854 // Check that the expected number of arguments are being passed.
4855 if (function->nargs != -1 && function->nargs != args->length()) {
Ben Murdochda12d292016-06-02 14:46:10 +01004856 ReportMessage(MessageTemplate::kRuntimeWrongNumArgs);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004857 *ok = false;
4858 return NULL;
4859 }
4860
4861 return factory()->NewCallRuntime(function, args, pos);
4862 }
4863
4864 int context_index = Context::IntrinsicIndexForName(name->string());
4865
4866 // Check that the function is defined.
4867 if (context_index == Context::kNotFound) {
4868 ParserTraits::ReportMessage(MessageTemplate::kNotDefined, name);
4869 *ok = false;
4870 return NULL;
4871 }
4872
4873 return factory()->NewCallRuntime(context_index, args, pos);
4874}
4875
4876
4877Literal* Parser::GetLiteralUndefined(int position) {
4878 return factory()->NewUndefinedLiteral(position);
4879}
4880
4881
4882void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
4883 Declaration* decl = scope->CheckConflictingVarDeclarations();
4884 if (decl != NULL) {
4885 // In ES6, conflicting variable bindings are early errors.
4886 const AstRawString* name = decl->proxy()->raw_name();
4887 int position = decl->proxy()->position();
4888 Scanner::Location location = position == RelocInfo::kNoPosition
4889 ? Scanner::Location::invalid()
4890 : Scanner::Location(position, position + 1);
4891 ParserTraits::ReportMessageAt(location, MessageTemplate::kVarRedeclaration,
4892 name);
4893 *ok = false;
4894 }
4895}
4896
4897
4898void Parser::InsertShadowingVarBindingInitializers(Block* inner_block) {
4899 // For each var-binding that shadows a parameter, insert an assignment
4900 // initializing the variable with the parameter.
4901 Scope* inner_scope = inner_block->scope();
4902 DCHECK(inner_scope->is_declaration_scope());
4903 Scope* function_scope = inner_scope->outer_scope();
4904 DCHECK(function_scope->is_function_scope());
4905 ZoneList<Declaration*>* decls = inner_scope->declarations();
4906 for (int i = 0; i < decls->length(); ++i) {
4907 Declaration* decl = decls->at(i);
4908 if (decl->mode() != VAR || !decl->IsVariableDeclaration()) continue;
4909 const AstRawString* name = decl->proxy()->raw_name();
4910 Variable* parameter = function_scope->LookupLocal(name);
4911 if (parameter == nullptr) continue;
4912 VariableProxy* to = inner_scope->NewUnresolved(factory(), name);
4913 VariableProxy* from = factory()->NewVariableProxy(parameter);
4914 Expression* assignment = factory()->NewAssignment(
4915 Token::ASSIGN, to, from, RelocInfo::kNoPosition);
4916 Statement* statement = factory()->NewExpressionStatement(
4917 assignment, RelocInfo::kNoPosition);
4918 inner_block->statements()->InsertAt(0, statement, zone());
4919 }
4920}
4921
4922
4923void Parser::InsertSloppyBlockFunctionVarBindings(Scope* scope, bool* ok) {
4924 // For each variable which is used as a function declaration in a sloppy
4925 // block,
4926 DCHECK(scope->is_declaration_scope());
4927 SloppyBlockFunctionMap* map = scope->sloppy_block_function_map();
4928 for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
4929 AstRawString* name = static_cast<AstRawString*>(p->key);
4930 // If the variable wouldn't conflict with a lexical declaration,
4931 Variable* var = scope->LookupLocal(name);
4932 if (var == nullptr || !IsLexicalVariableMode(var->mode())) {
4933 // Declare a var-style binding for the function in the outer scope
4934 VariableProxy* proxy = scope->NewUnresolved(factory(), name);
4935 Declaration* declaration = factory()->NewVariableDeclaration(
4936 proxy, VAR, scope, RelocInfo::kNoPosition);
4937 Declare(declaration, DeclarationDescriptor::NORMAL, true, ok, scope);
4938 DCHECK(ok); // Based on the preceding check, this should not fail
4939 if (!ok) return;
4940
4941 // Write in assignments to var for each block-scoped function declaration
4942 auto delegates = static_cast<SloppyBlockFunctionMap::Vector*>(p->value);
4943 for (SloppyBlockFunctionStatement* delegate : *delegates) {
4944 // Read from the local lexical scope and write to the function scope
4945 VariableProxy* to = scope->NewUnresolved(factory(), name);
4946 VariableProxy* from = delegate->scope()->NewUnresolved(factory(), name);
4947 Expression* assignment = factory()->NewAssignment(
4948 Token::ASSIGN, to, from, RelocInfo::kNoPosition);
4949 Statement* statement = factory()->NewExpressionStatement(
4950 assignment, RelocInfo::kNoPosition);
4951 delegate->set_statement(statement);
4952 }
4953 }
4954 }
4955}
4956
4957
4958// ----------------------------------------------------------------------------
4959// Parser support
4960
4961bool Parser::TargetStackContainsLabel(const AstRawString* label) {
4962 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4963 if (ContainsLabel(t->statement()->labels(), label)) return true;
4964 }
4965 return false;
4966}
4967
4968
4969BreakableStatement* Parser::LookupBreakTarget(const AstRawString* label,
4970 bool* ok) {
4971 bool anonymous = label == NULL;
4972 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4973 BreakableStatement* stat = t->statement();
4974 if ((anonymous && stat->is_target_for_anonymous()) ||
4975 (!anonymous && ContainsLabel(stat->labels(), label))) {
4976 return stat;
4977 }
4978 }
4979 return NULL;
4980}
4981
4982
4983IterationStatement* Parser::LookupContinueTarget(const AstRawString* label,
4984 bool* ok) {
4985 bool anonymous = label == NULL;
4986 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4987 IterationStatement* stat = t->statement()->AsIterationStatement();
4988 if (stat == NULL) continue;
4989
4990 DCHECK(stat->is_target_for_anonymous());
4991 if (anonymous || ContainsLabel(stat->labels(), label)) {
4992 return stat;
4993 }
4994 }
4995 return NULL;
4996}
4997
4998
4999void Parser::HandleSourceURLComments(Isolate* isolate, Handle<Script> script) {
5000 if (scanner_.source_url()->length() > 0) {
5001 Handle<String> source_url = scanner_.source_url()->Internalize(isolate);
5002 script->set_source_url(*source_url);
5003 }
5004 if (scanner_.source_mapping_url()->length() > 0) {
5005 Handle<String> source_mapping_url =
5006 scanner_.source_mapping_url()->Internalize(isolate);
5007 script->set_source_mapping_url(*source_mapping_url);
5008 }
5009}
5010
5011
5012void Parser::Internalize(Isolate* isolate, Handle<Script> script, bool error) {
5013 // Internalize strings.
5014 ast_value_factory()->Internalize(isolate);
5015
5016 // Error processing.
5017 if (error) {
5018 if (stack_overflow()) {
5019 isolate->StackOverflow();
5020 } else {
5021 DCHECK(pending_error_handler_.has_pending_error());
5022 pending_error_handler_.ThrowPendingError(isolate, script);
5023 }
5024 }
5025
5026 // Move statistics to Isolate.
5027 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
5028 ++feature) {
5029 for (int i = 0; i < use_counts_[feature]; ++i) {
5030 isolate->CountUsage(v8::Isolate::UseCounterFeature(feature));
5031 }
5032 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01005033 if (scanner_.FoundHtmlComment()) {
5034 isolate->CountUsage(v8::Isolate::kHtmlComment);
5035 if (script->line_offset() == 0 && script->column_offset() == 0) {
5036 isolate->CountUsage(v8::Isolate::kHtmlCommentInExternalScript);
5037 }
5038 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005039 isolate->counters()->total_preparse_skipped()->Increment(
5040 total_preparse_skipped_);
5041}
5042
5043
5044// ----------------------------------------------------------------------------
5045// The Parser interface.
5046
5047
5048bool Parser::ParseStatic(ParseInfo* info) {
5049 Parser parser(info);
5050 if (parser.Parse(info)) {
5051 info->set_language_mode(info->literal()->language_mode());
5052 return true;
5053 }
5054 return false;
5055}
5056
5057
5058bool Parser::Parse(ParseInfo* info) {
5059 DCHECK(info->literal() == NULL);
5060 FunctionLiteral* result = NULL;
5061 // Ok to use Isolate here; this function is only called in the main thread.
5062 DCHECK(parsing_on_main_thread_);
5063 Isolate* isolate = info->isolate();
5064 pre_parse_timer_ = isolate->counters()->pre_parse();
5065 if (FLAG_trace_parse || allow_natives() || extension_ != NULL) {
5066 // If intrinsics are allowed, the Parser cannot operate independent of the
5067 // V8 heap because of Runtime. Tell the string table to internalize strings
5068 // and values right after they're created.
5069 ast_value_factory()->Internalize(isolate);
5070 }
5071
5072 if (info->is_lazy()) {
5073 DCHECK(!info->is_eval());
5074 if (info->shared_info()->is_function()) {
5075 result = ParseLazy(isolate, info);
5076 } else {
5077 result = ParseProgram(isolate, info);
5078 }
5079 } else {
5080 SetCachedData(info);
5081 result = ParseProgram(isolate, info);
5082 }
5083 info->set_literal(result);
5084
5085 Internalize(isolate, info->script(), result == NULL);
5086 DCHECK(ast_value_factory()->IsInternalized());
5087 return (result != NULL);
5088}
5089
5090
5091void Parser::ParseOnBackground(ParseInfo* info) {
5092 parsing_on_main_thread_ = false;
5093
5094 DCHECK(info->literal() == NULL);
5095 FunctionLiteral* result = NULL;
5096 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
5097
5098 CompleteParserRecorder recorder;
5099 if (produce_cached_parse_data()) log_ = &recorder;
5100
5101 DCHECK(info->source_stream() != NULL);
5102 ExternalStreamingStream stream(info->source_stream(),
5103 info->source_stream_encoding());
5104 scanner_.Initialize(&stream);
5105 DCHECK(info->context().is_null() || info->context()->IsNativeContext());
5106
5107 // When streaming, we don't know the length of the source until we have parsed
5108 // it. The raw data can be UTF-8, so we wouldn't know the source length until
5109 // we have decoded it anyway even if we knew the raw data length (which we
5110 // don't). We work around this by storing all the scopes which need their end
5111 // position set at the end of the script (the top scope and possible eval
5112 // scopes) and set their end position after we know the script length.
5113 result = DoParseProgram(info);
5114
5115 info->set_literal(result);
5116
5117 // We cannot internalize on a background thread; a foreground task will take
5118 // care of calling Parser::Internalize just before compilation.
5119
5120 if (produce_cached_parse_data()) {
5121 if (result != NULL) *info->cached_data() = recorder.GetScriptData();
5122 log_ = NULL;
5123 }
5124}
5125
5126
5127ParserTraits::TemplateLiteralState Parser::OpenTemplateLiteral(int pos) {
5128 return new (zone()) ParserTraits::TemplateLiteral(zone(), pos);
5129}
5130
5131
5132void Parser::AddTemplateSpan(TemplateLiteralState* state, bool tail) {
5133 int pos = scanner()->location().beg_pos;
5134 int end = scanner()->location().end_pos - (tail ? 1 : 2);
5135 const AstRawString* tv = scanner()->CurrentSymbol(ast_value_factory());
5136 const AstRawString* trv = scanner()->CurrentRawSymbol(ast_value_factory());
5137 Literal* cooked = factory()->NewStringLiteral(tv, pos);
5138 Literal* raw = factory()->NewStringLiteral(trv, pos);
5139 (*state)->AddTemplateSpan(cooked, raw, end, zone());
5140}
5141
5142
5143void Parser::AddTemplateExpression(TemplateLiteralState* state,
5144 Expression* expression) {
5145 (*state)->AddExpression(expression, zone());
5146}
5147
5148
5149Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start,
5150 Expression* tag) {
5151 TemplateLiteral* lit = *state;
5152 int pos = lit->position();
5153 const ZoneList<Expression*>* cooked_strings = lit->cooked();
5154 const ZoneList<Expression*>* raw_strings = lit->raw();
5155 const ZoneList<Expression*>* expressions = lit->expressions();
5156 DCHECK_EQ(cooked_strings->length(), raw_strings->length());
5157 DCHECK_EQ(cooked_strings->length(), expressions->length() + 1);
5158
5159 if (!tag) {
5160 // Build tree of BinaryOps to simplify code-generation
5161 Expression* expr = cooked_strings->at(0);
5162 int i = 0;
5163 while (i < expressions->length()) {
5164 Expression* sub = expressions->at(i++);
5165 Expression* cooked_str = cooked_strings->at(i);
5166
5167 // Let middle be ToString(sub).
5168 ZoneList<Expression*>* args =
5169 new (zone()) ZoneList<Expression*>(1, zone());
5170 args->Add(sub, zone());
5171 Expression* middle = factory()->NewCallRuntime(Runtime::kInlineToString,
5172 args, sub->position());
5173
5174 expr = factory()->NewBinaryOperation(
5175 Token::ADD, factory()->NewBinaryOperation(
5176 Token::ADD, expr, middle, expr->position()),
5177 cooked_str, sub->position());
5178 }
5179 return expr;
5180 } else {
5181 uint32_t hash = ComputeTemplateLiteralHash(lit);
5182
5183 int cooked_idx = function_state_->NextMaterializedLiteralIndex();
5184 int raw_idx = function_state_->NextMaterializedLiteralIndex();
5185
5186 // $getTemplateCallSite
5187 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(4, zone());
5188 args->Add(factory()->NewArrayLiteral(
5189 const_cast<ZoneList<Expression*>*>(cooked_strings),
Ben Murdochda12d292016-06-02 14:46:10 +01005190 cooked_idx, pos),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005191 zone());
5192 args->Add(
5193 factory()->NewArrayLiteral(
Ben Murdochda12d292016-06-02 14:46:10 +01005194 const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx, pos),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005195 zone());
5196
5197 // Ensure hash is suitable as a Smi value
5198 Smi* hash_obj = Smi::cast(Internals::IntToSmi(static_cast<int>(hash)));
5199 args->Add(factory()->NewSmiLiteral(hash_obj->value(), pos), zone());
5200
5201 Expression* call_site = factory()->NewCallRuntime(
5202 Context::GET_TEMPLATE_CALL_SITE_INDEX, args, start);
5203
5204 // Call TagFn
5205 ZoneList<Expression*>* call_args =
5206 new (zone()) ZoneList<Expression*>(expressions->length() + 1, zone());
5207 call_args->Add(call_site, zone());
5208 call_args->AddAll(*expressions, zone());
5209 return factory()->NewCall(tag, call_args, pos);
5210 }
5211}
5212
5213
5214uint32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) {
5215 const ZoneList<Expression*>* raw_strings = lit->raw();
5216 int total = raw_strings->length();
5217 DCHECK(total);
5218
5219 uint32_t running_hash = 0;
5220
5221 for (int index = 0; index < total; ++index) {
5222 if (index) {
5223 running_hash = StringHasher::ComputeRunningHashOneByte(
5224 running_hash, "${}", 3);
5225 }
5226
5227 const AstRawString* raw_string =
5228 raw_strings->at(index)->AsLiteral()->raw_value()->AsString();
5229 if (raw_string->is_one_byte()) {
5230 const char* data = reinterpret_cast<const char*>(raw_string->raw_data());
5231 running_hash = StringHasher::ComputeRunningHashOneByte(
5232 running_hash, data, raw_string->length());
5233 } else {
5234 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data());
5235 running_hash = StringHasher::ComputeRunningHash(running_hash, data,
5236 raw_string->length());
5237 }
5238 }
5239
5240 return running_hash;
5241}
5242
5243
5244ZoneList<v8::internal::Expression*>* Parser::PrepareSpreadArguments(
5245 ZoneList<v8::internal::Expression*>* list) {
5246 ZoneList<v8::internal::Expression*>* args =
5247 new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
5248 if (list->length() == 1) {
5249 // Spread-call with single spread argument produces an InternalArray
5250 // containing the values from the array.
5251 //
5252 // Function is called or constructed with the produced array of arguments
5253 //
5254 // EG: Apply(Func, Spread(spread0))
5255 ZoneList<Expression*>* spread_list =
5256 new (zone()) ZoneList<Expression*>(0, zone());
5257 spread_list->Add(list->at(0)->AsSpread()->expression(), zone());
5258 args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX,
5259 spread_list, RelocInfo::kNoPosition),
5260 zone());
5261 return args;
5262 } else {
5263 // Spread-call with multiple arguments produces array literals for each
5264 // sequences of unspread arguments, and converts each spread iterable to
5265 // an Internal array. Finally, all of these produced arrays are flattened
5266 // into a single InternalArray, containing the arguments for the call.
5267 //
5268 // EG: Apply(Func, Flatten([unspread0, unspread1], Spread(spread0),
5269 // Spread(spread1), [unspread2, unspread3]))
5270 int i = 0;
5271 int n = list->length();
5272 while (i < n) {
5273 if (!list->at(i)->IsSpread()) {
5274 ZoneList<v8::internal::Expression*>* unspread =
5275 new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
5276
5277 // Push array of unspread parameters
5278 while (i < n && !list->at(i)->IsSpread()) {
5279 unspread->Add(list->at(i++), zone());
5280 }
5281 int literal_index = function_state_->NextMaterializedLiteralIndex();
5282 args->Add(factory()->NewArrayLiteral(unspread, literal_index,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005283 RelocInfo::kNoPosition),
5284 zone());
5285
5286 if (i == n) break;
5287 }
5288
5289 // Push eagerly spread argument
5290 ZoneList<v8::internal::Expression*>* spread_list =
5291 new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
5292 spread_list->Add(list->at(i++)->AsSpread()->expression(), zone());
5293 args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX,
5294 spread_list, RelocInfo::kNoPosition),
5295 zone());
5296 }
5297
5298 list = new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
5299 list->Add(factory()->NewCallRuntime(Context::SPREAD_ARGUMENTS_INDEX, args,
5300 RelocInfo::kNoPosition),
5301 zone());
5302 return list;
5303 }
5304 UNREACHABLE();
5305}
5306
5307
5308Expression* Parser::SpreadCall(Expression* function,
5309 ZoneList<v8::internal::Expression*>* args,
5310 int pos) {
5311 if (function->IsSuperCallReference()) {
5312 // Super calls
5313 // $super_constructor = %_GetSuperConstructor(<this-function>)
5314 // %reflect_construct($super_constructor, args, new.target)
5315 ZoneList<Expression*>* tmp = new (zone()) ZoneList<Expression*>(1, zone());
5316 tmp->Add(function->AsSuperCallReference()->this_function_var(), zone());
5317 Expression* super_constructor = factory()->NewCallRuntime(
5318 Runtime::kInlineGetSuperConstructor, tmp, pos);
5319 args->InsertAt(0, super_constructor, zone());
5320 args->Add(function->AsSuperCallReference()->new_target_var(), zone());
5321 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args,
5322 pos);
5323 } else {
5324 if (function->IsProperty()) {
5325 // Method calls
5326 if (function->AsProperty()->IsSuperAccess()) {
5327 Expression* home =
5328 ThisExpression(scope_, factory(), RelocInfo::kNoPosition);
5329 args->InsertAt(0, function, zone());
5330 args->InsertAt(1, home, zone());
5331 } else {
5332 Variable* temp =
5333 scope_->NewTemporary(ast_value_factory()->empty_string());
5334 VariableProxy* obj = factory()->NewVariableProxy(temp);
5335 Assignment* assign_obj = factory()->NewAssignment(
5336 Token::ASSIGN, obj, function->AsProperty()->obj(),
5337 RelocInfo::kNoPosition);
5338 function = factory()->NewProperty(
5339 assign_obj, function->AsProperty()->key(), RelocInfo::kNoPosition);
5340 args->InsertAt(0, function, zone());
5341 obj = factory()->NewVariableProxy(temp);
5342 args->InsertAt(1, obj, zone());
5343 }
5344 } else {
5345 // Non-method calls
5346 args->InsertAt(0, function, zone());
5347 args->InsertAt(1, factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
5348 zone());
5349 }
5350 return factory()->NewCallRuntime(Context::REFLECT_APPLY_INDEX, args, pos);
5351 }
5352}
5353
5354
5355Expression* Parser::SpreadCallNew(Expression* function,
5356 ZoneList<v8::internal::Expression*>* args,
5357 int pos) {
5358 args->InsertAt(0, function, zone());
5359
5360 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos);
5361}
5362
5363
5364void Parser::SetLanguageMode(Scope* scope, LanguageMode mode) {
5365 v8::Isolate::UseCounterFeature feature;
5366 if (is_sloppy(mode))
5367 feature = v8::Isolate::kSloppyMode;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005368 else if (is_strict(mode))
5369 feature = v8::Isolate::kStrictMode;
5370 else
5371 UNREACHABLE();
5372 ++use_counts_[feature];
5373 scope->SetLanguageMode(mode);
5374}
5375
5376
5377void Parser::RaiseLanguageMode(LanguageMode mode) {
Ben Murdochda12d292016-06-02 14:46:10 +01005378 LanguageMode old = scope_->language_mode();
5379 SetLanguageMode(scope_, old > mode ? old : mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005380}
5381
5382
5383void ParserTraits::RewriteDestructuringAssignments() {
5384 parser_->RewriteDestructuringAssignments();
5385}
5386
Ben Murdochda12d292016-06-02 14:46:10 +01005387Expression* ParserTraits::RewriteExponentiation(Expression* left,
5388 Expression* right, int pos) {
5389 return parser_->RewriteExponentiation(left, right, pos);
5390}
5391
5392Expression* ParserTraits::RewriteAssignExponentiation(Expression* left,
5393 Expression* right,
5394 int pos) {
5395 return parser_->RewriteAssignExponentiation(left, right, pos);
5396}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005397
Ben Murdoch097c5b22016-05-18 11:27:45 +01005398void ParserTraits::RewriteNonPattern(Type::ExpressionClassifier* classifier,
5399 bool* ok) {
5400 parser_->RewriteNonPattern(classifier, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005401}
5402
5403
Ben Murdoch097c5b22016-05-18 11:27:45 +01005404Zone* ParserTraits::zone() const {
5405 return parser_->function_state_->scope()->zone();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005406}
5407
5408
Ben Murdoch097c5b22016-05-18 11:27:45 +01005409ZoneList<Expression*>* ParserTraits::GetNonPatternList() const {
5410 return parser_->function_state_->non_patterns_to_rewrite();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005411}
5412
5413
Ben Murdoch097c5b22016-05-18 11:27:45 +01005414class NonPatternRewriter : public AstExpressionRewriter {
5415 public:
5416 NonPatternRewriter(uintptr_t stack_limit, Parser* parser)
5417 : AstExpressionRewriter(stack_limit), parser_(parser) {}
5418 ~NonPatternRewriter() override {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005419
Ben Murdoch097c5b22016-05-18 11:27:45 +01005420 private:
5421 bool RewriteExpression(Expression* expr) override {
5422 if (expr->IsRewritableExpression()) return true;
5423 // Rewrite only what could have been a pattern but is not.
5424 if (expr->IsArrayLiteral()) {
5425 // Spread rewriting in array literals.
5426 ArrayLiteral* lit = expr->AsArrayLiteral();
5427 VisitExpressions(lit->values());
5428 replacement_ = parser_->RewriteSpreads(lit);
5429 return false;
5430 }
5431 if (expr->IsObjectLiteral()) {
5432 return true;
5433 }
5434 if (expr->IsBinaryOperation() &&
5435 expr->AsBinaryOperation()->op() == Token::COMMA) {
5436 return true;
5437 }
5438 // Everything else does not need rewriting.
5439 return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005440 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01005441
5442 void VisitObjectLiteralProperty(ObjectLiteralProperty* property) override {
5443 if (property == nullptr) return;
5444 // Do not rewrite (computed) key expressions
5445 AST_REWRITE_PROPERTY(Expression, property, value);
5446 }
5447
5448 Parser* parser_;
5449};
5450
5451
5452void Parser::RewriteNonPattern(ExpressionClassifier* classifier, bool* ok) {
5453 ValidateExpression(classifier, ok);
5454 if (!*ok) return;
5455 auto non_patterns_to_rewrite = function_state_->non_patterns_to_rewrite();
5456 int begin = classifier->GetNonPatternBegin();
5457 int end = non_patterns_to_rewrite->length();
5458 if (begin < end) {
5459 NonPatternRewriter rewriter(stack_limit_, this);
5460 for (int i = begin; i < end; i++) {
5461 DCHECK(non_patterns_to_rewrite->at(i)->IsRewritableExpression());
5462 rewriter.Rewrite(non_patterns_to_rewrite->at(i));
5463 }
5464 non_patterns_to_rewrite->Rewind(begin);
5465 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005466}
5467
5468
5469void Parser::RewriteDestructuringAssignments() {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005470 const auto& assignments =
5471 function_state_->destructuring_assignments_to_rewrite();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005472 for (int i = assignments.length() - 1; i >= 0; --i) {
5473 // Rewrite list in reverse, so that nested assignment patterns are rewritten
5474 // correctly.
Ben Murdoch097c5b22016-05-18 11:27:45 +01005475 const DestructuringAssignment& pair = assignments.at(i);
5476 RewritableExpression* to_rewrite =
5477 pair.assignment->AsRewritableExpression();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005478 DCHECK_NOT_NULL(to_rewrite);
5479 if (!to_rewrite->is_rewritten()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005480 PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite,
5481 pair.scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005482 }
5483 }
5484}
5485
Ben Murdochda12d292016-06-02 14:46:10 +01005486Expression* Parser::RewriteExponentiation(Expression* left, Expression* right,
5487 int pos) {
5488 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
5489 args->Add(left, zone());
5490 args->Add(right, zone());
5491 return factory()->NewCallRuntime(Context::MATH_POW_METHOD_INDEX, args, pos);
5492}
5493
5494Expression* Parser::RewriteAssignExponentiation(Expression* left,
5495 Expression* right, int pos) {
5496 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
5497 if (left->IsVariableProxy()) {
5498 VariableProxy* lhs = left->AsVariableProxy();
5499
5500 Expression* result;
5501 DCHECK_NOT_NULL(lhs->raw_name());
5502 result =
5503 this->ExpressionFromIdentifier(lhs->raw_name(), lhs->position(),
5504 lhs->end_position(), scope_, factory());
5505 args->Add(left, zone());
5506 args->Add(right, zone());
5507 Expression* call =
5508 factory()->NewCallRuntime(Context::MATH_POW_METHOD_INDEX, args, pos);
5509 return factory()->NewAssignment(Token::ASSIGN, result, call, pos);
5510 } else if (left->IsProperty()) {
5511 Property* prop = left->AsProperty();
5512 auto temp_obj = scope_->NewTemporary(ast_value_factory()->empty_string());
5513 auto temp_key = scope_->NewTemporary(ast_value_factory()->empty_string());
5514 Expression* assign_obj = factory()->NewAssignment(
5515 Token::ASSIGN, factory()->NewVariableProxy(temp_obj), prop->obj(),
5516 RelocInfo::kNoPosition);
5517 Expression* assign_key = factory()->NewAssignment(
5518 Token::ASSIGN, factory()->NewVariableProxy(temp_key), prop->key(),
5519 RelocInfo::kNoPosition);
5520 args->Add(factory()->NewProperty(factory()->NewVariableProxy(temp_obj),
5521 factory()->NewVariableProxy(temp_key),
5522 left->position()),
5523 zone());
5524 args->Add(right, zone());
5525 Expression* call =
5526 factory()->NewCallRuntime(Context::MATH_POW_METHOD_INDEX, args, pos);
5527 Expression* target = factory()->NewProperty(
5528 factory()->NewVariableProxy(temp_obj),
5529 factory()->NewVariableProxy(temp_key), RelocInfo::kNoPosition);
5530 Expression* assign =
5531 factory()->NewAssignment(Token::ASSIGN, target, call, pos);
5532 return factory()->NewBinaryOperation(
5533 Token::COMMA, assign_obj,
5534 factory()->NewBinaryOperation(Token::COMMA, assign_key, assign, pos),
5535 pos);
5536 }
5537 UNREACHABLE();
5538 return nullptr;
5539}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005540
Ben Murdoch097c5b22016-05-18 11:27:45 +01005541Expression* Parser::RewriteSpreads(ArrayLiteral* lit) {
5542 // Array literals containing spreads are rewritten using do expressions, e.g.
5543 // [1, 2, 3, ...x, 4, ...y, 5]
5544 // is roughly rewritten as:
5545 // do {
5546 // $R = [1, 2, 3];
5547 // for ($i of x) %AppendElement($R, $i);
5548 // %AppendElement($R, 4);
5549 // for ($j of y) %AppendElement($R, $j);
5550 // %AppendElement($R, 5);
5551 // $R
5552 // }
5553 // where $R, $i and $j are fresh temporary variables.
5554 ZoneList<Expression*>::iterator s = lit->FirstSpread();
5555 if (s == lit->EndValue()) return nullptr; // no spread, no rewriting...
5556 Variable* result =
5557 scope_->NewTemporary(ast_value_factory()->dot_result_string());
5558 // NOTE: The value assigned to R is the whole original array literal,
5559 // spreads included. This will be fixed before the rewritten AST is returned.
5560 // $R = lit
5561 Expression* init_result =
5562 factory()->NewAssignment(Token::INIT, factory()->NewVariableProxy(result),
5563 lit, RelocInfo::kNoPosition);
5564 Block* do_block =
5565 factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition);
5566 do_block->statements()->Add(
5567 factory()->NewExpressionStatement(init_result, RelocInfo::kNoPosition),
5568 zone());
5569 // Traverse the array literal starting from the first spread.
5570 while (s != lit->EndValue()) {
5571 Expression* value = *s++;
5572 Spread* spread = value->AsSpread();
5573 if (spread == nullptr) {
5574 // If the element is not a spread, we're adding a single:
5575 // %AppendElement($R, value)
5576 ZoneList<Expression*>* append_element_args = NewExpressionList(2, zone());
5577 append_element_args->Add(factory()->NewVariableProxy(result), zone());
5578 append_element_args->Add(value, zone());
5579 do_block->statements()->Add(
5580 factory()->NewExpressionStatement(
5581 factory()->NewCallRuntime(Runtime::kAppendElement,
5582 append_element_args,
5583 RelocInfo::kNoPosition),
5584 RelocInfo::kNoPosition),
5585 zone());
5586 } else {
5587 // If it's a spread, we're adding a for/of loop iterating through it.
5588 Variable* each =
5589 scope_->NewTemporary(ast_value_factory()->dot_for_string());
5590 Expression* subject = spread->expression();
Ben Murdoch097c5b22016-05-18 11:27:45 +01005591 // %AppendElement($R, each)
5592 Statement* append_body;
5593 {
5594 ZoneList<Expression*>* append_element_args =
5595 NewExpressionList(2, zone());
5596 append_element_args->Add(factory()->NewVariableProxy(result), zone());
5597 append_element_args->Add(factory()->NewVariableProxy(each), zone());
5598 append_body = factory()->NewExpressionStatement(
5599 factory()->NewCallRuntime(Runtime::kAppendElement,
5600 append_element_args,
5601 RelocInfo::kNoPosition),
5602 RelocInfo::kNoPosition);
5603 }
5604 // for (each of spread) %AppendElement($R, each)
5605 ForEachStatement* loop = factory()->NewForEachStatement(
5606 ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition);
Ben Murdochda12d292016-06-02 14:46:10 +01005607 InitializeForOfStatement(loop->AsForOfStatement(),
5608 factory()->NewVariableProxy(each), subject,
5609 append_body, spread->expression_position());
5610 do_block->statements()->Add(loop, zone());
Ben Murdoch097c5b22016-05-18 11:27:45 +01005611 }
5612 }
5613 // Now, rewind the original array literal to truncate everything from the
5614 // first spread (included) until the end. This fixes $R's initialization.
5615 lit->RewindSpreads();
5616 return factory()->NewDoExpression(do_block, result, lit->position());
5617}
5618
5619
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005620void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005621 DCHECK(expr->IsRewritableExpression());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005622 parser_->function_state_->AddDestructuringAssignment(
5623 Parser::DestructuringAssignment(expr, parser_->scope_));
5624}
5625
5626
Ben Murdoch097c5b22016-05-18 11:27:45 +01005627void ParserTraits::QueueNonPatternForRewriting(Expression* expr) {
5628 DCHECK(expr->IsRewritableExpression());
5629 parser_->function_state_->AddNonPatternForRewriting(expr);
5630}
5631
5632
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005633void ParserTraits::SetFunctionNameFromPropertyName(
5634 ObjectLiteralProperty* property, const AstRawString* name) {
5635 Expression* value = property->value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005636
Ben Murdoch097c5b22016-05-18 11:27:45 +01005637 // Computed name setting must happen at runtime.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005638 if (property->is_computed_name()) return;
Ben Murdoch097c5b22016-05-18 11:27:45 +01005639
5640 // Getter and setter names are handled here because their names
5641 // change in ES2015, even though they are not anonymous.
5642 auto function = value->AsFunctionLiteral();
5643 if (function != nullptr) {
5644 bool is_getter = property->kind() == ObjectLiteralProperty::GETTER;
5645 bool is_setter = property->kind() == ObjectLiteralProperty::SETTER;
5646 if (is_getter || is_setter) {
5647 DCHECK_NOT_NULL(name);
5648 const AstRawString* prefix =
5649 is_getter ? parser_->ast_value_factory()->get_space_string()
5650 : parser_->ast_value_factory()->set_space_string();
5651 function->set_raw_name(
5652 parser_->ast_value_factory()->NewConsString(prefix, name));
5653 return;
5654 }
5655 }
5656
5657 if (!value->IsAnonymousFunctionDefinition()) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005658 DCHECK_NOT_NULL(name);
5659
5660 // Ignore "__proto__" as a name when it's being used to set the [[Prototype]]
5661 // of an object literal.
5662 if (property->kind() == ObjectLiteralProperty::PROTOTYPE) return;
5663
Ben Murdoch097c5b22016-05-18 11:27:45 +01005664 if (function != nullptr) {
5665 function->set_raw_name(name);
5666 DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005667 } else {
5668 DCHECK(value->IsClassLiteral());
5669 DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind());
Ben Murdoch097c5b22016-05-18 11:27:45 +01005670 value->AsClassLiteral()->constructor()->set_raw_name(name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005671 }
5672}
5673
5674
5675void ParserTraits::SetFunctionNameFromIdentifierRef(Expression* value,
5676 Expression* identifier) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005677 if (!value->IsAnonymousFunctionDefinition()) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005678 if (!identifier->IsVariableProxy()) return;
5679
5680 auto name = identifier->AsVariableProxy()->raw_name();
5681 DCHECK_NOT_NULL(name);
5682
Ben Murdoch097c5b22016-05-18 11:27:45 +01005683 auto function = value->AsFunctionLiteral();
5684 if (function != nullptr) {
5685 function->set_raw_name(name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005686 } else {
5687 DCHECK(value->IsClassLiteral());
Ben Murdoch097c5b22016-05-18 11:27:45 +01005688 value->AsClassLiteral()->constructor()->set_raw_name(name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005689 }
5690}
5691
5692
Ben Murdoch097c5b22016-05-18 11:27:45 +01005693// Desugaring of yield*
5694// ====================
5695//
5696// With the help of do-expressions and function.sent, we desugar yield* into a
5697// loop containing a "raw" yield (a yield that doesn't wrap an iterator result
5698// object around its argument). Concretely, "yield* iterable" turns into
5699// roughly the following code:
5700//
5701// do {
5702// const kNext = 0;
5703// const kReturn = 1;
5704// const kThrow = 2;
5705//
5706// let input = function.sent;
5707// let mode = kNext;
5708// let output = undefined;
5709//
5710// let iterator = iterable[Symbol.iterator]();
5711// if (!IS_RECEIVER(iterator)) throw MakeTypeError(kSymbolIteratorInvalid);
5712//
5713// while (true) {
5714// // From the generator to the iterator:
5715// // Forward input according to resume mode and obtain output.
5716// switch (mode) {
5717// case kNext:
5718// output = iterator.next(input);
5719// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
5720// break;
5721// case kReturn:
5722// IteratorClose(iterator, input, output); // See below.
5723// break;
5724// case kThrow:
5725// let iteratorThrow = iterator.throw;
5726// if (IS_NULL_OR_UNDEFINED(iteratorThrow)) {
5727// IteratorClose(iterator); // See below.
5728// throw MakeTypeError(kThrowMethodMissing);
5729// }
5730// output = %_Call(iteratorThrow, iterator, input);
5731// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
5732// break;
5733// }
5734// if (output.done) break;
5735//
5736// // From the generator to its user:
5737// // Forward output, receive new input, and determine resume mode.
5738// mode = kReturn;
5739// try {
5740// try {
5741// RawYield(output); // See explanation above.
5742// mode = kNext;
5743// } catch (error) {
5744// mode = kThrow;
5745// }
5746// } finally {
5747// input = function.sent;
5748// continue;
5749// }
5750// }
5751//
5752// output.value;
5753// }
5754//
5755// IteratorClose(iterator) expands to the following:
5756//
5757// let iteratorReturn = iterator.return;
5758// if (IS_NULL_OR_UNDEFINED(iteratorReturn)) return;
5759// let output = %_Call(iteratorReturn, iterator);
5760// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
5761//
5762// IteratorClose(iterator, input, output) expands to the following:
5763//
5764// let iteratorReturn = iterator.return;
5765// if (IS_NULL_OR_UNDEFINED(iteratorReturn)) return input;
5766// output = %_Call(iteratorReturn, iterator, input);
5767// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
5768
5769
5770Expression* ParserTraits::RewriteYieldStar(
5771 Expression* generator, Expression* iterable, int pos) {
5772
5773 const int nopos = RelocInfo::kNoPosition;
5774
5775 auto factory = parser_->factory();
5776 auto avfactory = parser_->ast_value_factory();
5777 auto scope = parser_->scope_;
5778 auto zone = parser_->zone();
5779
5780
5781 // Forward definition for break/continue statements.
5782 WhileStatement* loop = factory->NewWhileStatement(nullptr, nopos);
5783
5784
5785 // let input = undefined;
5786 Variable* var_input = scope->NewTemporary(avfactory->empty_string());
5787 Statement* initialize_input;
5788 {
5789 Expression* input_proxy = factory->NewVariableProxy(var_input);
5790 Expression* assignment = factory->NewAssignment(
5791 Token::ASSIGN, input_proxy, factory->NewUndefinedLiteral(nopos), nopos);
5792 initialize_input = factory->NewExpressionStatement(assignment, nopos);
5793 }
5794
5795
5796 // let mode = kNext;
5797 Variable* var_mode = scope->NewTemporary(avfactory->empty_string());
5798 Statement* initialize_mode;
5799 {
5800 Expression* mode_proxy = factory->NewVariableProxy(var_mode);
5801 Expression* knext = factory->NewSmiLiteral(JSGeneratorObject::NEXT, nopos);
5802 Expression* assignment =
5803 factory->NewAssignment(Token::ASSIGN, mode_proxy, knext, nopos);
5804 initialize_mode = factory->NewExpressionStatement(assignment, nopos);
5805 }
5806
5807
5808 // let output = undefined;
5809 Variable* var_output = scope->NewTemporary(avfactory->empty_string());
5810 Statement* initialize_output;
5811 {
5812 Expression* output_proxy = factory->NewVariableProxy(var_output);
5813 Expression* assignment = factory->NewAssignment(
5814 Token::ASSIGN, output_proxy, factory->NewUndefinedLiteral(nopos),
5815 nopos);
5816 initialize_output = factory->NewExpressionStatement(assignment, nopos);
5817 }
5818
5819
5820 // let iterator = iterable[Symbol.iterator];
5821 Variable* var_iterator = scope->NewTemporary(avfactory->empty_string());
5822 Statement* get_iterator;
5823 {
5824 Expression* iterator = GetIterator(iterable, factory, nopos);
5825 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator);
5826 Expression* assignment = factory->NewAssignment(
5827 Token::ASSIGN, iterator_proxy, iterator, nopos);
5828 get_iterator = factory->NewExpressionStatement(assignment, nopos);
5829 }
5830
5831
5832 // if (!IS_RECEIVER(iterator)) throw MakeTypeError(kSymbolIteratorInvalid);
5833 Statement* validate_iterator;
5834 {
5835 Expression* is_receiver_call;
5836 {
5837 auto args = new (zone) ZoneList<Expression*>(1, zone);
5838 args->Add(factory->NewVariableProxy(var_iterator), zone);
5839 is_receiver_call =
5840 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
5841 }
5842
5843 Statement* throw_call;
5844 {
5845 Expression* call = NewThrowTypeError(
5846 MessageTemplate::kSymbolIteratorInvalid, avfactory->empty_string(),
5847 nopos);
5848 throw_call = factory->NewExpressionStatement(call, nopos);
5849 }
5850
5851 validate_iterator = factory->NewIfStatement(
5852 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
5853 }
5854
5855
5856 // output = iterator.next(input);
5857 Statement* call_next;
5858 {
5859 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator);
5860 Expression* literal =
5861 factory->NewStringLiteral(avfactory->next_string(), nopos);
5862 Expression* next_property =
5863 factory->NewProperty(iterator_proxy, literal, nopos);
5864 Expression* input_proxy = factory->NewVariableProxy(var_input);
5865 auto args = new (zone) ZoneList<Expression*>(1, zone);
5866 args->Add(input_proxy, zone);
5867 Expression* call = factory->NewCall(next_property, args, nopos);
5868 Expression* output_proxy = factory->NewVariableProxy(var_output);
5869 Expression* assignment =
5870 factory->NewAssignment(Token::ASSIGN, output_proxy, call, nopos);
5871 call_next = factory->NewExpressionStatement(assignment, nopos);
5872 }
5873
5874
5875 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
5876 Statement* validate_next_output;
5877 {
5878 Expression* is_receiver_call;
5879 {
5880 auto args = new (zone) ZoneList<Expression*>(1, zone);
5881 args->Add(factory->NewVariableProxy(var_output), zone);
5882 is_receiver_call =
5883 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
5884 }
5885
5886 Statement* throw_call;
5887 {
5888 auto args = new (zone) ZoneList<Expression*>(1, zone);
5889 args->Add(factory->NewVariableProxy(var_output), zone);
5890 Expression* call = factory->NewCallRuntime(
5891 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
5892 throw_call = factory->NewExpressionStatement(call, nopos);
5893 }
5894
5895 validate_next_output = factory->NewIfStatement(
5896 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
5897 }
5898
5899
5900 // let iteratorThrow = iterator.throw;
5901 Variable* var_throw = scope->NewTemporary(avfactory->empty_string());
5902 Statement* get_throw;
5903 {
5904 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator);
5905 Expression* literal =
5906 factory->NewStringLiteral(avfactory->throw_string(), nopos);
5907 Expression* property =
5908 factory->NewProperty(iterator_proxy, literal, nopos);
5909 Expression* throw_proxy = factory->NewVariableProxy(var_throw);
5910 Expression* assignment = factory->NewAssignment(
5911 Token::ASSIGN, throw_proxy, property, nopos);
5912 get_throw = factory->NewExpressionStatement(assignment, nopos);
5913 }
5914
5915
5916 // if (IS_NULL_OR_UNDEFINED(iteratorThrow) {
5917 // IteratorClose(iterator);
5918 // throw MakeTypeError(kThrowMethodMissing);
5919 // }
5920 Statement* check_throw;
5921 {
5922 Expression* condition = factory->NewCompareOperation(
5923 Token::EQ, factory->NewVariableProxy(var_throw),
5924 factory->NewNullLiteral(nopos), nopos);
5925
5926 Expression* call = NewThrowTypeError(
5927 MessageTemplate::kThrowMethodMissing,
5928 avfactory->empty_string(), nopos);
5929 Statement* throw_call = factory->NewExpressionStatement(call, nopos);
5930
5931 Block* then = factory->NewBlock(nullptr, 4+1, false, nopos);
5932 Variable* var_tmp = scope->NewTemporary(avfactory->empty_string());
Ben Murdochda12d292016-06-02 14:46:10 +01005933 BuildIteratorClose(then->statements(), var_iterator, Nothing<Variable*>(),
5934 var_tmp);
Ben Murdoch097c5b22016-05-18 11:27:45 +01005935 then->statements()->Add(throw_call, zone);
5936 check_throw = factory->NewIfStatement(
5937 condition, then, factory->NewEmptyStatement(nopos), nopos);
5938 }
5939
5940
5941 // output = %_Call(iteratorThrow, iterator, input);
5942 Statement* call_throw;
5943 {
5944 auto args = new (zone) ZoneList<Expression*>(3, zone);
5945 args->Add(factory->NewVariableProxy(var_throw), zone);
5946 args->Add(factory->NewVariableProxy(var_iterator), zone);
5947 args->Add(factory->NewVariableProxy(var_input), zone);
5948 Expression* call =
5949 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
5950 Expression* assignment = factory->NewAssignment(
5951 Token::ASSIGN, factory->NewVariableProxy(var_output), call, nopos);
5952 call_throw = factory->NewExpressionStatement(assignment, nopos);
5953 }
5954
5955
5956 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
5957 Statement* validate_throw_output;
5958 {
5959 Expression* is_receiver_call;
5960 {
5961 auto args = new (zone) ZoneList<Expression*>(1, zone);
5962 args->Add(factory->NewVariableProxy(var_output), zone);
5963 is_receiver_call =
5964 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
5965 }
5966
5967 Statement* throw_call;
5968 {
5969 auto args = new (zone) ZoneList<Expression*>(1, zone);
5970 args->Add(factory->NewVariableProxy(var_output), zone);
5971 Expression* call = factory->NewCallRuntime(
5972 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
5973 throw_call = factory->NewExpressionStatement(call, nopos);
5974 }
5975
5976 validate_throw_output = factory->NewIfStatement(
5977 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
5978 }
5979
5980
5981 // if (output.done) break;
5982 Statement* if_done;
5983 {
5984 Expression* output_proxy = factory->NewVariableProxy(var_output);
5985 Expression* literal =
5986 factory->NewStringLiteral(avfactory->done_string(), nopos);
5987 Expression* property = factory->NewProperty(output_proxy, literal, nopos);
5988 BreakStatement* break_loop = factory->NewBreakStatement(loop, nopos);
5989 if_done = factory->NewIfStatement(
5990 property, break_loop, factory->NewEmptyStatement(nopos), nopos);
5991 }
5992
5993
5994 // mode = kReturn;
5995 Statement* set_mode_return;
5996 {
5997 Expression* mode_proxy = factory->NewVariableProxy(var_mode);
5998 Expression* kreturn =
5999 factory->NewSmiLiteral(JSGeneratorObject::RETURN, nopos);
6000 Expression* assignment =
6001 factory->NewAssignment(Token::ASSIGN, mode_proxy, kreturn, nopos);
6002 set_mode_return = factory->NewExpressionStatement(assignment, nopos);
6003 }
6004
Ben Murdochda12d292016-06-02 14:46:10 +01006005 // Yield(output);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006006 Statement* yield_output;
6007 {
6008 Expression* output_proxy = factory->NewVariableProxy(var_output);
Ben Murdochda12d292016-06-02 14:46:10 +01006009 Yield* yield = factory->NewYield(generator, output_proxy, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006010 yield_output = factory->NewExpressionStatement(yield, nopos);
6011 }
6012
6013
6014 // mode = kNext;
6015 Statement* set_mode_next;
6016 {
6017 Expression* mode_proxy = factory->NewVariableProxy(var_mode);
6018 Expression* knext = factory->NewSmiLiteral(JSGeneratorObject::NEXT, nopos);
6019 Expression* assignment =
6020 factory->NewAssignment(Token::ASSIGN, mode_proxy, knext, nopos);
6021 set_mode_next = factory->NewExpressionStatement(assignment, nopos);
6022 }
6023
6024
6025 // mode = kThrow;
6026 Statement* set_mode_throw;
6027 {
6028 Expression* mode_proxy = factory->NewVariableProxy(var_mode);
6029 Expression* kthrow =
6030 factory->NewSmiLiteral(JSGeneratorObject::THROW, nopos);
6031 Expression* assignment =
6032 factory->NewAssignment(Token::ASSIGN, mode_proxy, kthrow, nopos);
6033 set_mode_throw = factory->NewExpressionStatement(assignment, nopos);
6034 }
6035
6036
6037 // input = function.sent;
6038 Statement* get_input;
6039 {
6040 Expression* function_sent = FunctionSentExpression(scope, factory, nopos);
6041 Expression* input_proxy = factory->NewVariableProxy(var_input);
6042 Expression* assignment = factory->NewAssignment(
6043 Token::ASSIGN, input_proxy, function_sent, nopos);
6044 get_input = factory->NewExpressionStatement(assignment, nopos);
6045 }
6046
6047
6048 // output.value;
6049 Statement* get_value;
6050 {
6051 Expression* output_proxy = factory->NewVariableProxy(var_output);
6052 Expression* literal =
6053 factory->NewStringLiteral(avfactory->value_string(), nopos);
6054 Expression* property = factory->NewProperty(output_proxy, literal, nopos);
6055 get_value = factory->NewExpressionStatement(property, nopos);
6056 }
6057
6058
6059 // Now put things together.
6060
6061
6062 // try { ... } catch(e) { ... }
6063 Statement* try_catch;
6064 {
6065 Block* try_block = factory->NewBlock(nullptr, 2, false, nopos);
6066 try_block->statements()->Add(yield_output, zone);
6067 try_block->statements()->Add(set_mode_next, zone);
6068
6069 Block* catch_block = factory->NewBlock(nullptr, 1, false, nopos);
6070 catch_block->statements()->Add(set_mode_throw, zone);
6071
6072 Scope* catch_scope = NewScope(scope, CATCH_SCOPE);
6073 const AstRawString* name = avfactory->dot_catch_string();
6074 Variable* catch_variable =
6075 catch_scope->DeclareLocal(name, VAR, kCreatedInitialized,
6076 Variable::NORMAL);
6077
6078 try_catch = factory->NewTryCatchStatement(
6079 try_block, catch_scope, catch_variable, catch_block, nopos);
6080 }
6081
6082
6083 // try { ... } finally { ... }
6084 Statement* try_finally;
6085 {
6086 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
6087 try_block->statements()->Add(try_catch, zone);
6088
6089 Block* finally = factory->NewBlock(nullptr, 2, false, nopos);
6090 finally->statements()->Add(get_input, zone);
6091 finally->statements()->Add(
6092 factory->NewContinueStatement(loop, nopos), zone);
6093
6094 try_finally = factory->NewTryFinallyStatement(try_block, finally, nopos);
6095 }
6096
6097
6098 // switch (mode) { ... }
6099 SwitchStatement* switch_mode = factory->NewSwitchStatement(nullptr, nopos);
6100 {
6101 auto case_next = new (zone) ZoneList<Statement*>(3, zone);
6102 case_next->Add(call_next, zone);
6103 case_next->Add(validate_next_output, zone);
6104 case_next->Add(factory->NewBreakStatement(switch_mode, nopos), zone);
6105
6106 auto case_return = new (zone) ZoneList<Statement*>(5, zone);
Ben Murdochda12d292016-06-02 14:46:10 +01006107 BuildIteratorClose(case_return, var_iterator, Just(var_input), var_output);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006108 case_return->Add(factory->NewBreakStatement(switch_mode, nopos), zone);
6109
6110 auto case_throw = new (zone) ZoneList<Statement*>(5, zone);
6111 case_throw->Add(get_throw, zone);
6112 case_throw->Add(check_throw, zone);
6113 case_throw->Add(call_throw, zone);
6114 case_throw->Add(validate_throw_output, zone);
6115 case_throw->Add(factory->NewBreakStatement(switch_mode, nopos), zone);
6116
6117 auto cases = new (zone) ZoneList<CaseClause*>(3, zone);
6118 Expression* knext = factory->NewSmiLiteral(JSGeneratorObject::NEXT, nopos);
6119 Expression* kreturn =
6120 factory->NewSmiLiteral(JSGeneratorObject::RETURN, nopos);
6121 Expression* kthrow =
6122 factory->NewSmiLiteral(JSGeneratorObject::THROW, nopos);
6123 cases->Add(factory->NewCaseClause(knext, case_next, nopos), zone);
6124 cases->Add(factory->NewCaseClause(kreturn, case_return, nopos), zone);
6125 cases->Add(factory->NewCaseClause(kthrow, case_throw, nopos), zone);
6126
6127 switch_mode->Initialize(factory->NewVariableProxy(var_mode), cases);
6128 }
6129
6130
6131 // while (true) { ... }
6132 // Already defined earlier: WhileStatement* loop = ...
6133 {
6134 Block* loop_body = factory->NewBlock(nullptr, 4, false, nopos);
6135 loop_body->statements()->Add(switch_mode, zone);
6136 loop_body->statements()->Add(if_done, zone);
6137 loop_body->statements()->Add(set_mode_return, zone);
6138 loop_body->statements()->Add(try_finally, zone);
6139
6140 loop->Initialize(factory->NewBooleanLiteral(true, nopos), loop_body);
6141 }
6142
6143
6144 // do { ... }
6145 DoExpression* yield_star;
6146 {
6147 // The rewriter needs to process the get_value statement only, hence we
6148 // put the preceding statements into an init block.
6149
6150 Block* do_block_ = factory->NewBlock(nullptr, 6, true, nopos);
6151 do_block_->statements()->Add(initialize_input, zone);
6152 do_block_->statements()->Add(initialize_mode, zone);
6153 do_block_->statements()->Add(initialize_output, zone);
6154 do_block_->statements()->Add(get_iterator, zone);
6155 do_block_->statements()->Add(validate_iterator, zone);
6156 do_block_->statements()->Add(loop, zone);
6157
6158 Block* do_block = factory->NewBlock(nullptr, 2, false, nopos);
6159 do_block->statements()->Add(do_block_, zone);
6160 do_block->statements()->Add(get_value, zone);
6161
6162 Variable* dot_result = scope->NewTemporary(avfactory->dot_result_string());
6163 yield_star = factory->NewDoExpression(do_block, dot_result, nopos);
6164 Rewriter::Rewrite(parser_, yield_star, avfactory);
6165 }
6166
6167 return yield_star;
6168}
6169
6170// Desugaring of (lhs) instanceof (rhs)
6171// ====================================
6172//
6173// We desugar instanceof into a load of property @@hasInstance on the rhs.
6174// We end up with roughly the following code (O, C):
6175//
6176// do {
6177// let O = lhs;
6178// let C = rhs;
6179// if (!IS_RECEIVER(C)) throw MakeTypeError(kNonObjectInInstanceOfCheck);
6180// let handler_result = C[Symbol.hasInstance];
6181// if (handler_result === undefined) {
6182// if (!IS_CALLABLE(C)) {
6183// throw MakeTypeError(kCalledNonCallableInstanceOf);
6184// }
Ben Murdochda12d292016-06-02 14:46:10 +01006185// handler_result = %_GetOrdinaryHasInstance()
6186// handler_result = %_Call(handler_result, C, O);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006187// } else {
6188// handler_result = !!(%_Call(handler_result, C, O));
6189// }
6190// handler_result;
6191// }
6192//
6193Expression* ParserTraits::RewriteInstanceof(Expression* lhs, Expression* rhs,
6194 int pos) {
6195 const int nopos = RelocInfo::kNoPosition;
6196
6197 auto factory = parser_->factory();
6198 auto avfactory = parser_->ast_value_factory();
6199 auto scope = parser_->scope_;
6200 auto zone = parser_->zone();
6201
6202 // let O = lhs;
6203 Variable* var_O = scope->NewTemporary(avfactory->empty_string());
6204 Statement* get_O;
6205 {
6206 Expression* O_proxy = factory->NewVariableProxy(var_O);
6207 Expression* assignment =
6208 factory->NewAssignment(Token::ASSIGN, O_proxy, lhs, nopos);
6209 get_O = factory->NewExpressionStatement(assignment, nopos);
6210 }
6211
6212 // let C = lhs;
6213 Variable* var_C = scope->NewTemporary(avfactory->empty_string());
6214 Statement* get_C;
6215 {
6216 Expression* C_proxy = factory->NewVariableProxy(var_C);
6217 Expression* assignment =
6218 factory->NewAssignment(Token::ASSIGN, C_proxy, rhs, nopos);
6219 get_C = factory->NewExpressionStatement(assignment, nopos);
6220 }
6221
6222 // if (!IS_RECEIVER(C)) throw MakeTypeError(kNonObjectInInstanceOfCheck);
6223 Statement* validate_C;
6224 {
6225 auto args = new (zone) ZoneList<Expression*>(1, zone);
6226 args->Add(factory->NewVariableProxy(var_C), zone);
6227 Expression* is_receiver_call =
6228 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
6229 Expression* call =
6230 NewThrowTypeError(MessageTemplate::kNonObjectInInstanceOfCheck,
Ben Murdochda12d292016-06-02 14:46:10 +01006231 avfactory->empty_string(), pos);
6232 Statement* throw_call = factory->NewExpressionStatement(call, pos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006233
6234 validate_C =
6235 factory->NewIfStatement(is_receiver_call,
6236 factory->NewEmptyStatement(nopos),
6237 throw_call,
6238 nopos);
6239 }
6240
6241 // let handler_result = C[Symbol.hasInstance];
6242 Variable* var_handler_result = scope->NewTemporary(avfactory->empty_string());
6243 Statement* initialize_handler;
6244 {
6245 Expression* hasInstance_symbol_literal =
6246 factory->NewSymbolLiteral("hasInstance_symbol", RelocInfo::kNoPosition);
6247 Expression* prop = factory->NewProperty(factory->NewVariableProxy(var_C),
6248 hasInstance_symbol_literal, pos);
6249 Expression* handler_proxy = factory->NewVariableProxy(var_handler_result);
6250 Expression* assignment =
6251 factory->NewAssignment(Token::ASSIGN, handler_proxy, prop, nopos);
6252 initialize_handler = factory->NewExpressionStatement(assignment, nopos);
6253 }
6254
6255 // if (handler_result === undefined) {
6256 // if (!IS_CALLABLE(C)) {
6257 // throw MakeTypeError(kCalledNonCallableInstanceOf);
6258 // }
Ben Murdochda12d292016-06-02 14:46:10 +01006259 // handler_result = %_GetOrdinaryHasInstance()
6260 // handler_result = %_Call(handler_result, C, O);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006261 // } else {
6262 // handler_result = !!%_Call(handler_result, C, O);
6263 // }
6264 Statement* call_handler;
6265 {
6266 Expression* condition = factory->NewCompareOperation(
6267 Token::EQ_STRICT, factory->NewVariableProxy(var_handler_result),
6268 factory->NewUndefinedLiteral(nopos), nopos);
6269
Ben Murdochda12d292016-06-02 14:46:10 +01006270 Block* then_side = factory->NewBlock(nullptr, 3, false, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006271 {
6272 Expression* throw_expr =
6273 NewThrowTypeError(MessageTemplate::kCalledNonCallableInstanceOf,
Ben Murdochda12d292016-06-02 14:46:10 +01006274 avfactory->empty_string(), pos);
6275 Statement* validate_C = CheckCallable(var_C, throw_expr, pos);
6276
6277 ZoneList<Expression*>* empty_args =
6278 new (zone) ZoneList<Expression*>(0, zone);
6279 Expression* ordinary_has_instance = factory->NewCallRuntime(
6280 Runtime::kInlineGetOrdinaryHasInstance, empty_args, pos);
6281 Expression* handler_proxy = factory->NewVariableProxy(var_handler_result);
6282 Expression* assignment_handler = factory->NewAssignment(
6283 Token::ASSIGN, handler_proxy, ordinary_has_instance, nopos);
6284 Statement* assignment_get_handler =
6285 factory->NewExpressionStatement(assignment_handler, nopos);
6286
6287 ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(3, zone);
6288 args->Add(factory->NewVariableProxy(var_handler_result), zone);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006289 args->Add(factory->NewVariableProxy(var_C), zone);
6290 args->Add(factory->NewVariableProxy(var_O), zone);
Ben Murdochda12d292016-06-02 14:46:10 +01006291 Expression* call =
6292 factory->NewCallRuntime(Runtime::kInlineCall, args, pos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006293 Expression* result_proxy = factory->NewVariableProxy(var_handler_result);
6294 Expression* assignment =
6295 factory->NewAssignment(Token::ASSIGN, result_proxy, call, nopos);
6296 Statement* assignment_return =
6297 factory->NewExpressionStatement(assignment, nopos);
6298
6299 then_side->statements()->Add(validate_C, zone);
Ben Murdochda12d292016-06-02 14:46:10 +01006300 then_side->statements()->Add(assignment_get_handler, zone);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006301 then_side->statements()->Add(assignment_return, zone);
6302 }
6303
6304 Statement* else_side;
6305 {
6306 auto args = new (zone) ZoneList<Expression*>(3, zone);
6307 args->Add(factory->NewVariableProxy(var_handler_result), zone);
6308 args->Add(factory->NewVariableProxy(var_C), zone);
6309 args->Add(factory->NewVariableProxy(var_O), zone);
6310 Expression* call =
6311 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
6312 Expression* inner_not =
6313 factory->NewUnaryOperation(Token::NOT, call, nopos);
6314 Expression* outer_not =
6315 factory->NewUnaryOperation(Token::NOT, inner_not, nopos);
6316 Expression* result_proxy = factory->NewVariableProxy(var_handler_result);
6317 Expression* assignment =
6318 factory->NewAssignment(Token::ASSIGN, result_proxy, outer_not, nopos);
6319
6320 else_side = factory->NewExpressionStatement(assignment, nopos);
6321 }
6322 call_handler =
6323 factory->NewIfStatement(condition, then_side, else_side, nopos);
6324 }
6325
6326 // do { ... }
6327 DoExpression* instanceof;
6328 {
6329 Block* block = factory->NewBlock(nullptr, 5, true, nopos);
6330 block->statements()->Add(get_O, zone);
6331 block->statements()->Add(get_C, zone);
6332 block->statements()->Add(validate_C, zone);
6333 block->statements()->Add(initialize_handler, zone);
6334 block->statements()->Add(call_handler, zone);
6335
6336 // Here is the desugared instanceof.
6337 instanceof = factory->NewDoExpression(block, var_handler_result, nopos);
6338 Rewriter::Rewrite(parser_, instanceof, avfactory);
6339 }
6340
6341 return instanceof;
6342}
6343
Ben Murdochda12d292016-06-02 14:46:10 +01006344Statement* ParserTraits::CheckCallable(Variable* var, Expression* error,
6345 int pos) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01006346 auto factory = parser_->factory();
6347 auto avfactory = parser_->ast_value_factory();
6348 const int nopos = RelocInfo::kNoPosition;
6349 Statement* validate_var;
6350 {
6351 Expression* type_of = factory->NewUnaryOperation(
6352 Token::TYPEOF, factory->NewVariableProxy(var), nopos);
6353 Expression* function_literal =
6354 factory->NewStringLiteral(avfactory->function_string(), nopos);
6355 Expression* condition = factory->NewCompareOperation(
6356 Token::EQ_STRICT, type_of, function_literal, nopos);
6357
Ben Murdochda12d292016-06-02 14:46:10 +01006358 Statement* throw_call = factory->NewExpressionStatement(error, pos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006359
6360 validate_var = factory->NewIfStatement(
6361 condition, factory->NewEmptyStatement(nopos), throw_call, nopos);
6362 }
6363 return validate_var;
6364}
6365
6366void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements,
6367 Variable* iterator,
Ben Murdochda12d292016-06-02 14:46:10 +01006368 Maybe<Variable*> input,
Ben Murdoch097c5b22016-05-18 11:27:45 +01006369 Variable* var_output) {
6370 //
6371 // This function adds four statements to [statements], corresponding to the
6372 // following code:
6373 //
6374 // let iteratorReturn = iterator.return;
Ben Murdochda12d292016-06-02 14:46:10 +01006375 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return |input|;
6376 // output = %_Call(iteratorReturn, iterator|, input|);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006377 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
6378 //
Ben Murdochda12d292016-06-02 14:46:10 +01006379 // Here, |...| denotes optional parts, depending on the presence of the
6380 // input variable. The reason for allowing input is that BuildIteratorClose
6381 // can then be reused to handle the return case in yield*.
6382 //
Ben Murdoch097c5b22016-05-18 11:27:45 +01006383
6384 const int nopos = RelocInfo::kNoPosition;
6385 auto factory = parser_->factory();
6386 auto avfactory = parser_->ast_value_factory();
6387 auto zone = parser_->zone();
6388
6389 // let iteratorReturn = iterator.return;
6390 Variable* var_return = var_output; // Reusing the output variable.
6391 Statement* get_return;
6392 {
6393 Expression* iterator_proxy = factory->NewVariableProxy(iterator);
6394 Expression* literal =
6395 factory->NewStringLiteral(avfactory->return_string(), nopos);
6396 Expression* property =
6397 factory->NewProperty(iterator_proxy, literal, nopos);
6398 Expression* return_proxy = factory->NewVariableProxy(var_return);
6399 Expression* assignment = factory->NewAssignment(
6400 Token::ASSIGN, return_proxy, property, nopos);
6401 get_return = factory->NewExpressionStatement(assignment, nopos);
6402 }
6403
Ben Murdochda12d292016-06-02 14:46:10 +01006404 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return |input|;
Ben Murdoch097c5b22016-05-18 11:27:45 +01006405 Statement* check_return;
6406 {
6407 Expression* condition = factory->NewCompareOperation(
6408 Token::EQ, factory->NewVariableProxy(var_return),
6409 factory->NewNullLiteral(nopos), nopos);
6410
Ben Murdochda12d292016-06-02 14:46:10 +01006411 Expression* value = input.IsJust()
6412 ? static_cast<Expression*>(
6413 factory->NewVariableProxy(input.FromJust()))
6414 : factory->NewUndefinedLiteral(nopos);
6415
6416 Statement* return_input = factory->NewReturnStatement(value, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006417
6418 check_return = factory->NewIfStatement(
6419 condition, return_input, factory->NewEmptyStatement(nopos), nopos);
6420 }
6421
Ben Murdochda12d292016-06-02 14:46:10 +01006422 // output = %_Call(iteratorReturn, iterator, |input|);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006423 Statement* call_return;
6424 {
6425 auto args = new (zone) ZoneList<Expression*>(3, zone);
6426 args->Add(factory->NewVariableProxy(var_return), zone);
6427 args->Add(factory->NewVariableProxy(iterator), zone);
Ben Murdochda12d292016-06-02 14:46:10 +01006428 if (input.IsJust()) {
6429 args->Add(factory->NewVariableProxy(input.FromJust()), zone);
6430 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01006431
6432 Expression* call =
6433 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
6434 Expression* output_proxy = factory->NewVariableProxy(var_output);
6435 Expression* assignment = factory->NewAssignment(
6436 Token::ASSIGN, output_proxy, call, nopos);
6437 call_return = factory->NewExpressionStatement(assignment, nopos);
6438 }
6439
6440 // if (!IS_RECEIVER(output)) %ThrowIteratorResultNotAnObject(output);
6441 Statement* validate_output;
6442 {
6443 Expression* is_receiver_call;
6444 {
6445 auto args = new (zone) ZoneList<Expression*>(1, zone);
6446 args->Add(factory->NewVariableProxy(var_output), zone);
6447 is_receiver_call =
6448 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
6449 }
6450
6451 Statement* throw_call;
6452 {
6453 auto args = new (zone) ZoneList<Expression*>(1, zone);
6454 args->Add(factory->NewVariableProxy(var_output), zone);
6455 Expression* call = factory->NewCallRuntime(
6456 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
6457 throw_call = factory->NewExpressionStatement(call, nopos);
6458 }
6459
6460 validate_output = factory->NewIfStatement(
6461 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
6462 }
6463
6464 statements->Add(get_return, zone);
6465 statements->Add(check_return, zone);
6466 statements->Add(call_return, zone);
6467 statements->Add(validate_output, zone);
6468}
6469
Ben Murdochda12d292016-06-02 14:46:10 +01006470void ParserTraits::FinalizeIteratorUse(Variable* completion,
6471 Expression* condition, Variable* iter,
6472 Block* iterator_use, Block* target) {
6473 if (!FLAG_harmony_iterator_close) return;
Ben Murdoch097c5b22016-05-18 11:27:45 +01006474
Ben Murdochda12d292016-06-02 14:46:10 +01006475 //
6476 // This function adds two statements to [target], corresponding to the
6477 // following code:
6478 //
6479 // completion = kNormalCompletion;
6480 // try {
6481 // try {
6482 // iterator_use
6483 // } catch(e) {
6484 // if (completion === kAbruptCompletion) completion = kThrowCompletion;
6485 // %ReThrow(e);
6486 // }
6487 // } finally {
6488 // if (condition) {
6489 // #BuildIteratorCloseForCompletion(iter, completion)
6490 // }
6491 // }
6492 //
6493
6494 const int nopos = RelocInfo::kNoPosition;
6495 auto factory = parser_->factory();
6496 auto avfactory = parser_->ast_value_factory();
6497 auto scope = parser_->scope_;
6498 auto zone = parser_->zone();
6499
6500 // completion = kNormalCompletion;
6501 Statement* initialize_completion;
6502 {
6503 Expression* proxy = factory->NewVariableProxy(completion);
6504 Expression* assignment = factory->NewAssignment(
6505 Token::ASSIGN, proxy,
6506 factory->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
6507 initialize_completion = factory->NewExpressionStatement(assignment, nopos);
6508 }
6509
6510 // if (completion === kAbruptCompletion) completion = kThrowCompletion;
6511 Statement* set_completion_throw;
6512 {
6513 Expression* condition = factory->NewCompareOperation(
6514 Token::EQ_STRICT, factory->NewVariableProxy(completion),
6515 factory->NewSmiLiteral(Parser::kAbruptCompletion, nopos), nopos);
6516
6517 Expression* proxy = factory->NewVariableProxy(completion);
6518 Expression* assignment = factory->NewAssignment(
6519 Token::ASSIGN, proxy,
6520 factory->NewSmiLiteral(Parser::kThrowCompletion, nopos), nopos);
6521 Statement* statement = factory->NewExpressionStatement(assignment, nopos);
6522 set_completion_throw = factory->NewIfStatement(
6523 condition, statement, factory->NewEmptyStatement(nopos), nopos);
6524 }
6525
6526 // if (condition) {
6527 // #BuildIteratorCloseForCompletion(iter, completion)
6528 // }
6529 Block* maybe_close;
6530 {
6531 Block* block = factory->NewBlock(nullptr, 2, true, nopos);
6532 parser_->BuildIteratorCloseForCompletion(block->statements(), iter,
6533 completion);
6534 DCHECK(block->statements()->length() == 2);
6535
6536 maybe_close = factory->NewBlock(nullptr, 1, true, nopos);
6537 maybe_close->statements()->Add(
6538 factory->NewIfStatement(condition, block,
6539 factory->NewEmptyStatement(nopos), nopos),
6540 zone);
6541 }
6542
6543 // try { #try_block }
6544 // catch(e) {
6545 // #set_completion_throw;
6546 // %ReThrow(e);
6547 // }
6548 Statement* try_catch;
6549 {
6550 Scope* catch_scope = parser_->NewScope(scope, CATCH_SCOPE);
6551 Variable* catch_variable =
6552 catch_scope->DeclareLocal(avfactory->dot_catch_string(), VAR,
6553 kCreatedInitialized, Variable::NORMAL);
6554
6555 Statement* rethrow;
6556 // We use %ReThrow rather than the ordinary throw because we want to
6557 // preserve the original exception message. This is also why we create a
6558 // TryCatchStatementForReThrow below (which does not clear the pending
6559 // message), rather than a TryCatchStatement.
6560 {
6561 auto args = new (zone) ZoneList<Expression*>(1, zone);
6562 args->Add(factory->NewVariableProxy(catch_variable), zone);
6563 rethrow = factory->NewExpressionStatement(
6564 factory->NewCallRuntime(Runtime::kReThrow, args, nopos), nopos);
6565 }
6566
6567 Block* catch_block = factory->NewBlock(nullptr, 2, false, nopos);
6568 catch_block->statements()->Add(set_completion_throw, zone);
6569 catch_block->statements()->Add(rethrow, zone);
6570
6571 try_catch = factory->NewTryCatchStatementForReThrow(
6572 iterator_use, catch_scope, catch_variable, catch_block, nopos);
6573 }
6574
6575 // try { #try_catch } finally { #maybe_close }
6576 Statement* try_finally;
6577 {
6578 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
6579 try_block->statements()->Add(try_catch, zone);
6580
6581 try_finally =
6582 factory->NewTryFinallyStatement(try_block, maybe_close, nopos);
6583 }
6584
6585 target->statements()->Add(initialize_completion, zone);
6586 target->statements()->Add(try_finally, zone);
6587}
Ben Murdoch097c5b22016-05-18 11:27:45 +01006588
6589void ParserTraits::BuildIteratorCloseForCompletion(
6590 ZoneList<Statement*>* statements, Variable* iterator,
6591 Variable* completion) {
6592 //
6593 // This function adds two statements to [statements], corresponding to the
6594 // following code:
6595 //
6596 // let iteratorReturn = iterator.return;
6597 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
Ben Murdochda12d292016-06-02 14:46:10 +01006598 // if (completion === kThrowCompletion) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01006599 // if (!IS_CALLABLE(iteratorReturn)) {
6600 // throw MakeTypeError(kReturnMethodNotCallable);
6601 // }
Ben Murdochda12d292016-06-02 14:46:10 +01006602 // try { %_Call(iteratorReturn, iterator) } catch (_) { }
Ben Murdoch097c5b22016-05-18 11:27:45 +01006603 // } else {
Ben Murdochda12d292016-06-02 14:46:10 +01006604 // let output = %_Call(iteratorReturn, iterator);
6605 // if (!IS_RECEIVER(output)) {
6606 // %ThrowIterResultNotAnObject(output);
6607 // }
Ben Murdoch097c5b22016-05-18 11:27:45 +01006608 // }
Ben Murdoch097c5b22016-05-18 11:27:45 +01006609 // }
6610 //
6611
6612 const int nopos = RelocInfo::kNoPosition;
6613 auto factory = parser_->factory();
6614 auto avfactory = parser_->ast_value_factory();
6615 auto scope = parser_->scope_;
6616 auto zone = parser_->zone();
6617
Ben Murdoch097c5b22016-05-18 11:27:45 +01006618
6619 // let iteratorReturn = iterator.return;
Ben Murdochda12d292016-06-02 14:46:10 +01006620 Variable* var_return = scope->NewTemporary(avfactory->empty_string());
Ben Murdoch097c5b22016-05-18 11:27:45 +01006621 Statement* get_return;
6622 {
6623 Expression* iterator_proxy = factory->NewVariableProxy(iterator);
6624 Expression* literal =
6625 factory->NewStringLiteral(avfactory->return_string(), nopos);
6626 Expression* property =
6627 factory->NewProperty(iterator_proxy, literal, nopos);
6628 Expression* return_proxy = factory->NewVariableProxy(var_return);
6629 Expression* assignment = factory->NewAssignment(
6630 Token::ASSIGN, return_proxy, property, nopos);
6631 get_return = factory->NewExpressionStatement(assignment, nopos);
6632 }
6633
6634 // if (!IS_CALLABLE(iteratorReturn)) {
6635 // throw MakeTypeError(kReturnMethodNotCallable);
6636 // }
6637 Statement* check_return_callable;
6638 {
6639 Expression* throw_expr = NewThrowTypeError(
6640 MessageTemplate::kReturnMethodNotCallable,
6641 avfactory->empty_string(), nopos);
Ben Murdochda12d292016-06-02 14:46:10 +01006642 check_return_callable = CheckCallable(var_return, throw_expr, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006643 }
6644
Ben Murdochda12d292016-06-02 14:46:10 +01006645 // try { %_Call(iteratorReturn, iterator) } catch (_) { }
Ben Murdoch097c5b22016-05-18 11:27:45 +01006646 Statement* try_call_return;
6647 {
6648 auto args = new (zone) ZoneList<Expression*>(2, zone);
6649 args->Add(factory->NewVariableProxy(var_return), zone);
6650 args->Add(factory->NewVariableProxy(iterator), zone);
6651
6652 Expression* call =
6653 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006654
6655 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
Ben Murdochda12d292016-06-02 14:46:10 +01006656 try_block->statements()->Add(factory->NewExpressionStatement(call, nopos),
6657 zone);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006658
6659 Block* catch_block = factory->NewBlock(nullptr, 0, false, nopos);
6660
6661 Scope* catch_scope = NewScope(scope, CATCH_SCOPE);
6662 Variable* catch_variable = catch_scope->DeclareLocal(
6663 avfactory->dot_catch_string(), VAR, kCreatedInitialized,
6664 Variable::NORMAL);
6665
6666 try_call_return = factory->NewTryCatchStatement(
6667 try_block, catch_scope, catch_variable, catch_block, nopos);
6668 }
6669
Ben Murdochda12d292016-06-02 14:46:10 +01006670 // let output = %_Call(iteratorReturn, iterator);
6671 // if (!IS_RECEIVER(output)) {
6672 // %ThrowIteratorResultNotAnObject(output);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006673 // }
Ben Murdochda12d292016-06-02 14:46:10 +01006674 Block* validate_return;
Ben Murdoch097c5b22016-05-18 11:27:45 +01006675 {
Ben Murdochda12d292016-06-02 14:46:10 +01006676 Variable* var_output = scope->NewTemporary(avfactory->empty_string());
6677 Statement* call_return;
6678 {
6679 auto args = new (zone) ZoneList<Expression*>(2, zone);
6680 args->Add(factory->NewVariableProxy(var_return), zone);
6681 args->Add(factory->NewVariableProxy(iterator), zone);
6682 Expression* call =
6683 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006684
Ben Murdochda12d292016-06-02 14:46:10 +01006685 Expression* output_proxy = factory->NewVariableProxy(var_output);
6686 Expression* assignment =
6687 factory->NewAssignment(Token::ASSIGN, output_proxy, call, nopos);
6688 call_return = factory->NewExpressionStatement(assignment, nopos);
6689 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01006690
Ben Murdoch097c5b22016-05-18 11:27:45 +01006691 Expression* is_receiver_call;
6692 {
6693 auto args = new (zone) ZoneList<Expression*>(1, zone);
6694 args->Add(factory->NewVariableProxy(var_output), zone);
6695 is_receiver_call =
6696 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
6697 }
6698
6699 Statement* throw_call;
6700 {
6701 auto args = new (zone) ZoneList<Expression*>(1, zone);
6702 args->Add(factory->NewVariableProxy(var_output), zone);
6703 Expression* call = factory->NewCallRuntime(
6704 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
6705 throw_call = factory->NewExpressionStatement(call, nopos);
6706 }
6707
Ben Murdochda12d292016-06-02 14:46:10 +01006708 Statement* check_return = factory->NewIfStatement(
Ben Murdoch097c5b22016-05-18 11:27:45 +01006709 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
Ben Murdochda12d292016-06-02 14:46:10 +01006710
6711 validate_return = factory->NewBlock(nullptr, 2, false, nopos);
6712 validate_return->statements()->Add(call_return, zone);
6713 validate_return->statements()->Add(check_return, zone);
6714 }
6715
6716 // if (completion === kThrowCompletion) {
6717 // #check_return_callable;
6718 // #try_call_return;
6719 // } else {
6720 // #validate_return;
6721 // }
6722 Statement* call_return_carefully;
6723 {
6724 Expression* condition = factory->NewCompareOperation(
6725 Token::EQ_STRICT, factory->NewVariableProxy(completion),
6726 factory->NewSmiLiteral(Parser::kThrowCompletion, nopos), nopos);
6727
6728 Block* then_block = factory->NewBlock(nullptr, 2, false, nopos);
6729 then_block->statements()->Add(check_return_callable, zone);
6730 then_block->statements()->Add(try_call_return, zone);
6731
6732 call_return_carefully =
6733 factory->NewIfStatement(condition, then_block, validate_return, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006734 }
6735
6736 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { ... }
6737 Statement* maybe_call_return;
6738 {
6739 Expression* condition = factory->NewCompareOperation(
6740 Token::EQ, factory->NewVariableProxy(var_return),
6741 factory->NewNullLiteral(nopos), nopos);
6742
Ben Murdochda12d292016-06-02 14:46:10 +01006743 maybe_call_return =
6744 factory->NewIfStatement(condition, factory->NewEmptyStatement(nopos),
6745 call_return_carefully, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006746 }
6747
6748
6749 statements->Add(get_return, zone);
6750 statements->Add(maybe_call_return, zone);
6751}
6752
6753
6754Statement* ParserTraits::FinalizeForOfStatement(ForOfStatement* loop, int pos) {
6755 if (!FLAG_harmony_iterator_close) return loop;
6756
6757 //
6758 // This function replaces the loop with the following wrapping:
6759 //
Ben Murdochda12d292016-06-02 14:46:10 +01006760 // let each;
6761 // let completion = kNormalCompletion;
Ben Murdoch097c5b22016-05-18 11:27:45 +01006762 // try {
Ben Murdochda12d292016-06-02 14:46:10 +01006763 // try {
6764 // #loop;
6765 // } catch(e) {
6766 // if (completion === kAbruptCompletion) completion = kThrowCompletion;
6767 // %ReThrow(e);
6768 // }
Ben Murdoch097c5b22016-05-18 11:27:45 +01006769 // } finally {
Ben Murdochda12d292016-06-02 14:46:10 +01006770 // if (!(completion === kNormalCompletion || IS_UNDEFINED(#iterator))) {
6771 // #BuildIteratorCloseForCompletion(#iterator, completion)
Ben Murdoch097c5b22016-05-18 11:27:45 +01006772 // }
6773 // }
6774 //
6775 // where the loop's body is wrapped as follows:
6776 //
6777 // {
Ben Murdoch097c5b22016-05-18 11:27:45 +01006778 // #loop-body
Ben Murdochda12d292016-06-02 14:46:10 +01006779 // {{completion = kNormalCompletion;}}
Ben Murdoch097c5b22016-05-18 11:27:45 +01006780 // }
Ben Murdochda12d292016-06-02 14:46:10 +01006781 //
6782 // and the loop's assign_each is wrapped as follows
6783 //
6784 // do {
6785 // {{completion = kAbruptCompletion;}}
6786 // #assign-each
6787 // }
6788 //
Ben Murdoch097c5b22016-05-18 11:27:45 +01006789
6790 const int nopos = RelocInfo::kNoPosition;
6791 auto factory = parser_->factory();
6792 auto avfactory = parser_->ast_value_factory();
6793 auto scope = parser_->scope_;
6794 auto zone = parser_->zone();
6795
Ben Murdoch097c5b22016-05-18 11:27:45 +01006796 Variable* var_completion = scope->NewTemporary(avfactory->empty_string());
Ben Murdochda12d292016-06-02 14:46:10 +01006797
6798 // let each;
6799 Variable* var_each = scope->NewTemporary(avfactory->empty_string());
6800 Statement* initialize_each;
Ben Murdoch097c5b22016-05-18 11:27:45 +01006801 {
Ben Murdochda12d292016-06-02 14:46:10 +01006802 Expression* proxy = factory->NewVariableProxy(var_each);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006803 Expression* assignment = factory->NewAssignment(
6804 Token::ASSIGN, proxy,
Ben Murdochda12d292016-06-02 14:46:10 +01006805 factory->NewUndefinedLiteral(nopos), nopos);
6806 initialize_each =
Ben Murdoch097c5b22016-05-18 11:27:45 +01006807 factory->NewExpressionStatement(assignment, nopos);
6808 }
6809
Ben Murdochda12d292016-06-02 14:46:10 +01006810 // !(completion === kNormalCompletion || IS_UNDEFINED(#iterator))
6811 Expression* closing_condition;
Ben Murdoch097c5b22016-05-18 11:27:45 +01006812 {
Ben Murdochda12d292016-06-02 14:46:10 +01006813 Expression* lhs = factory->NewCompareOperation(
Ben Murdoch097c5b22016-05-18 11:27:45 +01006814 Token::EQ_STRICT, factory->NewVariableProxy(var_completion),
Ben Murdochda12d292016-06-02 14:46:10 +01006815 factory->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
6816 Expression* rhs = factory->NewCompareOperation(
Ben Murdoch097c5b22016-05-18 11:27:45 +01006817 Token::EQ_STRICT, factory->NewVariableProxy(loop->iterator()),
6818 factory->NewUndefinedLiteral(nopos), nopos);
Ben Murdochda12d292016-06-02 14:46:10 +01006819 closing_condition = factory->NewUnaryOperation(
6820 Token::NOT, factory->NewBinaryOperation(Token::OR, lhs, rhs, nopos),
6821 nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006822 }
6823
Ben Murdochda12d292016-06-02 14:46:10 +01006824 // {{completion = kNormalCompletion;}}
Ben Murdoch097c5b22016-05-18 11:27:45 +01006825 Statement* set_completion_normal;
6826 {
6827 Expression* proxy = factory->NewVariableProxy(var_completion);
6828 Expression* assignment = factory->NewAssignment(
Ben Murdochda12d292016-06-02 14:46:10 +01006829 Token::ASSIGN, proxy,
6830 factory->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006831
6832 Block* block = factory->NewBlock(nullptr, 1, true, nopos);
6833 block->statements()->Add(
6834 factory->NewExpressionStatement(assignment, nopos), zone);
6835 set_completion_normal = block;
6836 }
6837
Ben Murdochda12d292016-06-02 14:46:10 +01006838 // {{completion = kAbruptCompletion;}}
6839 Statement* set_completion_abrupt;
6840 {
6841 Expression* proxy = factory->NewVariableProxy(var_completion);
6842 Expression* assignment = factory->NewAssignment(
6843 Token::ASSIGN, proxy,
6844 factory->NewSmiLiteral(Parser::kAbruptCompletion, nopos), nopos);
6845
6846 Block* block = factory->NewBlock(nullptr, 1, true, nopos);
6847 block->statements()->Add(factory->NewExpressionStatement(assignment, nopos),
6848 zone);
6849 set_completion_abrupt = block;
6850 }
6851
6852 // { #loop-body; #set_completion_normal }
Ben Murdoch097c5b22016-05-18 11:27:45 +01006853 Block* new_body = factory->NewBlock(nullptr, 2, false, nopos);
Ben Murdochda12d292016-06-02 14:46:10 +01006854 {
6855 new_body->statements()->Add(loop->body(), zone);
6856 new_body->statements()->Add(set_completion_normal, zone);
6857 }
6858
6859 // { #set_completion_abrupt; #assign-each }
6860 Block* new_assign_each = factory->NewBlock(nullptr, 2, false, nopos);
6861 {
6862 new_assign_each->statements()->Add(set_completion_abrupt, zone);
6863 new_assign_each->statements()->Add(
6864 factory->NewExpressionStatement(loop->assign_each(), nopos), zone);
6865 }
6866
6867 // Now put things together.
Ben Murdoch097c5b22016-05-18 11:27:45 +01006868
6869 loop->set_body(new_body);
Ben Murdochda12d292016-06-02 14:46:10 +01006870 loop->set_assign_each(
6871 factory->NewDoExpression(new_assign_each, var_each, nopos));
6872
6873 Statement* final_loop;
6874 {
6875 Block* target = factory->NewBlock(nullptr, 3, false, nopos);
6876 target->statements()->Add(initialize_each, zone);
6877
6878 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
6879 try_block->statements()->Add(loop, zone);
6880
6881 FinalizeIteratorUse(var_completion, closing_condition, loop->iterator(),
6882 try_block, target);
6883 final_loop = target;
6884 }
6885
Ben Murdoch097c5b22016-05-18 11:27:45 +01006886 return final_loop;
6887}
6888
6889
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006890} // namespace internal
6891} // namespace v8