blob: 968e8ed4ff5ef8521e38abe94791e73e0e184237 [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 }
442 default:
443 break;
444 }
445 }
446 return false;
447}
448
449
450Expression* ParserTraits::BuildUnaryExpression(Expression* expression,
451 Token::Value op, int pos,
452 AstNodeFactory* factory) {
453 DCHECK(expression != NULL);
454 if (expression->IsLiteral()) {
455 const AstValue* literal = expression->AsLiteral()->raw_value();
456 if (op == Token::NOT) {
457 // Convert the literal to a boolean condition and negate it.
458 bool condition = literal->BooleanValue();
459 return factory->NewBooleanLiteral(!condition, pos);
460 } else if (literal->IsNumber()) {
461 // Compute some expressions involving only number literals.
462 double value = literal->AsNumber();
463 bool has_dot = literal->ContainsDot();
464 switch (op) {
465 case Token::ADD:
466 return expression;
467 case Token::SUB:
468 return factory->NewNumberLiteral(-value, pos, has_dot);
469 case Token::BIT_NOT:
470 return factory->NewNumberLiteral(~DoubleToInt32(value), pos, has_dot);
471 default:
472 break;
473 }
474 }
475 }
476 // Desugar '+foo' => 'foo*1'
477 if (op == Token::ADD) {
478 return factory->NewBinaryOperation(
479 Token::MUL, expression, factory->NewNumberLiteral(1, pos, true), pos);
480 }
481 // The same idea for '-foo' => 'foo*(-1)'.
482 if (op == Token::SUB) {
483 return factory->NewBinaryOperation(
484 Token::MUL, expression, factory->NewNumberLiteral(-1, pos), pos);
485 }
486 // ...and one more time for '~foo' => 'foo^(~0)'.
487 if (op == Token::BIT_NOT) {
488 return factory->NewBinaryOperation(
489 Token::BIT_XOR, expression, factory->NewNumberLiteral(~0, pos), pos);
490 }
491 return factory->NewUnaryOperation(op, expression, pos);
492}
493
494
495Expression* ParserTraits::NewThrowReferenceError(
496 MessageTemplate::Template message, int pos) {
497 return NewThrowError(Runtime::kNewReferenceError, message,
498 parser_->ast_value_factory()->empty_string(), pos);
499}
500
501
502Expression* ParserTraits::NewThrowSyntaxError(MessageTemplate::Template message,
503 const AstRawString* arg,
504 int pos) {
505 return NewThrowError(Runtime::kNewSyntaxError, message, arg, pos);
506}
507
508
509Expression* ParserTraits::NewThrowTypeError(MessageTemplate::Template message,
510 const AstRawString* arg, int pos) {
511 return NewThrowError(Runtime::kNewTypeError, message, arg, pos);
512}
513
514
515Expression* ParserTraits::NewThrowError(Runtime::FunctionId id,
516 MessageTemplate::Template message,
517 const AstRawString* arg, int pos) {
518 Zone* zone = parser_->zone();
519 ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(2, zone);
520 args->Add(parser_->factory()->NewSmiLiteral(message, pos), zone);
521 args->Add(parser_->factory()->NewStringLiteral(arg, pos), zone);
522 CallRuntime* call_constructor =
523 parser_->factory()->NewCallRuntime(id, args, pos);
524 return parser_->factory()->NewThrow(call_constructor, pos);
525}
526
527
528void ParserTraits::ReportMessageAt(Scanner::Location source_location,
529 MessageTemplate::Template message,
530 const char* arg, ParseErrorType error_type) {
531 if (parser_->stack_overflow()) {
532 // Suppress the error message (syntax error or such) in the presence of a
533 // stack overflow. The isolate allows only one pending exception at at time
534 // and we want to report the stack overflow later.
535 return;
536 }
537 parser_->pending_error_handler_.ReportMessageAt(source_location.beg_pos,
538 source_location.end_pos,
539 message, arg, error_type);
540}
541
542
543void ParserTraits::ReportMessage(MessageTemplate::Template message,
544 const char* arg, ParseErrorType error_type) {
545 Scanner::Location source_location = parser_->scanner()->location();
546 ReportMessageAt(source_location, message, arg, error_type);
547}
548
549
550void ParserTraits::ReportMessage(MessageTemplate::Template message,
551 const AstRawString* arg,
552 ParseErrorType error_type) {
553 Scanner::Location source_location = parser_->scanner()->location();
554 ReportMessageAt(source_location, message, arg, error_type);
555}
556
557
558void ParserTraits::ReportMessageAt(Scanner::Location source_location,
559 MessageTemplate::Template message,
560 const AstRawString* arg,
561 ParseErrorType error_type) {
562 if (parser_->stack_overflow()) {
563 // Suppress the error message (syntax error or such) in the presence of a
564 // stack overflow. The isolate allows only one pending exception at at time
565 // and we want to report the stack overflow later.
566 return;
567 }
568 parser_->pending_error_handler_.ReportMessageAt(source_location.beg_pos,
569 source_location.end_pos,
570 message, arg, error_type);
571}
572
573
574const AstRawString* ParserTraits::GetSymbol(Scanner* scanner) {
575 const AstRawString* result =
576 parser_->scanner()->CurrentSymbol(parser_->ast_value_factory());
577 DCHECK(result != NULL);
578 return result;
579}
580
581
582const AstRawString* ParserTraits::GetNumberAsSymbol(Scanner* scanner) {
583 double double_value = parser_->scanner()->DoubleValue();
584 char array[100];
585 const char* string =
586 DoubleToCString(double_value, Vector<char>(array, arraysize(array)));
587 return parser_->ast_value_factory()->GetOneByteString(string);
588}
589
590
591const AstRawString* ParserTraits::GetNextSymbol(Scanner* scanner) {
592 return parser_->scanner()->NextSymbol(parser_->ast_value_factory());
593}
594
595
596Expression* ParserTraits::ThisExpression(Scope* scope, AstNodeFactory* factory,
597 int pos) {
598 return scope->NewUnresolved(factory,
599 parser_->ast_value_factory()->this_string(),
600 Variable::THIS, pos, pos + 4);
601}
602
603
604Expression* ParserTraits::SuperPropertyReference(Scope* scope,
605 AstNodeFactory* factory,
606 int pos) {
607 // this_function[home_object_symbol]
608 VariableProxy* this_function_proxy = scope->NewUnresolved(
609 factory, parser_->ast_value_factory()->this_function_string(),
610 Variable::NORMAL, pos);
611 Expression* home_object_symbol_literal =
612 factory->NewSymbolLiteral("home_object_symbol", RelocInfo::kNoPosition);
613 Expression* home_object = factory->NewProperty(
614 this_function_proxy, home_object_symbol_literal, pos);
615 return factory->NewSuperPropertyReference(
616 ThisExpression(scope, factory, pos)->AsVariableProxy(), home_object, pos);
617}
618
619
620Expression* ParserTraits::SuperCallReference(Scope* scope,
621 AstNodeFactory* factory, int pos) {
622 VariableProxy* new_target_proxy = scope->NewUnresolved(
623 factory, parser_->ast_value_factory()->new_target_string(),
624 Variable::NORMAL, pos);
625 VariableProxy* this_function_proxy = scope->NewUnresolved(
626 factory, parser_->ast_value_factory()->this_function_string(),
627 Variable::NORMAL, pos);
628 return factory->NewSuperCallReference(
629 ThisExpression(scope, factory, pos)->AsVariableProxy(), new_target_proxy,
630 this_function_proxy, pos);
631}
632
633
634Expression* ParserTraits::NewTargetExpression(Scope* scope,
635 AstNodeFactory* factory,
636 int pos) {
637 static const int kNewTargetStringLength = 10;
638 auto proxy = scope->NewUnresolved(
639 factory, parser_->ast_value_factory()->new_target_string(),
640 Variable::NORMAL, pos, pos + kNewTargetStringLength);
641 proxy->set_is_new_target();
642 return proxy;
643}
644
645
Ben Murdoch097c5b22016-05-18 11:27:45 +0100646Expression* ParserTraits::FunctionSentExpression(Scope* scope,
647 AstNodeFactory* factory,
648 int pos) {
649 // We desugar function.sent into %GeneratorGetInput(generator).
650 Zone* zone = parser_->zone();
651 ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(1, zone);
652 VariableProxy* generator = factory->NewVariableProxy(
653 parser_->function_state_->generator_object_variable());
654 args->Add(generator, zone);
655 return factory->NewCallRuntime(Runtime::kGeneratorGetInput, args, pos);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000656}
657
658
659Literal* ParserTraits::ExpressionFromLiteral(Token::Value token, int pos,
660 Scanner* scanner,
661 AstNodeFactory* factory) {
662 switch (token) {
663 case Token::NULL_LITERAL:
664 return factory->NewNullLiteral(pos);
665 case Token::TRUE_LITERAL:
666 return factory->NewBooleanLiteral(true, pos);
667 case Token::FALSE_LITERAL:
668 return factory->NewBooleanLiteral(false, pos);
669 case Token::SMI: {
670 int value = scanner->smi_value();
671 return factory->NewSmiLiteral(value, pos);
672 }
673 case Token::NUMBER: {
674 bool has_dot = scanner->ContainsDot();
675 double value = scanner->DoubleValue();
676 return factory->NewNumberLiteral(value, pos, has_dot);
677 }
678 default:
679 DCHECK(false);
680 }
681 return NULL;
682}
683
684
685Expression* ParserTraits::ExpressionFromIdentifier(const AstRawString* name,
686 int start_position,
687 int end_position,
688 Scope* scope,
689 AstNodeFactory* factory) {
690 if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name);
691 return scope->NewUnresolved(factory, name, Variable::NORMAL, start_position,
692 end_position);
693}
694
695
696Expression* ParserTraits::ExpressionFromString(int pos, Scanner* scanner,
697 AstNodeFactory* factory) {
698 const AstRawString* symbol = GetSymbol(scanner);
699 if (parser_->fni_ != NULL) parser_->fni_->PushLiteralName(symbol);
700 return factory->NewStringLiteral(symbol, pos);
701}
702
703
704Expression* ParserTraits::GetIterator(Expression* iterable,
705 AstNodeFactory* factory, int pos) {
706 Expression* iterator_symbol_literal =
707 factory->NewSymbolLiteral("iterator_symbol", RelocInfo::kNoPosition);
708 Expression* prop =
709 factory->NewProperty(iterable, iterator_symbol_literal, pos);
710 Zone* zone = parser_->zone();
711 ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(0, zone);
712 return factory->NewCall(prop, args, pos);
713}
714
715
716Literal* ParserTraits::GetLiteralTheHole(int position,
717 AstNodeFactory* factory) {
718 return factory->NewTheHoleLiteral(RelocInfo::kNoPosition);
719}
720
721
722Expression* ParserTraits::ParseV8Intrinsic(bool* ok) {
723 return parser_->ParseV8Intrinsic(ok);
724}
725
726
727FunctionLiteral* ParserTraits::ParseFunctionLiteral(
728 const AstRawString* name, Scanner::Location function_name_location,
729 FunctionNameValidity function_name_validity, FunctionKind kind,
730 int function_token_position, FunctionLiteral::FunctionType type,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000731 LanguageMode language_mode, bool* ok) {
732 return parser_->ParseFunctionLiteral(
733 name, function_name_location, function_name_validity, kind,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100734 function_token_position, type, language_mode, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000735}
736
737
738ClassLiteral* ParserTraits::ParseClassLiteral(
739 const AstRawString* name, Scanner::Location class_name_location,
740 bool name_is_strict_reserved, int pos, bool* ok) {
741 return parser_->ParseClassLiteral(name, class_name_location,
742 name_is_strict_reserved, pos, ok);
743}
744
745
746Parser::Parser(ParseInfo* info)
747 : ParserBase<ParserTraits>(info->zone(), &scanner_, info->stack_limit(),
748 info->extension(), info->ast_value_factory(),
749 NULL, this),
750 scanner_(info->unicode_cache()),
751 reusable_preparser_(NULL),
752 original_scope_(NULL),
753 target_stack_(NULL),
754 compile_options_(info->compile_options()),
755 cached_parse_data_(NULL),
756 total_preparse_skipped_(0),
757 pre_parse_timer_(NULL),
758 parsing_on_main_thread_(true) {
759 // Even though we were passed ParseInfo, we should not store it in
760 // Parser - this makes sure that Isolate is not accidentally accessed via
761 // ParseInfo during background parsing.
762 DCHECK(!info->script().is_null() || info->source_stream() != NULL);
763 set_allow_lazy(info->allow_lazy_parsing());
764 set_allow_natives(FLAG_allow_natives_syntax || info->is_native());
765 set_allow_harmony_sloppy(FLAG_harmony_sloppy);
766 set_allow_harmony_sloppy_function(FLAG_harmony_sloppy_function);
767 set_allow_harmony_sloppy_let(FLAG_harmony_sloppy_let);
768 set_allow_harmony_default_parameters(FLAG_harmony_default_parameters);
769 set_allow_harmony_destructuring_bind(FLAG_harmony_destructuring_bind);
770 set_allow_harmony_destructuring_assignment(
771 FLAG_harmony_destructuring_assignment);
772 set_allow_strong_mode(FLAG_strong_mode);
773 set_allow_legacy_const(FLAG_legacy_const);
774 set_allow_harmony_do_expressions(FLAG_harmony_do_expressions);
775 set_allow_harmony_function_name(FLAG_harmony_function_name);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100776 set_allow_harmony_function_sent(FLAG_harmony_function_sent);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000777 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
778 ++feature) {
779 use_counts_[feature] = 0;
780 }
781 if (info->ast_value_factory() == NULL) {
782 // info takes ownership of AstValueFactory.
783 info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed()));
784 info->set_ast_value_factory_owned();
785 ast_value_factory_ = info->ast_value_factory();
786 }
787}
788
789
790FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {
791 // TODO(bmeurer): We temporarily need to pass allow_nesting = true here,
792 // see comment for HistogramTimerScope class.
793
794 // It's OK to use the Isolate & counters here, since this function is only
795 // called in the main thread.
796 DCHECK(parsing_on_main_thread_);
797
798 HistogramTimerScope timer_scope(isolate->counters()->parse(), true);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100799 TRACE_EVENT0("v8", "V8.Parse");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000800 Handle<String> source(String::cast(info->script()->source()));
801 isolate->counters()->total_parse_size()->Increment(source->length());
802 base::ElapsedTimer timer;
803 if (FLAG_trace_parse) {
804 timer.Start();
805 }
806 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
807
808 // Initialize parser state.
809 CompleteParserRecorder recorder;
810
811 if (produce_cached_parse_data()) {
812 log_ = &recorder;
813 } else if (consume_cached_parse_data()) {
814 cached_parse_data_->Initialize();
815 }
816
817 source = String::Flatten(source);
818 FunctionLiteral* result;
819
820 if (source->IsExternalTwoByteString()) {
821 // Notice that the stream is destroyed at the end of the branch block.
822 // The last line of the blocks can't be moved outside, even though they're
823 // identical calls.
824 ExternalTwoByteStringUtf16CharacterStream stream(
825 Handle<ExternalTwoByteString>::cast(source), 0, source->length());
826 scanner_.Initialize(&stream);
827 result = DoParseProgram(info);
828 } else {
829 GenericStringUtf16CharacterStream stream(source, 0, source->length());
830 scanner_.Initialize(&stream);
831 result = DoParseProgram(info);
832 }
833 if (result != NULL) {
834 DCHECK_EQ(scanner_.peek_location().beg_pos, source->length());
835 }
836 HandleSourceURLComments(isolate, info->script());
837
838 if (FLAG_trace_parse && result != NULL) {
839 double ms = timer.Elapsed().InMillisecondsF();
840 if (info->is_eval()) {
841 PrintF("[parsing eval");
842 } else if (info->script()->name()->IsString()) {
843 String* name = String::cast(info->script()->name());
844 base::SmartArrayPointer<char> name_chars = name->ToCString();
845 PrintF("[parsing script: %s", name_chars.get());
846 } else {
847 PrintF("[parsing script");
848 }
849 PrintF(" - took %0.3f ms]\n", ms);
850 }
851 if (produce_cached_parse_data()) {
852 if (result != NULL) *info->cached_data() = recorder.GetScriptData();
853 log_ = NULL;
854 }
855 return result;
856}
857
858
859FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
860 // Note that this function can be called from the main thread or from a
861 // background thread. We should not access anything Isolate / heap dependent
862 // via ParseInfo, and also not pass it forward.
863 DCHECK(scope_ == NULL);
864 DCHECK(target_stack_ == NULL);
865
866 Mode parsing_mode = FLAG_lazy && allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY;
867 if (allow_natives() || extension_ != NULL) parsing_mode = PARSE_EAGERLY;
868
869 FunctionLiteral* result = NULL;
870 {
871 // TODO(wingo): Add an outer SCRIPT_SCOPE corresponding to the native
872 // context, which will have the "this" binding for script scopes.
873 Scope* scope = NewScope(scope_, SCRIPT_SCOPE);
874 info->set_script_scope(scope);
875 if (!info->context().is_null() && !info->context()->IsNativeContext()) {
876 scope = Scope::DeserializeScopeChain(info->isolate(), zone(),
877 *info->context(), scope);
878 // The Scope is backed up by ScopeInfo (which is in the V8 heap); this
879 // means the Parser cannot operate independent of the V8 heap. Tell the
880 // string table to internalize strings and values right after they're
881 // created. This kind of parsing can only be done in the main thread.
882 DCHECK(parsing_on_main_thread_);
883 ast_value_factory()->Internalize(info->isolate());
884 }
885 original_scope_ = scope;
886 if (info->is_eval()) {
887 if (!scope->is_script_scope() || is_strict(info->language_mode())) {
888 parsing_mode = PARSE_EAGERLY;
889 }
890 scope = NewScope(scope, EVAL_SCOPE);
891 } else if (info->is_module()) {
892 scope = NewScope(scope, MODULE_SCOPE);
893 }
894
895 scope->set_start_position(0);
896
897 // Enter 'scope' with the given parsing mode.
898 ParsingModeScope parsing_mode_scope(this, parsing_mode);
899 AstNodeFactory function_factory(ast_value_factory());
900 FunctionState function_state(&function_state_, &scope_, scope,
901 kNormalFunction, &function_factory);
902
903 // Don't count the mode in the use counters--give the program a chance
904 // to enable script/module-wide strict/strong mode below.
905 scope_->SetLanguageMode(info->language_mode());
906 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
907 bool ok = true;
908 int beg_pos = scanner()->location().beg_pos;
909 if (info->is_module()) {
910 ParseModuleItemList(body, &ok);
911 } else {
912 ParseStatementList(body, Token::EOS, &ok);
913 }
914
915 // The parser will peek but not consume EOS. Our scope logically goes all
916 // the way to the EOS, though.
917 scope->set_end_position(scanner()->peek_location().beg_pos);
918
919 if (ok && is_strict(language_mode())) {
920 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
921 }
922 if (ok && is_sloppy(language_mode()) && allow_harmony_sloppy_function()) {
923 // TODO(littledan): Function bindings on the global object that modify
924 // pre-existing bindings should be made writable, enumerable and
925 // nonconfigurable if possible, whereas this code will leave attributes
926 // unchanged if the property already exists.
927 InsertSloppyBlockFunctionVarBindings(scope, &ok);
928 }
929 if (ok && (is_strict(language_mode()) || allow_harmony_sloppy() ||
930 allow_harmony_destructuring_bind())) {
931 CheckConflictingVarDeclarations(scope_, &ok);
932 }
933
934 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) {
935 if (body->length() != 1 ||
936 !body->at(0)->IsExpressionStatement() ||
937 !body->at(0)->AsExpressionStatement()->
938 expression()->IsFunctionLiteral()) {
939 ReportMessage(MessageTemplate::kSingleFunctionLiteral);
940 ok = false;
941 }
942 }
943
944 if (ok) {
945 ParserTraits::RewriteDestructuringAssignments();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100946 result = factory()->NewScriptOrEvalFunctionLiteral(
947 scope_, body, function_state.materialized_literal_count(),
948 function_state.expected_property_count());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000949 }
950 }
951
952 // Make sure the target stack is empty.
953 DCHECK(target_stack_ == NULL);
954
955 return result;
956}
957
958
959FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info) {
960 // It's OK to use the Isolate & counters here, since this function is only
961 // called in the main thread.
962 DCHECK(parsing_on_main_thread_);
963 HistogramTimerScope timer_scope(isolate->counters()->parse_lazy());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100964 TRACE_EVENT0("v8", "V8.ParseLazy");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000965 Handle<String> source(String::cast(info->script()->source()));
966 isolate->counters()->total_parse_size()->Increment(source->length());
967 base::ElapsedTimer timer;
968 if (FLAG_trace_parse) {
969 timer.Start();
970 }
971 Handle<SharedFunctionInfo> shared_info = info->shared_info();
972
973 // Initialize parser state.
974 source = String::Flatten(source);
975 FunctionLiteral* result;
976 if (source->IsExternalTwoByteString()) {
977 ExternalTwoByteStringUtf16CharacterStream stream(
978 Handle<ExternalTwoByteString>::cast(source),
979 shared_info->start_position(),
980 shared_info->end_position());
981 result = ParseLazy(isolate, info, &stream);
982 } else {
983 GenericStringUtf16CharacterStream stream(source,
984 shared_info->start_position(),
985 shared_info->end_position());
986 result = ParseLazy(isolate, info, &stream);
987 }
988
989 if (FLAG_trace_parse && result != NULL) {
990 double ms = timer.Elapsed().InMillisecondsF();
991 base::SmartArrayPointer<char> name_chars =
992 result->debug_name()->ToCString();
993 PrintF("[parsing function: %s - took %0.3f ms]\n", name_chars.get(), ms);
994 }
995 return result;
996}
997
Ben Murdoch097c5b22016-05-18 11:27:45 +0100998static FunctionLiteral::FunctionType ComputeFunctionType(
999 Handle<SharedFunctionInfo> shared_info) {
1000 if (shared_info->is_declaration()) {
1001 return FunctionLiteral::kDeclaration;
1002 } else if (shared_info->is_named_expression()) {
1003 return FunctionLiteral::kNamedExpression;
1004 } else if (IsConciseMethod(shared_info->kind()) ||
1005 IsAccessorFunction(shared_info->kind())) {
1006 return FunctionLiteral::kAccessorOrMethod;
1007 }
1008 return FunctionLiteral::kAnonymousExpression;
1009}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001010
1011FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
1012 Utf16CharacterStream* source) {
1013 Handle<SharedFunctionInfo> shared_info = info->shared_info();
1014 scanner_.Initialize(source);
1015 DCHECK(scope_ == NULL);
1016 DCHECK(target_stack_ == NULL);
1017
1018 Handle<String> name(String::cast(shared_info->name()));
1019 DCHECK(ast_value_factory());
1020 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
1021 const AstRawString* raw_name = ast_value_factory()->GetString(name);
1022 fni_->PushEnclosingName(raw_name);
1023
1024 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
1025
1026 // Place holder for the result.
1027 FunctionLiteral* result = NULL;
1028
1029 {
1030 // Parse the function literal.
1031 Scope* scope = NewScope(scope_, SCRIPT_SCOPE);
1032 info->set_script_scope(scope);
1033 if (!info->closure().is_null()) {
1034 // Ok to use Isolate here, since lazy function parsing is only done in the
1035 // main thread.
1036 DCHECK(parsing_on_main_thread_);
1037 scope = Scope::DeserializeScopeChain(isolate, zone(),
1038 info->closure()->context(), scope);
1039 }
1040 original_scope_ = scope;
1041 AstNodeFactory function_factory(ast_value_factory());
1042 FunctionState function_state(&function_state_, &scope_, scope,
1043 shared_info->kind(), &function_factory);
1044 DCHECK(is_sloppy(scope->language_mode()) ||
1045 is_strict(info->language_mode()));
1046 DCHECK(info->language_mode() == shared_info->language_mode());
1047 FunctionLiteral::FunctionType function_type =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001048 ComputeFunctionType(shared_info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001049 bool ok = true;
1050
1051 if (shared_info->is_arrow()) {
1052 // TODO(adamk): We should construct this scope from the ScopeInfo.
1053 Scope* scope =
1054 NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction);
1055
1056 // These two bits only need to be explicitly set because we're
1057 // not passing the ScopeInfo to the Scope constructor.
1058 // TODO(adamk): Remove these calls once the above NewScope call
1059 // passes the ScopeInfo.
1060 if (shared_info->scope_info()->CallsEval()) {
1061 scope->RecordEvalCall();
1062 }
1063 SetLanguageMode(scope, shared_info->language_mode());
1064
1065 scope->set_start_position(shared_info->start_position());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001066 ExpressionClassifier formals_classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001067 ParserFormalParameters formals(scope);
1068 Checkpoint checkpoint(this);
1069 {
1070 // Parsing patterns as variable reference expression creates
1071 // NewUnresolved references in current scope. Entrer arrow function
1072 // scope for formal parameter parsing.
1073 BlockState block_state(&scope_, scope);
1074 if (Check(Token::LPAREN)) {
1075 // '(' StrictFormalParameters ')'
1076 ParseFormalParameterList(&formals, &formals_classifier, &ok);
1077 if (ok) ok = Check(Token::RPAREN);
1078 } else {
1079 // BindingIdentifier
1080 ParseFormalParameter(&formals, &formals_classifier, &ok);
1081 if (ok) {
1082 DeclareFormalParameter(formals.scope, formals.at(0),
1083 &formals_classifier);
1084 }
1085 }
1086 }
1087
1088 if (ok) {
1089 checkpoint.Restore(&formals.materialized_literals_count);
1090 // Pass `accept_IN=true` to ParseArrowFunctionLiteral --- This should
1091 // not be observable, or else the preparser would have failed.
1092 Expression* expression =
1093 ParseArrowFunctionLiteral(true, formals, formals_classifier, &ok);
1094 if (ok) {
1095 // Scanning must end at the same position that was recorded
1096 // previously. If not, parsing has been interrupted due to a stack
1097 // overflow, at which point the partially parsed arrow function
1098 // concise body happens to be a valid expression. This is a problem
1099 // only for arrow functions with single expression bodies, since there
1100 // is no end token such as "}" for normal functions.
1101 if (scanner()->location().end_pos == shared_info->end_position()) {
1102 // The pre-parser saw an arrow function here, so the full parser
1103 // must produce a FunctionLiteral.
1104 DCHECK(expression->IsFunctionLiteral());
1105 result = expression->AsFunctionLiteral();
1106 } else {
1107 ok = false;
1108 }
1109 }
1110 }
1111 } else if (shared_info->is_default_constructor()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001112 result = DefaultConstructor(
1113 raw_name, IsSubclassConstructor(shared_info->kind()), scope,
1114 shared_info->start_position(), shared_info->end_position(),
1115 shared_info->language_mode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001116 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001117 result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(),
1118 kSkipFunctionNameCheck, shared_info->kind(),
1119 RelocInfo::kNoPosition, function_type,
1120 shared_info->language_mode(), &ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001121 }
1122 // Make sure the results agree.
1123 DCHECK(ok == (result != NULL));
1124 }
1125
1126 // Make sure the target stack is empty.
1127 DCHECK(target_stack_ == NULL);
1128
1129 if (result != NULL) {
1130 Handle<String> inferred_name(shared_info->inferred_name());
1131 result->set_inferred_name(inferred_name);
1132 }
1133 return result;
1134}
1135
1136
1137void* Parser::ParseStatementList(ZoneList<Statement*>* body, int end_token,
1138 bool* ok) {
1139 // StatementList ::
1140 // (StatementListItem)* <end_token>
1141
1142 // Allocate a target stack to use for this set of source
1143 // elements. This way, all scripts and functions get their own
1144 // target stack thus avoiding illegal breaks and continues across
1145 // functions.
1146 TargetScope scope(&this->target_stack_);
1147
1148 DCHECK(body != NULL);
1149 bool directive_prologue = true; // Parsing directive prologue.
1150
1151 while (peek() != end_token) {
1152 if (directive_prologue && peek() != Token::STRING) {
1153 directive_prologue = false;
1154 }
1155
1156 Scanner::Location token_loc = scanner()->peek_location();
1157 Scanner::Location old_this_loc = function_state_->this_location();
1158 Scanner::Location old_super_loc = function_state_->super_location();
1159 Statement* stat = ParseStatementListItem(CHECK_OK);
1160
1161 if (is_strong(language_mode()) && scope_->is_function_scope() &&
1162 IsClassConstructor(function_state_->kind())) {
1163 Scanner::Location this_loc = function_state_->this_location();
1164 Scanner::Location super_loc = function_state_->super_location();
1165 if (this_loc.beg_pos != old_this_loc.beg_pos &&
1166 this_loc.beg_pos != token_loc.beg_pos) {
1167 ReportMessageAt(this_loc, MessageTemplate::kStrongConstructorThis);
1168 *ok = false;
1169 return nullptr;
1170 }
1171 if (super_loc.beg_pos != old_super_loc.beg_pos &&
1172 super_loc.beg_pos != token_loc.beg_pos) {
1173 ReportMessageAt(super_loc, MessageTemplate::kStrongConstructorSuper);
1174 *ok = false;
1175 return nullptr;
1176 }
1177 }
1178
1179 if (stat == NULL || stat->IsEmpty()) {
1180 directive_prologue = false; // End of directive prologue.
1181 continue;
1182 }
1183
1184 if (directive_prologue) {
1185 // A shot at a directive.
1186 ExpressionStatement* e_stat;
1187 Literal* literal;
1188 // Still processing directive prologue?
1189 if ((e_stat = stat->AsExpressionStatement()) != NULL &&
1190 (literal = e_stat->expression()->AsLiteral()) != NULL &&
1191 literal->raw_value()->IsString()) {
1192 // Check "use strict" directive (ES5 14.1), "use asm" directive, and
1193 // "use strong" directive (experimental).
1194 bool use_strict_found =
1195 literal->raw_value()->AsString() ==
1196 ast_value_factory()->use_strict_string() &&
1197 token_loc.end_pos - token_loc.beg_pos ==
1198 ast_value_factory()->use_strict_string()->length() + 2;
1199 bool use_strong_found =
1200 allow_strong_mode() &&
1201 literal->raw_value()->AsString() ==
1202 ast_value_factory()->use_strong_string() &&
1203 token_loc.end_pos - token_loc.beg_pos ==
1204 ast_value_factory()->use_strong_string()->length() + 2;
1205 if (use_strict_found || use_strong_found) {
1206 // Strong mode implies strict mode. If there are several "use strict"
1207 // / "use strong" directives, do the strict mode changes only once.
1208 if (is_sloppy(scope_->language_mode())) {
1209 RaiseLanguageMode(STRICT);
1210 }
1211
1212 if (use_strong_found) {
1213 RaiseLanguageMode(STRONG);
1214 if (IsClassConstructor(function_state_->kind())) {
1215 // "use strong" cannot occur in a class constructor body, to avoid
1216 // unintuitive strong class object semantics.
1217 ParserTraits::ReportMessageAt(
1218 token_loc, MessageTemplate::kStrongConstructorDirective);
1219 *ok = false;
1220 return nullptr;
1221 }
1222 }
1223 if (!scope_->HasSimpleParameters()) {
1224 // TC39 deemed "use strict" directives to be an error when occurring
1225 // in the body of a function with non-simple parameter list, on
1226 // 29/7/2015. https://goo.gl/ueA7Ln
1227 //
1228 // In V8, this also applies to "use strong " directives.
1229 const AstRawString* string = literal->raw_value()->AsString();
1230 ParserTraits::ReportMessageAt(
1231 token_loc, MessageTemplate::kIllegalLanguageModeDirective,
1232 string);
1233 *ok = false;
1234 return nullptr;
1235 }
1236 // Because declarations in strict eval code don't leak into the scope
1237 // of the eval call, it is likely that functions declared in strict
1238 // eval code will be used within the eval code, so lazy parsing is
1239 // probably not a win.
1240 if (scope_->is_eval_scope()) mode_ = PARSE_EAGERLY;
1241 } else if (literal->raw_value()->AsString() ==
1242 ast_value_factory()->use_asm_string() &&
1243 token_loc.end_pos - token_loc.beg_pos ==
1244 ast_value_factory()->use_asm_string()->length() + 2) {
1245 // Store the usage count; The actual use counter on the isolate is
1246 // incremented after parsing is done.
1247 ++use_counts_[v8::Isolate::kUseAsm];
1248 scope_->SetAsmModule();
1249 } else {
1250 // Should not change mode, but will increment UseCounter
1251 // if appropriate. Ditto usages below.
1252 RaiseLanguageMode(SLOPPY);
1253 }
1254 } else {
1255 // End of the directive prologue.
1256 directive_prologue = false;
1257 RaiseLanguageMode(SLOPPY);
1258 }
1259 } else {
1260 RaiseLanguageMode(SLOPPY);
1261 }
1262
1263 body->Add(stat, zone());
1264 }
1265
1266 return 0;
1267}
1268
1269
1270Statement* Parser::ParseStatementListItem(bool* ok) {
1271 // (Ecma 262 6th Edition, 13.1):
1272 // StatementListItem:
1273 // Statement
1274 // Declaration
1275
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001276 switch (peek()) {
1277 case Token::FUNCTION:
1278 return ParseFunctionDeclaration(NULL, ok);
1279 case Token::CLASS:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001280 Consume(Token::CLASS);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001281 return ParseClassDeclaration(NULL, ok);
1282 case Token::CONST:
1283 if (allow_const()) {
1284 return ParseVariableStatement(kStatementListItem, NULL, ok);
1285 }
1286 break;
1287 case Token::VAR:
1288 return ParseVariableStatement(kStatementListItem, NULL, ok);
1289 case Token::LET:
1290 if (IsNextLetKeyword()) {
1291 return ParseVariableStatement(kStatementListItem, NULL, ok);
1292 }
1293 break;
1294 default:
1295 break;
1296 }
1297 return ParseStatement(NULL, ok);
1298}
1299
1300
1301Statement* Parser::ParseModuleItem(bool* ok) {
1302 // (Ecma 262 6th Edition, 15.2):
1303 // ModuleItem :
1304 // ImportDeclaration
1305 // ExportDeclaration
1306 // StatementListItem
1307
1308 switch (peek()) {
1309 case Token::IMPORT:
1310 return ParseImportDeclaration(ok);
1311 case Token::EXPORT:
1312 return ParseExportDeclaration(ok);
1313 default:
1314 return ParseStatementListItem(ok);
1315 }
1316}
1317
1318
1319void* Parser::ParseModuleItemList(ZoneList<Statement*>* body, bool* ok) {
1320 // (Ecma 262 6th Edition, 15.2):
1321 // Module :
1322 // ModuleBody?
1323 //
1324 // ModuleBody :
1325 // ModuleItem*
1326
1327 DCHECK(scope_->is_module_scope());
1328 RaiseLanguageMode(STRICT);
1329
1330 while (peek() != Token::EOS) {
1331 Statement* stat = ParseModuleItem(CHECK_OK);
1332 if (stat && !stat->IsEmpty()) {
1333 body->Add(stat, zone());
1334 }
1335 }
1336
1337 // Check that all exports are bound.
1338 ModuleDescriptor* descriptor = scope_->module();
1339 for (ModuleDescriptor::Iterator it = descriptor->iterator(); !it.done();
1340 it.Advance()) {
1341 if (scope_->LookupLocal(it.local_name()) == NULL) {
1342 // TODO(adamk): Pass both local_name and export_name once ParserTraits
1343 // supports multiple arg error messages.
1344 // Also try to report this at a better location.
1345 ParserTraits::ReportMessage(MessageTemplate::kModuleExportUndefined,
1346 it.local_name());
1347 *ok = false;
1348 return NULL;
1349 }
1350 }
1351
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001352 return NULL;
1353}
1354
1355
1356const AstRawString* Parser::ParseModuleSpecifier(bool* ok) {
1357 // ModuleSpecifier :
1358 // StringLiteral
1359
1360 Expect(Token::STRING, CHECK_OK);
1361 return GetSymbol(scanner());
1362}
1363
1364
1365void* Parser::ParseExportClause(ZoneList<const AstRawString*>* export_names,
1366 ZoneList<Scanner::Location>* export_locations,
1367 ZoneList<const AstRawString*>* local_names,
1368 Scanner::Location* reserved_loc, bool* ok) {
1369 // ExportClause :
1370 // '{' '}'
1371 // '{' ExportsList '}'
1372 // '{' ExportsList ',' '}'
1373 //
1374 // ExportsList :
1375 // ExportSpecifier
1376 // ExportsList ',' ExportSpecifier
1377 //
1378 // ExportSpecifier :
1379 // IdentifierName
1380 // IdentifierName 'as' IdentifierName
1381
1382 Expect(Token::LBRACE, CHECK_OK);
1383
1384 Token::Value name_tok;
1385 while ((name_tok = peek()) != Token::RBRACE) {
1386 // Keep track of the first reserved word encountered in case our
1387 // caller needs to report an error.
1388 if (!reserved_loc->IsValid() &&
1389 !Token::IsIdentifier(name_tok, STRICT, false)) {
1390 *reserved_loc = scanner()->location();
1391 }
1392 const AstRawString* local_name = ParseIdentifierName(CHECK_OK);
1393 const AstRawString* export_name = NULL;
1394 if (CheckContextualKeyword(CStrVector("as"))) {
1395 export_name = ParseIdentifierName(CHECK_OK);
1396 }
1397 if (export_name == NULL) {
1398 export_name = local_name;
1399 }
1400 export_names->Add(export_name, zone());
1401 local_names->Add(local_name, zone());
1402 export_locations->Add(scanner()->location(), zone());
1403 if (peek() == Token::RBRACE) break;
1404 Expect(Token::COMMA, CHECK_OK);
1405 }
1406
1407 Expect(Token::RBRACE, CHECK_OK);
1408
1409 return 0;
1410}
1411
1412
1413ZoneList<ImportDeclaration*>* Parser::ParseNamedImports(int pos, bool* ok) {
1414 // NamedImports :
1415 // '{' '}'
1416 // '{' ImportsList '}'
1417 // '{' ImportsList ',' '}'
1418 //
1419 // ImportsList :
1420 // ImportSpecifier
1421 // ImportsList ',' ImportSpecifier
1422 //
1423 // ImportSpecifier :
1424 // BindingIdentifier
1425 // IdentifierName 'as' BindingIdentifier
1426
1427 Expect(Token::LBRACE, CHECK_OK);
1428
1429 ZoneList<ImportDeclaration*>* result =
1430 new (zone()) ZoneList<ImportDeclaration*>(1, zone());
1431 while (peek() != Token::RBRACE) {
1432 const AstRawString* import_name = ParseIdentifierName(CHECK_OK);
1433 const AstRawString* local_name = import_name;
1434 // In the presence of 'as', the left-side of the 'as' can
1435 // be any IdentifierName. But without 'as', it must be a valid
1436 // BindingIdentifier.
1437 if (CheckContextualKeyword(CStrVector("as"))) {
1438 local_name = ParseIdentifierName(CHECK_OK);
1439 }
1440 if (!Token::IsIdentifier(scanner()->current_token(), STRICT, false)) {
1441 *ok = false;
1442 ReportMessage(MessageTemplate::kUnexpectedReserved);
1443 return NULL;
1444 } else if (IsEvalOrArguments(local_name)) {
1445 *ok = false;
1446 ReportMessage(MessageTemplate::kStrictEvalArguments);
1447 return NULL;
1448 } else if (is_strong(language_mode()) && IsUndefined(local_name)) {
1449 *ok = false;
1450 ReportMessage(MessageTemplate::kStrongUndefined);
1451 return NULL;
1452 }
1453 VariableProxy* proxy = NewUnresolved(local_name, IMPORT);
1454 ImportDeclaration* declaration =
1455 factory()->NewImportDeclaration(proxy, import_name, NULL, scope_, pos);
1456 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
1457 result->Add(declaration, zone());
1458 if (peek() == Token::RBRACE) break;
1459 Expect(Token::COMMA, CHECK_OK);
1460 }
1461
1462 Expect(Token::RBRACE, CHECK_OK);
1463
1464 return result;
1465}
1466
1467
1468Statement* Parser::ParseImportDeclaration(bool* ok) {
1469 // ImportDeclaration :
1470 // 'import' ImportClause 'from' ModuleSpecifier ';'
1471 // 'import' ModuleSpecifier ';'
1472 //
1473 // ImportClause :
1474 // NameSpaceImport
1475 // NamedImports
1476 // ImportedDefaultBinding
1477 // ImportedDefaultBinding ',' NameSpaceImport
1478 // ImportedDefaultBinding ',' NamedImports
1479 //
1480 // NameSpaceImport :
1481 // '*' 'as' ImportedBinding
1482
1483 int pos = peek_position();
1484 Expect(Token::IMPORT, CHECK_OK);
1485
1486 Token::Value tok = peek();
1487
1488 // 'import' ModuleSpecifier ';'
1489 if (tok == Token::STRING) {
1490 const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
1491 scope_->module()->AddModuleRequest(module_specifier, zone());
1492 ExpectSemicolon(CHECK_OK);
1493 return factory()->NewEmptyStatement(pos);
1494 }
1495
1496 // Parse ImportedDefaultBinding if present.
1497 ImportDeclaration* import_default_declaration = NULL;
1498 if (tok != Token::MUL && tok != Token::LBRACE) {
1499 const AstRawString* local_name =
1500 ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK);
1501 VariableProxy* proxy = NewUnresolved(local_name, IMPORT);
1502 import_default_declaration = factory()->NewImportDeclaration(
1503 proxy, ast_value_factory()->default_string(), NULL, scope_, pos);
1504 Declare(import_default_declaration, DeclarationDescriptor::NORMAL, true,
1505 CHECK_OK);
1506 }
1507
1508 const AstRawString* module_instance_binding = NULL;
1509 ZoneList<ImportDeclaration*>* named_declarations = NULL;
1510 if (import_default_declaration == NULL || Check(Token::COMMA)) {
1511 switch (peek()) {
1512 case Token::MUL: {
1513 Consume(Token::MUL);
1514 ExpectContextualKeyword(CStrVector("as"), CHECK_OK);
1515 module_instance_binding =
1516 ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK);
1517 // TODO(ES6): Add an appropriate declaration.
1518 break;
1519 }
1520
1521 case Token::LBRACE:
1522 named_declarations = ParseNamedImports(pos, CHECK_OK);
1523 break;
1524
1525 default:
1526 *ok = false;
1527 ReportUnexpectedToken(scanner()->current_token());
1528 return NULL;
1529 }
1530 }
1531
1532 ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
1533 const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
1534 scope_->module()->AddModuleRequest(module_specifier, zone());
1535
1536 if (module_instance_binding != NULL) {
1537 // TODO(ES6): Set the module specifier for the module namespace binding.
1538 }
1539
1540 if (import_default_declaration != NULL) {
1541 import_default_declaration->set_module_specifier(module_specifier);
1542 }
1543
1544 if (named_declarations != NULL) {
1545 for (int i = 0; i < named_declarations->length(); ++i) {
1546 named_declarations->at(i)->set_module_specifier(module_specifier);
1547 }
1548 }
1549
1550 ExpectSemicolon(CHECK_OK);
1551 return factory()->NewEmptyStatement(pos);
1552}
1553
1554
1555Statement* Parser::ParseExportDefault(bool* ok) {
1556 // Supports the following productions, starting after the 'default' token:
1557 // 'export' 'default' FunctionDeclaration
1558 // 'export' 'default' ClassDeclaration
1559 // 'export' 'default' AssignmentExpression[In] ';'
1560
1561 Expect(Token::DEFAULT, CHECK_OK);
1562 Scanner::Location default_loc = scanner()->location();
1563
Ben Murdoch097c5b22016-05-18 11:27:45 +01001564 const AstRawString* default_string = ast_value_factory()->default_string();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001565 ZoneList<const AstRawString*> names(1, zone());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001566 Statement* result = nullptr;
1567 Expression* default_export = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001568 switch (peek()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001569 case Token::FUNCTION: {
1570 Consume(Token::FUNCTION);
1571 int pos = position();
1572 bool is_generator = Check(Token::MUL);
1573 if (peek() == Token::LPAREN) {
1574 // FunctionDeclaration[+Default] ::
1575 // 'function' '(' FormalParameters ')' '{' FunctionBody '}'
1576 //
1577 // GeneratorDeclaration[+Default] ::
1578 // 'function' '*' '(' FormalParameters ')' '{' FunctionBody '}'
1579 default_export = ParseFunctionLiteral(
1580 default_string, Scanner::Location::invalid(),
1581 kSkipFunctionNameCheck,
1582 is_generator ? FunctionKind::kGeneratorFunction
1583 : FunctionKind::kNormalFunction,
1584 pos, FunctionLiteral::kDeclaration, language_mode(), CHECK_OK);
1585 result = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
1586 } else {
1587 result = ParseFunctionDeclaration(pos, is_generator, &names, CHECK_OK);
1588 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001589 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001590 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001591
1592 case Token::CLASS:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001593 Consume(Token::CLASS);
1594 if (peek() == Token::EXTENDS || peek() == Token::LBRACE) {
1595 // ClassDeclaration[+Default] ::
1596 // 'class' ('extends' LeftHandExpression)? '{' ClassBody '}'
1597 default_export =
1598 ParseClassLiteral(default_string, Scanner::Location::invalid(),
1599 false, position(), CHECK_OK);
1600 result = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
1601 } else {
1602 result = ParseClassDeclaration(&names, CHECK_OK);
1603 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001604 break;
1605
1606 default: {
1607 int pos = peek_position();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001608 ExpressionClassifier classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001609 Expression* expr = ParseAssignmentExpression(true, &classifier, CHECK_OK);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001610 RewriteNonPattern(&classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001611
1612 ExpectSemicolon(CHECK_OK);
1613 result = factory()->NewExpressionStatement(expr, pos);
1614 break;
1615 }
1616 }
1617
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001618 DCHECK_LE(names.length(), 1);
1619 if (names.length() == 1) {
1620 scope_->module()->AddLocalExport(default_string, names.first(), zone(), ok);
1621 if (!*ok) {
1622 ParserTraits::ReportMessageAt(
1623 default_loc, MessageTemplate::kDuplicateExport, default_string);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001624 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001625 }
1626 } else {
1627 // TODO(ES6): Assign result to a const binding with the name "*default*"
1628 // and add an export entry with "*default*" as the local name.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001629 USE(default_export);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001630 }
1631
1632 return result;
1633}
1634
1635
1636Statement* Parser::ParseExportDeclaration(bool* ok) {
1637 // ExportDeclaration:
1638 // 'export' '*' 'from' ModuleSpecifier ';'
1639 // 'export' ExportClause ('from' ModuleSpecifier)? ';'
1640 // 'export' VariableStatement
1641 // 'export' Declaration
1642 // 'export' 'default' ... (handled in ParseExportDefault)
1643
1644 int pos = peek_position();
1645 Expect(Token::EXPORT, CHECK_OK);
1646
1647 Statement* result = NULL;
1648 ZoneList<const AstRawString*> names(1, zone());
1649 switch (peek()) {
1650 case Token::DEFAULT:
1651 return ParseExportDefault(ok);
1652
1653 case Token::MUL: {
1654 Consume(Token::MUL);
1655 ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
1656 const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
1657 scope_->module()->AddModuleRequest(module_specifier, zone());
1658 // TODO(ES6): scope_->module()->AddStarExport(...)
1659 ExpectSemicolon(CHECK_OK);
1660 return factory()->NewEmptyStatement(pos);
1661 }
1662
1663 case Token::LBRACE: {
1664 // There are two cases here:
1665 //
1666 // 'export' ExportClause ';'
1667 // and
1668 // 'export' ExportClause FromClause ';'
1669 //
1670 // In the first case, the exported identifiers in ExportClause must
1671 // not be reserved words, while in the latter they may be. We
1672 // pass in a location that gets filled with the first reserved word
1673 // encountered, and then throw a SyntaxError if we are in the
1674 // non-FromClause case.
1675 Scanner::Location reserved_loc = Scanner::Location::invalid();
1676 ZoneList<const AstRawString*> export_names(1, zone());
1677 ZoneList<Scanner::Location> export_locations(1, zone());
1678 ZoneList<const AstRawString*> local_names(1, zone());
1679 ParseExportClause(&export_names, &export_locations, &local_names,
1680 &reserved_loc, CHECK_OK);
1681 const AstRawString* indirect_export_module_specifier = NULL;
1682 if (CheckContextualKeyword(CStrVector("from"))) {
1683 indirect_export_module_specifier = ParseModuleSpecifier(CHECK_OK);
1684 } else if (reserved_loc.IsValid()) {
1685 // No FromClause, so reserved words are invalid in ExportClause.
1686 *ok = false;
1687 ReportMessageAt(reserved_loc, MessageTemplate::kUnexpectedReserved);
1688 return NULL;
1689 }
1690 ExpectSemicolon(CHECK_OK);
1691 const int length = export_names.length();
1692 DCHECK_EQ(length, local_names.length());
1693 DCHECK_EQ(length, export_locations.length());
1694 if (indirect_export_module_specifier == NULL) {
1695 for (int i = 0; i < length; ++i) {
1696 scope_->module()->AddLocalExport(export_names[i], local_names[i],
1697 zone(), ok);
1698 if (!*ok) {
1699 ParserTraits::ReportMessageAt(export_locations[i],
1700 MessageTemplate::kDuplicateExport,
1701 export_names[i]);
1702 return NULL;
1703 }
1704 }
1705 } else {
1706 scope_->module()->AddModuleRequest(indirect_export_module_specifier,
1707 zone());
1708 for (int i = 0; i < length; ++i) {
1709 // TODO(ES6): scope_->module()->AddIndirectExport(...);(
1710 }
1711 }
1712 return factory()->NewEmptyStatement(pos);
1713 }
1714
1715 case Token::FUNCTION:
1716 result = ParseFunctionDeclaration(&names, CHECK_OK);
1717 break;
1718
1719 case Token::CLASS:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001720 Consume(Token::CLASS);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001721 result = ParseClassDeclaration(&names, CHECK_OK);
1722 break;
1723
1724 case Token::VAR:
1725 case Token::LET:
1726 case Token::CONST:
1727 result = ParseVariableStatement(kStatementListItem, &names, CHECK_OK);
1728 break;
1729
1730 default:
1731 *ok = false;
1732 ReportUnexpectedToken(scanner()->current_token());
1733 return NULL;
1734 }
1735
1736 // Extract declared names into export declarations.
1737 ModuleDescriptor* descriptor = scope_->module();
1738 for (int i = 0; i < names.length(); ++i) {
1739 descriptor->AddLocalExport(names[i], names[i], zone(), ok);
1740 if (!*ok) {
1741 // TODO(adamk): Possibly report this error at the right place.
1742 ParserTraits::ReportMessage(MessageTemplate::kDuplicateExport, names[i]);
1743 return NULL;
1744 }
1745 }
1746
1747 DCHECK_NOT_NULL(result);
1748 return result;
1749}
1750
1751
1752Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels,
1753 bool* ok) {
1754 // Statement ::
1755 // EmptyStatement
1756 // ...
1757
1758 if (peek() == Token::SEMICOLON) {
1759 Next();
1760 return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
1761 }
1762 return ParseSubStatement(labels, ok);
1763}
1764
1765
1766Statement* Parser::ParseSubStatement(ZoneList<const AstRawString*>* labels,
1767 bool* ok) {
1768 // Statement ::
1769 // Block
1770 // VariableStatement
1771 // EmptyStatement
1772 // ExpressionStatement
1773 // IfStatement
1774 // IterationStatement
1775 // ContinueStatement
1776 // BreakStatement
1777 // ReturnStatement
1778 // WithStatement
1779 // LabelledStatement
1780 // SwitchStatement
1781 // ThrowStatement
1782 // TryStatement
1783 // DebuggerStatement
1784
1785 // Note: Since labels can only be used by 'break' and 'continue'
1786 // statements, which themselves are only valid within blocks,
1787 // iterations or 'switch' statements (i.e., BreakableStatements),
1788 // labels can be simply ignored in all other cases; except for
1789 // trivial labeled break statements 'label: break label' which is
1790 // parsed into an empty statement.
1791 switch (peek()) {
1792 case Token::LBRACE:
1793 return ParseBlock(labels, ok);
1794
1795 case Token::SEMICOLON:
1796 if (is_strong(language_mode())) {
1797 ReportMessageAt(scanner()->peek_location(),
1798 MessageTemplate::kStrongEmpty);
1799 *ok = false;
1800 return NULL;
1801 }
1802 Next();
1803 return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
1804
1805 case Token::IF:
1806 return ParseIfStatement(labels, ok);
1807
1808 case Token::DO:
1809 return ParseDoWhileStatement(labels, ok);
1810
1811 case Token::WHILE:
1812 return ParseWhileStatement(labels, ok);
1813
1814 case Token::FOR:
1815 return ParseForStatement(labels, ok);
1816
1817 case Token::CONTINUE:
1818 case Token::BREAK:
1819 case Token::RETURN:
1820 case Token::THROW:
1821 case Token::TRY: {
1822 // These statements must have their labels preserved in an enclosing
1823 // block
1824 if (labels == NULL) {
1825 return ParseStatementAsUnlabelled(labels, ok);
1826 } else {
1827 Block* result =
1828 factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition);
1829 Target target(&this->target_stack_, result);
1830 Statement* statement = ParseStatementAsUnlabelled(labels, CHECK_OK);
1831 if (result) result->statements()->Add(statement, zone());
1832 return result;
1833 }
1834 }
1835
1836 case Token::WITH:
1837 return ParseWithStatement(labels, ok);
1838
1839 case Token::SWITCH:
1840 return ParseSwitchStatement(labels, ok);
1841
1842 case Token::FUNCTION: {
1843 // FunctionDeclaration is only allowed in the context of SourceElements
1844 // (Ecma 262 5th Edition, clause 14):
1845 // SourceElement:
1846 // Statement
1847 // FunctionDeclaration
1848 // Common language extension is to allow function declaration in place
1849 // of any statement. This language extension is disabled in strict mode.
1850 //
1851 // In Harmony mode, this case also handles the extension:
1852 // Statement:
1853 // GeneratorDeclaration
1854 if (is_strict(language_mode())) {
1855 ReportMessageAt(scanner()->peek_location(),
1856 MessageTemplate::kStrictFunction);
1857 *ok = false;
1858 return NULL;
1859 }
1860 return ParseFunctionDeclaration(NULL, ok);
1861 }
1862
1863 case Token::DEBUGGER:
1864 return ParseDebuggerStatement(ok);
1865
1866 case Token::VAR:
1867 return ParseVariableStatement(kStatement, NULL, ok);
1868
1869 case Token::CONST:
1870 // In ES6 CONST is not allowed as a Statement, only as a
1871 // LexicalDeclaration, however we continue to allow it in sloppy mode for
1872 // backwards compatibility.
1873 if (is_sloppy(language_mode()) && allow_legacy_const()) {
1874 return ParseVariableStatement(kStatement, NULL, ok);
1875 }
1876
1877 // Fall through.
1878 default:
1879 return ParseExpressionOrLabelledStatement(labels, ok);
1880 }
1881}
1882
1883Statement* Parser::ParseStatementAsUnlabelled(
1884 ZoneList<const AstRawString*>* labels, bool* ok) {
1885 switch (peek()) {
1886 case Token::CONTINUE:
1887 return ParseContinueStatement(ok);
1888
1889 case Token::BREAK:
1890 return ParseBreakStatement(labels, ok);
1891
1892 case Token::RETURN:
1893 return ParseReturnStatement(ok);
1894
1895 case Token::THROW:
1896 return ParseThrowStatement(ok);
1897
1898 case Token::TRY:
1899 return ParseTryStatement(ok);
1900
1901 default:
1902 UNREACHABLE();
1903 return NULL;
1904 }
1905}
1906
1907
1908VariableProxy* Parser::NewUnresolved(const AstRawString* name,
1909 VariableMode mode) {
1910 // If we are inside a function, a declaration of a var/const variable is a
1911 // truly local variable, and the scope of the variable is always the function
1912 // scope.
1913 // Let/const variables in harmony mode are always added to the immediately
1914 // enclosing scope.
1915 Scope* scope =
1916 IsLexicalVariableMode(mode) ? scope_ : scope_->DeclarationScope();
1917 return scope->NewUnresolved(factory(), name, Variable::NORMAL,
1918 scanner()->location().beg_pos,
1919 scanner()->location().end_pos);
1920}
1921
1922
1923Variable* Parser::Declare(Declaration* declaration,
1924 DeclarationDescriptor::Kind declaration_kind,
1925 bool resolve, bool* ok, Scope* scope) {
1926 VariableProxy* proxy = declaration->proxy();
1927 DCHECK(proxy->raw_name() != NULL);
1928 const AstRawString* name = proxy->raw_name();
1929 VariableMode mode = declaration->mode();
1930 bool is_function_declaration = declaration->IsFunctionDeclaration();
1931 if (scope == nullptr) scope = scope_;
1932 Scope* declaration_scope =
1933 IsLexicalVariableMode(mode) ? scope : scope->DeclarationScope();
1934 Variable* var = NULL;
1935
1936 // If a suitable scope exists, then we can statically declare this
1937 // variable and also set its mode. In any case, a Declaration node
1938 // will be added to the scope so that the declaration can be added
1939 // to the corresponding activation frame at runtime if necessary.
1940 // For instance, var declarations inside a sloppy eval scope need
1941 // to be added to the calling function context. Similarly, strict
1942 // mode eval scope and lexical eval bindings do not leak variable
1943 // declarations to the caller's scope so we declare all locals, too.
1944 if (declaration_scope->is_function_scope() ||
1945 declaration_scope->is_block_scope() ||
1946 declaration_scope->is_module_scope() ||
1947 declaration_scope->is_script_scope() ||
1948 (declaration_scope->is_eval_scope() &&
1949 (is_strict(declaration_scope->language_mode()) ||
1950 IsLexicalVariableMode(mode)))) {
1951 // Declare the variable in the declaration scope.
1952 var = declaration_scope->LookupLocal(name);
1953 if (var == NULL) {
1954 // Declare the name.
1955 Variable::Kind kind = Variable::NORMAL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001956 if (is_function_declaration) {
1957 kind = Variable::FUNCTION;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001958 }
1959 var = declaration_scope->DeclareLocal(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001960 name, mode, declaration->initialization(), kind, kNotAssigned);
1961 } else if ((mode == CONST_LEGACY || var->mode() == CONST_LEGACY) &&
1962 !declaration_scope->is_script_scope()) {
1963 // Duplicate legacy const definitions throw at runtime.
1964 DCHECK(is_sloppy(language_mode()));
1965 Expression* expression = NewThrowSyntaxError(
1966 MessageTemplate::kVarRedeclaration, name, declaration->position());
1967 declaration_scope->SetIllegalRedeclaration(expression);
1968 } else if ((IsLexicalVariableMode(mode) ||
1969 IsLexicalVariableMode(var->mode())) &&
1970 // Lexical bindings may appear for some parameters in sloppy
1971 // mode even with --harmony-sloppy off.
1972 (is_strict(language_mode()) || allow_harmony_sloppy())) {
1973 // Allow duplicate function decls for web compat, see bug 4693.
1974 if (is_sloppy(language_mode()) && is_function_declaration &&
1975 var->is_function()) {
1976 DCHECK(IsLexicalVariableMode(mode) &&
1977 IsLexicalVariableMode(var->mode()));
1978 ++use_counts_[v8::Isolate::kSloppyModeBlockScopedFunctionRedefinition];
1979 } else {
1980 // The name was declared in this scope before; check for conflicting
1981 // re-declarations. We have a conflict if either of the declarations
1982 // is not a var (in script scope, we also have to ignore legacy const
1983 // for compatibility). There is similar code in runtime.cc in the
1984 // Declare functions. The function CheckConflictingVarDeclarations
1985 // checks for var and let bindings from different scopes whereas this
1986 // is a check for conflicting declarations within the same scope. This
1987 // check also covers the special case
1988 //
1989 // function () { let x; { var x; } }
1990 //
1991 // because the var declaration is hoisted to the function scope where
1992 // 'x' is already bound.
1993 DCHECK(IsDeclaredVariableMode(var->mode()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001994 // In harmony we treat re-declarations as early errors. See
1995 // ES5 16 for a definition of early errors.
1996 if (declaration_kind == DeclarationDescriptor::NORMAL) {
1997 ParserTraits::ReportMessage(MessageTemplate::kVarRedeclaration, name);
1998 } else {
1999 ParserTraits::ReportMessage(MessageTemplate::kParamDupe);
2000 }
2001 *ok = false;
2002 return nullptr;
2003 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002004 } else if (mode == VAR) {
2005 var->set_maybe_assigned();
2006 }
2007 } else if (declaration_scope->is_eval_scope() &&
2008 is_sloppy(declaration_scope->language_mode()) &&
2009 !IsLexicalVariableMode(mode)) {
2010 // In a var binding in a sloppy direct eval, pollute the enclosing scope
2011 // with this new binding by doing the following:
2012 // The proxy is bound to a lookup variable to force a dynamic declaration
2013 // using the DeclareLookupSlot runtime function.
2014 Variable::Kind kind = Variable::NORMAL;
2015 // TODO(sigurds) figure out if kNotAssigned is OK here
2016 var = new (zone()) Variable(declaration_scope, name, mode, kind,
2017 declaration->initialization(), kNotAssigned);
2018 var->AllocateTo(VariableLocation::LOOKUP, -1);
2019 var->SetFromEval();
2020 resolve = true;
2021 }
2022
2023
2024 // We add a declaration node for every declaration. The compiler
2025 // will only generate code if necessary. In particular, declarations
2026 // for inner local variables that do not represent functions won't
2027 // result in any generated code.
2028 //
2029 // Note that we always add an unresolved proxy even if it's not
2030 // used, simply because we don't know in this method (w/o extra
2031 // parameters) if the proxy is needed or not. The proxy will be
2032 // bound during variable resolution time unless it was pre-bound
2033 // below.
2034 //
2035 // WARNING: This will lead to multiple declaration nodes for the
2036 // same variable if it is declared several times. This is not a
2037 // semantic issue as long as we keep the source order, but it may be
2038 // a performance issue since it may lead to repeated
2039 // RuntimeHidden_DeclareLookupSlot calls.
2040 declaration_scope->AddDeclaration(declaration);
2041
2042 if (mode == CONST_LEGACY && declaration_scope->is_script_scope()) {
2043 // For global const variables we bind the proxy to a variable.
2044 DCHECK(resolve); // should be set by all callers
2045 Variable::Kind kind = Variable::NORMAL;
2046 var = new (zone()) Variable(declaration_scope, name, mode, kind,
2047 kNeedsInitialization, kNotAssigned);
2048 }
2049
2050 // If requested and we have a local variable, bind the proxy to the variable
2051 // at parse-time. This is used for functions (and consts) declared inside
2052 // statements: the corresponding function (or const) variable must be in the
2053 // function scope and not a statement-local scope, e.g. as provided with a
2054 // 'with' statement:
2055 //
2056 // with (obj) {
2057 // function f() {}
2058 // }
2059 //
2060 // which is translated into:
2061 //
2062 // with (obj) {
2063 // // in this case this is not: 'var f; f = function () {};'
2064 // var f = function () {};
2065 // }
2066 //
2067 // Note that if 'f' is accessed from inside the 'with' statement, it
2068 // will be allocated in the context (because we must be able to look
2069 // it up dynamically) but it will also be accessed statically, i.e.,
2070 // with a context slot index and a context chain length for this
2071 // initialization code. Thus, inside the 'with' statement, we need
2072 // both access to the static and the dynamic context chain; the
2073 // runtime needs to provide both.
2074 if (resolve && var != NULL) {
2075 proxy->BindTo(var);
2076 }
2077 return var;
2078}
2079
2080
2081// Language extension which is only enabled for source files loaded
2082// through the API's extension mechanism. A native function
2083// declaration is resolved by looking up the function through a
2084// callback provided by the extension.
2085Statement* Parser::ParseNativeDeclaration(bool* ok) {
2086 int pos = peek_position();
2087 Expect(Token::FUNCTION, CHECK_OK);
2088 // Allow "eval" or "arguments" for backward compatibility.
2089 const AstRawString* name =
2090 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
2091 Expect(Token::LPAREN, CHECK_OK);
2092 bool done = (peek() == Token::RPAREN);
2093 while (!done) {
2094 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
2095 done = (peek() == Token::RPAREN);
2096 if (!done) {
2097 Expect(Token::COMMA, CHECK_OK);
2098 }
2099 }
2100 Expect(Token::RPAREN, CHECK_OK);
2101 Expect(Token::SEMICOLON, CHECK_OK);
2102
2103 // Make sure that the function containing the native declaration
2104 // isn't lazily compiled. The extension structures are only
2105 // accessible while parsing the first time not when reparsing
2106 // because of lazy compilation.
2107 // TODO(adamk): Should this be ClosureScope()?
2108 scope_->DeclarationScope()->ForceEagerCompilation();
2109
2110 // TODO(1240846): It's weird that native function declarations are
2111 // introduced dynamically when we meet their declarations, whereas
2112 // other functions are set up when entering the surrounding scope.
2113 VariableProxy* proxy = NewUnresolved(name, VAR);
2114 Declaration* declaration =
2115 factory()->NewVariableDeclaration(proxy, VAR, scope_, pos);
2116 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
2117 NativeFunctionLiteral* lit = factory()->NewNativeFunctionLiteral(
2118 name, extension_, RelocInfo::kNoPosition);
2119 return factory()->NewExpressionStatement(
2120 factory()->NewAssignment(Token::INIT, proxy, lit, RelocInfo::kNoPosition),
2121 pos);
2122}
2123
2124
2125Statement* Parser::ParseFunctionDeclaration(
2126 ZoneList<const AstRawString*>* names, bool* ok) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002127 Expect(Token::FUNCTION, CHECK_OK);
2128 int pos = position();
2129 bool is_generator = Check(Token::MUL);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002130 return ParseFunctionDeclaration(pos, is_generator, names, ok);
2131}
2132
2133
2134Statement* Parser::ParseFunctionDeclaration(
2135 int pos, bool is_generator, ZoneList<const AstRawString*>* names,
2136 bool* ok) {
2137 // FunctionDeclaration ::
2138 // 'function' Identifier '(' FormalParameters ')' '{' FunctionBody '}'
2139 // GeneratorDeclaration ::
2140 // 'function' '*' Identifier '(' FormalParameters ')' '{' FunctionBody '}'
2141 //
2142 // 'function' and '*' (if present) have been consumed by the caller.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002143 bool is_strict_reserved = false;
2144 const AstRawString* name = ParseIdentifierOrStrictReservedWord(
2145 &is_strict_reserved, CHECK_OK);
2146
2147 FuncNameInferrer::State fni_state(fni_);
2148 if (fni_ != NULL) fni_->PushEnclosingName(name);
2149 FunctionLiteral* fun = ParseFunctionLiteral(
2150 name, scanner()->location(),
2151 is_strict_reserved ? kFunctionNameIsStrictReserved
2152 : kFunctionNameValidityUnknown,
2153 is_generator ? FunctionKind::kGeneratorFunction
2154 : FunctionKind::kNormalFunction,
Ben Murdoch097c5b22016-05-18 11:27:45 +01002155 pos, FunctionLiteral::kDeclaration, language_mode(), CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002156
2157 // Even if we're not at the top-level of the global or a function
2158 // scope, we treat it as such and introduce the function with its
2159 // initial value upon entering the corresponding scope.
2160 // In ES6, a function behaves as a lexical binding, except in
2161 // a script scope, or the initial scope of eval or another function.
2162 VariableMode mode =
2163 is_strong(language_mode())
2164 ? CONST
2165 : (is_strict(language_mode()) || allow_harmony_sloppy_function()) &&
2166 !scope_->is_declaration_scope()
2167 ? LET
2168 : VAR;
2169 VariableProxy* proxy = NewUnresolved(name, mode);
2170 Declaration* declaration =
2171 factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);
2172 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
2173 if (names) names->Add(name, zone());
2174 EmptyStatement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
2175 if (is_sloppy(language_mode()) && allow_harmony_sloppy_function() &&
2176 !scope_->is_declaration_scope()) {
2177 SloppyBlockFunctionStatement* delegate =
2178 factory()->NewSloppyBlockFunctionStatement(empty, scope_);
2179 scope_->DeclarationScope()->sloppy_block_function_map()->Declare(name,
2180 delegate);
2181 return delegate;
2182 }
2183 return empty;
2184}
2185
2186
2187Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
2188 bool* ok) {
2189 // ClassDeclaration ::
2190 // 'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}'
2191 //
Ben Murdoch097c5b22016-05-18 11:27:45 +01002192 // 'class' is expected to be consumed by the caller.
2193 //
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002194 // A ClassDeclaration
2195 //
2196 // class C { ... }
2197 //
2198 // has the same semantics as:
2199 //
2200 // let C = class C { ... };
2201 //
2202 // so rewrite it as such.
2203
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002204 if (!allow_harmony_sloppy() && is_sloppy(language_mode())) {
2205 ReportMessage(MessageTemplate::kSloppyLexical);
2206 *ok = false;
2207 return NULL;
2208 }
2209
2210 int pos = position();
2211 bool is_strict_reserved = false;
2212 const AstRawString* name =
2213 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
2214 ClassLiteral* value = ParseClassLiteral(name, scanner()->location(),
2215 is_strict_reserved, pos, CHECK_OK);
2216
2217 VariableMode mode = is_strong(language_mode()) ? CONST : LET;
2218 VariableProxy* proxy = NewUnresolved(name, mode);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002219 Declaration* declaration =
2220 factory()->NewVariableDeclaration(proxy, mode, scope_, pos);
2221 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002222 proxy->var()->set_initializer_position(position());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002223 Assignment* assignment =
2224 factory()->NewAssignment(Token::INIT, proxy, value, pos);
2225 Statement* assignment_statement =
2226 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
2227 if (names) names->Add(name, zone());
2228 return assignment_statement;
2229}
2230
2231
2232Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels,
2233 bool finalize_block_scope, bool* ok) {
2234 // The harmony mode uses block elements instead of statements.
2235 //
2236 // Block ::
2237 // '{' StatementList '}'
2238
2239 // Construct block expecting 16 statements.
2240 Block* body =
2241 factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition);
2242 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
2243
2244 // Parse the statements and collect escaping labels.
2245 Expect(Token::LBRACE, CHECK_OK);
2246 block_scope->set_start_position(scanner()->location().beg_pos);
2247 { BlockState block_state(&scope_, block_scope);
2248 Target target(&this->target_stack_, body);
2249
2250 while (peek() != Token::RBRACE) {
2251 Statement* stat = ParseStatementListItem(CHECK_OK);
2252 if (stat && !stat->IsEmpty()) {
2253 body->statements()->Add(stat, zone());
2254 }
2255 }
2256 }
2257 Expect(Token::RBRACE, CHECK_OK);
2258 block_scope->set_end_position(scanner()->location().end_pos);
2259 if (finalize_block_scope) {
2260 block_scope = block_scope->FinalizeBlockScope();
2261 }
2262 body->set_scope(block_scope);
2263 return body;
2264}
2265
2266
2267Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) {
2268 return ParseBlock(labels, true, ok);
2269}
2270
2271
2272Block* Parser::DeclarationParsingResult::BuildInitializationBlock(
2273 ZoneList<const AstRawString*>* names, bool* ok) {
2274 Block* result = descriptor.parser->factory()->NewBlock(
2275 NULL, 1, true, descriptor.declaration_pos);
2276 for (auto declaration : declarations) {
2277 PatternRewriter::DeclareAndInitializeVariables(
2278 result, &descriptor, &declaration, names, CHECK_OK);
2279 }
2280 return result;
2281}
2282
2283
2284Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
2285 ZoneList<const AstRawString*>* names,
2286 bool* ok) {
2287 // VariableStatement ::
2288 // VariableDeclarations ';'
2289
2290 // The scope of a var/const declared variable anywhere inside a function
2291 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
2292 // transform a source-level var/const declaration into a (Function)
2293 // Scope declaration, and rewrite the source-level initialization into an
2294 // assignment statement. We use a block to collect multiple assignments.
2295 //
2296 // We mark the block as initializer block because we don't want the
2297 // rewriter to add a '.result' assignment to such a block (to get compliant
2298 // behavior for code such as print(eval('var x = 7')), and for cosmetic
2299 // reasons when pretty-printing. Also, unless an assignment (initialization)
2300 // is inside an initializer block, it is ignored.
2301
2302 DeclarationParsingResult parsing_result;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002303 Block* result =
2304 ParseVariableDeclarations(var_context, &parsing_result, names, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002305 ExpectSemicolon(CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002306 return result;
2307}
2308
Ben Murdoch097c5b22016-05-18 11:27:45 +01002309Block* Parser::ParseVariableDeclarations(
2310 VariableDeclarationContext var_context,
2311 DeclarationParsingResult* parsing_result,
2312 ZoneList<const AstRawString*>* names, bool* ok) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002313 // VariableDeclarations ::
2314 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
2315 //
2316 // The ES6 Draft Rev3 specifies the following grammar for const declarations
2317 //
2318 // ConstDeclaration ::
2319 // const ConstBinding (',' ConstBinding)* ';'
2320 // ConstBinding ::
2321 // Identifier '=' AssignmentExpression
2322 //
2323 // TODO(ES6):
2324 // ConstBinding ::
2325 // BindingPattern '=' AssignmentExpression
2326
2327 parsing_result->descriptor.parser = this;
2328 parsing_result->descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
2329 parsing_result->descriptor.declaration_pos = peek_position();
2330 parsing_result->descriptor.initialization_pos = peek_position();
2331 parsing_result->descriptor.mode = VAR;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002332
2333 Block* init_block = nullptr;
2334 if (var_context != kForStatement) {
2335 init_block = factory()->NewBlock(
2336 NULL, 1, true, parsing_result->descriptor.declaration_pos);
2337 }
2338
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002339 if (peek() == Token::VAR) {
2340 if (is_strong(language_mode())) {
2341 Scanner::Location location = scanner()->peek_location();
2342 ReportMessageAt(location, MessageTemplate::kStrongVar);
2343 *ok = false;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002344 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002345 }
2346 Consume(Token::VAR);
2347 } else if (peek() == Token::CONST && allow_const()) {
2348 Consume(Token::CONST);
2349 if (is_sloppy(language_mode()) && allow_legacy_const()) {
2350 parsing_result->descriptor.mode = CONST_LEGACY;
2351 ++use_counts_[v8::Isolate::kLegacyConst];
2352 } else {
2353 DCHECK(is_strict(language_mode()) || allow_harmony_sloppy());
2354 DCHECK(var_context != kStatement);
2355 parsing_result->descriptor.mode = CONST;
2356 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002357 } else if (peek() == Token::LET && allow_let()) {
2358 Consume(Token::LET);
2359 DCHECK(var_context != kStatement);
2360 parsing_result->descriptor.mode = LET;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002361 } else {
2362 UNREACHABLE(); // by current callers
2363 }
2364
2365 parsing_result->descriptor.scope = scope_;
2366 parsing_result->descriptor.hoist_scope = nullptr;
2367
2368
2369 bool first_declaration = true;
2370 int bindings_start = peek_position();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002371 do {
2372 FuncNameInferrer::State fni_state(fni_);
2373
2374 // Parse name.
2375 if (!first_declaration) Consume(Token::COMMA);
2376
2377 Expression* pattern;
2378 int decl_pos = peek_position();
2379 {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002380 ExpressionClassifier pattern_classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002381 Token::Value next = peek();
Ben Murdoch097c5b22016-05-18 11:27:45 +01002382 pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
2383 ValidateBindingPattern(&pattern_classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002384 if (IsLexicalVariableMode(parsing_result->descriptor.mode)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002385 ValidateLetPattern(&pattern_classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002386 }
2387 if (!allow_harmony_destructuring_bind() && !pattern->IsVariableProxy()) {
2388 ReportUnexpectedToken(next);
2389 *ok = false;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002390 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002391 }
2392 }
2393
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002394 Scanner::Location variable_loc = scanner()->location();
2395 const AstRawString* single_name =
2396 pattern->IsVariableProxy() ? pattern->AsVariableProxy()->raw_name()
2397 : nullptr;
2398 if (single_name != nullptr) {
2399 if (fni_ != NULL) fni_->PushVariableName(single_name);
2400 }
2401
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002402 Expression* value = NULL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002403 int initializer_position = RelocInfo::kNoPosition;
2404 if (Check(Token::ASSIGN)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002405 ExpressionClassifier classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002406 value = ParseAssignmentExpression(var_context != kForStatement,
Ben Murdoch097c5b22016-05-18 11:27:45 +01002407 &classifier, CHECK_OK);
2408 RewriteNonPattern(&classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002409 variable_loc.end_pos = scanner()->location().end_pos;
2410
2411 if (!parsing_result->first_initializer_loc.IsValid()) {
2412 parsing_result->first_initializer_loc = variable_loc;
2413 }
2414
2415 // Don't infer if it is "a = function(){...}();"-like expression.
2416 if (single_name) {
2417 if (fni_ != NULL && value->AsCall() == NULL &&
2418 value->AsCallNew() == NULL) {
2419 fni_->Infer();
2420 } else {
2421 fni_->RemoveLastFunction();
2422 }
2423 }
2424
Ben Murdoch097c5b22016-05-18 11:27:45 +01002425 if (allow_harmony_function_name()) {
2426 ParserTraits::SetFunctionNameFromIdentifierRef(value, pattern);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002427 }
2428
2429 // End position of the initializer is after the assignment expression.
2430 initializer_position = scanner()->location().end_pos;
2431 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002432 // Initializers may be either required or implied unless this is a
2433 // for-in/of iteration variable.
2434 if (var_context != kForStatement || !PeekInOrOf()) {
2435 // ES6 'const' and binding patterns require initializers.
2436 if (parsing_result->descriptor.mode == CONST ||
2437 !pattern->IsVariableProxy()) {
2438 ParserTraits::ReportMessageAt(
2439 Scanner::Location(decl_pos, scanner()->location().end_pos),
2440 MessageTemplate::kDeclarationMissingInitializer,
2441 !pattern->IsVariableProxy() ? "destructuring" : "const");
2442 *ok = false;
2443 return nullptr;
2444 }
2445
2446 // 'let x' and (legacy) 'const x' initialize 'x' to undefined.
2447 if (parsing_result->descriptor.mode == LET ||
2448 parsing_result->descriptor.mode == CONST_LEGACY) {
2449 value = GetLiteralUndefined(position());
2450 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002451 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002452
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002453 // End position of the initializer is after the variable.
2454 initializer_position = position();
2455 }
2456
Ben Murdoch097c5b22016-05-18 11:27:45 +01002457 DeclarationParsingResult::Declaration decl(pattern, initializer_position,
2458 value);
2459 if (var_context == kForStatement) {
2460 // Save the declaration for further handling in ParseForStatement.
2461 parsing_result->declarations.Add(decl);
2462 } else {
2463 // Immediately declare the variable otherwise. This avoids O(N^2)
2464 // behavior (where N is the number of variables in a single
2465 // declaration) in the PatternRewriter having to do with removing
2466 // and adding VariableProxies to the Scope (see bug 4699).
2467 DCHECK_NOT_NULL(init_block);
2468 PatternRewriter::DeclareAndInitializeVariables(
2469 init_block, &parsing_result->descriptor, &decl, names, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002470 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002471 first_declaration = false;
2472 } while (peek() == Token::COMMA);
2473
2474 parsing_result->bindings_loc =
2475 Scanner::Location(bindings_start, scanner()->location().end_pos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002476
2477 DCHECK(*ok);
2478 return init_block;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002479}
2480
2481
2482static bool ContainsLabel(ZoneList<const AstRawString*>* labels,
2483 const AstRawString* label) {
2484 DCHECK(label != NULL);
2485 if (labels != NULL) {
2486 for (int i = labels->length(); i-- > 0; ) {
2487 if (labels->at(i) == label) {
2488 return true;
2489 }
2490 }
2491 }
2492 return false;
2493}
2494
2495
2496Statement* Parser::ParseExpressionOrLabelledStatement(
2497 ZoneList<const AstRawString*>* labels, bool* ok) {
2498 // ExpressionStatement | LabelledStatement ::
2499 // Expression ';'
2500 // Identifier ':' Statement
2501 //
2502 // ExpressionStatement[Yield] :
2503 // [lookahead ∉ {{, function, class, let [}] Expression[In, ?Yield] ;
2504
2505 int pos = peek_position();
2506
2507 switch (peek()) {
2508 case Token::FUNCTION:
2509 case Token::LBRACE:
2510 UNREACHABLE(); // Always handled by the callers.
2511 case Token::CLASS:
2512 ReportUnexpectedToken(Next());
2513 *ok = false;
2514 return nullptr;
2515
2516 case Token::THIS:
2517 if (!FLAG_strong_this) break;
2518 // Fall through.
2519 case Token::SUPER:
2520 if (is_strong(language_mode()) &&
2521 IsClassConstructor(function_state_->kind())) {
2522 bool is_this = peek() == Token::THIS;
2523 Expression* expr;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002524 ExpressionClassifier classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002525 if (is_this) {
2526 expr = ParseStrongInitializationExpression(&classifier, CHECK_OK);
2527 } else {
2528 expr = ParseStrongSuperCallExpression(&classifier, CHECK_OK);
2529 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002530 RewriteNonPattern(&classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002531 switch (peek()) {
2532 case Token::SEMICOLON:
2533 Consume(Token::SEMICOLON);
2534 break;
2535 case Token::RBRACE:
2536 case Token::EOS:
2537 break;
2538 default:
2539 if (!scanner()->HasAnyLineTerminatorBeforeNext()) {
2540 ReportMessageAt(function_state_->this_location(),
2541 is_this
2542 ? MessageTemplate::kStrongConstructorThis
2543 : MessageTemplate::kStrongConstructorSuper);
2544 *ok = false;
2545 return nullptr;
2546 }
2547 }
2548 return factory()->NewExpressionStatement(expr, pos);
2549 }
2550 break;
2551
2552 default:
2553 break;
2554 }
2555
2556 bool starts_with_idenfifier = peek_any_identifier();
2557 Expression* expr = ParseExpression(true, CHECK_OK);
2558 if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL &&
2559 expr->AsVariableProxy() != NULL &&
2560 !expr->AsVariableProxy()->is_this()) {
2561 // Expression is a single identifier, and not, e.g., a parenthesized
2562 // identifier.
2563 VariableProxy* var = expr->AsVariableProxy();
2564 const AstRawString* label = var->raw_name();
2565 // TODO(1240780): We don't check for redeclaration of labels
2566 // during preparsing since keeping track of the set of active
2567 // labels requires nontrivial changes to the way scopes are
2568 // structured. However, these are probably changes we want to
2569 // make later anyway so we should go back and fix this then.
2570 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
2571 ParserTraits::ReportMessage(MessageTemplate::kLabelRedeclaration, label);
2572 *ok = false;
2573 return NULL;
2574 }
2575 if (labels == NULL) {
2576 labels = new(zone()) ZoneList<const AstRawString*>(4, zone());
2577 }
2578 labels->Add(label, zone());
2579 // Remove the "ghost" variable that turned out to be a label
2580 // from the top scope. This way, we don't try to resolve it
2581 // during the scope processing.
2582 scope_->RemoveUnresolved(var);
2583 Expect(Token::COLON, CHECK_OK);
2584 return ParseStatement(labels, ok);
2585 }
2586
2587 // If we have an extension, we allow a native function declaration.
2588 // A native function declaration starts with "native function" with
2589 // no line-terminator between the two words.
2590 if (extension_ != NULL && peek() == Token::FUNCTION &&
2591 !scanner()->HasAnyLineTerminatorBeforeNext() && expr != NULL &&
2592 expr->AsVariableProxy() != NULL &&
2593 expr->AsVariableProxy()->raw_name() ==
2594 ast_value_factory()->native_string() &&
2595 !scanner()->literal_contains_escapes()) {
2596 return ParseNativeDeclaration(ok);
2597 }
2598
2599 // Parsed expression statement, followed by semicolon.
2600 // Detect attempts at 'let' declarations in sloppy mode.
2601 if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER &&
2602 expr->AsVariableProxy() != NULL &&
2603 expr->AsVariableProxy()->raw_name() ==
2604 ast_value_factory()->let_string()) {
2605 ReportMessage(MessageTemplate::kSloppyLexical, NULL);
2606 *ok = false;
2607 return NULL;
2608 }
2609 ExpectSemicolon(CHECK_OK);
2610 return factory()->NewExpressionStatement(expr, pos);
2611}
2612
2613
2614IfStatement* Parser::ParseIfStatement(ZoneList<const AstRawString*>* labels,
2615 bool* ok) {
2616 // IfStatement ::
2617 // 'if' '(' Expression ')' Statement ('else' Statement)?
2618
2619 int pos = peek_position();
2620 Expect(Token::IF, CHECK_OK);
2621 Expect(Token::LPAREN, CHECK_OK);
2622 Expression* condition = ParseExpression(true, CHECK_OK);
2623 Expect(Token::RPAREN, CHECK_OK);
2624 Statement* then_statement = ParseSubStatement(labels, CHECK_OK);
2625 Statement* else_statement = NULL;
2626 if (peek() == Token::ELSE) {
2627 Next();
2628 else_statement = ParseSubStatement(labels, CHECK_OK);
2629 } else {
2630 else_statement = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
2631 }
2632 return factory()->NewIfStatement(
2633 condition, then_statement, else_statement, pos);
2634}
2635
2636
2637Statement* Parser::ParseContinueStatement(bool* ok) {
2638 // ContinueStatement ::
2639 // 'continue' Identifier? ';'
2640
2641 int pos = peek_position();
2642 Expect(Token::CONTINUE, CHECK_OK);
2643 const AstRawString* label = NULL;
2644 Token::Value tok = peek();
2645 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
2646 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
2647 // ECMA allows "eval" or "arguments" as labels even in strict mode.
2648 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
2649 }
2650 IterationStatement* target = LookupContinueTarget(label, CHECK_OK);
2651 if (target == NULL) {
2652 // Illegal continue statement.
2653 MessageTemplate::Template message = MessageTemplate::kIllegalContinue;
2654 if (label != NULL) {
2655 message = MessageTemplate::kUnknownLabel;
2656 }
2657 ParserTraits::ReportMessage(message, label);
2658 *ok = false;
2659 return NULL;
2660 }
2661 ExpectSemicolon(CHECK_OK);
2662 return factory()->NewContinueStatement(target, pos);
2663}
2664
2665
2666Statement* Parser::ParseBreakStatement(ZoneList<const AstRawString*>* labels,
2667 bool* ok) {
2668 // BreakStatement ::
2669 // 'break' Identifier? ';'
2670
2671 int pos = peek_position();
2672 Expect(Token::BREAK, CHECK_OK);
2673 const AstRawString* label = NULL;
2674 Token::Value tok = peek();
2675 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
2676 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
2677 // ECMA allows "eval" or "arguments" as labels even in strict mode.
2678 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
2679 }
2680 // Parse labeled break statements that target themselves into
2681 // empty statements, e.g. 'l1: l2: l3: break l2;'
2682 if (label != NULL && ContainsLabel(labels, label)) {
2683 ExpectSemicolon(CHECK_OK);
2684 return factory()->NewEmptyStatement(pos);
2685 }
2686 BreakableStatement* target = NULL;
2687 target = LookupBreakTarget(label, CHECK_OK);
2688 if (target == NULL) {
2689 // Illegal break statement.
2690 MessageTemplate::Template message = MessageTemplate::kIllegalBreak;
2691 if (label != NULL) {
2692 message = MessageTemplate::kUnknownLabel;
2693 }
2694 ParserTraits::ReportMessage(message, label);
2695 *ok = false;
2696 return NULL;
2697 }
2698 ExpectSemicolon(CHECK_OK);
2699 return factory()->NewBreakStatement(target, pos);
2700}
2701
2702
2703Statement* Parser::ParseReturnStatement(bool* ok) {
2704 // ReturnStatement ::
2705 // 'return' Expression? ';'
2706
2707 // Consume the return token. It is necessary to do that before
2708 // reporting any errors on it, because of the way errors are
2709 // reported (underlining).
2710 Expect(Token::RETURN, CHECK_OK);
2711 Scanner::Location loc = scanner()->location();
2712 function_state_->set_return_location(loc);
2713
2714 Token::Value tok = peek();
2715 Statement* result;
2716 Expression* return_value;
2717 if (scanner()->HasAnyLineTerminatorBeforeNext() ||
2718 tok == Token::SEMICOLON ||
2719 tok == Token::RBRACE ||
2720 tok == Token::EOS) {
2721 if (IsSubclassConstructor(function_state_->kind())) {
2722 return_value = ThisExpression(scope_, factory(), loc.beg_pos);
2723 } else {
2724 return_value = GetLiteralUndefined(position());
2725 }
2726 } else {
2727 if (is_strong(language_mode()) &&
2728 IsClassConstructor(function_state_->kind())) {
2729 int pos = peek_position();
2730 ReportMessageAt(Scanner::Location(pos, pos + 1),
2731 MessageTemplate::kStrongConstructorReturnValue);
2732 *ok = false;
2733 return NULL;
2734 }
2735
2736 int pos = peek_position();
2737 return_value = ParseExpression(true, CHECK_OK);
2738
2739 if (IsSubclassConstructor(function_state_->kind())) {
2740 // For subclass constructors we need to return this in case of undefined
Ben Murdoch097c5b22016-05-18 11:27:45 +01002741 // return a Smi (transformed into an exception in the ConstructStub)
2742 // for a non object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002743 //
2744 // return expr;
2745 //
2746 // Is rewritten as:
2747 //
2748 // return (temp = expr) === undefined ? this :
Ben Murdoch097c5b22016-05-18 11:27:45 +01002749 // %_IsJSReceiver(temp) ? temp : 1;
2750
2751 // temp = expr
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002752 Variable* temp = scope_->NewTemporary(
2753 ast_value_factory()->empty_string());
2754 Assignment* assign = factory()->NewAssignment(
2755 Token::ASSIGN, factory()->NewVariableProxy(temp), return_value, pos);
2756
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002757 // %_IsJSReceiver(temp)
2758 ZoneList<Expression*>* is_spec_object_args =
2759 new (zone()) ZoneList<Expression*>(1, zone());
2760 is_spec_object_args->Add(factory()->NewVariableProxy(temp), zone());
2761 Expression* is_spec_object_call = factory()->NewCallRuntime(
2762 Runtime::kInlineIsJSReceiver, is_spec_object_args, pos);
2763
2764 // %_IsJSReceiver(temp) ? temp : throw_expression
2765 Expression* is_object_conditional = factory()->NewConditional(
2766 is_spec_object_call, factory()->NewVariableProxy(temp),
Ben Murdoch097c5b22016-05-18 11:27:45 +01002767 factory()->NewSmiLiteral(1, pos), pos);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002768
2769 // temp === undefined
2770 Expression* is_undefined = factory()->NewCompareOperation(
2771 Token::EQ_STRICT, assign,
2772 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), pos);
2773
2774 // is_undefined ? this : is_object_conditional
2775 return_value = factory()->NewConditional(
2776 is_undefined, ThisExpression(scope_, factory(), pos),
2777 is_object_conditional, pos);
2778 }
2779
Ben Murdoch097c5b22016-05-18 11:27:45 +01002780 // ES6 14.6.1 Static Semantics: IsInTailPosition
2781 if (FLAG_harmony_tailcalls && !is_sloppy(language_mode())) {
2782 function_state_->AddExpressionInTailPosition(return_value);
2783 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002784 }
2785 ExpectSemicolon(CHECK_OK);
2786
2787 if (is_generator()) {
2788 Expression* generator = factory()->NewVariableProxy(
2789 function_state_->generator_object_variable());
2790 Expression* yield = factory()->NewYield(
2791 generator, return_value, Yield::kFinal, loc.beg_pos);
2792 result = factory()->NewExpressionStatement(yield, loc.beg_pos);
2793 } else {
2794 result = factory()->NewReturnStatement(return_value, loc.beg_pos);
2795 }
2796
2797 Scope* decl_scope = scope_->DeclarationScope();
2798 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) {
2799 ReportMessageAt(loc, MessageTemplate::kIllegalReturn);
2800 *ok = false;
2801 return NULL;
2802 }
2803 return result;
2804}
2805
2806
2807Statement* Parser::ParseWithStatement(ZoneList<const AstRawString*>* labels,
2808 bool* ok) {
2809 // WithStatement ::
2810 // 'with' '(' Expression ')' Statement
2811
2812 Expect(Token::WITH, CHECK_OK);
2813 int pos = position();
2814
2815 if (is_strict(language_mode())) {
2816 ReportMessage(MessageTemplate::kStrictWith);
2817 *ok = false;
2818 return NULL;
2819 }
2820
2821 Expect(Token::LPAREN, CHECK_OK);
2822 Expression* expr = ParseExpression(true, CHECK_OK);
2823 Expect(Token::RPAREN, CHECK_OK);
2824
2825 scope_->DeclarationScope()->RecordWithStatement();
2826 Scope* with_scope = NewScope(scope_, WITH_SCOPE);
2827 Block* body;
2828 { BlockState block_state(&scope_, with_scope);
2829 with_scope->set_start_position(scanner()->peek_location().beg_pos);
2830
2831 // The body of the with statement must be enclosed in an additional
2832 // lexical scope in case the body is a FunctionDeclaration.
2833 body = factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition);
2834 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
2835 block_scope->set_start_position(scanner()->location().beg_pos);
2836 {
2837 BlockState block_state(&scope_, block_scope);
2838 Target target(&this->target_stack_, body);
2839 Statement* stmt = ParseSubStatement(labels, CHECK_OK);
2840 body->statements()->Add(stmt, zone());
2841 block_scope->set_end_position(scanner()->location().end_pos);
2842 block_scope = block_scope->FinalizeBlockScope();
2843 body->set_scope(block_scope);
2844 }
2845
2846 with_scope->set_end_position(scanner()->location().end_pos);
2847 }
2848 return factory()->NewWithStatement(with_scope, expr, body, pos);
2849}
2850
2851
2852CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
2853 // CaseClause ::
2854 // 'case' Expression ':' StatementList
2855 // 'default' ':' StatementList
2856
2857 Expression* label = NULL; // NULL expression indicates default case
2858 if (peek() == Token::CASE) {
2859 Expect(Token::CASE, CHECK_OK);
2860 label = ParseExpression(true, CHECK_OK);
2861 } else {
2862 Expect(Token::DEFAULT, CHECK_OK);
2863 if (*default_seen_ptr) {
2864 ReportMessage(MessageTemplate::kMultipleDefaultsInSwitch);
2865 *ok = false;
2866 return NULL;
2867 }
2868 *default_seen_ptr = true;
2869 }
2870 Expect(Token::COLON, CHECK_OK);
2871 int pos = position();
2872 ZoneList<Statement*>* statements =
2873 new(zone()) ZoneList<Statement*>(5, zone());
2874 Statement* stat = NULL;
2875 while (peek() != Token::CASE &&
2876 peek() != Token::DEFAULT &&
2877 peek() != Token::RBRACE) {
2878 stat = ParseStatementListItem(CHECK_OK);
2879 statements->Add(stat, zone());
2880 }
2881 if (is_strong(language_mode()) && stat != NULL && !stat->IsJump() &&
2882 peek() != Token::RBRACE) {
2883 ReportMessageAt(scanner()->location(),
2884 MessageTemplate::kStrongSwitchFallthrough);
2885 *ok = false;
2886 return NULL;
2887 }
2888 return factory()->NewCaseClause(label, statements, pos);
2889}
2890
2891
2892Statement* Parser::ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
2893 bool* ok) {
2894 // SwitchStatement ::
2895 // 'switch' '(' Expression ')' '{' CaseClause* '}'
2896 // In order to get the CaseClauses to execute in their own lexical scope,
2897 // but without requiring downstream code to have special scope handling
2898 // code for switch statements, desugar into blocks as follows:
2899 // { // To group the statements--harmless to evaluate Expression in scope
2900 // .tag_variable = Expression;
2901 // { // To give CaseClauses a scope
2902 // switch (.tag_variable) { CaseClause* }
2903 // }
2904 // }
2905
2906 Block* switch_block =
2907 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
2908 int switch_pos = peek_position();
2909
2910 Expect(Token::SWITCH, CHECK_OK);
2911 Expect(Token::LPAREN, CHECK_OK);
2912 Expression* tag = ParseExpression(true, CHECK_OK);
2913 Expect(Token::RPAREN, CHECK_OK);
2914
2915 Variable* tag_variable =
2916 scope_->NewTemporary(ast_value_factory()->dot_switch_tag_string());
2917 Assignment* tag_assign = factory()->NewAssignment(
2918 Token::ASSIGN, factory()->NewVariableProxy(tag_variable), tag,
2919 tag->position());
2920 Statement* tag_statement =
2921 factory()->NewExpressionStatement(tag_assign, RelocInfo::kNoPosition);
2922 switch_block->statements()->Add(tag_statement, zone());
2923
2924 // make statement: undefined;
2925 // This is needed so the tag isn't returned as the value, in case the switch
2926 // statements don't have a value.
2927 switch_block->statements()->Add(
2928 factory()->NewExpressionStatement(
2929 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
2930 RelocInfo::kNoPosition),
2931 zone());
2932
2933 Block* cases_block =
2934 factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
2935 Scope* cases_scope = NewScope(scope_, BLOCK_SCOPE);
2936 cases_scope->SetNonlinear();
2937
2938 SwitchStatement* switch_statement =
2939 factory()->NewSwitchStatement(labels, switch_pos);
2940
2941 cases_scope->set_start_position(scanner()->location().beg_pos);
2942 {
2943 BlockState cases_block_state(&scope_, cases_scope);
2944 Target target(&this->target_stack_, switch_statement);
2945
2946 Expression* tag_read = factory()->NewVariableProxy(tag_variable);
2947
2948 bool default_seen = false;
2949 ZoneList<CaseClause*>* cases =
2950 new (zone()) ZoneList<CaseClause*>(4, zone());
2951 Expect(Token::LBRACE, CHECK_OK);
2952 while (peek() != Token::RBRACE) {
2953 CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
2954 cases->Add(clause, zone());
2955 }
2956 switch_statement->Initialize(tag_read, cases);
2957 cases_block->statements()->Add(switch_statement, zone());
2958 }
2959 Expect(Token::RBRACE, CHECK_OK);
2960
2961 cases_scope->set_end_position(scanner()->location().end_pos);
2962 cases_scope = cases_scope->FinalizeBlockScope();
2963 cases_block->set_scope(cases_scope);
2964
2965 switch_block->statements()->Add(cases_block, zone());
2966
2967 return switch_block;
2968}
2969
2970
2971Statement* Parser::ParseThrowStatement(bool* ok) {
2972 // ThrowStatement ::
2973 // 'throw' Expression ';'
2974
2975 Expect(Token::THROW, CHECK_OK);
2976 int pos = position();
2977 if (scanner()->HasAnyLineTerminatorBeforeNext()) {
2978 ReportMessage(MessageTemplate::kNewlineAfterThrow);
2979 *ok = false;
2980 return NULL;
2981 }
2982 Expression* exception = ParseExpression(true, CHECK_OK);
2983 ExpectSemicolon(CHECK_OK);
2984
2985 return factory()->NewExpressionStatement(
2986 factory()->NewThrow(exception, pos), pos);
2987}
2988
Ben Murdoch097c5b22016-05-18 11:27:45 +01002989class Parser::DontCollectExpressionsInTailPositionScope {
2990 public:
2991 DontCollectExpressionsInTailPositionScope(
2992 Parser::FunctionState* function_state)
2993 : function_state_(function_state),
2994 old_value_(function_state->collect_expressions_in_tail_position()) {
2995 function_state->set_collect_expressions_in_tail_position(false);
2996 }
2997 ~DontCollectExpressionsInTailPositionScope() {
2998 function_state_->set_collect_expressions_in_tail_position(old_value_);
2999 }
3000
3001 private:
3002 Parser::FunctionState* function_state_;
3003 bool old_value_;
3004};
3005
3006// Collects all return expressions at tail call position in this scope
3007// to a separate list.
3008class Parser::CollectExpressionsInTailPositionToListScope {
3009 public:
3010 CollectExpressionsInTailPositionToListScope(
3011 Parser::FunctionState* function_state, List<Expression*>* list)
3012 : function_state_(function_state), list_(list) {
3013 function_state->expressions_in_tail_position().Swap(list_);
3014 }
3015 ~CollectExpressionsInTailPositionToListScope() {
3016 function_state_->expressions_in_tail_position().Swap(list_);
3017 }
3018
3019 private:
3020 Parser::FunctionState* function_state_;
3021 List<Expression*>* list_;
3022};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003023
3024TryStatement* Parser::ParseTryStatement(bool* ok) {
3025 // TryStatement ::
3026 // 'try' Block Catch
3027 // 'try' Block Finally
3028 // 'try' Block Catch Finally
3029 //
3030 // Catch ::
3031 // 'catch' '(' Identifier ')' Block
3032 //
3033 // Finally ::
3034 // 'finally' Block
3035
3036 Expect(Token::TRY, CHECK_OK);
3037 int pos = position();
3038
Ben Murdoch097c5b22016-05-18 11:27:45 +01003039 Block* try_block;
3040 {
3041 DontCollectExpressionsInTailPositionScope no_tail_calls(function_state_);
3042 try_block = ParseBlock(NULL, CHECK_OK);
3043 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003044
3045 Token::Value tok = peek();
3046 if (tok != Token::CATCH && tok != Token::FINALLY) {
3047 ReportMessage(MessageTemplate::kNoCatchOrFinally);
3048 *ok = false;
3049 return NULL;
3050 }
3051
3052 Scope* catch_scope = NULL;
3053 Variable* catch_variable = NULL;
3054 Block* catch_block = NULL;
Ben Murdoch097c5b22016-05-18 11:27:45 +01003055 List<Expression*> expressions_in_tail_position_in_catch_block;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003056 if (tok == Token::CATCH) {
3057 Consume(Token::CATCH);
3058
3059 Expect(Token::LPAREN, CHECK_OK);
3060 catch_scope = NewScope(scope_, CATCH_SCOPE);
3061 catch_scope->set_start_position(scanner()->location().beg_pos);
3062
Ben Murdoch097c5b22016-05-18 11:27:45 +01003063 ExpressionClassifier pattern_classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003064 Expression* pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
3065 ValidateBindingPattern(&pattern_classifier, CHECK_OK);
3066
3067 const AstRawString* name = ast_value_factory()->dot_catch_string();
3068 bool is_simple = pattern->IsVariableProxy();
3069 if (is_simple) {
3070 auto proxy = pattern->AsVariableProxy();
3071 scope_->RemoveUnresolved(proxy);
3072 name = proxy->raw_name();
3073 }
3074
3075 catch_variable = catch_scope->DeclareLocal(name, VAR, kCreatedInitialized,
3076 Variable::NORMAL);
3077
3078 Expect(Token::RPAREN, CHECK_OK);
3079
3080 {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003081 CollectExpressionsInTailPositionToListScope
3082 collect_expressions_in_tail_position_scope(
3083 function_state_, &expressions_in_tail_position_in_catch_block);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003084 BlockState block_state(&scope_, catch_scope);
3085
3086 // TODO(adamk): Make a version of ParseBlock that takes a scope and
3087 // a block.
3088 catch_block =
3089 factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition);
3090 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
3091
3092 block_scope->set_start_position(scanner()->location().beg_pos);
3093 {
3094 BlockState block_state(&scope_, block_scope);
3095 Target target(&this->target_stack_, catch_block);
3096
3097 if (!is_simple) {
3098 DeclarationDescriptor descriptor;
3099 descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
3100 descriptor.parser = this;
3101 descriptor.scope = scope_;
3102 descriptor.hoist_scope = nullptr;
3103 descriptor.mode = LET;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003104 descriptor.declaration_pos = pattern->position();
3105 descriptor.initialization_pos = pattern->position();
3106
3107 DeclarationParsingResult::Declaration decl(
3108 pattern, pattern->position(),
3109 factory()->NewVariableProxy(catch_variable));
3110
3111 PatternRewriter::DeclareAndInitializeVariables(
3112 catch_block, &descriptor, &decl, nullptr, CHECK_OK);
3113 }
3114
3115 Expect(Token::LBRACE, CHECK_OK);
3116 while (peek() != Token::RBRACE) {
3117 Statement* stat = ParseStatementListItem(CHECK_OK);
3118 if (stat && !stat->IsEmpty()) {
3119 catch_block->statements()->Add(stat, zone());
3120 }
3121 }
3122 Consume(Token::RBRACE);
3123 }
3124 block_scope->set_end_position(scanner()->location().end_pos);
3125 block_scope = block_scope->FinalizeBlockScope();
3126 catch_block->set_scope(block_scope);
3127 }
3128
3129 catch_scope->set_end_position(scanner()->location().end_pos);
3130 tok = peek();
3131 }
3132
3133 Block* finally_block = NULL;
3134 DCHECK(tok == Token::FINALLY || catch_block != NULL);
3135 if (tok == Token::FINALLY) {
3136 Consume(Token::FINALLY);
3137 finally_block = ParseBlock(NULL, CHECK_OK);
3138 }
3139
3140 // Simplify the AST nodes by converting:
3141 // 'try B0 catch B1 finally B2'
3142 // to:
3143 // 'try { try B0 catch B1 } finally B2'
3144
3145 if (catch_block != NULL && finally_block != NULL) {
3146 // If we have both, create an inner try/catch.
3147 DCHECK(catch_scope != NULL && catch_variable != NULL);
3148 TryCatchStatement* statement =
3149 factory()->NewTryCatchStatement(try_block, catch_scope, catch_variable,
3150 catch_block, RelocInfo::kNoPosition);
3151 try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
3152 try_block->statements()->Add(statement, zone());
3153 catch_block = NULL; // Clear to indicate it's been handled.
3154 }
3155
3156 TryStatement* result = NULL;
3157 if (catch_block != NULL) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003158 // For a try-catch construct append return expressions from the catch block
3159 // to the list of return expressions.
3160 function_state_->expressions_in_tail_position().AddAll(
3161 expressions_in_tail_position_in_catch_block);
3162
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003163 DCHECK(finally_block == NULL);
3164 DCHECK(catch_scope != NULL && catch_variable != NULL);
3165 result = factory()->NewTryCatchStatement(try_block, catch_scope,
3166 catch_variable, catch_block, pos);
3167 } else {
3168 DCHECK(finally_block != NULL);
3169 result = factory()->NewTryFinallyStatement(try_block, finally_block, pos);
3170 }
3171
3172 return result;
3173}
3174
3175
3176DoWhileStatement* Parser::ParseDoWhileStatement(
3177 ZoneList<const AstRawString*>* labels, bool* ok) {
3178 // DoStatement ::
3179 // 'do' Statement 'while' '(' Expression ')' ';'
3180
3181 DoWhileStatement* loop =
3182 factory()->NewDoWhileStatement(labels, peek_position());
3183 Target target(&this->target_stack_, loop);
3184
3185 Expect(Token::DO, CHECK_OK);
3186 Statement* body = ParseSubStatement(NULL, CHECK_OK);
3187 Expect(Token::WHILE, CHECK_OK);
3188 Expect(Token::LPAREN, CHECK_OK);
3189
3190 Expression* cond = ParseExpression(true, CHECK_OK);
3191 Expect(Token::RPAREN, CHECK_OK);
3192
3193 // Allow do-statements to be terminated with and without
3194 // semi-colons. This allows code such as 'do;while(0)return' to
3195 // parse, which would not be the case if we had used the
3196 // ExpectSemicolon() functionality here.
3197 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
3198
3199 if (loop != NULL) loop->Initialize(cond, body);
3200 return loop;
3201}
3202
3203
3204WhileStatement* Parser::ParseWhileStatement(
3205 ZoneList<const AstRawString*>* labels, bool* ok) {
3206 // WhileStatement ::
3207 // 'while' '(' Expression ')' Statement
3208
3209 WhileStatement* loop = factory()->NewWhileStatement(labels, peek_position());
3210 Target target(&this->target_stack_, loop);
3211
3212 Expect(Token::WHILE, CHECK_OK);
3213 Expect(Token::LPAREN, CHECK_OK);
3214 Expression* cond = ParseExpression(true, CHECK_OK);
3215 Expect(Token::RPAREN, CHECK_OK);
3216 Statement* body = ParseSubStatement(NULL, CHECK_OK);
3217
3218 if (loop != NULL) loop->Initialize(cond, body);
3219 return loop;
3220}
3221
3222
3223// !%_IsJSReceiver(result = iterator.next()) &&
3224// %ThrowIteratorResultNotAnObject(result)
3225Expression* Parser::BuildIteratorNextResult(Expression* iterator,
3226 Variable* result, int pos) {
3227 Expression* next_literal = factory()->NewStringLiteral(
3228 ast_value_factory()->next_string(), RelocInfo::kNoPosition);
3229 Expression* next_property =
3230 factory()->NewProperty(iterator, next_literal, RelocInfo::kNoPosition);
3231 ZoneList<Expression*>* next_arguments =
3232 new (zone()) ZoneList<Expression*>(0, zone());
3233 Expression* next_call =
3234 factory()->NewCall(next_property, next_arguments, pos);
3235 Expression* result_proxy = factory()->NewVariableProxy(result);
3236 Expression* left =
3237 factory()->NewAssignment(Token::ASSIGN, result_proxy, next_call, pos);
3238
3239 // %_IsJSReceiver(...)
3240 ZoneList<Expression*>* is_spec_object_args =
3241 new (zone()) ZoneList<Expression*>(1, zone());
3242 is_spec_object_args->Add(left, zone());
3243 Expression* is_spec_object_call = factory()->NewCallRuntime(
3244 Runtime::kInlineIsJSReceiver, is_spec_object_args, pos);
3245
3246 // %ThrowIteratorResultNotAnObject(result)
3247 Expression* result_proxy_again = factory()->NewVariableProxy(result);
3248 ZoneList<Expression*>* throw_arguments =
3249 new (zone()) ZoneList<Expression*>(1, zone());
3250 throw_arguments->Add(result_proxy_again, zone());
3251 Expression* throw_call = factory()->NewCallRuntime(
3252 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos);
3253
3254 return factory()->NewBinaryOperation(
3255 Token::AND,
3256 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos),
3257 throw_call, pos);
3258}
3259
3260
3261void Parser::InitializeForEachStatement(ForEachStatement* stmt,
3262 Expression* each, Expression* subject,
3263 Statement* body,
3264 bool is_destructuring) {
3265 DCHECK(!is_destructuring || allow_harmony_destructuring_assignment());
3266 ForOfStatement* for_of = stmt->AsForOfStatement();
3267
3268 if (for_of != NULL) {
3269 Variable* iterator = scope_->NewTemporary(
3270 ast_value_factory()->dot_iterator_string());
3271 Variable* result = scope_->NewTemporary(
3272 ast_value_factory()->dot_result_string());
3273
3274 Expression* assign_iterator;
3275 Expression* next_result;
3276 Expression* result_done;
3277 Expression* assign_each;
3278
3279 // iterator = subject[Symbol.iterator]()
3280 // Hackily disambiguate o from o.next and o [Symbol.iterator]().
3281 // TODO(verwaest): Come up with a better solution.
3282 assign_iterator = factory()->NewAssignment(
3283 Token::ASSIGN, factory()->NewVariableProxy(iterator),
3284 GetIterator(subject, factory(), subject->position() - 2),
3285 subject->position());
3286
3287 // !%_IsJSReceiver(result = iterator.next()) &&
3288 // %ThrowIteratorResultNotAnObject(result)
3289 {
3290 // result = iterator.next()
3291 Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
3292 // Hackily disambiguate o from o.next and o [Symbol.iterator]().
3293 // TODO(verwaest): Come up with a better solution.
3294 next_result = BuildIteratorNextResult(iterator_proxy, result,
3295 subject->position() - 1);
3296 }
3297
3298 // result.done
3299 {
3300 Expression* done_literal = factory()->NewStringLiteral(
3301 ast_value_factory()->done_string(), RelocInfo::kNoPosition);
3302 Expression* result_proxy = factory()->NewVariableProxy(result);
3303 result_done = factory()->NewProperty(
3304 result_proxy, done_literal, RelocInfo::kNoPosition);
3305 }
3306
3307 // each = result.value
3308 {
3309 Expression* value_literal = factory()->NewStringLiteral(
3310 ast_value_factory()->value_string(), RelocInfo::kNoPosition);
3311 Expression* result_proxy = factory()->NewVariableProxy(result);
3312 Expression* result_value = factory()->NewProperty(
3313 result_proxy, value_literal, RelocInfo::kNoPosition);
3314 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value,
3315 RelocInfo::kNoPosition);
3316 if (is_destructuring) {
3317 assign_each = PatternRewriter::RewriteDestructuringAssignment(
3318 this, assign_each->AsAssignment(), scope_);
3319 }
3320 }
3321
3322 for_of->Initialize(each, subject, body,
Ben Murdoch097c5b22016-05-18 11:27:45 +01003323 iterator,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003324 assign_iterator,
3325 next_result,
3326 result_done,
3327 assign_each);
3328 } else {
3329 if (is_destructuring) {
3330 Variable* temp =
3331 scope_->NewTemporary(ast_value_factory()->empty_string());
3332 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
3333 Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment(
3334 this, factory()->NewAssignment(Token::ASSIGN, each, temp_proxy,
3335 RelocInfo::kNoPosition),
3336 scope_);
3337 auto block =
3338 factory()->NewBlock(nullptr, 2, false, RelocInfo::kNoPosition);
3339 block->statements()->Add(factory()->NewExpressionStatement(
3340 assign_each, RelocInfo::kNoPosition),
3341 zone());
3342 block->statements()->Add(body, zone());
3343 body = block;
3344 each = factory()->NewVariableProxy(temp);
3345 }
3346 stmt->Initialize(each, subject, body);
3347 }
3348}
3349
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003350Statement* Parser::DesugarLexicalBindingsInForStatement(
Ben Murdoch097c5b22016-05-18 11:27:45 +01003351 Scope* inner_scope, VariableMode mode, ZoneList<const AstRawString*>* names,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003352 ForStatement* loop, Statement* init, Expression* cond, Statement* next,
3353 Statement* body, bool* ok) {
3354 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are
3355 // copied into a new environment. Moreover, the "next" statement must be
3356 // evaluated not in the environment of the just completed iteration but in
3357 // that of the upcoming one. We achieve this with the following desugaring.
3358 // Extra care is needed to preserve the completion value of the original loop.
3359 //
3360 // We are given a for statement of the form
3361 //
3362 // labels: for (let/const x = i; cond; next) body
3363 //
3364 // and rewrite it as follows. Here we write {{ ... }} for init-blocks, ie.,
3365 // blocks whose ignore_completion_value_ flag is set.
3366 //
3367 // {
3368 // let/const x = i;
3369 // temp_x = x;
3370 // first = 1;
3371 // undefined;
3372 // outer: for (;;) {
3373 // let/const x = temp_x;
3374 // {{ if (first == 1) {
3375 // first = 0;
3376 // } else {
3377 // next;
3378 // }
3379 // flag = 1;
3380 // if (!cond) break;
3381 // }}
3382 // labels: for (; flag == 1; flag = 0, temp_x = x) {
3383 // body
3384 // }
3385 // {{ if (flag == 1) // Body used break.
3386 // break;
3387 // }}
3388 // }
3389 // }
3390
3391 DCHECK(names->length() > 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003392 ZoneList<Variable*> temps(names->length(), zone());
3393
3394 Block* outer_block = factory()->NewBlock(NULL, names->length() + 4, false,
3395 RelocInfo::kNoPosition);
3396
3397 // Add statement: let/const x = i.
3398 outer_block->statements()->Add(init, zone());
3399
3400 const AstRawString* temp_name = ast_value_factory()->dot_for_string();
3401
3402 // For each lexical variable x:
3403 // make statement: temp_x = x.
3404 for (int i = 0; i < names->length(); i++) {
3405 VariableProxy* proxy = NewUnresolved(names->at(i), LET);
3406 Variable* temp = scope_->NewTemporary(temp_name);
3407 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
3408 Assignment* assignment = factory()->NewAssignment(
3409 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition);
3410 Statement* assignment_statement = factory()->NewExpressionStatement(
3411 assignment, RelocInfo::kNoPosition);
3412 outer_block->statements()->Add(assignment_statement, zone());
3413 temps.Add(temp, zone());
3414 }
3415
3416 Variable* first = NULL;
3417 // Make statement: first = 1.
3418 if (next) {
3419 first = scope_->NewTemporary(temp_name);
3420 VariableProxy* first_proxy = factory()->NewVariableProxy(first);
3421 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
3422 Assignment* assignment = factory()->NewAssignment(
3423 Token::ASSIGN, first_proxy, const1, RelocInfo::kNoPosition);
3424 Statement* assignment_statement =
3425 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
3426 outer_block->statements()->Add(assignment_statement, zone());
3427 }
3428
3429 // make statement: undefined;
3430 outer_block->statements()->Add(
3431 factory()->NewExpressionStatement(
3432 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
3433 RelocInfo::kNoPosition),
3434 zone());
3435
3436 // Make statement: outer: for (;;)
3437 // Note that we don't actually create the label, or set this loop up as an
3438 // explicit break target, instead handing it directly to those nodes that
3439 // need to know about it. This should be safe because we don't run any code
3440 // in this function that looks up break targets.
3441 ForStatement* outer_loop =
3442 factory()->NewForStatement(NULL, RelocInfo::kNoPosition);
3443 outer_block->statements()->Add(outer_loop, zone());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003444 outer_block->set_scope(scope_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003445
3446 Block* inner_block =
3447 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003448 {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003449 BlockState block_state(&scope_, inner_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003450
Ben Murdoch097c5b22016-05-18 11:27:45 +01003451 Block* ignore_completion_block = factory()->NewBlock(
3452 NULL, names->length() + 3, true, RelocInfo::kNoPosition);
3453 ZoneList<Variable*> inner_vars(names->length(), zone());
3454 // For each let variable x:
3455 // make statement: let/const x = temp_x.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003456 for (int i = 0; i < names->length(); i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003457 VariableProxy* proxy = NewUnresolved(names->at(i), mode);
3458 Declaration* declaration = factory()->NewVariableDeclaration(
3459 proxy, mode, scope_, RelocInfo::kNoPosition);
3460 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
3461 inner_vars.Add(declaration->proxy()->var(), zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003462 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003463 Assignment* assignment = factory()->NewAssignment(
Ben Murdoch097c5b22016-05-18 11:27:45 +01003464 Token::INIT, proxy, temp_proxy, RelocInfo::kNoPosition);
3465 Statement* assignment_statement =
3466 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
3467 DCHECK(init->position() != RelocInfo::kNoPosition);
3468 proxy->var()->set_initializer_position(init->position());
3469 ignore_completion_block->statements()->Add(assignment_statement, zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003470 }
3471
Ben Murdoch097c5b22016-05-18 11:27:45 +01003472 // Make statement: if (first == 1) { first = 0; } else { next; }
3473 if (next) {
3474 DCHECK(first);
3475 Expression* compare = NULL;
3476 // Make compare expression: first == 1.
3477 {
3478 Expression* const1 =
3479 factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
3480 VariableProxy* first_proxy = factory()->NewVariableProxy(first);
3481 compare = factory()->NewCompareOperation(Token::EQ, first_proxy, const1,
3482 RelocInfo::kNoPosition);
3483 }
3484 Statement* clear_first = NULL;
3485 // Make statement: first = 0.
3486 {
3487 VariableProxy* first_proxy = factory()->NewVariableProxy(first);
3488 Expression* const0 =
3489 factory()->NewSmiLiteral(0, RelocInfo::kNoPosition);
3490 Assignment* assignment = factory()->NewAssignment(
3491 Token::ASSIGN, first_proxy, const0, RelocInfo::kNoPosition);
3492 clear_first = factory()->NewExpressionStatement(assignment,
3493 RelocInfo::kNoPosition);
3494 }
3495 Statement* clear_first_or_next = factory()->NewIfStatement(
3496 compare, clear_first, next, RelocInfo::kNoPosition);
3497 ignore_completion_block->statements()->Add(clear_first_or_next, zone());
3498 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003499
Ben Murdoch097c5b22016-05-18 11:27:45 +01003500 Variable* flag = scope_->NewTemporary(temp_name);
3501 // Make statement: flag = 1.
3502 {
3503 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
3504 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
3505 Assignment* assignment = factory()->NewAssignment(
3506 Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition);
3507 Statement* assignment_statement =
3508 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
3509 ignore_completion_block->statements()->Add(assignment_statement, zone());
3510 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003511
Ben Murdoch097c5b22016-05-18 11:27:45 +01003512 // Make statement: if (!cond) break.
3513 if (cond) {
3514 Statement* stop =
3515 factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition);
3516 Statement* noop = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
3517 ignore_completion_block->statements()->Add(
3518 factory()->NewIfStatement(cond, noop, stop, cond->position()),
3519 zone());
3520 }
3521
3522 inner_block->statements()->Add(ignore_completion_block, zone());
3523 // Make cond expression for main loop: flag == 1.
3524 Expression* flag_cond = NULL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003525 {
3526 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
3527 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003528 flag_cond = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
3529 RelocInfo::kNoPosition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003530 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003531
Ben Murdoch097c5b22016-05-18 11:27:45 +01003532 // Create chain of expressions "flag = 0, temp_x = x, ..."
3533 Statement* compound_next_statement = NULL;
3534 {
3535 Expression* compound_next = NULL;
3536 // Make expression: flag = 0.
3537 {
3538 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
3539 Expression* const0 =
3540 factory()->NewSmiLiteral(0, RelocInfo::kNoPosition);
3541 compound_next = factory()->NewAssignment(
3542 Token::ASSIGN, flag_proxy, const0, RelocInfo::kNoPosition);
3543 }
3544
3545 // Make the comma-separated list of temp_x = x assignments.
3546 int inner_var_proxy_pos = scanner()->location().beg_pos;
3547 for (int i = 0; i < names->length(); i++) {
3548 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
3549 VariableProxy* proxy =
3550 factory()->NewVariableProxy(inner_vars.at(i), inner_var_proxy_pos);
3551 Assignment* assignment = factory()->NewAssignment(
3552 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition);
3553 compound_next = factory()->NewBinaryOperation(
3554 Token::COMMA, compound_next, assignment, RelocInfo::kNoPosition);
3555 }
3556
3557 compound_next_statement = factory()->NewExpressionStatement(
3558 compound_next, RelocInfo::kNoPosition);
3559 }
3560
3561 // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x)
3562 // Note that we re-use the original loop node, which retains its labels
3563 // and ensures that any break or continue statements in body point to
3564 // the right place.
3565 loop->Initialize(NULL, flag_cond, compound_next_statement, body);
3566 inner_block->statements()->Add(loop, zone());
3567
3568 // Make statement: {{if (flag == 1) break;}}
3569 {
3570 Expression* compare = NULL;
3571 // Make compare expresion: flag == 1.
3572 {
3573 Expression* const1 =
3574 factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
3575 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
3576 compare = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
3577 RelocInfo::kNoPosition);
3578 }
3579 Statement* stop =
3580 factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition);
3581 Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
3582 Statement* if_flag_break = factory()->NewIfStatement(
3583 compare, stop, empty, RelocInfo::kNoPosition);
3584 Block* ignore_completion_block =
3585 factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
3586 ignore_completion_block->statements()->Add(if_flag_break, zone());
3587 inner_block->statements()->Add(ignore_completion_block, zone());
3588 }
3589
3590 inner_scope->set_end_position(scanner()->location().end_pos);
3591 inner_block->set_scope(inner_scope);
3592 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003593
3594 outer_loop->Initialize(NULL, NULL, NULL, inner_block);
3595 return outer_block;
3596}
3597
3598
3599Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
3600 bool* ok) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003601 int stmt_pos = peek_position();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003602 Statement* init = NULL;
3603 ZoneList<const AstRawString*> lexical_bindings(1, zone());
3604
3605 // Create an in-between scope for let-bound iteration variables.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003606 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003607
3608 BlockState block_state(&scope_, for_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003609 Expect(Token::FOR, CHECK_OK);
3610 Expect(Token::LPAREN, CHECK_OK);
3611 for_scope->set_start_position(scanner()->location().beg_pos);
3612 bool is_let_identifier_expression = false;
3613 DeclarationParsingResult parsing_result;
3614 if (peek() != Token::SEMICOLON) {
3615 if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) ||
3616 (peek() == Token::LET && IsNextLetKeyword())) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003617 ParseVariableDeclarations(kForStatement, &parsing_result, nullptr,
3618 CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003619
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003620 ForEachStatement::VisitMode mode;
3621 int each_beg_pos = scanner()->location().beg_pos;
3622 int each_end_pos = scanner()->location().end_pos;
3623
Ben Murdoch097c5b22016-05-18 11:27:45 +01003624 if (CheckInOrOf(&mode, ok)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003625 if (!*ok) return nullptr;
Ben Murdoch097c5b22016-05-18 11:27:45 +01003626 if (parsing_result.declarations.length() != 1) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003627 ParserTraits::ReportMessageAt(
3628 parsing_result.bindings_loc,
Ben Murdoch097c5b22016-05-18 11:27:45 +01003629 MessageTemplate::kForInOfLoopMultiBindings,
3630 ForEachStatement::VisitModeString(mode));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003631 *ok = false;
3632 return nullptr;
3633 }
3634 DeclarationParsingResult::Declaration& decl =
3635 parsing_result.declarations[0];
3636 if (parsing_result.first_initializer_loc.IsValid() &&
3637 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE ||
3638 IsLexicalVariableMode(parsing_result.descriptor.mode) ||
3639 !decl.pattern->IsVariableProxy())) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003640 ParserTraits::ReportMessageAt(
3641 parsing_result.first_initializer_loc,
3642 MessageTemplate::kForInOfLoopInitializer,
3643 ForEachStatement::VisitModeString(mode));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003644 *ok = false;
3645 return nullptr;
3646 }
3647
3648 Block* init_block = nullptr;
3649
3650 // special case for legacy for (var/const x =.... in)
3651 if (!IsLexicalVariableMode(parsing_result.descriptor.mode) &&
3652 decl.pattern->IsVariableProxy() && decl.initializer != nullptr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003653 ++use_counts_[v8::Isolate::kForInInitializer];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003654 const AstRawString* name =
3655 decl.pattern->AsVariableProxy()->raw_name();
3656 VariableProxy* single_var = scope_->NewUnresolved(
3657 factory(), name, Variable::NORMAL, each_beg_pos, each_end_pos);
3658 init_block = factory()->NewBlock(
3659 nullptr, 2, true, parsing_result.descriptor.declaration_pos);
3660 init_block->statements()->Add(
3661 factory()->NewExpressionStatement(
3662 factory()->NewAssignment(Token::ASSIGN, single_var,
3663 decl.initializer,
3664 RelocInfo::kNoPosition),
3665 RelocInfo::kNoPosition),
3666 zone());
3667 }
3668
3669 // Rewrite a for-in/of statement of the form
3670 //
3671 // for (let/const/var x in/of e) b
3672 //
3673 // into
3674 //
3675 // {
3676 // <let x' be a temporary variable>
3677 // for (x' in/of e) {
3678 // let/const/var x;
3679 // x = x';
3680 // b;
3681 // }
3682 // let x; // for TDZ
3683 // }
3684
Ben Murdoch097c5b22016-05-18 11:27:45 +01003685 Variable* temp =
3686 scope_->NewTemporary(ast_value_factory()->dot_for_string());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003687 ForEachStatement* loop =
3688 factory()->NewForEachStatement(mode, labels, stmt_pos);
3689 Target target(&this->target_stack_, loop);
3690
Ben Murdoch097c5b22016-05-18 11:27:45 +01003691 Expression* enumerable;
3692 if (mode == ForEachStatement::ITERATE) {
3693 ExpressionClassifier classifier(this);
3694 enumerable = ParseAssignmentExpression(true, &classifier, CHECK_OK);
3695 RewriteNonPattern(&classifier, CHECK_OK);
3696 } else {
3697 enumerable = ParseExpression(true, CHECK_OK);
3698 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003699
3700 Expect(Token::RPAREN, CHECK_OK);
3701
3702 Scope* body_scope = NewScope(scope_, BLOCK_SCOPE);
3703 body_scope->set_start_position(scanner()->location().beg_pos);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003704
3705 Block* body_block =
3706 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
3707
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003708 {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003709 BlockState block_state(&scope_, body_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003710
Ben Murdoch097c5b22016-05-18 11:27:45 +01003711 Statement* body = ParseSubStatement(NULL, CHECK_OK);
3712
3713 auto each_initialization_block =
3714 factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
3715 {
3716 auto descriptor = parsing_result.descriptor;
3717 descriptor.declaration_pos = RelocInfo::kNoPosition;
3718 descriptor.initialization_pos = RelocInfo::kNoPosition;
3719 decl.initializer = factory()->NewVariableProxy(temp);
3720
3721 PatternRewriter::DeclareAndInitializeVariables(
3722 each_initialization_block, &descriptor, &decl,
3723 IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings
3724 : nullptr,
3725 CHECK_OK);
3726 }
3727
3728 body_block->statements()->Add(each_initialization_block, zone());
3729 body_block->statements()->Add(body, zone());
3730 VariableProxy* temp_proxy =
3731 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos);
3732 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block,
3733 false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003734 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003735 body_scope->set_end_position(scanner()->location().end_pos);
3736 body_scope = body_scope->FinalizeBlockScope();
Ben Murdoch097c5b22016-05-18 11:27:45 +01003737 body_block->set_scope(body_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003738
3739 // Create a TDZ for any lexically-bound names.
3740 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) {
3741 DCHECK_NULL(init_block);
3742
3743 init_block =
3744 factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition);
3745
3746 for (int i = 0; i < lexical_bindings.length(); ++i) {
3747 // TODO(adamk): This needs to be some sort of special
3748 // INTERNAL variable that's invisible to the debugger
3749 // but visible to everything else.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003750 VariableProxy* tdz_proxy =
3751 NewUnresolved(lexical_bindings[i], LET);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003752 Declaration* tdz_decl = factory()->NewVariableDeclaration(
3753 tdz_proxy, LET, scope_, RelocInfo::kNoPosition);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003754 Variable* tdz_var = Declare(
3755 tdz_decl, DeclarationDescriptor::NORMAL, true, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003756 tdz_var->set_initializer_position(position());
3757 }
3758 }
3759
Ben Murdoch097c5b22016-05-18 11:27:45 +01003760 Statement* final_loop = loop->IsForOfStatement()
3761 ? FinalizeForOfStatement(
3762 loop->AsForOfStatement(), RelocInfo::kNoPosition)
3763 : loop;
3764
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003765 for_scope->set_end_position(scanner()->location().end_pos);
3766 for_scope = for_scope->FinalizeBlockScope();
3767 // Parsed for-in loop w/ variable declarations.
3768 if (init_block != nullptr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003769 init_block->statements()->Add(final_loop, zone());
3770 init_block->set_scope(for_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003771 return init_block;
3772 } else {
3773 DCHECK_NULL(for_scope);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003774 return final_loop;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003775 }
3776 } else {
3777 init = parsing_result.BuildInitializationBlock(
3778 IsLexicalVariableMode(parsing_result.descriptor.mode)
3779 ? &lexical_bindings
3780 : nullptr,
3781 CHECK_OK);
3782 }
3783 } else {
3784 int lhs_beg_pos = peek_position();
Ben Murdoch097c5b22016-05-18 11:27:45 +01003785 ExpressionClassifier classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003786 Expression* expression = ParseExpression(false, &classifier, CHECK_OK);
3787 int lhs_end_pos = scanner()->location().end_pos;
3788 ForEachStatement::VisitMode mode;
3789 is_let_identifier_expression =
3790 expression->IsVariableProxy() &&
3791 expression->AsVariableProxy()->raw_name() ==
3792 ast_value_factory()->let_string();
3793
3794 bool is_for_each = CheckInOrOf(&mode, ok);
3795 if (!*ok) return nullptr;
3796 bool is_destructuring =
3797 is_for_each && allow_harmony_destructuring_assignment() &&
3798 (expression->IsArrayLiteral() || expression->IsObjectLiteral());
3799
3800 if (is_destructuring) {
3801 ValidateAssignmentPattern(&classifier, CHECK_OK);
3802 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003803 RewriteNonPattern(&classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003804 }
3805
3806 if (is_for_each) {
3807 if (!is_destructuring) {
3808 expression = this->CheckAndRewriteReferenceExpression(
3809 expression, lhs_beg_pos, lhs_end_pos,
3810 MessageTemplate::kInvalidLhsInFor, kSyntaxError, CHECK_OK);
3811 }
3812
3813 ForEachStatement* loop =
3814 factory()->NewForEachStatement(mode, labels, stmt_pos);
3815 Target target(&this->target_stack_, loop);
3816
Ben Murdoch097c5b22016-05-18 11:27:45 +01003817 Expression* enumerable;
3818 if (mode == ForEachStatement::ITERATE) {
3819 ExpressionClassifier classifier(this);
3820 enumerable = ParseAssignmentExpression(true, &classifier, CHECK_OK);
3821 RewriteNonPattern(&classifier, CHECK_OK);
3822 } else {
3823 enumerable = ParseExpression(true, CHECK_OK);
3824 }
3825
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003826 Expect(Token::RPAREN, CHECK_OK);
3827
3828 // Make a block around the statement in case a lexical binding
3829 // is introduced, e.g. by a FunctionDeclaration.
3830 // This block must not use for_scope as its scope because if a
3831 // lexical binding is introduced which overlaps with the for-in/of,
3832 // expressions in head of the loop should actually have variables
3833 // resolved in the outer scope.
3834 Scope* body_scope = NewScope(for_scope, BLOCK_SCOPE);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003835 {
3836 BlockState block_state(&scope_, body_scope);
3837 Block* block =
3838 factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
3839 Statement* body = ParseSubStatement(NULL, CHECK_OK);
3840 block->statements()->Add(body, zone());
3841 InitializeForEachStatement(loop, expression, enumerable, block,
3842 is_destructuring);
3843 body_scope->set_end_position(scanner()->location().end_pos);
3844 body_scope = body_scope->FinalizeBlockScope();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003845 block->set_scope(body_scope);
3846 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01003847
3848 Statement* final_loop = loop->IsForOfStatement()
3849 ? FinalizeForOfStatement(
3850 loop->AsForOfStatement(), RelocInfo::kNoPosition)
3851 : loop;
3852
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003853 for_scope->set_end_position(scanner()->location().end_pos);
3854 for_scope = for_scope->FinalizeBlockScope();
3855 DCHECK(for_scope == nullptr);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003856 return final_loop;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003857
3858 } else {
3859 init = factory()->NewExpressionStatement(expression, lhs_beg_pos);
3860 }
3861 }
3862 }
3863
3864 // Standard 'for' loop
3865 ForStatement* loop = factory()->NewForStatement(labels, stmt_pos);
3866 Target target(&this->target_stack_, loop);
3867
3868 // Parsed initializer at this point.
3869 // Detect attempts at 'let' declarations in sloppy mode.
3870 if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER &&
3871 is_sloppy(language_mode()) && is_let_identifier_expression) {
3872 ReportMessage(MessageTemplate::kSloppyLexical, NULL);
3873 *ok = false;
3874 return NULL;
3875 }
3876 Expect(Token::SEMICOLON, CHECK_OK);
3877
Ben Murdoch097c5b22016-05-18 11:27:45 +01003878 Expression* cond = NULL;
3879 Statement* next = NULL;
3880 Statement* body = NULL;
3881
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003882 // If there are let bindings, then condition and the next statement of the
3883 // for loop must be parsed in a new scope.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003884 Scope* inner_scope = scope_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003885 if (lexical_bindings.length() > 0) {
3886 inner_scope = NewScope(for_scope, BLOCK_SCOPE);
3887 inner_scope->set_start_position(scanner()->location().beg_pos);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003888 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01003889 {
3890 BlockState block_state(&scope_, inner_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003891
Ben Murdoch097c5b22016-05-18 11:27:45 +01003892 if (peek() != Token::SEMICOLON) {
3893 cond = ParseExpression(true, CHECK_OK);
3894 }
3895 Expect(Token::SEMICOLON, CHECK_OK);
3896
3897 if (peek() != Token::RPAREN) {
3898 Expression* exp = ParseExpression(true, CHECK_OK);
3899 next = factory()->NewExpressionStatement(exp, exp->position());
3900 }
3901 Expect(Token::RPAREN, CHECK_OK);
3902
3903 body = ParseSubStatement(NULL, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003904 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003905
3906 Statement* result = NULL;
3907 if (lexical_bindings.length() > 0) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003908 BlockState block_state(&scope_, for_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003909 result = DesugarLexicalBindingsInForStatement(
Ben Murdoch097c5b22016-05-18 11:27:45 +01003910 inner_scope, parsing_result.descriptor.mode, &lexical_bindings, loop,
3911 init, cond, next, body, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003912 for_scope->set_end_position(scanner()->location().end_pos);
3913 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003914 for_scope->set_end_position(scanner()->location().end_pos);
3915 for_scope = for_scope->FinalizeBlockScope();
3916 if (for_scope) {
3917 // Rewrite a for statement of the form
3918 // for (const x = i; c; n) b
3919 //
3920 // into
3921 //
3922 // {
3923 // const x = i;
3924 // for (; c; n) b
3925 // }
3926 //
3927 // or, desugar
3928 // for (; c; n) b
3929 // into
3930 // {
3931 // for (; c; n) b
3932 // }
3933 // just in case b introduces a lexical binding some other way, e.g., if b
3934 // is a FunctionDeclaration.
3935 Block* block =
3936 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
3937 if (init != nullptr) {
3938 block->statements()->Add(init, zone());
3939 }
3940 block->statements()->Add(loop, zone());
3941 block->set_scope(for_scope);
3942 loop->Initialize(NULL, cond, next, body);
3943 result = block;
3944 } else {
3945 loop->Initialize(init, cond, next, body);
3946 result = loop;
3947 }
3948 }
3949 return result;
3950}
3951
3952
3953DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
3954 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
3955 // contexts this is used as a statement which invokes the debugger as i a
3956 // break point is present.
3957 // DebuggerStatement ::
3958 // 'debugger' ';'
3959
3960 int pos = peek_position();
3961 Expect(Token::DEBUGGER, CHECK_OK);
3962 ExpectSemicolon(CHECK_OK);
3963 return factory()->NewDebuggerStatement(pos);
3964}
3965
3966
3967bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
3968 if (expression->IsLiteral()) return true;
3969 MaterializedLiteral* lit = expression->AsMaterializedLiteral();
3970 return lit != NULL && lit->is_simple();
3971}
3972
3973
3974Handle<FixedArray> CompileTimeValue::GetValue(Isolate* isolate,
3975 Expression* expression) {
3976 Factory* factory = isolate->factory();
3977 DCHECK(IsCompileTimeValue(expression));
3978 Handle<FixedArray> result = factory->NewFixedArray(2, TENURED);
3979 ObjectLiteral* object_literal = expression->AsObjectLiteral();
3980 if (object_literal != NULL) {
3981 DCHECK(object_literal->is_simple());
3982 if (object_literal->fast_elements()) {
3983 result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
3984 } else {
3985 result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
3986 }
3987 result->set(kElementsSlot, *object_literal->constant_properties());
3988 } else {
3989 ArrayLiteral* array_literal = expression->AsArrayLiteral();
3990 DCHECK(array_literal != NULL && array_literal->is_simple());
3991 result->set(kLiteralTypeSlot, Smi::FromInt(ARRAY_LITERAL));
3992 result->set(kElementsSlot, *array_literal->constant_elements());
3993 }
3994 return result;
3995}
3996
3997
3998CompileTimeValue::LiteralType CompileTimeValue::GetLiteralType(
3999 Handle<FixedArray> value) {
4000 Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot));
4001 return static_cast<LiteralType>(literal_type->value());
4002}
4003
4004
4005Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
4006 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
4007}
4008
4009
4010void ParserTraits::ParseArrowFunctionFormalParameters(
4011 ParserFormalParameters* parameters, Expression* expr,
4012 const Scanner::Location& params_loc, bool* ok) {
4013 if (parameters->Arity() >= Code::kMaxArguments) {
4014 ReportMessageAt(params_loc, MessageTemplate::kMalformedArrowFunParamList);
4015 *ok = false;
4016 return;
4017 }
4018
4019 // ArrowFunctionFormals ::
4020 // Binary(Token::COMMA, NonTailArrowFunctionFormals, Tail)
4021 // Tail
4022 // NonTailArrowFunctionFormals ::
4023 // Binary(Token::COMMA, NonTailArrowFunctionFormals, VariableProxy)
4024 // VariableProxy
4025 // Tail ::
4026 // VariableProxy
4027 // Spread(VariableProxy)
4028 //
4029 // As we need to visit the parameters in left-to-right order, we recurse on
4030 // the left-hand side of comma expressions.
4031 //
4032 if (expr->IsBinaryOperation()) {
4033 BinaryOperation* binop = expr->AsBinaryOperation();
4034 // The classifier has already run, so we know that the expression is a valid
4035 // arrow function formals production.
4036 DCHECK_EQ(binop->op(), Token::COMMA);
4037 Expression* left = binop->left();
4038 Expression* right = binop->right();
4039 ParseArrowFunctionFormalParameters(parameters, left, params_loc, ok);
4040 if (!*ok) return;
4041 // LHS of comma expression should be unparenthesized.
4042 expr = right;
4043 }
4044
4045 // Only the right-most expression may be a rest parameter.
4046 DCHECK(!parameters->has_rest);
4047
4048 bool is_rest = expr->IsSpread();
4049 if (is_rest) {
4050 expr = expr->AsSpread()->expression();
4051 parameters->has_rest = true;
4052 }
4053 if (parameters->is_simple) {
4054 parameters->is_simple = !is_rest && expr->IsVariableProxy();
4055 }
4056
4057 Expression* initializer = nullptr;
4058 if (expr->IsVariableProxy()) {
4059 // When the formal parameter was originally seen, it was parsed as a
4060 // VariableProxy and recorded as unresolved in the scope. Here we undo that
4061 // parse-time side-effect for parameters that are single-names (not
4062 // patterns; for patterns that happens uniformly in
4063 // PatternRewriter::VisitVariableProxy).
4064 parser_->scope_->RemoveUnresolved(expr->AsVariableProxy());
4065 } else if (expr->IsAssignment()) {
4066 Assignment* assignment = expr->AsAssignment();
4067 DCHECK(parser_->allow_harmony_default_parameters());
4068 DCHECK(!assignment->is_compound());
4069 initializer = assignment->value();
4070 expr = assignment->target();
4071
4072 // TODO(adamk): Only call this if necessary.
4073 RewriteParameterInitializerScope(parser_->stack_limit(), initializer,
4074 parser_->scope_, parameters->scope);
4075 }
4076
4077 // TODO(adamk): params_loc.end_pos is not the correct initializer position,
4078 // but it should be conservative enough to trigger hole checks for variables
4079 // referenced in the initializer (if any).
4080 AddFormalParameter(parameters, expr, initializer, params_loc.end_pos,
4081 is_rest);
4082}
4083
4084
4085DoExpression* Parser::ParseDoExpression(bool* ok) {
4086 // AssignmentExpression ::
4087 // do '{' StatementList '}'
4088 int pos = peek_position();
4089
4090 Expect(Token::DO, CHECK_OK);
4091 Variable* result =
4092 scope_->NewTemporary(ast_value_factory()->dot_result_string());
4093 Block* block = ParseBlock(nullptr, false, CHECK_OK);
4094 DoExpression* expr = factory()->NewDoExpression(block, result, pos);
4095 if (!Rewriter::Rewrite(this, expr, ast_value_factory())) {
4096 *ok = false;
4097 return nullptr;
4098 }
4099 block->set_scope(block->scope()->FinalizeBlockScope());
4100 return expr;
4101}
4102
4103
4104void ParserTraits::ParseArrowFunctionFormalParameterList(
4105 ParserFormalParameters* parameters, Expression* expr,
4106 const Scanner::Location& params_loc,
4107 Scanner::Location* duplicate_loc, bool* ok) {
4108 if (expr->IsEmptyParentheses()) return;
4109
4110 ParseArrowFunctionFormalParameters(parameters, expr, params_loc, ok);
4111 if (!*ok) return;
4112
Ben Murdoch097c5b22016-05-18 11:27:45 +01004113 Type::ExpressionClassifier classifier(parser_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004114 if (!parameters->is_simple) {
4115 classifier.RecordNonSimpleParameter();
4116 }
4117 for (int i = 0; i < parameters->Arity(); ++i) {
4118 auto parameter = parameters->at(i);
4119 DeclareFormalParameter(parameters->scope, parameter, &classifier);
4120 if (!duplicate_loc->IsValid()) {
4121 *duplicate_loc = classifier.duplicate_formal_parameter_error().location;
4122 }
4123 }
4124 DCHECK_EQ(parameters->is_simple, parameters->scope->has_simple_parameters());
4125}
4126
4127
4128void ParserTraits::ReindexLiterals(const ParserFormalParameters& parameters) {
4129 if (parser_->function_state_->materialized_literal_count() > 0) {
4130 AstLiteralReindexer reindexer;
4131
4132 for (const auto p : parameters.params) {
4133 if (p.pattern != nullptr) reindexer.Reindex(p.pattern);
4134 if (p.initializer != nullptr) reindexer.Reindex(p.initializer);
4135 }
4136
4137 DCHECK(reindexer.count() <=
4138 parser_->function_state_->materialized_literal_count());
4139 }
4140}
4141
4142
4143FunctionLiteral* Parser::ParseFunctionLiteral(
4144 const AstRawString* function_name, Scanner::Location function_name_location,
4145 FunctionNameValidity function_name_validity, FunctionKind kind,
4146 int function_token_pos, FunctionLiteral::FunctionType function_type,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004147 LanguageMode language_mode, bool* ok) {
4148 // Function ::
4149 // '(' FormalParameterList? ')' '{' FunctionBody '}'
4150 //
4151 // Getter ::
4152 // '(' ')' '{' FunctionBody '}'
4153 //
4154 // Setter ::
4155 // '(' PropertySetParameterList ')' '{' FunctionBody '}'
4156
4157 int pos = function_token_pos == RelocInfo::kNoPosition
4158 ? peek_position() : function_token_pos;
4159
4160 bool is_generator = IsGeneratorFunction(kind);
4161
4162 // Anonymous functions were passed either the empty symbol or a null
4163 // handle as the function name. Remember if we were passed a non-empty
4164 // handle to decide whether to invoke function name inference.
4165 bool should_infer_name = function_name == NULL;
4166
4167 // We want a non-null handle as the function name.
4168 if (should_infer_name) {
4169 function_name = ast_value_factory()->empty_string();
4170 }
4171
4172 // Function declarations are function scoped in normal mode, so they are
4173 // hoisted. In harmony block scoping mode they are block scoped, so they
4174 // are not hoisted.
4175 //
4176 // One tricky case are function declarations in a local sloppy-mode eval:
4177 // their declaration is hoisted, but they still see the local scope. E.g.,
4178 //
4179 // function() {
4180 // var x = 0
4181 // try { throw 1 } catch (x) { eval("function g() { return x }") }
4182 // return g()
4183 // }
4184 //
4185 // needs to return 1. To distinguish such cases, we need to detect
4186 // (1) whether a function stems from a sloppy eval, and
4187 // (2) whether it actually hoists across the eval.
4188 // Unfortunately, we do not represent sloppy eval scopes, so we do not have
4189 // either information available directly, especially not when lazily compiling
4190 // a function like 'g'. We hence rely on the following invariants:
4191 // - (1) is the case iff the innermost scope of the deserialized scope chain
4192 // under which we compile is _not_ a declaration scope. This holds because
4193 // in all normal cases, function declarations are fully hoisted to a
4194 // declaration scope and compiled relative to that.
4195 // - (2) is the case iff the current declaration scope is still the original
4196 // one relative to the deserialized scope chain. Otherwise we must be
4197 // compiling a function in an inner declaration scope in the eval, e.g. a
4198 // nested function, and hoisting works normally relative to that.
4199 Scope* declaration_scope = scope_->DeclarationScope();
4200 Scope* original_declaration_scope = original_scope_->DeclarationScope();
4201 Scope* scope = function_type == FunctionLiteral::kDeclaration &&
4202 is_sloppy(language_mode) &&
4203 !allow_harmony_sloppy_function() &&
4204 (original_scope_ == original_declaration_scope ||
4205 declaration_scope != original_declaration_scope)
4206 ? NewScope(declaration_scope, FUNCTION_SCOPE, kind)
4207 : NewScope(scope_, FUNCTION_SCOPE, kind);
4208 SetLanguageMode(scope, language_mode);
4209 ZoneList<Statement*>* body = NULL;
4210 int arity = -1;
4211 int materialized_literal_count = -1;
4212 int expected_property_count = -1;
4213 DuplicateFinder duplicate_finder(scanner()->unicode_cache());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004214 FunctionLiteral::EagerCompileHint eager_compile_hint =
4215 parenthesized_function_ ? FunctionLiteral::kShouldEagerCompile
4216 : FunctionLiteral::kShouldLazyCompile;
4217 bool should_be_used_once_hint = false;
Ben Murdoch097c5b22016-05-18 11:27:45 +01004218 bool has_duplicate_parameters;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004219 // Parse function.
4220 {
4221 AstNodeFactory function_factory(ast_value_factory());
4222 FunctionState function_state(&function_state_, &scope_, scope, kind,
4223 &function_factory);
4224 scope_->SetScopeName(function_name);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004225 ExpressionClassifier formals_classifier(this, &duplicate_finder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004226
4227 if (is_generator) {
4228 // For generators, allocating variables in contexts is currently a win
4229 // because it minimizes the work needed to suspend and resume an
4230 // activation.
4231 scope_->ForceContextAllocation();
4232
4233 // Calling a generator returns a generator object. That object is stored
4234 // in a temporary variable, a definition that is used by "yield"
4235 // expressions. This also marks the FunctionState as a generator.
4236 Variable* temp = scope_->NewTemporary(
4237 ast_value_factory()->dot_generator_object_string());
4238 function_state.set_generator_object_variable(temp);
4239 }
4240
4241 Expect(Token::LPAREN, CHECK_OK);
4242 int start_position = scanner()->location().beg_pos;
4243 scope_->set_start_position(start_position);
4244 ParserFormalParameters formals(scope);
4245 ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK);
4246 arity = formals.Arity();
4247 Expect(Token::RPAREN, CHECK_OK);
4248 int formals_end_position = scanner()->location().end_pos;
4249
Ben Murdoch097c5b22016-05-18 11:27:45 +01004250 CheckArityRestrictions(arity, kind, formals.has_rest, start_position,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004251 formals_end_position, CHECK_OK);
4252 Expect(Token::LBRACE, CHECK_OK);
4253
Ben Murdoch097c5b22016-05-18 11:27:45 +01004254 // Don't include the rest parameter into the function's formal parameter
4255 // count (esp. the SharedFunctionInfo::internal_formal_parameter_count,
4256 // which says whether we need to create an arguments adaptor frame).
4257 if (formals.has_rest) arity--;
4258
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004259 // Determine if the function can be parsed lazily. Lazy parsing is different
4260 // from lazy compilation; we need to parse more eagerly than we compile.
4261
4262 // We can only parse lazily if we also compile lazily. The heuristics for
4263 // lazy compilation are:
4264 // - It must not have been prohibited by the caller to Parse (some callers
4265 // need a full AST).
4266 // - The outer scope must allow lazy compilation of inner functions.
4267 // - The function mustn't be a function expression with an open parenthesis
4268 // before; we consider that a hint that the function will be called
4269 // immediately, and it would be a waste of time to make it lazily
4270 // compiled.
4271 // These are all things we can know at this point, without looking at the
4272 // function itself.
4273
4274 // In addition, we need to distinguish between these cases:
4275 // (function foo() {
4276 // bar = function() { return 1; }
4277 // })();
4278 // and
4279 // (function foo() {
4280 // var a = 1;
4281 // bar = function() { return a; }
4282 // })();
4283
4284 // Now foo will be parsed eagerly and compiled eagerly (optimization: assume
4285 // parenthesis before the function means that it will be called
4286 // immediately). The inner function *must* be parsed eagerly to resolve the
4287 // possible reference to the variable in foo's scope. However, it's possible
4288 // that it will be compiled lazily.
4289
4290 // To make this additional case work, both Parser and PreParser implement a
4291 // logic where only top-level functions will be parsed lazily.
4292 bool is_lazily_parsed = mode() == PARSE_LAZILY &&
4293 scope_->AllowsLazyParsing() &&
4294 !parenthesized_function_;
4295 parenthesized_function_ = false; // The bit was set for this function only.
4296
4297 // Eager or lazy parse?
4298 // If is_lazily_parsed, we'll parse lazy. If we can set a bookmark, we'll
4299 // pass it to SkipLazyFunctionBody, which may use it to abort lazy
4300 // parsing if it suspect that wasn't a good idea. If so, or if we didn't
4301 // try to lazy parse in the first place, we'll have to parse eagerly.
4302 Scanner::BookmarkScope bookmark(scanner());
4303 if (is_lazily_parsed) {
4304 Scanner::BookmarkScope* maybe_bookmark =
4305 bookmark.Set() ? &bookmark : nullptr;
4306 SkipLazyFunctionBody(&materialized_literal_count,
4307 &expected_property_count, /*CHECK_OK*/ ok,
4308 maybe_bookmark);
4309
4310 materialized_literal_count += formals.materialized_literals_count +
4311 function_state.materialized_literal_count();
4312
4313 if (bookmark.HasBeenReset()) {
4314 // Trigger eager (re-)parsing, just below this block.
4315 is_lazily_parsed = false;
4316
4317 // This is probably an initialization function. Inform the compiler it
4318 // should also eager-compile this function, and that we expect it to be
4319 // used once.
4320 eager_compile_hint = FunctionLiteral::kShouldEagerCompile;
4321 should_be_used_once_hint = true;
4322 }
4323 }
4324 if (!is_lazily_parsed) {
4325 // Determine whether the function body can be discarded after parsing.
4326 // The preconditions are:
4327 // - Lazy compilation has to be enabled.
4328 // - Neither V8 natives nor native function declarations can be allowed,
4329 // since parsing one would retroactively force the function to be
4330 // eagerly compiled.
4331 // - The invoker of this parser can't depend on the AST being eagerly
4332 // built (either because the function is about to be compiled, or
4333 // because the AST is going to be inspected for some reason).
4334 // - Because of the above, we can't be attempting to parse a
4335 // FunctionExpression; even without enclosing parentheses it might be
4336 // immediately invoked.
4337 // - The function literal shouldn't be hinted to eagerly compile.
4338 bool use_temp_zone =
4339 FLAG_lazy && !allow_natives() && extension_ == NULL && allow_lazy() &&
4340 function_type == FunctionLiteral::kDeclaration &&
4341 eager_compile_hint != FunctionLiteral::kShouldEagerCompile;
4342 // Open a new BodyScope, which sets our AstNodeFactory to allocate in the
4343 // new temporary zone if the preconditions are satisfied, and ensures that
4344 // the previous zone is always restored after parsing the body.
4345 // For the purpose of scope analysis, some ZoneObjects allocated by the
4346 // factory must persist after the function body is thrown away and
4347 // temp_zone is deallocated. These objects are instead allocated in a
4348 // parser-persistent zone (see parser_zone_ in AstNodeFactory).
4349 {
4350 Zone temp_zone;
4351 AstNodeFactory::BodyScope inner(factory(), &temp_zone, use_temp_zone);
4352
4353 body = ParseEagerFunctionBody(function_name, pos, formals, kind,
4354 function_type, CHECK_OK);
4355 }
4356 materialized_literal_count = function_state.materialized_literal_count();
4357 expected_property_count = function_state.expected_property_count();
4358 if (use_temp_zone) {
4359 // If the preconditions are correct the function body should never be
4360 // accessed, but do this anyway for better behaviour if they're wrong.
4361 body = NULL;
4362 }
4363 }
4364
4365 // Parsing the body may change the language mode in our scope.
4366 language_mode = scope->language_mode();
4367
4368 if (is_strong(language_mode) && IsSubclassConstructor(kind)) {
4369 if (!function_state.super_location().IsValid()) {
4370 ReportMessageAt(function_name_location,
4371 MessageTemplate::kStrongSuperCallMissing,
4372 kReferenceError);
4373 *ok = false;
4374 return nullptr;
4375 }
4376 }
4377
4378 // Validate name and parameter names. We can do this only after parsing the
4379 // function, since the function can declare itself strict.
4380 CheckFunctionName(language_mode, function_name, function_name_validity,
4381 function_name_location, CHECK_OK);
4382 const bool allow_duplicate_parameters =
4383 is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind);
4384 ValidateFormalParameters(&formals_classifier, language_mode,
4385 allow_duplicate_parameters, CHECK_OK);
4386
4387 if (is_strict(language_mode)) {
4388 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(),
4389 CHECK_OK);
4390 }
4391 if (is_sloppy(language_mode) && allow_harmony_sloppy_function()) {
4392 InsertSloppyBlockFunctionVarBindings(scope, CHECK_OK);
4393 }
4394 if (is_strict(language_mode) || allow_harmony_sloppy() ||
4395 allow_harmony_destructuring_bind()) {
4396 CheckConflictingVarDeclarations(scope, CHECK_OK);
4397 }
4398
4399 if (body) {
4400 // If body can be inspected, rewrite queued destructuring assignments
4401 ParserTraits::RewriteDestructuringAssignments();
4402 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01004403 has_duplicate_parameters =
4404 !formals_classifier.is_valid_formal_parameter_list_without_duplicates();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004405 }
4406
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004407 FunctionLiteral::ParameterFlag duplicate_parameters =
4408 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters
4409 : FunctionLiteral::kNoDuplicateParameters;
4410
4411 FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
4412 function_name, scope, body, materialized_literal_count,
4413 expected_property_count, arity, duplicate_parameters, function_type,
4414 eager_compile_hint, kind, pos);
4415 function_literal->set_function_token_position(function_token_pos);
4416 if (should_be_used_once_hint)
4417 function_literal->set_should_be_used_once_hint();
4418
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004419 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
4420 return function_literal;
4421}
4422
4423
4424void Parser::SkipLazyFunctionBody(int* materialized_literal_count,
4425 int* expected_property_count, bool* ok,
4426 Scanner::BookmarkScope* bookmark) {
4427 DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet());
4428 if (produce_cached_parse_data()) CHECK(log_);
4429
4430 int function_block_pos = position();
4431 if (consume_cached_parse_data() && !cached_parse_data_->rejected()) {
4432 // If we have cached data, we use it to skip parsing the function body. The
4433 // data contains the information we need to construct the lazy function.
4434 FunctionEntry entry =
4435 cached_parse_data_->GetFunctionEntry(function_block_pos);
4436 // Check that cached data is valid. If not, mark it as invalid (the embedder
4437 // handles it). Note that end position greater than end of stream is safe,
4438 // and hard to check.
4439 if (entry.is_valid() && entry.end_pos() > function_block_pos) {
4440 scanner()->SeekForward(entry.end_pos() - 1);
4441
4442 scope_->set_end_position(entry.end_pos());
4443 Expect(Token::RBRACE, ok);
4444 if (!*ok) {
4445 return;
4446 }
4447 total_preparse_skipped_ += scope_->end_position() - function_block_pos;
4448 *materialized_literal_count = entry.literal_count();
4449 *expected_property_count = entry.property_count();
4450 SetLanguageMode(scope_, entry.language_mode());
4451 if (entry.uses_super_property()) scope_->RecordSuperPropertyUsage();
4452 if (entry.calls_eval()) scope_->RecordEvalCall();
4453 return;
4454 }
4455 cached_parse_data_->Reject();
4456 }
4457 // With no cached data, we partially parse the function, without building an
4458 // AST. This gathers the data needed to build a lazy function.
4459 SingletonLogger logger;
4460 PreParser::PreParseResult result =
4461 ParseLazyFunctionBodyWithPreParser(&logger, bookmark);
4462 if (bookmark && bookmark->HasBeenReset()) {
4463 return; // Return immediately if pre-parser devided to abort parsing.
4464 }
4465 if (result == PreParser::kPreParseStackOverflow) {
4466 // Propagate stack overflow.
4467 set_stack_overflow();
4468 *ok = false;
4469 return;
4470 }
4471 if (logger.has_error()) {
4472 ParserTraits::ReportMessageAt(
4473 Scanner::Location(logger.start(), logger.end()), logger.message(),
4474 logger.argument_opt(), logger.error_type());
4475 *ok = false;
4476 return;
4477 }
4478 scope_->set_end_position(logger.end());
4479 Expect(Token::RBRACE, ok);
4480 if (!*ok) {
4481 return;
4482 }
4483 total_preparse_skipped_ += scope_->end_position() - function_block_pos;
4484 *materialized_literal_count = logger.literals();
4485 *expected_property_count = logger.properties();
4486 SetLanguageMode(scope_, logger.language_mode());
4487 if (logger.uses_super_property()) {
4488 scope_->RecordSuperPropertyUsage();
4489 }
4490 if (logger.calls_eval()) {
4491 scope_->RecordEvalCall();
4492 }
4493 if (produce_cached_parse_data()) {
4494 DCHECK(log_);
4495 // Position right after terminal '}'.
4496 int body_end = scanner()->location().end_pos;
4497 log_->LogFunction(function_block_pos, body_end, *materialized_literal_count,
4498 *expected_property_count, scope_->language_mode(),
4499 scope_->uses_super_property(), scope_->calls_eval());
4500 }
4501}
4502
4503
4504Statement* Parser::BuildAssertIsCoercible(Variable* var) {
4505 // if (var === null || var === undefined)
4506 // throw /* type error kNonCoercible) */;
4507
4508 Expression* condition = factory()->NewBinaryOperation(
4509 Token::OR, factory()->NewCompareOperation(
4510 Token::EQ_STRICT, factory()->NewVariableProxy(var),
4511 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
4512 RelocInfo::kNoPosition),
4513 factory()->NewCompareOperation(
4514 Token::EQ_STRICT, factory()->NewVariableProxy(var),
4515 factory()->NewNullLiteral(RelocInfo::kNoPosition),
4516 RelocInfo::kNoPosition),
4517 RelocInfo::kNoPosition);
4518 Expression* throw_type_error = this->NewThrowTypeError(
4519 MessageTemplate::kNonCoercible, ast_value_factory()->empty_string(),
4520 RelocInfo::kNoPosition);
4521 IfStatement* if_statement = factory()->NewIfStatement(
4522 condition, factory()->NewExpressionStatement(throw_type_error,
4523 RelocInfo::kNoPosition),
4524 factory()->NewEmptyStatement(RelocInfo::kNoPosition),
4525 RelocInfo::kNoPosition);
4526 return if_statement;
4527}
4528
4529
4530class InitializerRewriter : public AstExpressionVisitor {
4531 public:
4532 InitializerRewriter(uintptr_t stack_limit, Expression* root, Parser* parser,
4533 Scope* scope)
4534 : AstExpressionVisitor(stack_limit, root),
4535 parser_(parser),
4536 scope_(scope) {}
4537
4538 private:
Ben Murdoch097c5b22016-05-18 11:27:45 +01004539 void VisitExpression(Expression* expr) override {
4540 RewritableExpression* to_rewrite = expr->AsRewritableExpression();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004541 if (to_rewrite == nullptr || to_rewrite->is_rewritten()) return;
4542
4543 Parser::PatternRewriter::RewriteDestructuringAssignment(parser_, to_rewrite,
4544 scope_);
4545 }
4546
Ben Murdoch097c5b22016-05-18 11:27:45 +01004547 // Code in function literals does not need to be eagerly rewritten, it will be
4548 // rewritten when scheduled.
4549 void VisitFunctionLiteral(FunctionLiteral* expr) override {}
4550
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004551 private:
4552 Parser* parser_;
4553 Scope* scope_;
4554};
4555
4556
4557void Parser::RewriteParameterInitializer(Expression* expr, Scope* scope) {
4558 InitializerRewriter rewriter(stack_limit_, expr, this, scope);
4559 rewriter.Run();
4560}
4561
4562
4563Block* Parser::BuildParameterInitializationBlock(
4564 const ParserFormalParameters& parameters, bool* ok) {
4565 DCHECK(!parameters.is_simple);
4566 DCHECK(scope_->is_function_scope());
4567 Block* init_block =
4568 factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
4569 for (int i = 0; i < parameters.params.length(); ++i) {
4570 auto parameter = parameters.params[i];
4571 if (parameter.is_rest && parameter.pattern->IsVariableProxy()) break;
4572 DeclarationDescriptor descriptor;
4573 descriptor.declaration_kind = DeclarationDescriptor::PARAMETER;
4574 descriptor.parser = this;
4575 descriptor.scope = scope_;
4576 descriptor.hoist_scope = nullptr;
4577 descriptor.mode = LET;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004578 descriptor.declaration_pos = parameter.pattern->position();
4579 // The position that will be used by the AssignmentExpression
4580 // which copies from the temp parameter to the pattern.
4581 //
4582 // TODO(adamk): Should this be RelocInfo::kNoPosition, since
4583 // it's just copying from a temp var to the real param var?
4584 descriptor.initialization_pos = parameter.pattern->position();
4585 // The initializer position which will end up in,
4586 // Variable::initializer_position(), used for hole check elimination.
4587 int initializer_position = parameter.pattern->position();
4588 Expression* initial_value =
4589 factory()->NewVariableProxy(parameters.scope->parameter(i));
4590 if (parameter.initializer != nullptr) {
4591 // IS_UNDEFINED($param) ? initializer : $param
4592
4593 // Ensure initializer is rewritten
4594 RewriteParameterInitializer(parameter.initializer, scope_);
4595
4596 auto condition = factory()->NewCompareOperation(
4597 Token::EQ_STRICT,
4598 factory()->NewVariableProxy(parameters.scope->parameter(i)),
4599 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
4600 RelocInfo::kNoPosition);
4601 initial_value = factory()->NewConditional(
4602 condition, parameter.initializer, initial_value,
4603 RelocInfo::kNoPosition);
4604 descriptor.initialization_pos = parameter.initializer->position();
4605 initializer_position = parameter.initializer_end_position;
4606 }
4607
4608 Scope* param_scope = scope_;
4609 Block* param_block = init_block;
4610 if (!parameter.is_simple() && scope_->calls_sloppy_eval()) {
4611 param_scope = NewScope(scope_, BLOCK_SCOPE);
4612 param_scope->set_is_declaration_scope();
4613 param_scope->set_start_position(parameter.pattern->position());
4614 param_scope->set_end_position(RelocInfo::kNoPosition);
4615 param_scope->RecordEvalCall();
4616 param_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition);
4617 param_block->set_scope(param_scope);
4618 descriptor.hoist_scope = scope_;
4619 }
4620
4621 {
4622 BlockState block_state(&scope_, param_scope);
4623 DeclarationParsingResult::Declaration decl(
4624 parameter.pattern, initializer_position, initial_value);
4625 PatternRewriter::DeclareAndInitializeVariables(param_block, &descriptor,
4626 &decl, nullptr, CHECK_OK);
4627 }
4628
4629 if (!parameter.is_simple() && scope_->calls_sloppy_eval()) {
4630 param_scope = param_scope->FinalizeBlockScope();
4631 if (param_scope != nullptr) {
4632 CheckConflictingVarDeclarations(param_scope, CHECK_OK);
4633 }
4634 init_block->statements()->Add(param_block, zone());
4635 }
4636 }
4637 return init_block;
4638}
4639
4640
4641ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
4642 const AstRawString* function_name, int pos,
4643 const ParserFormalParameters& parameters, FunctionKind kind,
4644 FunctionLiteral::FunctionType function_type, bool* ok) {
4645 // Everything inside an eagerly parsed function will be parsed eagerly
4646 // (see comment above).
4647 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
4648 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone());
4649
4650 static const int kFunctionNameAssignmentIndex = 0;
4651 if (function_type == FunctionLiteral::kNamedExpression) {
4652 DCHECK(function_name != NULL);
4653 // If we have a named function expression, we add a local variable
4654 // declaration to the body of the function with the name of the
4655 // function and let it refer to the function itself (closure).
4656 // Not having parsed the function body, the language mode may still change,
4657 // so we reserve a spot and create the actual const assignment later.
4658 DCHECK_EQ(kFunctionNameAssignmentIndex, result->length());
4659 result->Add(NULL, zone());
4660 }
4661
4662 ZoneList<Statement*>* body = result;
4663 Scope* inner_scope = scope_;
4664 Block* inner_block = nullptr;
4665 if (!parameters.is_simple) {
4666 inner_scope = NewScope(scope_, BLOCK_SCOPE);
4667 inner_scope->set_is_declaration_scope();
4668 inner_scope->set_start_position(scanner()->location().beg_pos);
4669 inner_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition);
4670 inner_block->set_scope(inner_scope);
4671 body = inner_block->statements();
4672 }
4673
4674 {
4675 BlockState block_state(&scope_, inner_scope);
4676
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004677 if (IsGeneratorFunction(kind)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004678 // We produce:
4679 //
4680 // try { InitialYield; ...body...; FinalYield }
4681 // finally { %GeneratorClose(generator) }
4682 //
4683 // - InitialYield yields the actual generator object.
4684 // - FinalYield yields {value: foo, done: true} where foo is the
4685 // completion value of body. (This is needed here in case the body
4686 // falls through without an explicit return.)
4687 // - Any return statement inside the body will be converted into a similar
4688 // FinalYield.
4689 // - If the generator terminates for whatever reason, we must close it.
4690 // Hence the finally clause.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004691
Ben Murdoch097c5b22016-05-18 11:27:45 +01004692 Block* try_block =
4693 factory()->NewBlock(nullptr, 3, false, RelocInfo::kNoPosition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004694
Ben Murdoch097c5b22016-05-18 11:27:45 +01004695 {
4696 ZoneList<Expression*>* arguments =
4697 new (zone()) ZoneList<Expression*>(0, zone());
4698 CallRuntime* allocation = factory()->NewCallRuntime(
4699 Runtime::kCreateJSGeneratorObject, arguments, pos);
4700 VariableProxy* init_proxy = factory()->NewVariableProxy(
4701 function_state_->generator_object_variable());
4702 Assignment* assignment = factory()->NewAssignment(
4703 Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition);
4704 VariableProxy* get_proxy = factory()->NewVariableProxy(
4705 function_state_->generator_object_variable());
4706 Yield* yield = factory()->NewYield(
4707 get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition);
4708 try_block->statements()->Add(
4709 factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition),
4710 zone());
4711 }
4712
4713 ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK);
4714
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004715 VariableProxy* get_proxy = factory()->NewVariableProxy(
4716 function_state_->generator_object_variable());
4717 Expression* undefined =
4718 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition);
4719 Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal,
4720 RelocInfo::kNoPosition);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004721 try_block->statements()->Add(
4722 factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition),
4723 zone());
4724
4725 Block* finally_block =
4726 factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition);
4727 ZoneList<Expression*>* args =
4728 new (zone()) ZoneList<Expression*>(1, zone());
4729 VariableProxy* call_proxy = factory()->NewVariableProxy(
4730 function_state_->generator_object_variable());
4731 args->Add(call_proxy, zone());
4732 Expression* call = factory()->NewCallRuntime(
4733 Runtime::kGeneratorClose, args, RelocInfo::kNoPosition);
4734 finally_block->statements()->Add(
4735 factory()->NewExpressionStatement(call, RelocInfo::kNoPosition),
4736 zone());
4737
4738 body->Add(factory()->NewTryFinallyStatement(try_block, finally_block,
4739 RelocInfo::kNoPosition),
4740 zone());
4741 } else {
4742 ParseStatementList(body, Token::RBRACE, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004743 }
4744
4745 if (IsSubclassConstructor(kind)) {
4746 body->Add(
4747 factory()->NewReturnStatement(
4748 this->ThisExpression(scope_, factory(), RelocInfo::kNoPosition),
4749 RelocInfo::kNoPosition),
4750 zone());
4751 }
4752 }
4753
4754 Expect(Token::RBRACE, CHECK_OK);
4755 scope_->set_end_position(scanner()->location().end_pos);
4756
4757 if (!parameters.is_simple) {
4758 DCHECK_NOT_NULL(inner_scope);
4759 DCHECK_EQ(body, inner_block->statements());
4760 SetLanguageMode(scope_, inner_scope->language_mode());
4761 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK);
4762 DCHECK_NOT_NULL(init_block);
4763
4764 inner_scope->set_end_position(scanner()->location().end_pos);
4765 inner_scope = inner_scope->FinalizeBlockScope();
4766 if (inner_scope != nullptr) {
4767 CheckConflictingVarDeclarations(inner_scope, CHECK_OK);
4768 InsertShadowingVarBindingInitializers(inner_block);
4769 }
4770
4771 result->Add(init_block, zone());
4772 result->Add(inner_block, zone());
4773 }
4774
4775 if (function_type == FunctionLiteral::kNamedExpression) {
4776 // Now that we know the language mode, we can create the const assignment
4777 // in the previously reserved spot.
4778 // NOTE: We create a proxy and resolve it here so that in the
4779 // future we can change the AST to only refer to VariableProxies
4780 // instead of Variables and Proxies as is the case now.
4781 VariableMode fvar_mode = is_strict(language_mode()) ? CONST : CONST_LEGACY;
4782 Variable* fvar = new (zone())
4783 Variable(scope_, function_name, fvar_mode, Variable::NORMAL,
4784 kCreatedInitialized, kNotAssigned);
4785 VariableProxy* proxy = factory()->NewVariableProxy(fvar);
4786 VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
4787 proxy, fvar_mode, scope_, RelocInfo::kNoPosition);
4788 scope_->DeclareFunctionVar(fvar_declaration);
4789
4790 VariableProxy* fproxy = factory()->NewVariableProxy(fvar);
4791 result->Set(kFunctionNameAssignmentIndex,
4792 factory()->NewExpressionStatement(
4793 factory()->NewAssignment(Token::INIT, fproxy,
4794 factory()->NewThisFunction(pos),
4795 RelocInfo::kNoPosition),
4796 RelocInfo::kNoPosition));
4797 }
4798
Ben Murdoch097c5b22016-05-18 11:27:45 +01004799 // ES6 14.6.1 Static Semantics: IsInTailPosition
4800 // Mark collected return expressions that are in tail call position.
4801 const List<Expression*>& expressions_in_tail_position =
4802 function_state_->expressions_in_tail_position();
4803 for (int i = 0; i < expressions_in_tail_position.length(); ++i) {
4804 expressions_in_tail_position[i]->MarkTail();
4805 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004806 return result;
4807}
4808
4809
4810PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
4811 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) {
4812 // This function may be called on a background thread too; record only the
4813 // main thread preparse times.
4814 if (pre_parse_timer_ != NULL) {
4815 pre_parse_timer_->Start();
4816 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01004817 TRACE_EVENT0("v8", "V8.PreParse");
4818
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004819 DCHECK_EQ(Token::LBRACE, scanner()->current_token());
4820
4821 if (reusable_preparser_ == NULL) {
4822 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(),
4823 NULL, stack_limit_);
4824 reusable_preparser_->set_allow_lazy(true);
4825#define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name());
4826 SET_ALLOW(natives);
4827 SET_ALLOW(harmony_sloppy);
4828 SET_ALLOW(harmony_sloppy_let);
4829 SET_ALLOW(harmony_default_parameters);
4830 SET_ALLOW(harmony_destructuring_bind);
4831 SET_ALLOW(harmony_destructuring_assignment);
4832 SET_ALLOW(strong_mode);
4833 SET_ALLOW(harmony_do_expressions);
4834 SET_ALLOW(harmony_function_name);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004835 SET_ALLOW(harmony_function_sent);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004836#undef SET_ALLOW
4837 }
4838 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
4839 language_mode(), function_state_->kind(), scope_->has_simple_parameters(),
4840 logger, bookmark);
4841 if (pre_parse_timer_ != NULL) {
4842 pre_parse_timer_->Stop();
4843 }
4844 return result;
4845}
4846
4847
4848ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name,
4849 Scanner::Location class_name_location,
4850 bool name_is_strict_reserved, int pos,
4851 bool* ok) {
4852 // All parts of a ClassDeclaration and ClassExpression are strict code.
4853 if (name_is_strict_reserved) {
4854 ReportMessageAt(class_name_location,
4855 MessageTemplate::kUnexpectedStrictReserved);
4856 *ok = false;
4857 return NULL;
4858 }
4859 if (IsEvalOrArguments(name)) {
4860 ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments);
4861 *ok = false;
4862 return NULL;
4863 }
4864 if (is_strong(language_mode()) && IsUndefined(name)) {
4865 ReportMessageAt(class_name_location, MessageTemplate::kStrongUndefined);
4866 *ok = false;
4867 return NULL;
4868 }
4869
4870 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
4871 BlockState block_state(&scope_, block_scope);
4872 RaiseLanguageMode(STRICT);
4873 scope_->SetScopeName(name);
4874
4875 VariableProxy* proxy = NULL;
4876 if (name != NULL) {
4877 proxy = NewUnresolved(name, CONST);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004878 Declaration* declaration =
4879 factory()->NewVariableDeclaration(proxy, CONST, block_scope, pos);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004880 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
4881 }
4882
4883 Expression* extends = NULL;
4884 if (Check(Token::EXTENDS)) {
4885 block_scope->set_start_position(scanner()->location().end_pos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004886 ExpressionClassifier classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004887 extends = ParseLeftHandSideExpression(&classifier, CHECK_OK);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004888 RewriteNonPattern(&classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004889 } else {
4890 block_scope->set_start_position(scanner()->location().end_pos);
4891 }
4892
4893
4894 ClassLiteralChecker checker(this);
4895 ZoneList<ObjectLiteral::Property*>* properties = NewPropertyList(4, zone());
4896 FunctionLiteral* constructor = NULL;
4897 bool has_seen_constructor = false;
4898
4899 Expect(Token::LBRACE, CHECK_OK);
4900
4901 const bool has_extends = extends != nullptr;
4902 while (peek() != Token::RBRACE) {
4903 if (Check(Token::SEMICOLON)) continue;
4904 FuncNameInferrer::State fni_state(fni_);
4905 const bool in_class = true;
4906 const bool is_static = false;
4907 bool is_computed_name = false; // Classes do not care about computed
4908 // property names here.
Ben Murdoch097c5b22016-05-18 11:27:45 +01004909 ExpressionClassifier classifier(this);
4910 const AstRawString* property_name = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004911 ObjectLiteral::Property* property = ParsePropertyDefinition(
4912 &checker, in_class, has_extends, is_static, &is_computed_name,
Ben Murdoch097c5b22016-05-18 11:27:45 +01004913 &has_seen_constructor, &classifier, &property_name, CHECK_OK);
4914 RewriteNonPattern(&classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004915
4916 if (has_seen_constructor && constructor == NULL) {
4917 constructor = GetPropertyValue(property)->AsFunctionLiteral();
4918 DCHECK_NOT_NULL(constructor);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004919 constructor->set_raw_name(
4920 name != nullptr ? name : ast_value_factory()->empty_string());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004921 } else {
4922 properties->Add(property, zone());
4923 }
4924
4925 if (fni_ != NULL) fni_->Infer();
4926
Ben Murdoch097c5b22016-05-18 11:27:45 +01004927 if (allow_harmony_function_name() &&
4928 property_name != ast_value_factory()->constructor_string()) {
4929 SetFunctionNameFromPropertyName(property, property_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004930 }
4931 }
4932
4933 Expect(Token::RBRACE, CHECK_OK);
4934 int end_pos = scanner()->location().end_pos;
4935
4936 if (constructor == NULL) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004937 constructor = DefaultConstructor(name, extends != NULL, block_scope, pos,
4938 end_pos, block_scope->language_mode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004939 }
4940
4941 // Note that we do not finalize this block scope because strong
4942 // mode uses it as a sentinel value indicating an anonymous class.
4943 block_scope->set_end_position(end_pos);
4944
4945 if (name != NULL) {
4946 DCHECK_NOT_NULL(proxy);
4947 proxy->var()->set_initializer_position(end_pos);
4948 }
4949
Ben Murdoch097c5b22016-05-18 11:27:45 +01004950 return factory()->NewClassLiteral(block_scope, proxy, extends, constructor,
4951 properties, pos, end_pos);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004952}
4953
4954
4955Expression* Parser::ParseV8Intrinsic(bool* ok) {
4956 // CallRuntime ::
4957 // '%' Identifier Arguments
4958
4959 int pos = peek_position();
4960 Expect(Token::MOD, CHECK_OK);
4961 // Allow "eval" or "arguments" for backward compatibility.
4962 const AstRawString* name = ParseIdentifier(kAllowRestrictedIdentifiers,
4963 CHECK_OK);
4964 Scanner::Location spread_pos;
Ben Murdoch097c5b22016-05-18 11:27:45 +01004965 ExpressionClassifier classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004966 ZoneList<Expression*>* args =
4967 ParseArguments(&spread_pos, &classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004968
4969 DCHECK(!spread_pos.IsValid());
4970
4971 if (extension_ != NULL) {
4972 // The extension structures are only accessible while parsing the
4973 // very first time not when reparsing because of lazy compilation.
4974 scope_->DeclarationScope()->ForceEagerCompilation();
4975 }
4976
4977 const Runtime::Function* function = Runtime::FunctionForName(name->string());
4978
4979 if (function != NULL) {
4980 // Check for possible name clash.
4981 DCHECK_EQ(Context::kNotFound,
4982 Context::IntrinsicIndexForName(name->string()));
4983 // Check for built-in IS_VAR macro.
4984 if (function->function_id == Runtime::kIS_VAR) {
4985 DCHECK_EQ(Runtime::RUNTIME, function->intrinsic_type);
4986 // %IS_VAR(x) evaluates to x if x is a variable,
4987 // leads to a parse error otherwise. Could be implemented as an
4988 // inline function %_IS_VAR(x) to eliminate this special case.
4989 if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
4990 return args->at(0);
4991 } else {
4992 ReportMessage(MessageTemplate::kNotIsvar);
4993 *ok = false;
4994 return NULL;
4995 }
4996 }
4997
4998 // Check that the expected number of arguments are being passed.
4999 if (function->nargs != -1 && function->nargs != args->length()) {
5000 ReportMessage(MessageTemplate::kIllegalAccess);
5001 *ok = false;
5002 return NULL;
5003 }
5004
5005 return factory()->NewCallRuntime(function, args, pos);
5006 }
5007
5008 int context_index = Context::IntrinsicIndexForName(name->string());
5009
5010 // Check that the function is defined.
5011 if (context_index == Context::kNotFound) {
5012 ParserTraits::ReportMessage(MessageTemplate::kNotDefined, name);
5013 *ok = false;
5014 return NULL;
5015 }
5016
5017 return factory()->NewCallRuntime(context_index, args, pos);
5018}
5019
5020
5021Literal* Parser::GetLiteralUndefined(int position) {
5022 return factory()->NewUndefinedLiteral(position);
5023}
5024
5025
5026void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
5027 Declaration* decl = scope->CheckConflictingVarDeclarations();
5028 if (decl != NULL) {
5029 // In ES6, conflicting variable bindings are early errors.
5030 const AstRawString* name = decl->proxy()->raw_name();
5031 int position = decl->proxy()->position();
5032 Scanner::Location location = position == RelocInfo::kNoPosition
5033 ? Scanner::Location::invalid()
5034 : Scanner::Location(position, position + 1);
5035 ParserTraits::ReportMessageAt(location, MessageTemplate::kVarRedeclaration,
5036 name);
5037 *ok = false;
5038 }
5039}
5040
5041
5042void Parser::InsertShadowingVarBindingInitializers(Block* inner_block) {
5043 // For each var-binding that shadows a parameter, insert an assignment
5044 // initializing the variable with the parameter.
5045 Scope* inner_scope = inner_block->scope();
5046 DCHECK(inner_scope->is_declaration_scope());
5047 Scope* function_scope = inner_scope->outer_scope();
5048 DCHECK(function_scope->is_function_scope());
5049 ZoneList<Declaration*>* decls = inner_scope->declarations();
5050 for (int i = 0; i < decls->length(); ++i) {
5051 Declaration* decl = decls->at(i);
5052 if (decl->mode() != VAR || !decl->IsVariableDeclaration()) continue;
5053 const AstRawString* name = decl->proxy()->raw_name();
5054 Variable* parameter = function_scope->LookupLocal(name);
5055 if (parameter == nullptr) continue;
5056 VariableProxy* to = inner_scope->NewUnresolved(factory(), name);
5057 VariableProxy* from = factory()->NewVariableProxy(parameter);
5058 Expression* assignment = factory()->NewAssignment(
5059 Token::ASSIGN, to, from, RelocInfo::kNoPosition);
5060 Statement* statement = factory()->NewExpressionStatement(
5061 assignment, RelocInfo::kNoPosition);
5062 inner_block->statements()->InsertAt(0, statement, zone());
5063 }
5064}
5065
5066
5067void Parser::InsertSloppyBlockFunctionVarBindings(Scope* scope, bool* ok) {
5068 // For each variable which is used as a function declaration in a sloppy
5069 // block,
5070 DCHECK(scope->is_declaration_scope());
5071 SloppyBlockFunctionMap* map = scope->sloppy_block_function_map();
5072 for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
5073 AstRawString* name = static_cast<AstRawString*>(p->key);
5074 // If the variable wouldn't conflict with a lexical declaration,
5075 Variable* var = scope->LookupLocal(name);
5076 if (var == nullptr || !IsLexicalVariableMode(var->mode())) {
5077 // Declare a var-style binding for the function in the outer scope
5078 VariableProxy* proxy = scope->NewUnresolved(factory(), name);
5079 Declaration* declaration = factory()->NewVariableDeclaration(
5080 proxy, VAR, scope, RelocInfo::kNoPosition);
5081 Declare(declaration, DeclarationDescriptor::NORMAL, true, ok, scope);
5082 DCHECK(ok); // Based on the preceding check, this should not fail
5083 if (!ok) return;
5084
5085 // Write in assignments to var for each block-scoped function declaration
5086 auto delegates = static_cast<SloppyBlockFunctionMap::Vector*>(p->value);
5087 for (SloppyBlockFunctionStatement* delegate : *delegates) {
5088 // Read from the local lexical scope and write to the function scope
5089 VariableProxy* to = scope->NewUnresolved(factory(), name);
5090 VariableProxy* from = delegate->scope()->NewUnresolved(factory(), name);
5091 Expression* assignment = factory()->NewAssignment(
5092 Token::ASSIGN, to, from, RelocInfo::kNoPosition);
5093 Statement* statement = factory()->NewExpressionStatement(
5094 assignment, RelocInfo::kNoPosition);
5095 delegate->set_statement(statement);
5096 }
5097 }
5098 }
5099}
5100
5101
5102// ----------------------------------------------------------------------------
5103// Parser support
5104
5105bool Parser::TargetStackContainsLabel(const AstRawString* label) {
5106 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
5107 if (ContainsLabel(t->statement()->labels(), label)) return true;
5108 }
5109 return false;
5110}
5111
5112
5113BreakableStatement* Parser::LookupBreakTarget(const AstRawString* label,
5114 bool* ok) {
5115 bool anonymous = label == NULL;
5116 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
5117 BreakableStatement* stat = t->statement();
5118 if ((anonymous && stat->is_target_for_anonymous()) ||
5119 (!anonymous && ContainsLabel(stat->labels(), label))) {
5120 return stat;
5121 }
5122 }
5123 return NULL;
5124}
5125
5126
5127IterationStatement* Parser::LookupContinueTarget(const AstRawString* label,
5128 bool* ok) {
5129 bool anonymous = label == NULL;
5130 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
5131 IterationStatement* stat = t->statement()->AsIterationStatement();
5132 if (stat == NULL) continue;
5133
5134 DCHECK(stat->is_target_for_anonymous());
5135 if (anonymous || ContainsLabel(stat->labels(), label)) {
5136 return stat;
5137 }
5138 }
5139 return NULL;
5140}
5141
5142
5143void Parser::HandleSourceURLComments(Isolate* isolate, Handle<Script> script) {
5144 if (scanner_.source_url()->length() > 0) {
5145 Handle<String> source_url = scanner_.source_url()->Internalize(isolate);
5146 script->set_source_url(*source_url);
5147 }
5148 if (scanner_.source_mapping_url()->length() > 0) {
5149 Handle<String> source_mapping_url =
5150 scanner_.source_mapping_url()->Internalize(isolate);
5151 script->set_source_mapping_url(*source_mapping_url);
5152 }
5153}
5154
5155
5156void Parser::Internalize(Isolate* isolate, Handle<Script> script, bool error) {
5157 // Internalize strings.
5158 ast_value_factory()->Internalize(isolate);
5159
5160 // Error processing.
5161 if (error) {
5162 if (stack_overflow()) {
5163 isolate->StackOverflow();
5164 } else {
5165 DCHECK(pending_error_handler_.has_pending_error());
5166 pending_error_handler_.ThrowPendingError(isolate, script);
5167 }
5168 }
5169
5170 // Move statistics to Isolate.
5171 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
5172 ++feature) {
5173 for (int i = 0; i < use_counts_[feature]; ++i) {
5174 isolate->CountUsage(v8::Isolate::UseCounterFeature(feature));
5175 }
5176 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01005177 if (scanner_.FoundHtmlComment()) {
5178 isolate->CountUsage(v8::Isolate::kHtmlComment);
5179 if (script->line_offset() == 0 && script->column_offset() == 0) {
5180 isolate->CountUsage(v8::Isolate::kHtmlCommentInExternalScript);
5181 }
5182 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005183 isolate->counters()->total_preparse_skipped()->Increment(
5184 total_preparse_skipped_);
5185}
5186
5187
5188// ----------------------------------------------------------------------------
5189// The Parser interface.
5190
5191
5192bool Parser::ParseStatic(ParseInfo* info) {
5193 Parser parser(info);
5194 if (parser.Parse(info)) {
5195 info->set_language_mode(info->literal()->language_mode());
5196 return true;
5197 }
5198 return false;
5199}
5200
5201
5202bool Parser::Parse(ParseInfo* info) {
5203 DCHECK(info->literal() == NULL);
5204 FunctionLiteral* result = NULL;
5205 // Ok to use Isolate here; this function is only called in the main thread.
5206 DCHECK(parsing_on_main_thread_);
5207 Isolate* isolate = info->isolate();
5208 pre_parse_timer_ = isolate->counters()->pre_parse();
5209 if (FLAG_trace_parse || allow_natives() || extension_ != NULL) {
5210 // If intrinsics are allowed, the Parser cannot operate independent of the
5211 // V8 heap because of Runtime. Tell the string table to internalize strings
5212 // and values right after they're created.
5213 ast_value_factory()->Internalize(isolate);
5214 }
5215
5216 if (info->is_lazy()) {
5217 DCHECK(!info->is_eval());
5218 if (info->shared_info()->is_function()) {
5219 result = ParseLazy(isolate, info);
5220 } else {
5221 result = ParseProgram(isolate, info);
5222 }
5223 } else {
5224 SetCachedData(info);
5225 result = ParseProgram(isolate, info);
5226 }
5227 info->set_literal(result);
5228
5229 Internalize(isolate, info->script(), result == NULL);
5230 DCHECK(ast_value_factory()->IsInternalized());
5231 return (result != NULL);
5232}
5233
5234
5235void Parser::ParseOnBackground(ParseInfo* info) {
5236 parsing_on_main_thread_ = false;
5237
5238 DCHECK(info->literal() == NULL);
5239 FunctionLiteral* result = NULL;
5240 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
5241
5242 CompleteParserRecorder recorder;
5243 if (produce_cached_parse_data()) log_ = &recorder;
5244
5245 DCHECK(info->source_stream() != NULL);
5246 ExternalStreamingStream stream(info->source_stream(),
5247 info->source_stream_encoding());
5248 scanner_.Initialize(&stream);
5249 DCHECK(info->context().is_null() || info->context()->IsNativeContext());
5250
5251 // When streaming, we don't know the length of the source until we have parsed
5252 // it. The raw data can be UTF-8, so we wouldn't know the source length until
5253 // we have decoded it anyway even if we knew the raw data length (which we
5254 // don't). We work around this by storing all the scopes which need their end
5255 // position set at the end of the script (the top scope and possible eval
5256 // scopes) and set their end position after we know the script length.
5257 result = DoParseProgram(info);
5258
5259 info->set_literal(result);
5260
5261 // We cannot internalize on a background thread; a foreground task will take
5262 // care of calling Parser::Internalize just before compilation.
5263
5264 if (produce_cached_parse_data()) {
5265 if (result != NULL) *info->cached_data() = recorder.GetScriptData();
5266 log_ = NULL;
5267 }
5268}
5269
5270
5271ParserTraits::TemplateLiteralState Parser::OpenTemplateLiteral(int pos) {
5272 return new (zone()) ParserTraits::TemplateLiteral(zone(), pos);
5273}
5274
5275
5276void Parser::AddTemplateSpan(TemplateLiteralState* state, bool tail) {
5277 int pos = scanner()->location().beg_pos;
5278 int end = scanner()->location().end_pos - (tail ? 1 : 2);
5279 const AstRawString* tv = scanner()->CurrentSymbol(ast_value_factory());
5280 const AstRawString* trv = scanner()->CurrentRawSymbol(ast_value_factory());
5281 Literal* cooked = factory()->NewStringLiteral(tv, pos);
5282 Literal* raw = factory()->NewStringLiteral(trv, pos);
5283 (*state)->AddTemplateSpan(cooked, raw, end, zone());
5284}
5285
5286
5287void Parser::AddTemplateExpression(TemplateLiteralState* state,
5288 Expression* expression) {
5289 (*state)->AddExpression(expression, zone());
5290}
5291
5292
5293Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start,
5294 Expression* tag) {
5295 TemplateLiteral* lit = *state;
5296 int pos = lit->position();
5297 const ZoneList<Expression*>* cooked_strings = lit->cooked();
5298 const ZoneList<Expression*>* raw_strings = lit->raw();
5299 const ZoneList<Expression*>* expressions = lit->expressions();
5300 DCHECK_EQ(cooked_strings->length(), raw_strings->length());
5301 DCHECK_EQ(cooked_strings->length(), expressions->length() + 1);
5302
5303 if (!tag) {
5304 // Build tree of BinaryOps to simplify code-generation
5305 Expression* expr = cooked_strings->at(0);
5306 int i = 0;
5307 while (i < expressions->length()) {
5308 Expression* sub = expressions->at(i++);
5309 Expression* cooked_str = cooked_strings->at(i);
5310
5311 // Let middle be ToString(sub).
5312 ZoneList<Expression*>* args =
5313 new (zone()) ZoneList<Expression*>(1, zone());
5314 args->Add(sub, zone());
5315 Expression* middle = factory()->NewCallRuntime(Runtime::kInlineToString,
5316 args, sub->position());
5317
5318 expr = factory()->NewBinaryOperation(
5319 Token::ADD, factory()->NewBinaryOperation(
5320 Token::ADD, expr, middle, expr->position()),
5321 cooked_str, sub->position());
5322 }
5323 return expr;
5324 } else {
5325 uint32_t hash = ComputeTemplateLiteralHash(lit);
5326
5327 int cooked_idx = function_state_->NextMaterializedLiteralIndex();
5328 int raw_idx = function_state_->NextMaterializedLiteralIndex();
5329
5330 // $getTemplateCallSite
5331 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(4, zone());
5332 args->Add(factory()->NewArrayLiteral(
5333 const_cast<ZoneList<Expression*>*>(cooked_strings),
5334 cooked_idx, is_strong(language_mode()), pos),
5335 zone());
5336 args->Add(
5337 factory()->NewArrayLiteral(
5338 const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx,
5339 is_strong(language_mode()), pos),
5340 zone());
5341
5342 // Ensure hash is suitable as a Smi value
5343 Smi* hash_obj = Smi::cast(Internals::IntToSmi(static_cast<int>(hash)));
5344 args->Add(factory()->NewSmiLiteral(hash_obj->value(), pos), zone());
5345
5346 Expression* call_site = factory()->NewCallRuntime(
5347 Context::GET_TEMPLATE_CALL_SITE_INDEX, args, start);
5348
5349 // Call TagFn
5350 ZoneList<Expression*>* call_args =
5351 new (zone()) ZoneList<Expression*>(expressions->length() + 1, zone());
5352 call_args->Add(call_site, zone());
5353 call_args->AddAll(*expressions, zone());
5354 return factory()->NewCall(tag, call_args, pos);
5355 }
5356}
5357
5358
5359uint32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) {
5360 const ZoneList<Expression*>* raw_strings = lit->raw();
5361 int total = raw_strings->length();
5362 DCHECK(total);
5363
5364 uint32_t running_hash = 0;
5365
5366 for (int index = 0; index < total; ++index) {
5367 if (index) {
5368 running_hash = StringHasher::ComputeRunningHashOneByte(
5369 running_hash, "${}", 3);
5370 }
5371
5372 const AstRawString* raw_string =
5373 raw_strings->at(index)->AsLiteral()->raw_value()->AsString();
5374 if (raw_string->is_one_byte()) {
5375 const char* data = reinterpret_cast<const char*>(raw_string->raw_data());
5376 running_hash = StringHasher::ComputeRunningHashOneByte(
5377 running_hash, data, raw_string->length());
5378 } else {
5379 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data());
5380 running_hash = StringHasher::ComputeRunningHash(running_hash, data,
5381 raw_string->length());
5382 }
5383 }
5384
5385 return running_hash;
5386}
5387
5388
5389ZoneList<v8::internal::Expression*>* Parser::PrepareSpreadArguments(
5390 ZoneList<v8::internal::Expression*>* list) {
5391 ZoneList<v8::internal::Expression*>* args =
5392 new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
5393 if (list->length() == 1) {
5394 // Spread-call with single spread argument produces an InternalArray
5395 // containing the values from the array.
5396 //
5397 // Function is called or constructed with the produced array of arguments
5398 //
5399 // EG: Apply(Func, Spread(spread0))
5400 ZoneList<Expression*>* spread_list =
5401 new (zone()) ZoneList<Expression*>(0, zone());
5402 spread_list->Add(list->at(0)->AsSpread()->expression(), zone());
5403 args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX,
5404 spread_list, RelocInfo::kNoPosition),
5405 zone());
5406 return args;
5407 } else {
5408 // Spread-call with multiple arguments produces array literals for each
5409 // sequences of unspread arguments, and converts each spread iterable to
5410 // an Internal array. Finally, all of these produced arrays are flattened
5411 // into a single InternalArray, containing the arguments for the call.
5412 //
5413 // EG: Apply(Func, Flatten([unspread0, unspread1], Spread(spread0),
5414 // Spread(spread1), [unspread2, unspread3]))
5415 int i = 0;
5416 int n = list->length();
5417 while (i < n) {
5418 if (!list->at(i)->IsSpread()) {
5419 ZoneList<v8::internal::Expression*>* unspread =
5420 new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
5421
5422 // Push array of unspread parameters
5423 while (i < n && !list->at(i)->IsSpread()) {
5424 unspread->Add(list->at(i++), zone());
5425 }
5426 int literal_index = function_state_->NextMaterializedLiteralIndex();
5427 args->Add(factory()->NewArrayLiteral(unspread, literal_index,
5428 is_strong(language_mode()),
5429 RelocInfo::kNoPosition),
5430 zone());
5431
5432 if (i == n) break;
5433 }
5434
5435 // Push eagerly spread argument
5436 ZoneList<v8::internal::Expression*>* spread_list =
5437 new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
5438 spread_list->Add(list->at(i++)->AsSpread()->expression(), zone());
5439 args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX,
5440 spread_list, RelocInfo::kNoPosition),
5441 zone());
5442 }
5443
5444 list = new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
5445 list->Add(factory()->NewCallRuntime(Context::SPREAD_ARGUMENTS_INDEX, args,
5446 RelocInfo::kNoPosition),
5447 zone());
5448 return list;
5449 }
5450 UNREACHABLE();
5451}
5452
5453
5454Expression* Parser::SpreadCall(Expression* function,
5455 ZoneList<v8::internal::Expression*>* args,
5456 int pos) {
5457 if (function->IsSuperCallReference()) {
5458 // Super calls
5459 // $super_constructor = %_GetSuperConstructor(<this-function>)
5460 // %reflect_construct($super_constructor, args, new.target)
5461 ZoneList<Expression*>* tmp = new (zone()) ZoneList<Expression*>(1, zone());
5462 tmp->Add(function->AsSuperCallReference()->this_function_var(), zone());
5463 Expression* super_constructor = factory()->NewCallRuntime(
5464 Runtime::kInlineGetSuperConstructor, tmp, pos);
5465 args->InsertAt(0, super_constructor, zone());
5466 args->Add(function->AsSuperCallReference()->new_target_var(), zone());
5467 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args,
5468 pos);
5469 } else {
5470 if (function->IsProperty()) {
5471 // Method calls
5472 if (function->AsProperty()->IsSuperAccess()) {
5473 Expression* home =
5474 ThisExpression(scope_, factory(), RelocInfo::kNoPosition);
5475 args->InsertAt(0, function, zone());
5476 args->InsertAt(1, home, zone());
5477 } else {
5478 Variable* temp =
5479 scope_->NewTemporary(ast_value_factory()->empty_string());
5480 VariableProxy* obj = factory()->NewVariableProxy(temp);
5481 Assignment* assign_obj = factory()->NewAssignment(
5482 Token::ASSIGN, obj, function->AsProperty()->obj(),
5483 RelocInfo::kNoPosition);
5484 function = factory()->NewProperty(
5485 assign_obj, function->AsProperty()->key(), RelocInfo::kNoPosition);
5486 args->InsertAt(0, function, zone());
5487 obj = factory()->NewVariableProxy(temp);
5488 args->InsertAt(1, obj, zone());
5489 }
5490 } else {
5491 // Non-method calls
5492 args->InsertAt(0, function, zone());
5493 args->InsertAt(1, factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
5494 zone());
5495 }
5496 return factory()->NewCallRuntime(Context::REFLECT_APPLY_INDEX, args, pos);
5497 }
5498}
5499
5500
5501Expression* Parser::SpreadCallNew(Expression* function,
5502 ZoneList<v8::internal::Expression*>* args,
5503 int pos) {
5504 args->InsertAt(0, function, zone());
5505
5506 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos);
5507}
5508
5509
5510void Parser::SetLanguageMode(Scope* scope, LanguageMode mode) {
5511 v8::Isolate::UseCounterFeature feature;
5512 if (is_sloppy(mode))
5513 feature = v8::Isolate::kSloppyMode;
5514 else if (is_strong(mode))
5515 feature = v8::Isolate::kStrongMode;
5516 else if (is_strict(mode))
5517 feature = v8::Isolate::kStrictMode;
5518 else
5519 UNREACHABLE();
5520 ++use_counts_[feature];
5521 scope->SetLanguageMode(mode);
5522}
5523
5524
5525void Parser::RaiseLanguageMode(LanguageMode mode) {
5526 SetLanguageMode(scope_,
5527 static_cast<LanguageMode>(scope_->language_mode() | mode));
5528}
5529
5530
5531void ParserTraits::RewriteDestructuringAssignments() {
5532 parser_->RewriteDestructuringAssignments();
5533}
5534
5535
Ben Murdoch097c5b22016-05-18 11:27:45 +01005536void ParserTraits::RewriteNonPattern(Type::ExpressionClassifier* classifier,
5537 bool* ok) {
5538 parser_->RewriteNonPattern(classifier, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005539}
5540
5541
Ben Murdoch097c5b22016-05-18 11:27:45 +01005542Zone* ParserTraits::zone() const {
5543 return parser_->function_state_->scope()->zone();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005544}
5545
5546
Ben Murdoch097c5b22016-05-18 11:27:45 +01005547ZoneList<Expression*>* ParserTraits::GetNonPatternList() const {
5548 return parser_->function_state_->non_patterns_to_rewrite();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005549}
5550
5551
Ben Murdoch097c5b22016-05-18 11:27:45 +01005552class NonPatternRewriter : public AstExpressionRewriter {
5553 public:
5554 NonPatternRewriter(uintptr_t stack_limit, Parser* parser)
5555 : AstExpressionRewriter(stack_limit), parser_(parser) {}
5556 ~NonPatternRewriter() override {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005557
Ben Murdoch097c5b22016-05-18 11:27:45 +01005558 private:
5559 bool RewriteExpression(Expression* expr) override {
5560 if (expr->IsRewritableExpression()) return true;
5561 // Rewrite only what could have been a pattern but is not.
5562 if (expr->IsArrayLiteral()) {
5563 // Spread rewriting in array literals.
5564 ArrayLiteral* lit = expr->AsArrayLiteral();
5565 VisitExpressions(lit->values());
5566 replacement_ = parser_->RewriteSpreads(lit);
5567 return false;
5568 }
5569 if (expr->IsObjectLiteral()) {
5570 return true;
5571 }
5572 if (expr->IsBinaryOperation() &&
5573 expr->AsBinaryOperation()->op() == Token::COMMA) {
5574 return true;
5575 }
5576 // Everything else does not need rewriting.
5577 return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005578 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01005579
5580 void VisitObjectLiteralProperty(ObjectLiteralProperty* property) override {
5581 if (property == nullptr) return;
5582 // Do not rewrite (computed) key expressions
5583 AST_REWRITE_PROPERTY(Expression, property, value);
5584 }
5585
5586 Parser* parser_;
5587};
5588
5589
5590void Parser::RewriteNonPattern(ExpressionClassifier* classifier, bool* ok) {
5591 ValidateExpression(classifier, ok);
5592 if (!*ok) return;
5593 auto non_patterns_to_rewrite = function_state_->non_patterns_to_rewrite();
5594 int begin = classifier->GetNonPatternBegin();
5595 int end = non_patterns_to_rewrite->length();
5596 if (begin < end) {
5597 NonPatternRewriter rewriter(stack_limit_, this);
5598 for (int i = begin; i < end; i++) {
5599 DCHECK(non_patterns_to_rewrite->at(i)->IsRewritableExpression());
5600 rewriter.Rewrite(non_patterns_to_rewrite->at(i));
5601 }
5602 non_patterns_to_rewrite->Rewind(begin);
5603 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005604}
5605
5606
5607void Parser::RewriteDestructuringAssignments() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005608 if (!allow_harmony_destructuring_assignment()) return;
Ben Murdoch097c5b22016-05-18 11:27:45 +01005609 const auto& assignments =
5610 function_state_->destructuring_assignments_to_rewrite();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005611 for (int i = assignments.length() - 1; i >= 0; --i) {
5612 // Rewrite list in reverse, so that nested assignment patterns are rewritten
5613 // correctly.
Ben Murdoch097c5b22016-05-18 11:27:45 +01005614 const DestructuringAssignment& pair = assignments.at(i);
5615 RewritableExpression* to_rewrite =
5616 pair.assignment->AsRewritableExpression();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005617 DCHECK_NOT_NULL(to_rewrite);
5618 if (!to_rewrite->is_rewritten()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005619 PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite,
5620 pair.scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005621 }
5622 }
5623}
5624
5625
Ben Murdoch097c5b22016-05-18 11:27:45 +01005626Expression* Parser::RewriteSpreads(ArrayLiteral* lit) {
5627 // Array literals containing spreads are rewritten using do expressions, e.g.
5628 // [1, 2, 3, ...x, 4, ...y, 5]
5629 // is roughly rewritten as:
5630 // do {
5631 // $R = [1, 2, 3];
5632 // for ($i of x) %AppendElement($R, $i);
5633 // %AppendElement($R, 4);
5634 // for ($j of y) %AppendElement($R, $j);
5635 // %AppendElement($R, 5);
5636 // $R
5637 // }
5638 // where $R, $i and $j are fresh temporary variables.
5639 ZoneList<Expression*>::iterator s = lit->FirstSpread();
5640 if (s == lit->EndValue()) return nullptr; // no spread, no rewriting...
5641 Variable* result =
5642 scope_->NewTemporary(ast_value_factory()->dot_result_string());
5643 // NOTE: The value assigned to R is the whole original array literal,
5644 // spreads included. This will be fixed before the rewritten AST is returned.
5645 // $R = lit
5646 Expression* init_result =
5647 factory()->NewAssignment(Token::INIT, factory()->NewVariableProxy(result),
5648 lit, RelocInfo::kNoPosition);
5649 Block* do_block =
5650 factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition);
5651 do_block->statements()->Add(
5652 factory()->NewExpressionStatement(init_result, RelocInfo::kNoPosition),
5653 zone());
5654 // Traverse the array literal starting from the first spread.
5655 while (s != lit->EndValue()) {
5656 Expression* value = *s++;
5657 Spread* spread = value->AsSpread();
5658 if (spread == nullptr) {
5659 // If the element is not a spread, we're adding a single:
5660 // %AppendElement($R, value)
5661 ZoneList<Expression*>* append_element_args = NewExpressionList(2, zone());
5662 append_element_args->Add(factory()->NewVariableProxy(result), zone());
5663 append_element_args->Add(value, zone());
5664 do_block->statements()->Add(
5665 factory()->NewExpressionStatement(
5666 factory()->NewCallRuntime(Runtime::kAppendElement,
5667 append_element_args,
5668 RelocInfo::kNoPosition),
5669 RelocInfo::kNoPosition),
5670 zone());
5671 } else {
5672 // If it's a spread, we're adding a for/of loop iterating through it.
5673 Variable* each =
5674 scope_->NewTemporary(ast_value_factory()->dot_for_string());
5675 Expression* subject = spread->expression();
5676 Variable* iterator =
5677 scope_->NewTemporary(ast_value_factory()->dot_iterator_string());
5678 Variable* element =
5679 scope_->NewTemporary(ast_value_factory()->dot_result_string());
5680 // iterator = subject[Symbol.iterator]()
5681 Expression* assign_iterator = factory()->NewAssignment(
5682 Token::ASSIGN, factory()->NewVariableProxy(iterator),
5683 GetIterator(subject, factory(), spread->expression_position()),
5684 subject->position());
5685 // !%_IsJSReceiver(element = iterator.next()) &&
5686 // %ThrowIteratorResultNotAnObject(element)
5687 Expression* next_element;
5688 {
5689 // element = iterator.next()
5690 Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
5691 next_element = BuildIteratorNextResult(iterator_proxy, element,
5692 spread->expression_position());
5693 }
5694 // element.done
5695 Expression* element_done;
5696 {
5697 Expression* done_literal = factory()->NewStringLiteral(
5698 ast_value_factory()->done_string(), RelocInfo::kNoPosition);
5699 Expression* element_proxy = factory()->NewVariableProxy(element);
5700 element_done = factory()->NewProperty(element_proxy, done_literal,
5701 RelocInfo::kNoPosition);
5702 }
5703 // each = element.value
5704 Expression* assign_each;
5705 {
5706 Expression* value_literal = factory()->NewStringLiteral(
5707 ast_value_factory()->value_string(), RelocInfo::kNoPosition);
5708 Expression* element_proxy = factory()->NewVariableProxy(element);
5709 Expression* element_value = factory()->NewProperty(
5710 element_proxy, value_literal, RelocInfo::kNoPosition);
5711 assign_each = factory()->NewAssignment(
5712 Token::ASSIGN, factory()->NewVariableProxy(each), element_value,
5713 RelocInfo::kNoPosition);
5714 }
5715 // %AppendElement($R, each)
5716 Statement* append_body;
5717 {
5718 ZoneList<Expression*>* append_element_args =
5719 NewExpressionList(2, zone());
5720 append_element_args->Add(factory()->NewVariableProxy(result), zone());
5721 append_element_args->Add(factory()->NewVariableProxy(each), zone());
5722 append_body = factory()->NewExpressionStatement(
5723 factory()->NewCallRuntime(Runtime::kAppendElement,
5724 append_element_args,
5725 RelocInfo::kNoPosition),
5726 RelocInfo::kNoPosition);
5727 }
5728 // for (each of spread) %AppendElement($R, each)
5729 ForEachStatement* loop = factory()->NewForEachStatement(
5730 ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition);
5731 ForOfStatement* for_of = loop->AsForOfStatement();
5732 for_of->Initialize(factory()->NewVariableProxy(each), subject,
5733 append_body, iterator, assign_iterator, next_element,
5734 element_done, assign_each);
5735 do_block->statements()->Add(for_of, zone());
5736 }
5737 }
5738 // Now, rewind the original array literal to truncate everything from the
5739 // first spread (included) until the end. This fixes $R's initialization.
5740 lit->RewindSpreads();
5741 return factory()->NewDoExpression(do_block, result, lit->position());
5742}
5743
5744
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005745void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005746 DCHECK(expr->IsRewritableExpression());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005747 parser_->function_state_->AddDestructuringAssignment(
5748 Parser::DestructuringAssignment(expr, parser_->scope_));
5749}
5750
5751
Ben Murdoch097c5b22016-05-18 11:27:45 +01005752void ParserTraits::QueueNonPatternForRewriting(Expression* expr) {
5753 DCHECK(expr->IsRewritableExpression());
5754 parser_->function_state_->AddNonPatternForRewriting(expr);
5755}
5756
5757
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005758void ParserTraits::SetFunctionNameFromPropertyName(
5759 ObjectLiteralProperty* property, const AstRawString* name) {
5760 Expression* value = property->value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005761
Ben Murdoch097c5b22016-05-18 11:27:45 +01005762 // Computed name setting must happen at runtime.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005763 if (property->is_computed_name()) return;
Ben Murdoch097c5b22016-05-18 11:27:45 +01005764
5765 // Getter and setter names are handled here because their names
5766 // change in ES2015, even though they are not anonymous.
5767 auto function = value->AsFunctionLiteral();
5768 if (function != nullptr) {
5769 bool is_getter = property->kind() == ObjectLiteralProperty::GETTER;
5770 bool is_setter = property->kind() == ObjectLiteralProperty::SETTER;
5771 if (is_getter || is_setter) {
5772 DCHECK_NOT_NULL(name);
5773 const AstRawString* prefix =
5774 is_getter ? parser_->ast_value_factory()->get_space_string()
5775 : parser_->ast_value_factory()->set_space_string();
5776 function->set_raw_name(
5777 parser_->ast_value_factory()->NewConsString(prefix, name));
5778 return;
5779 }
5780 }
5781
5782 if (!value->IsAnonymousFunctionDefinition()) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005783 DCHECK_NOT_NULL(name);
5784
5785 // Ignore "__proto__" as a name when it's being used to set the [[Prototype]]
5786 // of an object literal.
5787 if (property->kind() == ObjectLiteralProperty::PROTOTYPE) return;
5788
Ben Murdoch097c5b22016-05-18 11:27:45 +01005789 if (function != nullptr) {
5790 function->set_raw_name(name);
5791 DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005792 } else {
5793 DCHECK(value->IsClassLiteral());
5794 DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind());
Ben Murdoch097c5b22016-05-18 11:27:45 +01005795 value->AsClassLiteral()->constructor()->set_raw_name(name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005796 }
5797}
5798
5799
5800void ParserTraits::SetFunctionNameFromIdentifierRef(Expression* value,
5801 Expression* identifier) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005802 if (!value->IsAnonymousFunctionDefinition()) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005803 if (!identifier->IsVariableProxy()) return;
5804
5805 auto name = identifier->AsVariableProxy()->raw_name();
5806 DCHECK_NOT_NULL(name);
5807
Ben Murdoch097c5b22016-05-18 11:27:45 +01005808 auto function = value->AsFunctionLiteral();
5809 if (function != nullptr) {
5810 function->set_raw_name(name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005811 } else {
5812 DCHECK(value->IsClassLiteral());
Ben Murdoch097c5b22016-05-18 11:27:45 +01005813 value->AsClassLiteral()->constructor()->set_raw_name(name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005814 }
5815}
5816
5817
Ben Murdoch097c5b22016-05-18 11:27:45 +01005818// Desugaring of yield*
5819// ====================
5820//
5821// With the help of do-expressions and function.sent, we desugar yield* into a
5822// loop containing a "raw" yield (a yield that doesn't wrap an iterator result
5823// object around its argument). Concretely, "yield* iterable" turns into
5824// roughly the following code:
5825//
5826// do {
5827// const kNext = 0;
5828// const kReturn = 1;
5829// const kThrow = 2;
5830//
5831// let input = function.sent;
5832// let mode = kNext;
5833// let output = undefined;
5834//
5835// let iterator = iterable[Symbol.iterator]();
5836// if (!IS_RECEIVER(iterator)) throw MakeTypeError(kSymbolIteratorInvalid);
5837//
5838// while (true) {
5839// // From the generator to the iterator:
5840// // Forward input according to resume mode and obtain output.
5841// switch (mode) {
5842// case kNext:
5843// output = iterator.next(input);
5844// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
5845// break;
5846// case kReturn:
5847// IteratorClose(iterator, input, output); // See below.
5848// break;
5849// case kThrow:
5850// let iteratorThrow = iterator.throw;
5851// if (IS_NULL_OR_UNDEFINED(iteratorThrow)) {
5852// IteratorClose(iterator); // See below.
5853// throw MakeTypeError(kThrowMethodMissing);
5854// }
5855// output = %_Call(iteratorThrow, iterator, input);
5856// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
5857// break;
5858// }
5859// if (output.done) break;
5860//
5861// // From the generator to its user:
5862// // Forward output, receive new input, and determine resume mode.
5863// mode = kReturn;
5864// try {
5865// try {
5866// RawYield(output); // See explanation above.
5867// mode = kNext;
5868// } catch (error) {
5869// mode = kThrow;
5870// }
5871// } finally {
5872// input = function.sent;
5873// continue;
5874// }
5875// }
5876//
5877// output.value;
5878// }
5879//
5880// IteratorClose(iterator) expands to the following:
5881//
5882// let iteratorReturn = iterator.return;
5883// if (IS_NULL_OR_UNDEFINED(iteratorReturn)) return;
5884// let output = %_Call(iteratorReturn, iterator);
5885// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
5886//
5887// IteratorClose(iterator, input, output) expands to the following:
5888//
5889// let iteratorReturn = iterator.return;
5890// if (IS_NULL_OR_UNDEFINED(iteratorReturn)) return input;
5891// output = %_Call(iteratorReturn, iterator, input);
5892// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
5893
5894
5895Expression* ParserTraits::RewriteYieldStar(
5896 Expression* generator, Expression* iterable, int pos) {
5897
5898 const int nopos = RelocInfo::kNoPosition;
5899
5900 auto factory = parser_->factory();
5901 auto avfactory = parser_->ast_value_factory();
5902 auto scope = parser_->scope_;
5903 auto zone = parser_->zone();
5904
5905
5906 // Forward definition for break/continue statements.
5907 WhileStatement* loop = factory->NewWhileStatement(nullptr, nopos);
5908
5909
5910 // let input = undefined;
5911 Variable* var_input = scope->NewTemporary(avfactory->empty_string());
5912 Statement* initialize_input;
5913 {
5914 Expression* input_proxy = factory->NewVariableProxy(var_input);
5915 Expression* assignment = factory->NewAssignment(
5916 Token::ASSIGN, input_proxy, factory->NewUndefinedLiteral(nopos), nopos);
5917 initialize_input = factory->NewExpressionStatement(assignment, nopos);
5918 }
5919
5920
5921 // let mode = kNext;
5922 Variable* var_mode = scope->NewTemporary(avfactory->empty_string());
5923 Statement* initialize_mode;
5924 {
5925 Expression* mode_proxy = factory->NewVariableProxy(var_mode);
5926 Expression* knext = factory->NewSmiLiteral(JSGeneratorObject::NEXT, nopos);
5927 Expression* assignment =
5928 factory->NewAssignment(Token::ASSIGN, mode_proxy, knext, nopos);
5929 initialize_mode = factory->NewExpressionStatement(assignment, nopos);
5930 }
5931
5932
5933 // let output = undefined;
5934 Variable* var_output = scope->NewTemporary(avfactory->empty_string());
5935 Statement* initialize_output;
5936 {
5937 Expression* output_proxy = factory->NewVariableProxy(var_output);
5938 Expression* assignment = factory->NewAssignment(
5939 Token::ASSIGN, output_proxy, factory->NewUndefinedLiteral(nopos),
5940 nopos);
5941 initialize_output = factory->NewExpressionStatement(assignment, nopos);
5942 }
5943
5944
5945 // let iterator = iterable[Symbol.iterator];
5946 Variable* var_iterator = scope->NewTemporary(avfactory->empty_string());
5947 Statement* get_iterator;
5948 {
5949 Expression* iterator = GetIterator(iterable, factory, nopos);
5950 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator);
5951 Expression* assignment = factory->NewAssignment(
5952 Token::ASSIGN, iterator_proxy, iterator, nopos);
5953 get_iterator = factory->NewExpressionStatement(assignment, nopos);
5954 }
5955
5956
5957 // if (!IS_RECEIVER(iterator)) throw MakeTypeError(kSymbolIteratorInvalid);
5958 Statement* validate_iterator;
5959 {
5960 Expression* is_receiver_call;
5961 {
5962 auto args = new (zone) ZoneList<Expression*>(1, zone);
5963 args->Add(factory->NewVariableProxy(var_iterator), zone);
5964 is_receiver_call =
5965 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
5966 }
5967
5968 Statement* throw_call;
5969 {
5970 Expression* call = NewThrowTypeError(
5971 MessageTemplate::kSymbolIteratorInvalid, avfactory->empty_string(),
5972 nopos);
5973 throw_call = factory->NewExpressionStatement(call, nopos);
5974 }
5975
5976 validate_iterator = factory->NewIfStatement(
5977 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
5978 }
5979
5980
5981 // output = iterator.next(input);
5982 Statement* call_next;
5983 {
5984 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator);
5985 Expression* literal =
5986 factory->NewStringLiteral(avfactory->next_string(), nopos);
5987 Expression* next_property =
5988 factory->NewProperty(iterator_proxy, literal, nopos);
5989 Expression* input_proxy = factory->NewVariableProxy(var_input);
5990 auto args = new (zone) ZoneList<Expression*>(1, zone);
5991 args->Add(input_proxy, zone);
5992 Expression* call = factory->NewCall(next_property, args, nopos);
5993 Expression* output_proxy = factory->NewVariableProxy(var_output);
5994 Expression* assignment =
5995 factory->NewAssignment(Token::ASSIGN, output_proxy, call, nopos);
5996 call_next = factory->NewExpressionStatement(assignment, nopos);
5997 }
5998
5999
6000 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
6001 Statement* validate_next_output;
6002 {
6003 Expression* is_receiver_call;
6004 {
6005 auto args = new (zone) ZoneList<Expression*>(1, zone);
6006 args->Add(factory->NewVariableProxy(var_output), zone);
6007 is_receiver_call =
6008 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
6009 }
6010
6011 Statement* throw_call;
6012 {
6013 auto args = new (zone) ZoneList<Expression*>(1, zone);
6014 args->Add(factory->NewVariableProxy(var_output), zone);
6015 Expression* call = factory->NewCallRuntime(
6016 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
6017 throw_call = factory->NewExpressionStatement(call, nopos);
6018 }
6019
6020 validate_next_output = factory->NewIfStatement(
6021 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
6022 }
6023
6024
6025 // let iteratorThrow = iterator.throw;
6026 Variable* var_throw = scope->NewTemporary(avfactory->empty_string());
6027 Statement* get_throw;
6028 {
6029 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator);
6030 Expression* literal =
6031 factory->NewStringLiteral(avfactory->throw_string(), nopos);
6032 Expression* property =
6033 factory->NewProperty(iterator_proxy, literal, nopos);
6034 Expression* throw_proxy = factory->NewVariableProxy(var_throw);
6035 Expression* assignment = factory->NewAssignment(
6036 Token::ASSIGN, throw_proxy, property, nopos);
6037 get_throw = factory->NewExpressionStatement(assignment, nopos);
6038 }
6039
6040
6041 // if (IS_NULL_OR_UNDEFINED(iteratorThrow) {
6042 // IteratorClose(iterator);
6043 // throw MakeTypeError(kThrowMethodMissing);
6044 // }
6045 Statement* check_throw;
6046 {
6047 Expression* condition = factory->NewCompareOperation(
6048 Token::EQ, factory->NewVariableProxy(var_throw),
6049 factory->NewNullLiteral(nopos), nopos);
6050
6051 Expression* call = NewThrowTypeError(
6052 MessageTemplate::kThrowMethodMissing,
6053 avfactory->empty_string(), nopos);
6054 Statement* throw_call = factory->NewExpressionStatement(call, nopos);
6055
6056 Block* then = factory->NewBlock(nullptr, 4+1, false, nopos);
6057 Variable* var_tmp = scope->NewTemporary(avfactory->empty_string());
6058 BuildIteratorClose(
6059 then->statements(), var_iterator, factory->NewUndefinedLiteral(nopos),
6060 var_tmp);
6061 then->statements()->Add(throw_call, zone);
6062 check_throw = factory->NewIfStatement(
6063 condition, then, factory->NewEmptyStatement(nopos), nopos);
6064 }
6065
6066
6067 // output = %_Call(iteratorThrow, iterator, input);
6068 Statement* call_throw;
6069 {
6070 auto args = new (zone) ZoneList<Expression*>(3, zone);
6071 args->Add(factory->NewVariableProxy(var_throw), zone);
6072 args->Add(factory->NewVariableProxy(var_iterator), zone);
6073 args->Add(factory->NewVariableProxy(var_input), zone);
6074 Expression* call =
6075 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
6076 Expression* assignment = factory->NewAssignment(
6077 Token::ASSIGN, factory->NewVariableProxy(var_output), call, nopos);
6078 call_throw = factory->NewExpressionStatement(assignment, nopos);
6079 }
6080
6081
6082 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
6083 Statement* validate_throw_output;
6084 {
6085 Expression* is_receiver_call;
6086 {
6087 auto args = new (zone) ZoneList<Expression*>(1, zone);
6088 args->Add(factory->NewVariableProxy(var_output), zone);
6089 is_receiver_call =
6090 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
6091 }
6092
6093 Statement* throw_call;
6094 {
6095 auto args = new (zone) ZoneList<Expression*>(1, zone);
6096 args->Add(factory->NewVariableProxy(var_output), zone);
6097 Expression* call = factory->NewCallRuntime(
6098 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
6099 throw_call = factory->NewExpressionStatement(call, nopos);
6100 }
6101
6102 validate_throw_output = factory->NewIfStatement(
6103 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
6104 }
6105
6106
6107 // if (output.done) break;
6108 Statement* if_done;
6109 {
6110 Expression* output_proxy = factory->NewVariableProxy(var_output);
6111 Expression* literal =
6112 factory->NewStringLiteral(avfactory->done_string(), nopos);
6113 Expression* property = factory->NewProperty(output_proxy, literal, nopos);
6114 BreakStatement* break_loop = factory->NewBreakStatement(loop, nopos);
6115 if_done = factory->NewIfStatement(
6116 property, break_loop, factory->NewEmptyStatement(nopos), nopos);
6117 }
6118
6119
6120 // mode = kReturn;
6121 Statement* set_mode_return;
6122 {
6123 Expression* mode_proxy = factory->NewVariableProxy(var_mode);
6124 Expression* kreturn =
6125 factory->NewSmiLiteral(JSGeneratorObject::RETURN, nopos);
6126 Expression* assignment =
6127 factory->NewAssignment(Token::ASSIGN, mode_proxy, kreturn, nopos);
6128 set_mode_return = factory->NewExpressionStatement(assignment, nopos);
6129 }
6130
6131
6132 // RawYield(output);
6133 Statement* yield_output;
6134 {
6135 Expression* output_proxy = factory->NewVariableProxy(var_output);
6136 Yield* yield = factory->NewYield(
6137 generator, output_proxy, Yield::kInitial, nopos);
6138 yield_output = factory->NewExpressionStatement(yield, nopos);
6139 }
6140
6141
6142 // mode = kNext;
6143 Statement* set_mode_next;
6144 {
6145 Expression* mode_proxy = factory->NewVariableProxy(var_mode);
6146 Expression* knext = factory->NewSmiLiteral(JSGeneratorObject::NEXT, nopos);
6147 Expression* assignment =
6148 factory->NewAssignment(Token::ASSIGN, mode_proxy, knext, nopos);
6149 set_mode_next = factory->NewExpressionStatement(assignment, nopos);
6150 }
6151
6152
6153 // mode = kThrow;
6154 Statement* set_mode_throw;
6155 {
6156 Expression* mode_proxy = factory->NewVariableProxy(var_mode);
6157 Expression* kthrow =
6158 factory->NewSmiLiteral(JSGeneratorObject::THROW, nopos);
6159 Expression* assignment =
6160 factory->NewAssignment(Token::ASSIGN, mode_proxy, kthrow, nopos);
6161 set_mode_throw = factory->NewExpressionStatement(assignment, nopos);
6162 }
6163
6164
6165 // input = function.sent;
6166 Statement* get_input;
6167 {
6168 Expression* function_sent = FunctionSentExpression(scope, factory, nopos);
6169 Expression* input_proxy = factory->NewVariableProxy(var_input);
6170 Expression* assignment = factory->NewAssignment(
6171 Token::ASSIGN, input_proxy, function_sent, nopos);
6172 get_input = factory->NewExpressionStatement(assignment, nopos);
6173 }
6174
6175
6176 // output.value;
6177 Statement* get_value;
6178 {
6179 Expression* output_proxy = factory->NewVariableProxy(var_output);
6180 Expression* literal =
6181 factory->NewStringLiteral(avfactory->value_string(), nopos);
6182 Expression* property = factory->NewProperty(output_proxy, literal, nopos);
6183 get_value = factory->NewExpressionStatement(property, nopos);
6184 }
6185
6186
6187 // Now put things together.
6188
6189
6190 // try { ... } catch(e) { ... }
6191 Statement* try_catch;
6192 {
6193 Block* try_block = factory->NewBlock(nullptr, 2, false, nopos);
6194 try_block->statements()->Add(yield_output, zone);
6195 try_block->statements()->Add(set_mode_next, zone);
6196
6197 Block* catch_block = factory->NewBlock(nullptr, 1, false, nopos);
6198 catch_block->statements()->Add(set_mode_throw, zone);
6199
6200 Scope* catch_scope = NewScope(scope, CATCH_SCOPE);
6201 const AstRawString* name = avfactory->dot_catch_string();
6202 Variable* catch_variable =
6203 catch_scope->DeclareLocal(name, VAR, kCreatedInitialized,
6204 Variable::NORMAL);
6205
6206 try_catch = factory->NewTryCatchStatement(
6207 try_block, catch_scope, catch_variable, catch_block, nopos);
6208 }
6209
6210
6211 // try { ... } finally { ... }
6212 Statement* try_finally;
6213 {
6214 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
6215 try_block->statements()->Add(try_catch, zone);
6216
6217 Block* finally = factory->NewBlock(nullptr, 2, false, nopos);
6218 finally->statements()->Add(get_input, zone);
6219 finally->statements()->Add(
6220 factory->NewContinueStatement(loop, nopos), zone);
6221
6222 try_finally = factory->NewTryFinallyStatement(try_block, finally, nopos);
6223 }
6224
6225
6226 // switch (mode) { ... }
6227 SwitchStatement* switch_mode = factory->NewSwitchStatement(nullptr, nopos);
6228 {
6229 auto case_next = new (zone) ZoneList<Statement*>(3, zone);
6230 case_next->Add(call_next, zone);
6231 case_next->Add(validate_next_output, zone);
6232 case_next->Add(factory->NewBreakStatement(switch_mode, nopos), zone);
6233
6234 auto case_return = new (zone) ZoneList<Statement*>(5, zone);
6235 BuildIteratorClose(case_return, var_iterator,
6236 factory->NewVariableProxy(var_input, nopos), var_output);
6237 case_return->Add(factory->NewBreakStatement(switch_mode, nopos), zone);
6238
6239 auto case_throw = new (zone) ZoneList<Statement*>(5, zone);
6240 case_throw->Add(get_throw, zone);
6241 case_throw->Add(check_throw, zone);
6242 case_throw->Add(call_throw, zone);
6243 case_throw->Add(validate_throw_output, zone);
6244 case_throw->Add(factory->NewBreakStatement(switch_mode, nopos), zone);
6245
6246 auto cases = new (zone) ZoneList<CaseClause*>(3, zone);
6247 Expression* knext = factory->NewSmiLiteral(JSGeneratorObject::NEXT, nopos);
6248 Expression* kreturn =
6249 factory->NewSmiLiteral(JSGeneratorObject::RETURN, nopos);
6250 Expression* kthrow =
6251 factory->NewSmiLiteral(JSGeneratorObject::THROW, nopos);
6252 cases->Add(factory->NewCaseClause(knext, case_next, nopos), zone);
6253 cases->Add(factory->NewCaseClause(kreturn, case_return, nopos), zone);
6254 cases->Add(factory->NewCaseClause(kthrow, case_throw, nopos), zone);
6255
6256 switch_mode->Initialize(factory->NewVariableProxy(var_mode), cases);
6257 }
6258
6259
6260 // while (true) { ... }
6261 // Already defined earlier: WhileStatement* loop = ...
6262 {
6263 Block* loop_body = factory->NewBlock(nullptr, 4, false, nopos);
6264 loop_body->statements()->Add(switch_mode, zone);
6265 loop_body->statements()->Add(if_done, zone);
6266 loop_body->statements()->Add(set_mode_return, zone);
6267 loop_body->statements()->Add(try_finally, zone);
6268
6269 loop->Initialize(factory->NewBooleanLiteral(true, nopos), loop_body);
6270 }
6271
6272
6273 // do { ... }
6274 DoExpression* yield_star;
6275 {
6276 // The rewriter needs to process the get_value statement only, hence we
6277 // put the preceding statements into an init block.
6278
6279 Block* do_block_ = factory->NewBlock(nullptr, 6, true, nopos);
6280 do_block_->statements()->Add(initialize_input, zone);
6281 do_block_->statements()->Add(initialize_mode, zone);
6282 do_block_->statements()->Add(initialize_output, zone);
6283 do_block_->statements()->Add(get_iterator, zone);
6284 do_block_->statements()->Add(validate_iterator, zone);
6285 do_block_->statements()->Add(loop, zone);
6286
6287 Block* do_block = factory->NewBlock(nullptr, 2, false, nopos);
6288 do_block->statements()->Add(do_block_, zone);
6289 do_block->statements()->Add(get_value, zone);
6290
6291 Variable* dot_result = scope->NewTemporary(avfactory->dot_result_string());
6292 yield_star = factory->NewDoExpression(do_block, dot_result, nopos);
6293 Rewriter::Rewrite(parser_, yield_star, avfactory);
6294 }
6295
6296 return yield_star;
6297}
6298
6299// Desugaring of (lhs) instanceof (rhs)
6300// ====================================
6301//
6302// We desugar instanceof into a load of property @@hasInstance on the rhs.
6303// We end up with roughly the following code (O, C):
6304//
6305// do {
6306// let O = lhs;
6307// let C = rhs;
6308// if (!IS_RECEIVER(C)) throw MakeTypeError(kNonObjectInInstanceOfCheck);
6309// let handler_result = C[Symbol.hasInstance];
6310// if (handler_result === undefined) {
6311// if (!IS_CALLABLE(C)) {
6312// throw MakeTypeError(kCalledNonCallableInstanceOf);
6313// }
6314// handler_result = %ordinary_has_instance(C, O);
6315// } else {
6316// handler_result = !!(%_Call(handler_result, C, O));
6317// }
6318// handler_result;
6319// }
6320//
6321Expression* ParserTraits::RewriteInstanceof(Expression* lhs, Expression* rhs,
6322 int pos) {
6323 const int nopos = RelocInfo::kNoPosition;
6324
6325 auto factory = parser_->factory();
6326 auto avfactory = parser_->ast_value_factory();
6327 auto scope = parser_->scope_;
6328 auto zone = parser_->zone();
6329
6330 // let O = lhs;
6331 Variable* var_O = scope->NewTemporary(avfactory->empty_string());
6332 Statement* get_O;
6333 {
6334 Expression* O_proxy = factory->NewVariableProxy(var_O);
6335 Expression* assignment =
6336 factory->NewAssignment(Token::ASSIGN, O_proxy, lhs, nopos);
6337 get_O = factory->NewExpressionStatement(assignment, nopos);
6338 }
6339
6340 // let C = lhs;
6341 Variable* var_C = scope->NewTemporary(avfactory->empty_string());
6342 Statement* get_C;
6343 {
6344 Expression* C_proxy = factory->NewVariableProxy(var_C);
6345 Expression* assignment =
6346 factory->NewAssignment(Token::ASSIGN, C_proxy, rhs, nopos);
6347 get_C = factory->NewExpressionStatement(assignment, nopos);
6348 }
6349
6350 // if (!IS_RECEIVER(C)) throw MakeTypeError(kNonObjectInInstanceOfCheck);
6351 Statement* validate_C;
6352 {
6353 auto args = new (zone) ZoneList<Expression*>(1, zone);
6354 args->Add(factory->NewVariableProxy(var_C), zone);
6355 Expression* is_receiver_call =
6356 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
6357 Expression* call =
6358 NewThrowTypeError(MessageTemplate::kNonObjectInInstanceOfCheck,
6359 avfactory->empty_string(), nopos);
6360 Statement* throw_call = factory->NewExpressionStatement(call, nopos);
6361
6362 validate_C =
6363 factory->NewIfStatement(is_receiver_call,
6364 factory->NewEmptyStatement(nopos),
6365 throw_call,
6366 nopos);
6367 }
6368
6369 // let handler_result = C[Symbol.hasInstance];
6370 Variable* var_handler_result = scope->NewTemporary(avfactory->empty_string());
6371 Statement* initialize_handler;
6372 {
6373 Expression* hasInstance_symbol_literal =
6374 factory->NewSymbolLiteral("hasInstance_symbol", RelocInfo::kNoPosition);
6375 Expression* prop = factory->NewProperty(factory->NewVariableProxy(var_C),
6376 hasInstance_symbol_literal, pos);
6377 Expression* handler_proxy = factory->NewVariableProxy(var_handler_result);
6378 Expression* assignment =
6379 factory->NewAssignment(Token::ASSIGN, handler_proxy, prop, nopos);
6380 initialize_handler = factory->NewExpressionStatement(assignment, nopos);
6381 }
6382
6383 // if (handler_result === undefined) {
6384 // if (!IS_CALLABLE(C)) {
6385 // throw MakeTypeError(kCalledNonCallableInstanceOf);
6386 // }
6387 // result = %ordinary_has_instance(C, O);
6388 // } else {
6389 // handler_result = !!%_Call(handler_result, C, O);
6390 // }
6391 Statement* call_handler;
6392 {
6393 Expression* condition = factory->NewCompareOperation(
6394 Token::EQ_STRICT, factory->NewVariableProxy(var_handler_result),
6395 factory->NewUndefinedLiteral(nopos), nopos);
6396
6397 Block* then_side = factory->NewBlock(nullptr, 2, false, nopos);
6398 {
6399 Expression* throw_expr =
6400 NewThrowTypeError(MessageTemplate::kCalledNonCallableInstanceOf,
6401 avfactory->empty_string(), nopos);
6402 Statement* validate_C = CheckCallable(var_C, throw_expr);
6403 ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(2, zone);
6404 args->Add(factory->NewVariableProxy(var_C), zone);
6405 args->Add(factory->NewVariableProxy(var_O), zone);
6406 CallRuntime* call = factory->NewCallRuntime(
6407 Context::ORDINARY_HAS_INSTANCE_INDEX, args, pos);
6408 Expression* result_proxy = factory->NewVariableProxy(var_handler_result);
6409 Expression* assignment =
6410 factory->NewAssignment(Token::ASSIGN, result_proxy, call, nopos);
6411 Statement* assignment_return =
6412 factory->NewExpressionStatement(assignment, nopos);
6413
6414 then_side->statements()->Add(validate_C, zone);
6415 then_side->statements()->Add(assignment_return, zone);
6416 }
6417
6418 Statement* else_side;
6419 {
6420 auto args = new (zone) ZoneList<Expression*>(3, zone);
6421 args->Add(factory->NewVariableProxy(var_handler_result), zone);
6422 args->Add(factory->NewVariableProxy(var_C), zone);
6423 args->Add(factory->NewVariableProxy(var_O), zone);
6424 Expression* call =
6425 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
6426 Expression* inner_not =
6427 factory->NewUnaryOperation(Token::NOT, call, nopos);
6428 Expression* outer_not =
6429 factory->NewUnaryOperation(Token::NOT, inner_not, nopos);
6430 Expression* result_proxy = factory->NewVariableProxy(var_handler_result);
6431 Expression* assignment =
6432 factory->NewAssignment(Token::ASSIGN, result_proxy, outer_not, nopos);
6433
6434 else_side = factory->NewExpressionStatement(assignment, nopos);
6435 }
6436 call_handler =
6437 factory->NewIfStatement(condition, then_side, else_side, nopos);
6438 }
6439
6440 // do { ... }
6441 DoExpression* instanceof;
6442 {
6443 Block* block = factory->NewBlock(nullptr, 5, true, nopos);
6444 block->statements()->Add(get_O, zone);
6445 block->statements()->Add(get_C, zone);
6446 block->statements()->Add(validate_C, zone);
6447 block->statements()->Add(initialize_handler, zone);
6448 block->statements()->Add(call_handler, zone);
6449
6450 // Here is the desugared instanceof.
6451 instanceof = factory->NewDoExpression(block, var_handler_result, nopos);
6452 Rewriter::Rewrite(parser_, instanceof, avfactory);
6453 }
6454
6455 return instanceof;
6456}
6457
6458Statement* ParserTraits::CheckCallable(Variable* var, Expression* error) {
6459 auto factory = parser_->factory();
6460 auto avfactory = parser_->ast_value_factory();
6461 const int nopos = RelocInfo::kNoPosition;
6462 Statement* validate_var;
6463 {
6464 Expression* type_of = factory->NewUnaryOperation(
6465 Token::TYPEOF, factory->NewVariableProxy(var), nopos);
6466 Expression* function_literal =
6467 factory->NewStringLiteral(avfactory->function_string(), nopos);
6468 Expression* condition = factory->NewCompareOperation(
6469 Token::EQ_STRICT, type_of, function_literal, nopos);
6470
6471 Statement* throw_call = factory->NewExpressionStatement(error, nopos);
6472
6473 validate_var = factory->NewIfStatement(
6474 condition, factory->NewEmptyStatement(nopos), throw_call, nopos);
6475 }
6476 return validate_var;
6477}
6478
6479void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements,
6480 Variable* iterator,
6481 Expression* input,
6482 Variable* var_output) {
6483 //
6484 // This function adds four statements to [statements], corresponding to the
6485 // following code:
6486 //
6487 // let iteratorReturn = iterator.return;
6488 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return input;
6489 // output = %_Call(iteratorReturn, iterator);
6490 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
6491 //
6492
6493 const int nopos = RelocInfo::kNoPosition;
6494 auto factory = parser_->factory();
6495 auto avfactory = parser_->ast_value_factory();
6496 auto zone = parser_->zone();
6497
6498 // let iteratorReturn = iterator.return;
6499 Variable* var_return = var_output; // Reusing the output variable.
6500 Statement* get_return;
6501 {
6502 Expression* iterator_proxy = factory->NewVariableProxy(iterator);
6503 Expression* literal =
6504 factory->NewStringLiteral(avfactory->return_string(), nopos);
6505 Expression* property =
6506 factory->NewProperty(iterator_proxy, literal, nopos);
6507 Expression* return_proxy = factory->NewVariableProxy(var_return);
6508 Expression* assignment = factory->NewAssignment(
6509 Token::ASSIGN, return_proxy, property, nopos);
6510 get_return = factory->NewExpressionStatement(assignment, nopos);
6511 }
6512
6513 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) return input;
6514 Statement* check_return;
6515 {
6516 Expression* condition = factory->NewCompareOperation(
6517 Token::EQ, factory->NewVariableProxy(var_return),
6518 factory->NewNullLiteral(nopos), nopos);
6519
6520 Statement* return_input = factory->NewReturnStatement(input, nopos);
6521
6522 check_return = factory->NewIfStatement(
6523 condition, return_input, factory->NewEmptyStatement(nopos), nopos);
6524 }
6525
6526 // output = %_Call(iteratorReturn, iterator);
6527 Statement* call_return;
6528 {
6529 auto args = new (zone) ZoneList<Expression*>(3, zone);
6530 args->Add(factory->NewVariableProxy(var_return), zone);
6531 args->Add(factory->NewVariableProxy(iterator), zone);
6532
6533 Expression* call =
6534 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
6535 Expression* output_proxy = factory->NewVariableProxy(var_output);
6536 Expression* assignment = factory->NewAssignment(
6537 Token::ASSIGN, output_proxy, call, nopos);
6538 call_return = factory->NewExpressionStatement(assignment, nopos);
6539 }
6540
6541 // if (!IS_RECEIVER(output)) %ThrowIteratorResultNotAnObject(output);
6542 Statement* validate_output;
6543 {
6544 Expression* is_receiver_call;
6545 {
6546 auto args = new (zone) ZoneList<Expression*>(1, zone);
6547 args->Add(factory->NewVariableProxy(var_output), zone);
6548 is_receiver_call =
6549 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
6550 }
6551
6552 Statement* throw_call;
6553 {
6554 auto args = new (zone) ZoneList<Expression*>(1, zone);
6555 args->Add(factory->NewVariableProxy(var_output), zone);
6556 Expression* call = factory->NewCallRuntime(
6557 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
6558 throw_call = factory->NewExpressionStatement(call, nopos);
6559 }
6560
6561 validate_output = factory->NewIfStatement(
6562 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
6563 }
6564
6565 statements->Add(get_return, zone);
6566 statements->Add(check_return, zone);
6567 statements->Add(call_return, zone);
6568 statements->Add(validate_output, zone);
6569}
6570
6571
6572// Runtime encoding of different completion modes.
6573enum ForOfLoopBodyCompletion { BODY_COMPLETED, BODY_ABORTED, BODY_THREW };
6574
6575void ParserTraits::BuildIteratorCloseForCompletion(
6576 ZoneList<Statement*>* statements, Variable* iterator,
6577 Variable* completion) {
6578 //
6579 // This function adds two statements to [statements], corresponding to the
6580 // following code:
6581 //
6582 // let iteratorReturn = iterator.return;
6583 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
6584 // let output;
6585 // if (completion === BODY_THREW) {
6586 // if (!IS_CALLABLE(iteratorReturn)) {
6587 // throw MakeTypeError(kReturnMethodNotCallable);
6588 // }
6589 // try { output = %_Call(iteratorReturn, iterator) } catch (_) { }
6590 // } else {
6591 // output = %_Call(iteratorReturn, iterator);
6592 // }
6593 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
6594 // }
6595 //
6596
6597 const int nopos = RelocInfo::kNoPosition;
6598 auto factory = parser_->factory();
6599 auto avfactory = parser_->ast_value_factory();
6600 auto scope = parser_->scope_;
6601 auto zone = parser_->zone();
6602
6603 // let output;
6604 Variable* var_output = scope->NewTemporary(avfactory->empty_string());
6605
6606 // let iteratorReturn = iterator.return;
6607 Variable* var_return = var_output; // Reusing the output variable.
6608 Statement* get_return;
6609 {
6610 Expression* iterator_proxy = factory->NewVariableProxy(iterator);
6611 Expression* literal =
6612 factory->NewStringLiteral(avfactory->return_string(), nopos);
6613 Expression* property =
6614 factory->NewProperty(iterator_proxy, literal, nopos);
6615 Expression* return_proxy = factory->NewVariableProxy(var_return);
6616 Expression* assignment = factory->NewAssignment(
6617 Token::ASSIGN, return_proxy, property, nopos);
6618 get_return = factory->NewExpressionStatement(assignment, nopos);
6619 }
6620
6621 // if (!IS_CALLABLE(iteratorReturn)) {
6622 // throw MakeTypeError(kReturnMethodNotCallable);
6623 // }
6624 Statement* check_return_callable;
6625 {
6626 Expression* throw_expr = NewThrowTypeError(
6627 MessageTemplate::kReturnMethodNotCallable,
6628 avfactory->empty_string(), nopos);
6629 check_return_callable = CheckCallable(var_return, throw_expr);
6630 }
6631
6632 // output = %_Call(iteratorReturn, iterator);
6633 Statement* call_return;
6634 {
6635 auto args = new (zone) ZoneList<Expression*>(2, zone);
6636 args->Add(factory->NewVariableProxy(var_return), zone);
6637 args->Add(factory->NewVariableProxy(iterator), zone);
6638 Expression* call =
6639 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
6640
6641 Expression* output_proxy = factory->NewVariableProxy(var_output);
6642 Expression* assignment = factory->NewAssignment(
6643 Token::ASSIGN, output_proxy, call, nopos);
6644 call_return = factory->NewExpressionStatement(assignment, nopos);
6645 }
6646
6647 // try { output = %_Call(iteratorReturn, iterator) } catch (_) { }
6648 Statement* try_call_return;
6649 {
6650 auto args = new (zone) ZoneList<Expression*>(2, zone);
6651 args->Add(factory->NewVariableProxy(var_return), zone);
6652 args->Add(factory->NewVariableProxy(iterator), zone);
6653
6654 Expression* call =
6655 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
6656 Expression* assignment = factory->NewAssignment(
6657 Token::ASSIGN, factory->NewVariableProxy(var_output), call, nopos);
6658
6659 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
6660 try_block->statements()->Add(
6661 factory->NewExpressionStatement(assignment, nopos), zone);
6662
6663 Block* catch_block = factory->NewBlock(nullptr, 0, false, nopos);
6664
6665 Scope* catch_scope = NewScope(scope, CATCH_SCOPE);
6666 Variable* catch_variable = catch_scope->DeclareLocal(
6667 avfactory->dot_catch_string(), VAR, kCreatedInitialized,
6668 Variable::NORMAL);
6669
6670 try_call_return = factory->NewTryCatchStatement(
6671 try_block, catch_scope, catch_variable, catch_block, nopos);
6672 }
6673
6674 // if (completion === ABRUPT_THROW) {
6675 // #check_return_callable;
6676 // #try_call_return;
6677 // } else {
6678 // #call_return;
6679 // }
6680 Statement* call_return_carefully;
6681 {
6682 Expression* condition = factory->NewCompareOperation(
6683 Token::EQ_STRICT, factory->NewVariableProxy(completion),
6684 factory->NewSmiLiteral(BODY_THREW, nopos), nopos);
6685
6686 Block* then_block = factory->NewBlock(nullptr, 2, false, nopos);
6687 then_block->statements()->Add(check_return_callable, zone);
6688 then_block->statements()->Add(try_call_return, zone);
6689
6690 call_return_carefully =
6691 factory->NewIfStatement(condition, then_block, call_return, nopos);
6692 }
6693
6694 // if (!IS_RECEIVER(output)) %ThrowIteratorResultNotAnObject(output);
6695 Statement* validate_output;
6696 {
6697 Expression* is_receiver_call;
6698 {
6699 auto args = new (zone) ZoneList<Expression*>(1, zone);
6700 args->Add(factory->NewVariableProxy(var_output), zone);
6701 is_receiver_call =
6702 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
6703 }
6704
6705 Statement* throw_call;
6706 {
6707 auto args = new (zone) ZoneList<Expression*>(1, zone);
6708 args->Add(factory->NewVariableProxy(var_output), zone);
6709 Expression* call = factory->NewCallRuntime(
6710 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
6711 throw_call = factory->NewExpressionStatement(call, nopos);
6712 }
6713
6714 validate_output = factory->NewIfStatement(
6715 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
6716 }
6717
6718 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { ... }
6719 Statement* maybe_call_return;
6720 {
6721 Expression* condition = factory->NewCompareOperation(
6722 Token::EQ, factory->NewVariableProxy(var_return),
6723 factory->NewNullLiteral(nopos), nopos);
6724
6725 Block* block = factory->NewBlock(nullptr, 2, false, nopos);
6726 block->statements()->Add(call_return_carefully, zone);
6727 block->statements()->Add(validate_output, zone);
6728
6729 maybe_call_return = factory->NewIfStatement(
6730 condition, factory->NewEmptyStatement(nopos), block, nopos);
6731 }
6732
6733
6734 statements->Add(get_return, zone);
6735 statements->Add(maybe_call_return, zone);
6736}
6737
6738
6739Statement* ParserTraits::FinalizeForOfStatement(ForOfStatement* loop, int pos) {
6740 if (!FLAG_harmony_iterator_close) return loop;
6741
6742 //
6743 // This function replaces the loop with the following wrapping:
6744 //
6745 // let completion = BODY_COMPLETED;
6746 // try {
6747 // #loop;
6748 // } catch(e) {
6749 // if (completion === BODY_ABORTED) completion = BODY_THREW;
6750 // throw e;
6751 // } finally {
6752 // if (!(completion === BODY_COMPLETED || IS_UNDEFINED(#iterator))) {
6753 // #BuildIteratorClose(#iterator, completion) // See above.
6754 // }
6755 // }
6756 //
6757 // where the loop's body is wrapped as follows:
6758 //
6759 // {
6760 // {{completion = BODY_ABORTED;}}
6761 // #loop-body
6762 // {{completion = BODY_COMPLETED;}}
6763 // }
6764
6765 const int nopos = RelocInfo::kNoPosition;
6766 auto factory = parser_->factory();
6767 auto avfactory = parser_->ast_value_factory();
6768 auto scope = parser_->scope_;
6769 auto zone = parser_->zone();
6770
6771 // let completion = BODY_COMPLETED;
6772 Variable* var_completion = scope->NewTemporary(avfactory->empty_string());
6773 Statement* initialize_completion;
6774 {
6775 Expression* proxy = factory->NewVariableProxy(var_completion);
6776 Expression* assignment = factory->NewAssignment(
6777 Token::ASSIGN, proxy,
6778 factory->NewSmiLiteral(BODY_COMPLETED, nopos), nopos);
6779 initialize_completion =
6780 factory->NewExpressionStatement(assignment, nopos);
6781 }
6782
6783 // if (completion === BODY_ABORTED) completion = BODY_THREW;
6784 Statement* set_completion_throw;
6785 {
6786 Expression* condition = factory->NewCompareOperation(
6787 Token::EQ_STRICT, factory->NewVariableProxy(var_completion),
6788 factory->NewSmiLiteral(BODY_ABORTED, nopos), nopos);
6789
6790 Expression* proxy = factory->NewVariableProxy(var_completion);
6791 Expression* assignment = factory->NewAssignment(
6792 Token::ASSIGN, proxy, factory->NewSmiLiteral(BODY_THREW, nopos),
6793 nopos);
6794 Statement* statement = factory->NewExpressionStatement(assignment, nopos);
6795 set_completion_throw = factory->NewIfStatement(
6796 condition, statement, factory->NewEmptyStatement(nopos), nopos);
6797 }
6798
6799 // if (!(completion === BODY_COMPLETED || IS_UNDEFINED(#iterator))) {
6800 // #BuildIteratorClose(#iterator, completion)
6801 // }
6802 Block* maybe_close;
6803 {
6804 Expression* condition1 = factory->NewCompareOperation(
6805 Token::EQ_STRICT, factory->NewVariableProxy(var_completion),
6806 factory->NewSmiLiteral(BODY_COMPLETED, nopos), nopos);
6807 Expression* condition2 = factory->NewCompareOperation(
6808 Token::EQ_STRICT, factory->NewVariableProxy(loop->iterator()),
6809 factory->NewUndefinedLiteral(nopos), nopos);
6810 Expression* condition = factory->NewBinaryOperation(
6811 Token::OR, condition1, condition2, nopos);
6812
6813 Block* block = factory->NewBlock(nullptr, 2, false, nopos);
6814 BuildIteratorCloseForCompletion(
6815 block->statements(), loop->iterator(), var_completion);
6816 DCHECK(block->statements()->length() == 2);
6817
6818 maybe_close = factory->NewBlock(nullptr, 1, false, nopos);
6819 maybe_close->statements()->Add(factory->NewIfStatement(
6820 condition, factory->NewEmptyStatement(nopos), block, nopos), zone);
6821 }
6822
6823 // try { #try_block }
6824 // catch(e) {
6825 // #set_completion_throw;
6826 // throw e;
6827 // }
6828 Statement* try_catch;
6829 {
6830 Scope* catch_scope = NewScope(scope, CATCH_SCOPE);
6831 Variable* catch_variable = catch_scope->DeclareLocal(
6832 avfactory->dot_catch_string(), VAR, kCreatedInitialized,
6833 Variable::NORMAL);
6834
6835 Statement* rethrow;
6836 {
6837 Expression* proxy = factory->NewVariableProxy(catch_variable);
6838 rethrow = factory->NewExpressionStatement(
6839 factory->NewThrow(proxy, nopos), nopos);
6840 }
6841
6842 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
6843 try_block->statements()->Add(loop, zone);
6844
6845 Block* catch_block = factory->NewBlock(nullptr, 2, false, nopos);
6846 catch_block->statements()->Add(set_completion_throw, zone);
6847 catch_block->statements()->Add(rethrow, zone);
6848
6849 try_catch = factory->NewTryCatchStatement(
6850 try_block, catch_scope, catch_variable, catch_block, nopos);
6851 }
6852
6853 // try { #try_catch } finally { #maybe_close }
6854 Statement* try_finally;
6855 {
6856 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
6857 try_block->statements()->Add(try_catch, zone);
6858
6859 try_finally =
6860 factory->NewTryFinallyStatement(try_block, maybe_close, nopos);
6861 }
6862
6863 // #initialize_completion;
6864 // #try_finally;
6865 Statement* final_loop;
6866 {
6867 Block* block = factory->NewBlock(nullptr, 2, false, nopos);
6868 block->statements()->Add(initialize_completion, zone);
6869 block->statements()->Add(try_finally, zone);
6870 final_loop = block;
6871 }
6872
6873 // {{completion = BODY_ABORTED;}}
6874 Statement* set_completion_break;
6875 {
6876 Expression* proxy = factory->NewVariableProxy(var_completion);
6877 Expression* assignment = factory->NewAssignment(
6878 Token::ASSIGN, proxy,
6879 factory->NewSmiLiteral(BODY_ABORTED, nopos), nopos);
6880
6881 Block* block = factory->NewBlock(nullptr, 1, true, nopos);
6882 block->statements()->Add(
6883 factory->NewExpressionStatement(assignment, nopos), zone);
6884 set_completion_break = block;
6885 }
6886
6887 // {{completion = BODY_COMPLETED;}}
6888 Statement* set_completion_normal;
6889 {
6890 Expression* proxy = factory->NewVariableProxy(var_completion);
6891 Expression* assignment = factory->NewAssignment(
6892 Token::ASSIGN, proxy, factory->NewSmiLiteral(BODY_COMPLETED, nopos),
6893 nopos);
6894
6895 Block* block = factory->NewBlock(nullptr, 1, true, nopos);
6896 block->statements()->Add(
6897 factory->NewExpressionStatement(assignment, nopos), zone);
6898 set_completion_normal = block;
6899 }
6900
6901 // { #set_completion_break; #loop-body; #set_completion_normal }
6902 Block* new_body = factory->NewBlock(nullptr, 2, false, nopos);
6903 new_body->statements()->Add(set_completion_break, zone);
6904 new_body->statements()->Add(loop->body(), zone);
6905 new_body->statements()->Add(set_completion_normal, zone);
6906
6907 loop->set_body(new_body);
6908 return final_loop;
6909}
6910
6911
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006912} // namespace internal
6913} // namespace v8