blob: a39d0eec1284649fe8bc90f077550ed3c875e60a [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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000042ParseInfo::ParseInfo(Zone* zone)
43 : zone_(zone),
44 flags_(0),
45 source_stream_(nullptr),
46 source_stream_encoding_(ScriptCompiler::StreamedSource::ONE_BYTE),
47 extension_(nullptr),
48 compile_options_(ScriptCompiler::kNoCompileOptions),
49 script_scope_(nullptr),
50 unicode_cache_(nullptr),
51 stack_limit_(0),
52 hash_seed_(0),
Ben Murdochc5610432016-08-08 18:44:38 +010053 isolate_(nullptr),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000054 cached_data_(nullptr),
55 ast_value_factory_(nullptr),
56 literal_(nullptr),
57 scope_(nullptr) {}
58
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000059ParseInfo::ParseInfo(Zone* zone, Handle<JSFunction> function)
60 : ParseInfo(zone, Handle<SharedFunctionInfo>(function->shared())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000061 set_context(Handle<Context>(function->context()));
62}
63
64
65ParseInfo::ParseInfo(Zone* zone, Handle<SharedFunctionInfo> shared)
66 : ParseInfo(zone) {
67 isolate_ = shared->GetIsolate();
68
69 set_lazy();
70 set_hash_seed(isolate_->heap()->HashSeed());
71 set_stack_limit(isolate_->stack_guard()->real_climit());
72 set_unicode_cache(isolate_->unicode_cache());
73 set_language_mode(shared->language_mode());
74 set_shared_info(shared);
75
76 Handle<Script> script(Script::cast(shared->script()));
77 set_script(script);
78 if (!script.is_null() && script->type() == Script::TYPE_NATIVE) {
79 set_native();
80 }
81}
82
83
84ParseInfo::ParseInfo(Zone* zone, Handle<Script> script) : ParseInfo(zone) {
85 isolate_ = script->GetIsolate();
86
87 set_hash_seed(isolate_->heap()->HashSeed());
88 set_stack_limit(isolate_->stack_guard()->real_climit());
89 set_unicode_cache(isolate_->unicode_cache());
90 set_script(script);
91
92 if (script->type() == Script::TYPE_NATIVE) {
93 set_native();
94 }
95}
96
97
98FunctionEntry ParseData::GetFunctionEntry(int start) {
99 // The current pre-data entry must be a FunctionEntry with the given
100 // start position.
101 if ((function_index_ + FunctionEntry::kSize <= Length()) &&
102 (static_cast<int>(Data()[function_index_]) == start)) {
103 int index = function_index_;
104 function_index_ += FunctionEntry::kSize;
105 Vector<unsigned> subvector(&(Data()[index]), FunctionEntry::kSize);
106 return FunctionEntry(subvector);
107 }
108 return FunctionEntry();
109}
110
111
112int ParseData::FunctionCount() {
113 int functions_size = FunctionsSize();
114 if (functions_size < 0) return 0;
115 if (functions_size % FunctionEntry::kSize != 0) return 0;
116 return functions_size / FunctionEntry::kSize;
117}
118
119
120bool ParseData::IsSane() {
121 if (!IsAligned(script_data_->length(), sizeof(unsigned))) return false;
122 // Check that the header data is valid and doesn't specify
123 // point to positions outside the store.
124 int data_length = Length();
125 if (data_length < PreparseDataConstants::kHeaderSize) return false;
126 if (Magic() != PreparseDataConstants::kMagicNumber) return false;
127 if (Version() != PreparseDataConstants::kCurrentVersion) return false;
128 if (HasError()) return false;
129 // Check that the space allocated for function entries is sane.
130 int functions_size = FunctionsSize();
131 if (functions_size < 0) return false;
132 if (functions_size % FunctionEntry::kSize != 0) return false;
133 // Check that the total size has room for header and function entries.
134 int minimum_size =
135 PreparseDataConstants::kHeaderSize + functions_size;
136 if (data_length < minimum_size) return false;
137 return true;
138}
139
140
141void ParseData::Initialize() {
142 // Prepares state for use.
143 int data_length = Length();
144 if (data_length >= PreparseDataConstants::kHeaderSize) {
145 function_index_ = PreparseDataConstants::kHeaderSize;
146 }
147}
148
149
150bool ParseData::HasError() {
151 return Data()[PreparseDataConstants::kHasErrorOffset];
152}
153
154
155unsigned ParseData::Magic() {
156 return Data()[PreparseDataConstants::kMagicOffset];
157}
158
159
160unsigned ParseData::Version() {
161 return Data()[PreparseDataConstants::kVersionOffset];
162}
163
164
165int ParseData::FunctionsSize() {
166 return static_cast<int>(Data()[PreparseDataConstants::kFunctionsSizeOffset]);
167}
168
169
170void Parser::SetCachedData(ParseInfo* info) {
171 if (compile_options_ == ScriptCompiler::kNoCompileOptions) {
172 cached_parse_data_ = NULL;
173 } else {
174 DCHECK(info->cached_data() != NULL);
175 if (compile_options_ == ScriptCompiler::kConsumeParserCache) {
176 cached_parse_data_ = ParseData::FromCachedData(*info->cached_data());
177 }
178 }
179}
180
Ben Murdoch097c5b22016-05-18 11:27:45 +0100181FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name,
182 bool call_super, Scope* scope,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000183 int pos, int end_pos,
184 LanguageMode language_mode) {
185 int materialized_literal_count = -1;
186 int expected_property_count = -1;
187 int parameter_count = 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100188 if (name == nullptr) name = ast_value_factory()->empty_string();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000189
190 FunctionKind kind = call_super ? FunctionKind::kDefaultSubclassConstructor
191 : FunctionKind::kDefaultBaseConstructor;
192 Scope* function_scope = NewScope(scope, FUNCTION_SCOPE, kind);
193 SetLanguageMode(function_scope,
194 static_cast<LanguageMode>(language_mode | STRICT));
195 // Set start and end position to the same value
196 function_scope->set_start_position(pos);
197 function_scope->set_end_position(pos);
198 ZoneList<Statement*>* body = NULL;
199
200 {
201 AstNodeFactory function_factory(ast_value_factory());
202 FunctionState function_state(&function_state_, &scope_, function_scope,
203 kind, &function_factory);
204
205 body = new (zone()) ZoneList<Statement*>(call_super ? 2 : 1, zone());
206 if (call_super) {
207 // $super_constructor = %_GetSuperConstructor(<this-function>)
Ben Murdoch61f157c2016-09-16 13:49:30 +0100208 // %reflect_construct(
209 // $super_constructor, InternalArray(...args), new.target)
210 auto constructor_args_name = ast_value_factory()->empty_string();
211 bool is_duplicate;
212 bool is_rest = true;
213 bool is_optional = false;
214 Variable* constructor_args =
215 function_scope->DeclareParameter(constructor_args_name, TEMPORARY,
216 is_optional, is_rest, &is_duplicate);
217
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000218 ZoneList<Expression*>* args =
219 new (zone()) ZoneList<Expression*>(2, zone());
220 VariableProxy* this_function_proxy = scope_->NewUnresolved(
221 factory(), ast_value_factory()->this_function_string(),
222 Variable::NORMAL, pos);
223 ZoneList<Expression*>* tmp =
224 new (zone()) ZoneList<Expression*>(1, zone());
225 tmp->Add(this_function_proxy, zone());
226 Expression* super_constructor = factory()->NewCallRuntime(
227 Runtime::kInlineGetSuperConstructor, tmp, pos);
228 args->Add(super_constructor, zone());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100229 Spread* spread_args = factory()->NewSpread(
230 factory()->NewVariableProxy(constructor_args), pos, pos);
231 ZoneList<Expression*>* spread_args_expr =
232 new (zone()) ZoneList<Expression*>(1, zone());
233 spread_args_expr->Add(spread_args, zone());
234 args->AddAll(*PrepareSpreadArguments(spread_args_expr), zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000235 VariableProxy* new_target_proxy = scope_->NewUnresolved(
236 factory(), ast_value_factory()->new_target_string(), Variable::NORMAL,
237 pos);
238 args->Add(new_target_proxy, zone());
239 CallRuntime* call = factory()->NewCallRuntime(
240 Context::REFLECT_CONSTRUCT_INDEX, args, pos);
241 body->Add(factory()->NewReturnStatement(call, pos), zone());
242 }
243
244 materialized_literal_count = function_state.materialized_literal_count();
245 expected_property_count = function_state.expected_property_count();
246 }
247
248 FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
249 name, function_scope, body, materialized_literal_count,
250 expected_property_count, parameter_count,
251 FunctionLiteral::kNoDuplicateParameters,
252 FunctionLiteral::kAnonymousExpression,
253 FunctionLiteral::kShouldLazyCompile, kind, pos);
254
255 return function_literal;
256}
257
258
259// ----------------------------------------------------------------------------
260// Target is a support class to facilitate manipulation of the
261// Parser's target_stack_ (the stack of potential 'break' and
262// 'continue' statement targets). Upon construction, a new target is
263// added; it is removed upon destruction.
264
265class Target BASE_EMBEDDED {
266 public:
267 Target(Target** variable, BreakableStatement* statement)
268 : variable_(variable), statement_(statement), previous_(*variable) {
269 *variable = this;
270 }
271
272 ~Target() {
273 *variable_ = previous_;
274 }
275
276 Target* previous() { return previous_; }
277 BreakableStatement* statement() { return statement_; }
278
279 private:
280 Target** variable_;
281 BreakableStatement* statement_;
282 Target* previous_;
283};
284
285
286class TargetScope BASE_EMBEDDED {
287 public:
288 explicit TargetScope(Target** variable)
289 : variable_(variable), previous_(*variable) {
290 *variable = NULL;
291 }
292
293 ~TargetScope() {
294 *variable_ = previous_;
295 }
296
297 private:
298 Target** variable_;
299 Target* previous_;
300};
301
302
303// ----------------------------------------------------------------------------
304// The CHECK_OK macro is a convenient macro to enforce error
305// handling for functions that may fail (by returning !*ok).
306//
307// CAUTION: This macro appends extra statements after a call,
308// thus it must never be used where only a single statement
309// is correct (e.g. an if statement branch w/o braces)!
310
311#define CHECK_OK ok); \
312 if (!*ok) return NULL; \
313 ((void)0
314#define DUMMY ) // to make indentation work
315#undef DUMMY
316
317#define CHECK_FAILED /**/); \
318 if (failed_) return NULL; \
319 ((void)0
320#define DUMMY ) // to make indentation work
321#undef DUMMY
322
323// ----------------------------------------------------------------------------
324// Implementation of Parser
325
326bool ParserTraits::IsEval(const AstRawString* identifier) const {
327 return identifier == parser_->ast_value_factory()->eval_string();
328}
329
330
331bool ParserTraits::IsArguments(const AstRawString* identifier) const {
332 return identifier == parser_->ast_value_factory()->arguments_string();
333}
334
335
336bool ParserTraits::IsEvalOrArguments(const AstRawString* identifier) const {
337 return IsEval(identifier) || IsArguments(identifier);
338}
339
340bool ParserTraits::IsUndefined(const AstRawString* identifier) const {
341 return identifier == parser_->ast_value_factory()->undefined_string();
342}
343
Ben Murdochc5610432016-08-08 18:44:38 +0100344bool ParserTraits::IsAwait(const AstRawString* identifier) const {
345 return identifier == parser_->ast_value_factory()->await_string();
346}
347
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000348bool ParserTraits::IsPrototype(const AstRawString* identifier) const {
349 return identifier == parser_->ast_value_factory()->prototype_string();
350}
351
352
353bool ParserTraits::IsConstructor(const AstRawString* identifier) const {
354 return identifier == parser_->ast_value_factory()->constructor_string();
355}
356
357
358bool ParserTraits::IsThisProperty(Expression* expression) {
359 DCHECK(expression != NULL);
360 Property* property = expression->AsProperty();
361 return property != NULL && property->obj()->IsVariableProxy() &&
362 property->obj()->AsVariableProxy()->is_this();
363}
364
365
366bool ParserTraits::IsIdentifier(Expression* expression) {
367 VariableProxy* operand = expression->AsVariableProxy();
368 return operand != NULL && !operand->is_this();
369}
370
371
372void ParserTraits::PushPropertyName(FuncNameInferrer* fni,
373 Expression* expression) {
374 if (expression->IsPropertyName()) {
375 fni->PushLiteralName(expression->AsLiteral()->AsRawPropertyName());
376 } else {
377 fni->PushLiteralName(
378 parser_->ast_value_factory()->anonymous_function_string());
379 }
380}
381
382
383void ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left,
384 Expression* right) {
385 DCHECK(left != NULL);
386 if (left->IsProperty() && right->IsFunctionLiteral()) {
387 right->AsFunctionLiteral()->set_pretenure();
388 }
389}
390
391
392Expression* ParserTraits::MarkExpressionAsAssigned(Expression* expression) {
393 VariableProxy* proxy =
394 expression != NULL ? expression->AsVariableProxy() : NULL;
395 if (proxy != NULL) proxy->set_is_assigned();
396 return expression;
397}
398
399
400bool ParserTraits::ShortcutNumericLiteralBinaryExpression(
401 Expression** x, Expression* y, Token::Value op, int pos,
402 AstNodeFactory* factory) {
403 if ((*x)->AsLiteral() && (*x)->AsLiteral()->raw_value()->IsNumber() &&
404 y->AsLiteral() && y->AsLiteral()->raw_value()->IsNumber()) {
405 double x_val = (*x)->AsLiteral()->raw_value()->AsNumber();
406 double y_val = y->AsLiteral()->raw_value()->AsNumber();
407 bool x_has_dot = (*x)->AsLiteral()->raw_value()->ContainsDot();
408 bool y_has_dot = y->AsLiteral()->raw_value()->ContainsDot();
409 bool has_dot = x_has_dot || y_has_dot;
410 switch (op) {
411 case Token::ADD:
412 *x = factory->NewNumberLiteral(x_val + y_val, pos, has_dot);
413 return true;
414 case Token::SUB:
415 *x = factory->NewNumberLiteral(x_val - y_val, pos, has_dot);
416 return true;
417 case Token::MUL:
418 *x = factory->NewNumberLiteral(x_val * y_val, pos, has_dot);
419 return true;
420 case Token::DIV:
421 *x = factory->NewNumberLiteral(x_val / y_val, pos, has_dot);
422 return true;
423 case Token::BIT_OR: {
424 int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
425 *x = factory->NewNumberLiteral(value, pos, has_dot);
426 return true;
427 }
428 case Token::BIT_AND: {
429 int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
430 *x = factory->NewNumberLiteral(value, pos, has_dot);
431 return true;
432 }
433 case Token::BIT_XOR: {
434 int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
435 *x = factory->NewNumberLiteral(value, pos, has_dot);
436 return true;
437 }
438 case Token::SHL: {
439 int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
440 *x = factory->NewNumberLiteral(value, pos, has_dot);
441 return true;
442 }
443 case Token::SHR: {
444 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
445 uint32_t value = DoubleToUint32(x_val) >> shift;
446 *x = factory->NewNumberLiteral(value, pos, has_dot);
447 return true;
448 }
449 case Token::SAR: {
450 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
451 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
452 *x = factory->NewNumberLiteral(value, pos, has_dot);
453 return true;
454 }
Ben Murdochda12d292016-06-02 14:46:10 +0100455 case Token::EXP: {
456 double value = Pow(x_val, y_val);
457 int int_value = static_cast<int>(value);
458 *x = factory->NewNumberLiteral(
459 int_value == value && value != -0.0 ? int_value : value, pos,
460 has_dot);
461 return true;
462 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000463 default:
464 break;
465 }
466 }
467 return false;
468}
469
470
471Expression* ParserTraits::BuildUnaryExpression(Expression* expression,
472 Token::Value op, int pos,
473 AstNodeFactory* factory) {
474 DCHECK(expression != NULL);
475 if (expression->IsLiteral()) {
476 const AstValue* literal = expression->AsLiteral()->raw_value();
477 if (op == Token::NOT) {
478 // Convert the literal to a boolean condition and negate it.
479 bool condition = literal->BooleanValue();
480 return factory->NewBooleanLiteral(!condition, pos);
481 } else if (literal->IsNumber()) {
482 // Compute some expressions involving only number literals.
483 double value = literal->AsNumber();
484 bool has_dot = literal->ContainsDot();
485 switch (op) {
486 case Token::ADD:
487 return expression;
488 case Token::SUB:
489 return factory->NewNumberLiteral(-value, pos, has_dot);
490 case Token::BIT_NOT:
491 return factory->NewNumberLiteral(~DoubleToInt32(value), pos, has_dot);
492 default:
493 break;
494 }
495 }
496 }
497 // Desugar '+foo' => 'foo*1'
498 if (op == Token::ADD) {
499 return factory->NewBinaryOperation(
500 Token::MUL, expression, factory->NewNumberLiteral(1, pos, true), pos);
501 }
502 // The same idea for '-foo' => 'foo*(-1)'.
503 if (op == Token::SUB) {
504 return factory->NewBinaryOperation(
505 Token::MUL, expression, factory->NewNumberLiteral(-1, pos), pos);
506 }
507 // ...and one more time for '~foo' => 'foo^(~0)'.
508 if (op == Token::BIT_NOT) {
509 return factory->NewBinaryOperation(
510 Token::BIT_XOR, expression, factory->NewNumberLiteral(~0, pos), pos);
511 }
512 return factory->NewUnaryOperation(op, expression, pos);
513}
514
Ben Murdochda12d292016-06-02 14:46:10 +0100515Expression* ParserTraits::BuildIteratorResult(Expression* value, bool done) {
516 int pos = RelocInfo::kNoPosition;
517 AstNodeFactory* factory = parser_->factory();
518 Zone* zone = parser_->zone();
519
520 if (value == nullptr) value = factory->NewUndefinedLiteral(pos);
521
522 auto args = new (zone) ZoneList<Expression*>(2, zone);
523 args->Add(value, zone);
524 args->Add(factory->NewBooleanLiteral(done, pos), zone);
525
526 return factory->NewCallRuntime(Runtime::kInlineCreateIterResultObject, args,
527 pos);
528}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000529
530Expression* ParserTraits::NewThrowReferenceError(
531 MessageTemplate::Template message, int pos) {
532 return NewThrowError(Runtime::kNewReferenceError, message,
533 parser_->ast_value_factory()->empty_string(), pos);
534}
535
536
537Expression* ParserTraits::NewThrowSyntaxError(MessageTemplate::Template message,
538 const AstRawString* arg,
539 int pos) {
540 return NewThrowError(Runtime::kNewSyntaxError, message, arg, pos);
541}
542
543
544Expression* ParserTraits::NewThrowTypeError(MessageTemplate::Template message,
545 const AstRawString* arg, int pos) {
546 return NewThrowError(Runtime::kNewTypeError, message, arg, pos);
547}
548
549
550Expression* ParserTraits::NewThrowError(Runtime::FunctionId id,
551 MessageTemplate::Template message,
552 const AstRawString* arg, int pos) {
553 Zone* zone = parser_->zone();
554 ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(2, zone);
555 args->Add(parser_->factory()->NewSmiLiteral(message, pos), zone);
556 args->Add(parser_->factory()->NewStringLiteral(arg, pos), zone);
557 CallRuntime* call_constructor =
558 parser_->factory()->NewCallRuntime(id, args, pos);
559 return parser_->factory()->NewThrow(call_constructor, pos);
560}
561
562
563void ParserTraits::ReportMessageAt(Scanner::Location source_location,
564 MessageTemplate::Template message,
565 const char* arg, ParseErrorType error_type) {
566 if (parser_->stack_overflow()) {
567 // Suppress the error message (syntax error or such) in the presence of a
568 // stack overflow. The isolate allows only one pending exception at at time
569 // and we want to report the stack overflow later.
570 return;
571 }
572 parser_->pending_error_handler_.ReportMessageAt(source_location.beg_pos,
573 source_location.end_pos,
574 message, arg, error_type);
575}
576
577
578void ParserTraits::ReportMessage(MessageTemplate::Template message,
579 const char* arg, ParseErrorType error_type) {
580 Scanner::Location source_location = parser_->scanner()->location();
581 ReportMessageAt(source_location, message, arg, error_type);
582}
583
584
585void ParserTraits::ReportMessage(MessageTemplate::Template message,
586 const AstRawString* arg,
587 ParseErrorType error_type) {
588 Scanner::Location source_location = parser_->scanner()->location();
589 ReportMessageAt(source_location, message, arg, error_type);
590}
591
592
593void ParserTraits::ReportMessageAt(Scanner::Location source_location,
594 MessageTemplate::Template message,
595 const AstRawString* arg,
596 ParseErrorType error_type) {
597 if (parser_->stack_overflow()) {
598 // Suppress the error message (syntax error or such) in the presence of a
599 // stack overflow. The isolate allows only one pending exception at at time
600 // and we want to report the stack overflow later.
601 return;
602 }
603 parser_->pending_error_handler_.ReportMessageAt(source_location.beg_pos,
604 source_location.end_pos,
605 message, arg, error_type);
606}
607
608
609const AstRawString* ParserTraits::GetSymbol(Scanner* scanner) {
610 const AstRawString* result =
611 parser_->scanner()->CurrentSymbol(parser_->ast_value_factory());
612 DCHECK(result != NULL);
613 return result;
614}
615
616
617const AstRawString* ParserTraits::GetNumberAsSymbol(Scanner* scanner) {
618 double double_value = parser_->scanner()->DoubleValue();
619 char array[100];
Ben Murdochc5610432016-08-08 18:44:38 +0100620 const char* string = DoubleToCString(double_value, ArrayVector(array));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000621 return parser_->ast_value_factory()->GetOneByteString(string);
622}
623
624
625const AstRawString* ParserTraits::GetNextSymbol(Scanner* scanner) {
626 return parser_->scanner()->NextSymbol(parser_->ast_value_factory());
627}
628
629
630Expression* ParserTraits::ThisExpression(Scope* scope, AstNodeFactory* factory,
631 int pos) {
632 return scope->NewUnresolved(factory,
633 parser_->ast_value_factory()->this_string(),
634 Variable::THIS, pos, pos + 4);
635}
636
637
638Expression* ParserTraits::SuperPropertyReference(Scope* scope,
639 AstNodeFactory* factory,
640 int pos) {
641 // this_function[home_object_symbol]
642 VariableProxy* this_function_proxy = scope->NewUnresolved(
643 factory, parser_->ast_value_factory()->this_function_string(),
644 Variable::NORMAL, pos);
645 Expression* home_object_symbol_literal =
646 factory->NewSymbolLiteral("home_object_symbol", RelocInfo::kNoPosition);
647 Expression* home_object = factory->NewProperty(
648 this_function_proxy, home_object_symbol_literal, pos);
649 return factory->NewSuperPropertyReference(
650 ThisExpression(scope, factory, pos)->AsVariableProxy(), home_object, pos);
651}
652
653
654Expression* ParserTraits::SuperCallReference(Scope* scope,
655 AstNodeFactory* factory, int pos) {
656 VariableProxy* new_target_proxy = scope->NewUnresolved(
657 factory, parser_->ast_value_factory()->new_target_string(),
658 Variable::NORMAL, pos);
659 VariableProxy* this_function_proxy = scope->NewUnresolved(
660 factory, parser_->ast_value_factory()->this_function_string(),
661 Variable::NORMAL, pos);
662 return factory->NewSuperCallReference(
663 ThisExpression(scope, factory, pos)->AsVariableProxy(), new_target_proxy,
664 this_function_proxy, pos);
665}
666
667
668Expression* ParserTraits::NewTargetExpression(Scope* scope,
669 AstNodeFactory* factory,
670 int pos) {
671 static const int kNewTargetStringLength = 10;
672 auto proxy = scope->NewUnresolved(
673 factory, parser_->ast_value_factory()->new_target_string(),
674 Variable::NORMAL, pos, pos + kNewTargetStringLength);
675 proxy->set_is_new_target();
676 return proxy;
677}
678
679
Ben Murdoch097c5b22016-05-18 11:27:45 +0100680Expression* ParserTraits::FunctionSentExpression(Scope* scope,
681 AstNodeFactory* factory,
682 int pos) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100683 // We desugar function.sent into %_GeneratorGetInputOrDebugPos(generator).
Ben Murdoch097c5b22016-05-18 11:27:45 +0100684 Zone* zone = parser_->zone();
685 ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(1, zone);
686 VariableProxy* generator = factory->NewVariableProxy(
687 parser_->function_state_->generator_object_variable());
688 args->Add(generator, zone);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100689 return factory->NewCallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos,
690 args, pos);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000691}
692
693
694Literal* ParserTraits::ExpressionFromLiteral(Token::Value token, int pos,
695 Scanner* scanner,
696 AstNodeFactory* factory) {
697 switch (token) {
698 case Token::NULL_LITERAL:
699 return factory->NewNullLiteral(pos);
700 case Token::TRUE_LITERAL:
701 return factory->NewBooleanLiteral(true, pos);
702 case Token::FALSE_LITERAL:
703 return factory->NewBooleanLiteral(false, pos);
704 case Token::SMI: {
705 int value = scanner->smi_value();
706 return factory->NewSmiLiteral(value, pos);
707 }
708 case Token::NUMBER: {
709 bool has_dot = scanner->ContainsDot();
710 double value = scanner->DoubleValue();
711 return factory->NewNumberLiteral(value, pos, has_dot);
712 }
713 default:
714 DCHECK(false);
715 }
716 return NULL;
717}
718
719
720Expression* ParserTraits::ExpressionFromIdentifier(const AstRawString* name,
721 int start_position,
722 int end_position,
723 Scope* scope,
724 AstNodeFactory* factory) {
725 if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name);
726 return scope->NewUnresolved(factory, name, Variable::NORMAL, start_position,
727 end_position);
728}
729
730
731Expression* ParserTraits::ExpressionFromString(int pos, Scanner* scanner,
732 AstNodeFactory* factory) {
733 const AstRawString* symbol = GetSymbol(scanner);
734 if (parser_->fni_ != NULL) parser_->fni_->PushLiteralName(symbol);
735 return factory->NewStringLiteral(symbol, pos);
736}
737
738
739Expression* ParserTraits::GetIterator(Expression* iterable,
740 AstNodeFactory* factory, int pos) {
741 Expression* iterator_symbol_literal =
742 factory->NewSymbolLiteral("iterator_symbol", RelocInfo::kNoPosition);
743 Expression* prop =
744 factory->NewProperty(iterable, iterator_symbol_literal, pos);
745 Zone* zone = parser_->zone();
746 ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(0, zone);
747 return factory->NewCall(prop, args, pos);
748}
749
750
751Literal* ParserTraits::GetLiteralTheHole(int position,
752 AstNodeFactory* factory) {
753 return factory->NewTheHoleLiteral(RelocInfo::kNoPosition);
754}
755
756
757Expression* ParserTraits::ParseV8Intrinsic(bool* ok) {
758 return parser_->ParseV8Intrinsic(ok);
759}
760
761
762FunctionLiteral* ParserTraits::ParseFunctionLiteral(
763 const AstRawString* name, Scanner::Location function_name_location,
764 FunctionNameValidity function_name_validity, FunctionKind kind,
765 int function_token_position, FunctionLiteral::FunctionType type,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000766 LanguageMode language_mode, bool* ok) {
767 return parser_->ParseFunctionLiteral(
768 name, function_name_location, function_name_validity, kind,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100769 function_token_position, type, language_mode, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000770}
771
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000772ClassLiteral* ParserTraits::ParseClassLiteral(
Ben Murdochda12d292016-06-02 14:46:10 +0100773 Type::ExpressionClassifier* classifier, const AstRawString* name,
774 Scanner::Location class_name_location, bool name_is_strict_reserved,
775 int pos, bool* ok) {
776 return parser_->ParseClassLiteral(classifier, name, class_name_location,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000777 name_is_strict_reserved, pos, ok);
778}
779
Ben Murdochda12d292016-06-02 14:46:10 +0100780void ParserTraits::MarkTailPosition(Expression* expression) {
781 expression->MarkTail();
782}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000783
Ben Murdochc5610432016-08-08 18:44:38 +0100784void ParserTraits::MarkCollectedTailCallExpressions() {
785 parser_->MarkCollectedTailCallExpressions();
786}
787
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000788Parser::Parser(ParseInfo* info)
789 : ParserBase<ParserTraits>(info->zone(), &scanner_, info->stack_limit(),
790 info->extension(), info->ast_value_factory(),
791 NULL, this),
792 scanner_(info->unicode_cache()),
793 reusable_preparser_(NULL),
794 original_scope_(NULL),
795 target_stack_(NULL),
796 compile_options_(info->compile_options()),
797 cached_parse_data_(NULL),
798 total_preparse_skipped_(0),
799 pre_parse_timer_(NULL),
800 parsing_on_main_thread_(true) {
801 // Even though we were passed ParseInfo, we should not store it in
802 // Parser - this makes sure that Isolate is not accidentally accessed via
803 // ParseInfo during background parsing.
804 DCHECK(!info->script().is_null() || info->source_stream() != NULL);
805 set_allow_lazy(info->allow_lazy_parsing());
806 set_allow_natives(FLAG_allow_natives_syntax || info->is_native());
Ben Murdochda12d292016-06-02 14:46:10 +0100807 set_allow_tailcalls(FLAG_harmony_tailcalls && !info->is_native() &&
808 info->isolate()->is_tail_call_elimination_enabled());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000809 set_allow_harmony_do_expressions(FLAG_harmony_do_expressions);
Ben Murdochc5610432016-08-08 18:44:38 +0100810 set_allow_harmony_for_in(FLAG_harmony_for_in);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100811 set_allow_harmony_function_sent(FLAG_harmony_function_sent);
Ben Murdochda12d292016-06-02 14:46:10 +0100812 set_allow_harmony_restrictive_declarations(
813 FLAG_harmony_restrictive_declarations);
814 set_allow_harmony_exponentiation_operator(
815 FLAG_harmony_exponentiation_operator);
Ben Murdochc5610432016-08-08 18:44:38 +0100816 set_allow_harmony_async_await(FLAG_harmony_async_await);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100817 set_allow_harmony_restrictive_generators(FLAG_harmony_restrictive_generators);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000818 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
819 ++feature) {
820 use_counts_[feature] = 0;
821 }
822 if (info->ast_value_factory() == NULL) {
823 // info takes ownership of AstValueFactory.
824 info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed()));
825 info->set_ast_value_factory_owned();
826 ast_value_factory_ = info->ast_value_factory();
827 }
828}
829
830
831FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {
832 // TODO(bmeurer): We temporarily need to pass allow_nesting = true here,
833 // see comment for HistogramTimerScope class.
834
835 // It's OK to use the Isolate & counters here, since this function is only
836 // called in the main thread.
837 DCHECK(parsing_on_main_thread_);
838
839 HistogramTimerScope timer_scope(isolate->counters()->parse(), true);
Ben Murdochc5610432016-08-08 18:44:38 +0100840 RuntimeCallTimerScope runtime_timer(isolate, &RuntimeCallStats::Parse);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100841 TRACE_EVENT0("v8", "V8.Parse");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000842 Handle<String> source(String::cast(info->script()->source()));
843 isolate->counters()->total_parse_size()->Increment(source->length());
844 base::ElapsedTimer timer;
845 if (FLAG_trace_parse) {
846 timer.Start();
847 }
848 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
849
850 // Initialize parser state.
851 CompleteParserRecorder recorder;
852
853 if (produce_cached_parse_data()) {
854 log_ = &recorder;
855 } else if (consume_cached_parse_data()) {
856 cached_parse_data_->Initialize();
857 }
858
859 source = String::Flatten(source);
860 FunctionLiteral* result;
861
862 if (source->IsExternalTwoByteString()) {
863 // Notice that the stream is destroyed at the end of the branch block.
864 // The last line of the blocks can't be moved outside, even though they're
865 // identical calls.
866 ExternalTwoByteStringUtf16CharacterStream stream(
867 Handle<ExternalTwoByteString>::cast(source), 0, source->length());
868 scanner_.Initialize(&stream);
869 result = DoParseProgram(info);
870 } else {
871 GenericStringUtf16CharacterStream stream(source, 0, source->length());
872 scanner_.Initialize(&stream);
873 result = DoParseProgram(info);
874 }
875 if (result != NULL) {
876 DCHECK_EQ(scanner_.peek_location().beg_pos, source->length());
877 }
878 HandleSourceURLComments(isolate, info->script());
879
880 if (FLAG_trace_parse && result != NULL) {
881 double ms = timer.Elapsed().InMillisecondsF();
882 if (info->is_eval()) {
883 PrintF("[parsing eval");
884 } else if (info->script()->name()->IsString()) {
885 String* name = String::cast(info->script()->name());
886 base::SmartArrayPointer<char> name_chars = name->ToCString();
887 PrintF("[parsing script: %s", name_chars.get());
888 } else {
889 PrintF("[parsing script");
890 }
891 PrintF(" - took %0.3f ms]\n", ms);
892 }
893 if (produce_cached_parse_data()) {
894 if (result != NULL) *info->cached_data() = recorder.GetScriptData();
895 log_ = NULL;
896 }
897 return result;
898}
899
900
901FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
902 // Note that this function can be called from the main thread or from a
903 // background thread. We should not access anything Isolate / heap dependent
904 // via ParseInfo, and also not pass it forward.
905 DCHECK(scope_ == NULL);
906 DCHECK(target_stack_ == NULL);
907
908 Mode parsing_mode = FLAG_lazy && allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY;
909 if (allow_natives() || extension_ != NULL) parsing_mode = PARSE_EAGERLY;
910
911 FunctionLiteral* result = NULL;
912 {
913 // TODO(wingo): Add an outer SCRIPT_SCOPE corresponding to the native
914 // context, which will have the "this" binding for script scopes.
915 Scope* scope = NewScope(scope_, SCRIPT_SCOPE);
916 info->set_script_scope(scope);
917 if (!info->context().is_null() && !info->context()->IsNativeContext()) {
918 scope = Scope::DeserializeScopeChain(info->isolate(), zone(),
919 *info->context(), scope);
920 // The Scope is backed up by ScopeInfo (which is in the V8 heap); this
921 // means the Parser cannot operate independent of the V8 heap. Tell the
922 // string table to internalize strings and values right after they're
923 // created. This kind of parsing can only be done in the main thread.
924 DCHECK(parsing_on_main_thread_);
925 ast_value_factory()->Internalize(info->isolate());
926 }
927 original_scope_ = scope;
928 if (info->is_eval()) {
929 if (!scope->is_script_scope() || is_strict(info->language_mode())) {
930 parsing_mode = PARSE_EAGERLY;
931 }
932 scope = NewScope(scope, EVAL_SCOPE);
933 } else if (info->is_module()) {
934 scope = NewScope(scope, MODULE_SCOPE);
935 }
936
937 scope->set_start_position(0);
938
939 // Enter 'scope' with the given parsing mode.
940 ParsingModeScope parsing_mode_scope(this, parsing_mode);
941 AstNodeFactory function_factory(ast_value_factory());
942 FunctionState function_state(&function_state_, &scope_, scope,
943 kNormalFunction, &function_factory);
944
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000945 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
946 bool ok = true;
947 int beg_pos = scanner()->location().beg_pos;
Ben Murdochc5610432016-08-08 18:44:38 +0100948 parsing_module_ = info->is_module();
949 if (parsing_module_) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000950 ParseModuleItemList(body, &ok);
951 } else {
Ben Murdochc5610432016-08-08 18:44:38 +0100952 // Don't count the mode in the use counters--give the program a chance
953 // to enable script-wide strict mode below.
954 scope_->SetLanguageMode(info->language_mode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000955 ParseStatementList(body, Token::EOS, &ok);
956 }
957
958 // The parser will peek but not consume EOS. Our scope logically goes all
959 // the way to the EOS, though.
960 scope->set_end_position(scanner()->peek_location().beg_pos);
961
962 if (ok && is_strict(language_mode())) {
963 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
Ben Murdochc5610432016-08-08 18:44:38 +0100964 CheckDecimalLiteralWithLeadingZero(use_counts_, beg_pos,
965 scanner()->location().end_pos);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000966 }
Ben Murdochc5610432016-08-08 18:44:38 +0100967 if (ok && is_sloppy(language_mode())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000968 // TODO(littledan): Function bindings on the global object that modify
969 // pre-existing bindings should be made writable, enumerable and
970 // nonconfigurable if possible, whereas this code will leave attributes
971 // unchanged if the property already exists.
972 InsertSloppyBlockFunctionVarBindings(scope, &ok);
973 }
Ben Murdochda12d292016-06-02 14:46:10 +0100974 if (ok) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000975 CheckConflictingVarDeclarations(scope_, &ok);
976 }
977
978 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) {
979 if (body->length() != 1 ||
980 !body->at(0)->IsExpressionStatement() ||
981 !body->at(0)->AsExpressionStatement()->
982 expression()->IsFunctionLiteral()) {
983 ReportMessage(MessageTemplate::kSingleFunctionLiteral);
984 ok = false;
985 }
986 }
987
988 if (ok) {
989 ParserTraits::RewriteDestructuringAssignments();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100990 result = factory()->NewScriptOrEvalFunctionLiteral(
991 scope_, body, function_state.materialized_literal_count(),
992 function_state.expected_property_count());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000993 }
994 }
995
996 // Make sure the target stack is empty.
997 DCHECK(target_stack_ == NULL);
998
999 return result;
1000}
1001
1002
1003FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info) {
1004 // It's OK to use the Isolate & counters here, since this function is only
1005 // called in the main thread.
1006 DCHECK(parsing_on_main_thread_);
Ben Murdochc5610432016-08-08 18:44:38 +01001007 RuntimeCallTimerScope runtime_timer(isolate, &RuntimeCallStats::ParseLazy);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001008 HistogramTimerScope timer_scope(isolate->counters()->parse_lazy());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001009 TRACE_EVENT0("v8", "V8.ParseLazy");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001010 Handle<String> source(String::cast(info->script()->source()));
1011 isolate->counters()->total_parse_size()->Increment(source->length());
1012 base::ElapsedTimer timer;
1013 if (FLAG_trace_parse) {
1014 timer.Start();
1015 }
1016 Handle<SharedFunctionInfo> shared_info = info->shared_info();
1017
1018 // Initialize parser state.
1019 source = String::Flatten(source);
1020 FunctionLiteral* result;
1021 if (source->IsExternalTwoByteString()) {
1022 ExternalTwoByteStringUtf16CharacterStream stream(
1023 Handle<ExternalTwoByteString>::cast(source),
1024 shared_info->start_position(),
1025 shared_info->end_position());
1026 result = ParseLazy(isolate, info, &stream);
1027 } else {
1028 GenericStringUtf16CharacterStream stream(source,
1029 shared_info->start_position(),
1030 shared_info->end_position());
1031 result = ParseLazy(isolate, info, &stream);
1032 }
1033
1034 if (FLAG_trace_parse && result != NULL) {
1035 double ms = timer.Elapsed().InMillisecondsF();
1036 base::SmartArrayPointer<char> name_chars =
1037 result->debug_name()->ToCString();
1038 PrintF("[parsing function: %s - took %0.3f ms]\n", name_chars.get(), ms);
1039 }
1040 return result;
1041}
1042
Ben Murdoch097c5b22016-05-18 11:27:45 +01001043static FunctionLiteral::FunctionType ComputeFunctionType(
1044 Handle<SharedFunctionInfo> shared_info) {
1045 if (shared_info->is_declaration()) {
1046 return FunctionLiteral::kDeclaration;
1047 } else if (shared_info->is_named_expression()) {
1048 return FunctionLiteral::kNamedExpression;
1049 } else if (IsConciseMethod(shared_info->kind()) ||
1050 IsAccessorFunction(shared_info->kind())) {
1051 return FunctionLiteral::kAccessorOrMethod;
1052 }
1053 return FunctionLiteral::kAnonymousExpression;
1054}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001055
1056FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
1057 Utf16CharacterStream* source) {
1058 Handle<SharedFunctionInfo> shared_info = info->shared_info();
1059 scanner_.Initialize(source);
1060 DCHECK(scope_ == NULL);
1061 DCHECK(target_stack_ == NULL);
1062
1063 Handle<String> name(String::cast(shared_info->name()));
1064 DCHECK(ast_value_factory());
1065 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
1066 const AstRawString* raw_name = ast_value_factory()->GetString(name);
1067 fni_->PushEnclosingName(raw_name);
1068
1069 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
1070
1071 // Place holder for the result.
1072 FunctionLiteral* result = NULL;
1073
1074 {
1075 // Parse the function literal.
1076 Scope* scope = NewScope(scope_, SCRIPT_SCOPE);
1077 info->set_script_scope(scope);
Ben Murdochc5610432016-08-08 18:44:38 +01001078 if (!info->context().is_null()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001079 // Ok to use Isolate here, since lazy function parsing is only done in the
1080 // main thread.
1081 DCHECK(parsing_on_main_thread_);
Ben Murdochc5610432016-08-08 18:44:38 +01001082 scope = Scope::DeserializeScopeChain(isolate, zone(), *info->context(),
1083 scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001084 }
1085 original_scope_ = scope;
1086 AstNodeFactory function_factory(ast_value_factory());
1087 FunctionState function_state(&function_state_, &scope_, scope,
1088 shared_info->kind(), &function_factory);
1089 DCHECK(is_sloppy(scope->language_mode()) ||
1090 is_strict(info->language_mode()));
1091 DCHECK(info->language_mode() == shared_info->language_mode());
1092 FunctionLiteral::FunctionType function_type =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001093 ComputeFunctionType(shared_info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001094 bool ok = true;
1095
1096 if (shared_info->is_arrow()) {
Ben Murdochc5610432016-08-08 18:44:38 +01001097 bool is_async = allow_harmony_async_await() && shared_info->is_async();
1098 if (is_async) {
1099 DCHECK(!scanner()->HasAnyLineTerminatorAfterNext());
1100 Consume(Token::ASYNC);
1101 DCHECK(peek_any_identifier() || peek() == Token::LPAREN);
1102 }
1103
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001104 // TODO(adamk): We should construct this scope from the ScopeInfo.
1105 Scope* scope =
1106 NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction);
1107
1108 // These two bits only need to be explicitly set because we're
1109 // not passing the ScopeInfo to the Scope constructor.
1110 // TODO(adamk): Remove these calls once the above NewScope call
1111 // passes the ScopeInfo.
1112 if (shared_info->scope_info()->CallsEval()) {
1113 scope->RecordEvalCall();
1114 }
1115 SetLanguageMode(scope, shared_info->language_mode());
1116
1117 scope->set_start_position(shared_info->start_position());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001118 ExpressionClassifier formals_classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001119 ParserFormalParameters formals(scope);
1120 Checkpoint checkpoint(this);
1121 {
1122 // Parsing patterns as variable reference expression creates
1123 // NewUnresolved references in current scope. Entrer arrow function
1124 // scope for formal parameter parsing.
1125 BlockState block_state(&scope_, scope);
1126 if (Check(Token::LPAREN)) {
1127 // '(' StrictFormalParameters ')'
1128 ParseFormalParameterList(&formals, &formals_classifier, &ok);
1129 if (ok) ok = Check(Token::RPAREN);
1130 } else {
1131 // BindingIdentifier
1132 ParseFormalParameter(&formals, &formals_classifier, &ok);
1133 if (ok) {
1134 DeclareFormalParameter(formals.scope, formals.at(0),
1135 &formals_classifier);
1136 }
1137 }
1138 }
1139
1140 if (ok) {
1141 checkpoint.Restore(&formals.materialized_literals_count);
1142 // Pass `accept_IN=true` to ParseArrowFunctionLiteral --- This should
1143 // not be observable, or else the preparser would have failed.
Ben Murdochc5610432016-08-08 18:44:38 +01001144 Expression* expression = ParseArrowFunctionLiteral(
1145 true, formals, is_async, formals_classifier, &ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001146 if (ok) {
1147 // Scanning must end at the same position that was recorded
1148 // previously. If not, parsing has been interrupted due to a stack
1149 // overflow, at which point the partially parsed arrow function
1150 // concise body happens to be a valid expression. This is a problem
1151 // only for arrow functions with single expression bodies, since there
1152 // is no end token such as "}" for normal functions.
1153 if (scanner()->location().end_pos == shared_info->end_position()) {
1154 // The pre-parser saw an arrow function here, so the full parser
1155 // must produce a FunctionLiteral.
1156 DCHECK(expression->IsFunctionLiteral());
1157 result = expression->AsFunctionLiteral();
1158 } else {
1159 ok = false;
1160 }
1161 }
1162 }
1163 } else if (shared_info->is_default_constructor()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001164 result = DefaultConstructor(
1165 raw_name, IsSubclassConstructor(shared_info->kind()), scope,
1166 shared_info->start_position(), shared_info->end_position(),
1167 shared_info->language_mode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001168 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001169 result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(),
1170 kSkipFunctionNameCheck, shared_info->kind(),
1171 RelocInfo::kNoPosition, function_type,
1172 shared_info->language_mode(), &ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001173 }
1174 // Make sure the results agree.
1175 DCHECK(ok == (result != NULL));
1176 }
1177
1178 // Make sure the target stack is empty.
1179 DCHECK(target_stack_ == NULL);
1180
1181 if (result != NULL) {
1182 Handle<String> inferred_name(shared_info->inferred_name());
1183 result->set_inferred_name(inferred_name);
1184 }
1185 return result;
1186}
1187
1188
1189void* Parser::ParseStatementList(ZoneList<Statement*>* body, int end_token,
1190 bool* ok) {
1191 // StatementList ::
1192 // (StatementListItem)* <end_token>
1193
1194 // Allocate a target stack to use for this set of source
1195 // elements. This way, all scripts and functions get their own
1196 // target stack thus avoiding illegal breaks and continues across
1197 // functions.
1198 TargetScope scope(&this->target_stack_);
1199
1200 DCHECK(body != NULL);
1201 bool directive_prologue = true; // Parsing directive prologue.
1202
1203 while (peek() != end_token) {
1204 if (directive_prologue && peek() != Token::STRING) {
1205 directive_prologue = false;
1206 }
1207
1208 Scanner::Location token_loc = scanner()->peek_location();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001209 Statement* stat = ParseStatementListItem(CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001210 if (stat == NULL || stat->IsEmpty()) {
1211 directive_prologue = false; // End of directive prologue.
1212 continue;
1213 }
1214
1215 if (directive_prologue) {
1216 // A shot at a directive.
1217 ExpressionStatement* e_stat;
1218 Literal* literal;
1219 // Still processing directive prologue?
1220 if ((e_stat = stat->AsExpressionStatement()) != NULL &&
1221 (literal = e_stat->expression()->AsLiteral()) != NULL &&
1222 literal->raw_value()->IsString()) {
Ben Murdochda12d292016-06-02 14:46:10 +01001223 // Check "use strict" directive (ES5 14.1), "use asm" directive.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001224 bool use_strict_found =
1225 literal->raw_value()->AsString() ==
1226 ast_value_factory()->use_strict_string() &&
1227 token_loc.end_pos - token_loc.beg_pos ==
1228 ast_value_factory()->use_strict_string()->length() + 2;
Ben Murdochda12d292016-06-02 14:46:10 +01001229 if (use_strict_found) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001230 if (is_sloppy(scope_->language_mode())) {
1231 RaiseLanguageMode(STRICT);
1232 }
1233
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001234 if (!scope_->HasSimpleParameters()) {
1235 // TC39 deemed "use strict" directives to be an error when occurring
1236 // in the body of a function with non-simple parameter list, on
1237 // 29/7/2015. https://goo.gl/ueA7Ln
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001238 const AstRawString* string = literal->raw_value()->AsString();
1239 ParserTraits::ReportMessageAt(
1240 token_loc, MessageTemplate::kIllegalLanguageModeDirective,
1241 string);
1242 *ok = false;
1243 return nullptr;
1244 }
1245 // Because declarations in strict eval code don't leak into the scope
1246 // of the eval call, it is likely that functions declared in strict
1247 // eval code will be used within the eval code, so lazy parsing is
1248 // probably not a win.
1249 if (scope_->is_eval_scope()) mode_ = PARSE_EAGERLY;
1250 } else if (literal->raw_value()->AsString() ==
1251 ast_value_factory()->use_asm_string() &&
1252 token_loc.end_pos - token_loc.beg_pos ==
1253 ast_value_factory()->use_asm_string()->length() + 2) {
1254 // Store the usage count; The actual use counter on the isolate is
1255 // incremented after parsing is done.
1256 ++use_counts_[v8::Isolate::kUseAsm];
1257 scope_->SetAsmModule();
1258 } else {
1259 // Should not change mode, but will increment UseCounter
1260 // if appropriate. Ditto usages below.
1261 RaiseLanguageMode(SLOPPY);
1262 }
1263 } else {
1264 // End of the directive prologue.
1265 directive_prologue = false;
1266 RaiseLanguageMode(SLOPPY);
1267 }
1268 } else {
1269 RaiseLanguageMode(SLOPPY);
1270 }
1271
1272 body->Add(stat, zone());
1273 }
1274
1275 return 0;
1276}
1277
1278
1279Statement* Parser::ParseStatementListItem(bool* ok) {
1280 // (Ecma 262 6th Edition, 13.1):
1281 // StatementListItem:
1282 // Statement
1283 // Declaration
Ben Murdochc5610432016-08-08 18:44:38 +01001284 const Token::Value peeked = peek();
1285 switch (peeked) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001286 case Token::FUNCTION:
Ben Murdochc5610432016-08-08 18:44:38 +01001287 return ParseHoistableDeclaration(NULL, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001288 case Token::CLASS:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001289 Consume(Token::CLASS);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001290 return ParseClassDeclaration(NULL, ok);
1291 case Token::CONST:
Ben Murdochc5610432016-08-08 18:44:38 +01001292 return ParseVariableStatement(kStatementListItem, NULL, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001293 case Token::VAR:
1294 return ParseVariableStatement(kStatementListItem, NULL, ok);
1295 case Token::LET:
1296 if (IsNextLetKeyword()) {
1297 return ParseVariableStatement(kStatementListItem, NULL, ok);
1298 }
1299 break;
Ben Murdochc5610432016-08-08 18:44:38 +01001300 case Token::ASYNC:
1301 if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION &&
1302 !scanner()->HasAnyLineTerminatorAfterNext()) {
1303 Consume(Token::ASYNC);
1304 return ParseAsyncFunctionDeclaration(NULL, ok);
1305 }
1306 /* falls through */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001307 default:
1308 break;
1309 }
Ben Murdochda12d292016-06-02 14:46:10 +01001310 return ParseStatement(NULL, kAllowLabelledFunctionStatement, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001311}
1312
1313
1314Statement* Parser::ParseModuleItem(bool* ok) {
1315 // (Ecma 262 6th Edition, 15.2):
1316 // ModuleItem :
1317 // ImportDeclaration
1318 // ExportDeclaration
1319 // StatementListItem
1320
1321 switch (peek()) {
1322 case Token::IMPORT:
1323 return ParseImportDeclaration(ok);
1324 case Token::EXPORT:
1325 return ParseExportDeclaration(ok);
1326 default:
1327 return ParseStatementListItem(ok);
1328 }
1329}
1330
1331
1332void* Parser::ParseModuleItemList(ZoneList<Statement*>* body, bool* ok) {
1333 // (Ecma 262 6th Edition, 15.2):
1334 // Module :
1335 // ModuleBody?
1336 //
1337 // ModuleBody :
1338 // ModuleItem*
1339
1340 DCHECK(scope_->is_module_scope());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001341
1342 while (peek() != Token::EOS) {
1343 Statement* stat = ParseModuleItem(CHECK_OK);
1344 if (stat && !stat->IsEmpty()) {
1345 body->Add(stat, zone());
1346 }
1347 }
1348
1349 // Check that all exports are bound.
1350 ModuleDescriptor* descriptor = scope_->module();
1351 for (ModuleDescriptor::Iterator it = descriptor->iterator(); !it.done();
1352 it.Advance()) {
1353 if (scope_->LookupLocal(it.local_name()) == NULL) {
1354 // TODO(adamk): Pass both local_name and export_name once ParserTraits
1355 // supports multiple arg error messages.
1356 // Also try to report this at a better location.
1357 ParserTraits::ReportMessage(MessageTemplate::kModuleExportUndefined,
1358 it.local_name());
1359 *ok = false;
1360 return NULL;
1361 }
1362 }
1363
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001364 return NULL;
1365}
1366
1367
1368const AstRawString* Parser::ParseModuleSpecifier(bool* ok) {
1369 // ModuleSpecifier :
1370 // StringLiteral
1371
1372 Expect(Token::STRING, CHECK_OK);
1373 return GetSymbol(scanner());
1374}
1375
1376
1377void* Parser::ParseExportClause(ZoneList<const AstRawString*>* export_names,
1378 ZoneList<Scanner::Location>* export_locations,
1379 ZoneList<const AstRawString*>* local_names,
1380 Scanner::Location* reserved_loc, bool* ok) {
1381 // ExportClause :
1382 // '{' '}'
1383 // '{' ExportsList '}'
1384 // '{' ExportsList ',' '}'
1385 //
1386 // ExportsList :
1387 // ExportSpecifier
1388 // ExportsList ',' ExportSpecifier
1389 //
1390 // ExportSpecifier :
1391 // IdentifierName
1392 // IdentifierName 'as' IdentifierName
1393
1394 Expect(Token::LBRACE, CHECK_OK);
1395
1396 Token::Value name_tok;
1397 while ((name_tok = peek()) != Token::RBRACE) {
1398 // Keep track of the first reserved word encountered in case our
1399 // caller needs to report an error.
1400 if (!reserved_loc->IsValid() &&
Ben Murdochc5610432016-08-08 18:44:38 +01001401 !Token::IsIdentifier(name_tok, STRICT, false, parsing_module_)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001402 *reserved_loc = scanner()->location();
1403 }
1404 const AstRawString* local_name = ParseIdentifierName(CHECK_OK);
1405 const AstRawString* export_name = NULL;
1406 if (CheckContextualKeyword(CStrVector("as"))) {
1407 export_name = ParseIdentifierName(CHECK_OK);
1408 }
1409 if (export_name == NULL) {
1410 export_name = local_name;
1411 }
1412 export_names->Add(export_name, zone());
1413 local_names->Add(local_name, zone());
1414 export_locations->Add(scanner()->location(), zone());
1415 if (peek() == Token::RBRACE) break;
1416 Expect(Token::COMMA, CHECK_OK);
1417 }
1418
1419 Expect(Token::RBRACE, CHECK_OK);
1420
1421 return 0;
1422}
1423
1424
1425ZoneList<ImportDeclaration*>* Parser::ParseNamedImports(int pos, bool* ok) {
1426 // NamedImports :
1427 // '{' '}'
1428 // '{' ImportsList '}'
1429 // '{' ImportsList ',' '}'
1430 //
1431 // ImportsList :
1432 // ImportSpecifier
1433 // ImportsList ',' ImportSpecifier
1434 //
1435 // ImportSpecifier :
1436 // BindingIdentifier
1437 // IdentifierName 'as' BindingIdentifier
1438
1439 Expect(Token::LBRACE, CHECK_OK);
1440
1441 ZoneList<ImportDeclaration*>* result =
1442 new (zone()) ZoneList<ImportDeclaration*>(1, zone());
1443 while (peek() != Token::RBRACE) {
1444 const AstRawString* import_name = ParseIdentifierName(CHECK_OK);
1445 const AstRawString* local_name = import_name;
1446 // In the presence of 'as', the left-side of the 'as' can
1447 // be any IdentifierName. But without 'as', it must be a valid
1448 // BindingIdentifier.
1449 if (CheckContextualKeyword(CStrVector("as"))) {
1450 local_name = ParseIdentifierName(CHECK_OK);
1451 }
Ben Murdochc5610432016-08-08 18:44:38 +01001452 if (!Token::IsIdentifier(scanner()->current_token(), STRICT, false,
1453 parsing_module_)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001454 *ok = false;
1455 ReportMessage(MessageTemplate::kUnexpectedReserved);
1456 return NULL;
1457 } else if (IsEvalOrArguments(local_name)) {
1458 *ok = false;
1459 ReportMessage(MessageTemplate::kStrictEvalArguments);
1460 return NULL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001461 }
Ben Murdochc5610432016-08-08 18:44:38 +01001462 VariableProxy* proxy = NewUnresolved(local_name, CONST);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001463 ImportDeclaration* declaration =
1464 factory()->NewImportDeclaration(proxy, import_name, NULL, scope_, pos);
1465 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
1466 result->Add(declaration, zone());
1467 if (peek() == Token::RBRACE) break;
1468 Expect(Token::COMMA, CHECK_OK);
1469 }
1470
1471 Expect(Token::RBRACE, CHECK_OK);
1472
1473 return result;
1474}
1475
1476
1477Statement* Parser::ParseImportDeclaration(bool* ok) {
1478 // ImportDeclaration :
1479 // 'import' ImportClause 'from' ModuleSpecifier ';'
1480 // 'import' ModuleSpecifier ';'
1481 //
1482 // ImportClause :
1483 // NameSpaceImport
1484 // NamedImports
1485 // ImportedDefaultBinding
1486 // ImportedDefaultBinding ',' NameSpaceImport
1487 // ImportedDefaultBinding ',' NamedImports
1488 //
1489 // NameSpaceImport :
1490 // '*' 'as' ImportedBinding
1491
1492 int pos = peek_position();
1493 Expect(Token::IMPORT, CHECK_OK);
1494
1495 Token::Value tok = peek();
1496
1497 // 'import' ModuleSpecifier ';'
1498 if (tok == Token::STRING) {
1499 const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
1500 scope_->module()->AddModuleRequest(module_specifier, zone());
1501 ExpectSemicolon(CHECK_OK);
1502 return factory()->NewEmptyStatement(pos);
1503 }
1504
1505 // Parse ImportedDefaultBinding if present.
1506 ImportDeclaration* import_default_declaration = NULL;
1507 if (tok != Token::MUL && tok != Token::LBRACE) {
1508 const AstRawString* local_name =
1509 ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK);
Ben Murdochc5610432016-08-08 18:44:38 +01001510 VariableProxy* proxy = NewUnresolved(local_name, CONST);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001511 import_default_declaration = factory()->NewImportDeclaration(
1512 proxy, ast_value_factory()->default_string(), NULL, scope_, pos);
1513 Declare(import_default_declaration, DeclarationDescriptor::NORMAL, true,
1514 CHECK_OK);
1515 }
1516
1517 const AstRawString* module_instance_binding = NULL;
1518 ZoneList<ImportDeclaration*>* named_declarations = NULL;
1519 if (import_default_declaration == NULL || Check(Token::COMMA)) {
1520 switch (peek()) {
1521 case Token::MUL: {
1522 Consume(Token::MUL);
1523 ExpectContextualKeyword(CStrVector("as"), CHECK_OK);
1524 module_instance_binding =
1525 ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK);
1526 // TODO(ES6): Add an appropriate declaration.
1527 break;
1528 }
1529
1530 case Token::LBRACE:
1531 named_declarations = ParseNamedImports(pos, CHECK_OK);
1532 break;
1533
1534 default:
1535 *ok = false;
1536 ReportUnexpectedToken(scanner()->current_token());
1537 return NULL;
1538 }
1539 }
1540
1541 ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
1542 const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
1543 scope_->module()->AddModuleRequest(module_specifier, zone());
1544
1545 if (module_instance_binding != NULL) {
1546 // TODO(ES6): Set the module specifier for the module namespace binding.
1547 }
1548
1549 if (import_default_declaration != NULL) {
1550 import_default_declaration->set_module_specifier(module_specifier);
1551 }
1552
1553 if (named_declarations != NULL) {
1554 for (int i = 0; i < named_declarations->length(); ++i) {
1555 named_declarations->at(i)->set_module_specifier(module_specifier);
1556 }
1557 }
1558
1559 ExpectSemicolon(CHECK_OK);
1560 return factory()->NewEmptyStatement(pos);
1561}
1562
1563
1564Statement* Parser::ParseExportDefault(bool* ok) {
1565 // Supports the following productions, starting after the 'default' token:
1566 // 'export' 'default' FunctionDeclaration
1567 // 'export' 'default' ClassDeclaration
1568 // 'export' 'default' AssignmentExpression[In] ';'
1569
1570 Expect(Token::DEFAULT, CHECK_OK);
1571 Scanner::Location default_loc = scanner()->location();
1572
Ben Murdoch097c5b22016-05-18 11:27:45 +01001573 const AstRawString* default_string = ast_value_factory()->default_string();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001574 ZoneList<const AstRawString*> names(1, zone());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001575 Statement* result = nullptr;
1576 Expression* default_export = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001577 switch (peek()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001578 case Token::FUNCTION: {
1579 Consume(Token::FUNCTION);
1580 int pos = position();
1581 bool is_generator = Check(Token::MUL);
1582 if (peek() == Token::LPAREN) {
1583 // FunctionDeclaration[+Default] ::
1584 // 'function' '(' FormalParameters ')' '{' FunctionBody '}'
1585 //
1586 // GeneratorDeclaration[+Default] ::
1587 // 'function' '*' '(' FormalParameters ')' '{' FunctionBody '}'
1588 default_export = ParseFunctionLiteral(
1589 default_string, Scanner::Location::invalid(),
1590 kSkipFunctionNameCheck,
1591 is_generator ? FunctionKind::kGeneratorFunction
1592 : FunctionKind::kNormalFunction,
1593 pos, FunctionLiteral::kDeclaration, language_mode(), CHECK_OK);
1594 result = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
1595 } else {
Ben Murdochc5610432016-08-08 18:44:38 +01001596 result = ParseHoistableDeclaration(
1597 pos, is_generator ? ParseFunctionFlags::kIsGenerator
1598 : ParseFunctionFlags::kIsNormal,
1599 &names, CHECK_OK);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001600 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001601 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001602 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001603
1604 case Token::CLASS:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001605 Consume(Token::CLASS);
1606 if (peek() == Token::EXTENDS || peek() == Token::LBRACE) {
1607 // ClassDeclaration[+Default] ::
1608 // 'class' ('extends' LeftHandExpression)? '{' ClassBody '}'
Ben Murdochda12d292016-06-02 14:46:10 +01001609 default_export = ParseClassLiteral(nullptr, default_string,
1610 Scanner::Location::invalid(), false,
1611 position(), CHECK_OK);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001612 result = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
1613 } else {
1614 result = ParseClassDeclaration(&names, CHECK_OK);
1615 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001616 break;
1617
Ben Murdochc5610432016-08-08 18:44:38 +01001618 case Token::ASYNC:
1619 if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION &&
1620 !scanner()->HasAnyLineTerminatorAfterNext()) {
1621 Consume(Token::ASYNC);
1622 Consume(Token::FUNCTION);
1623 int pos = position();
1624 if (peek() == Token::LPAREN) {
1625 // AsyncFunctionDeclaration[+Default] ::
1626 // async [no LineTerminator here] function ( FormalParameters ) {
1627 // AsyncFunctionBody
1628 // }
1629 default_export = ParseFunctionLiteral(
1630 default_string, Scanner::Location::invalid(),
1631 kSkipFunctionNameCheck, FunctionKind::kAsyncFunction, pos,
1632 FunctionLiteral::kDeclaration, language_mode(), CHECK_OK);
1633 result = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
1634 } else {
1635 result = ParseHoistableDeclaration(pos, ParseFunctionFlags::kIsAsync,
1636 &names, CHECK_OK);
1637 }
1638 break;
1639 }
1640 /* falls through */
1641
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001642 default: {
1643 int pos = peek_position();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001644 ExpressionClassifier classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001645 Expression* expr = ParseAssignmentExpression(true, &classifier, CHECK_OK);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001646 RewriteNonPattern(&classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001647
1648 ExpectSemicolon(CHECK_OK);
1649 result = factory()->NewExpressionStatement(expr, pos);
1650 break;
1651 }
1652 }
1653
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001654 DCHECK_LE(names.length(), 1);
1655 if (names.length() == 1) {
1656 scope_->module()->AddLocalExport(default_string, names.first(), zone(), ok);
1657 if (!*ok) {
1658 ParserTraits::ReportMessageAt(
1659 default_loc, MessageTemplate::kDuplicateExport, default_string);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001660 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001661 }
1662 } else {
1663 // TODO(ES6): Assign result to a const binding with the name "*default*"
1664 // and add an export entry with "*default*" as the local name.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001665 USE(default_export);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001666 }
1667
1668 return result;
1669}
1670
1671
1672Statement* Parser::ParseExportDeclaration(bool* ok) {
1673 // ExportDeclaration:
1674 // 'export' '*' 'from' ModuleSpecifier ';'
1675 // 'export' ExportClause ('from' ModuleSpecifier)? ';'
1676 // 'export' VariableStatement
1677 // 'export' Declaration
1678 // 'export' 'default' ... (handled in ParseExportDefault)
1679
1680 int pos = peek_position();
1681 Expect(Token::EXPORT, CHECK_OK);
1682
1683 Statement* result = NULL;
1684 ZoneList<const AstRawString*> names(1, zone());
1685 switch (peek()) {
1686 case Token::DEFAULT:
1687 return ParseExportDefault(ok);
1688
1689 case Token::MUL: {
1690 Consume(Token::MUL);
1691 ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
1692 const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
1693 scope_->module()->AddModuleRequest(module_specifier, zone());
1694 // TODO(ES6): scope_->module()->AddStarExport(...)
1695 ExpectSemicolon(CHECK_OK);
1696 return factory()->NewEmptyStatement(pos);
1697 }
1698
1699 case Token::LBRACE: {
1700 // There are two cases here:
1701 //
1702 // 'export' ExportClause ';'
1703 // and
1704 // 'export' ExportClause FromClause ';'
1705 //
1706 // In the first case, the exported identifiers in ExportClause must
1707 // not be reserved words, while in the latter they may be. We
1708 // pass in a location that gets filled with the first reserved word
1709 // encountered, and then throw a SyntaxError if we are in the
1710 // non-FromClause case.
1711 Scanner::Location reserved_loc = Scanner::Location::invalid();
1712 ZoneList<const AstRawString*> export_names(1, zone());
1713 ZoneList<Scanner::Location> export_locations(1, zone());
1714 ZoneList<const AstRawString*> local_names(1, zone());
1715 ParseExportClause(&export_names, &export_locations, &local_names,
1716 &reserved_loc, CHECK_OK);
1717 const AstRawString* indirect_export_module_specifier = NULL;
1718 if (CheckContextualKeyword(CStrVector("from"))) {
1719 indirect_export_module_specifier = ParseModuleSpecifier(CHECK_OK);
1720 } else if (reserved_loc.IsValid()) {
1721 // No FromClause, so reserved words are invalid in ExportClause.
1722 *ok = false;
1723 ReportMessageAt(reserved_loc, MessageTemplate::kUnexpectedReserved);
1724 return NULL;
1725 }
1726 ExpectSemicolon(CHECK_OK);
1727 const int length = export_names.length();
1728 DCHECK_EQ(length, local_names.length());
1729 DCHECK_EQ(length, export_locations.length());
1730 if (indirect_export_module_specifier == NULL) {
1731 for (int i = 0; i < length; ++i) {
1732 scope_->module()->AddLocalExport(export_names[i], local_names[i],
1733 zone(), ok);
1734 if (!*ok) {
1735 ParserTraits::ReportMessageAt(export_locations[i],
1736 MessageTemplate::kDuplicateExport,
1737 export_names[i]);
1738 return NULL;
1739 }
1740 }
1741 } else {
1742 scope_->module()->AddModuleRequest(indirect_export_module_specifier,
1743 zone());
1744 for (int i = 0; i < length; ++i) {
1745 // TODO(ES6): scope_->module()->AddIndirectExport(...);(
1746 }
1747 }
1748 return factory()->NewEmptyStatement(pos);
1749 }
1750
1751 case Token::FUNCTION:
Ben Murdochc5610432016-08-08 18:44:38 +01001752 result = ParseHoistableDeclaration(&names, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001753 break;
1754
1755 case Token::CLASS:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001756 Consume(Token::CLASS);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001757 result = ParseClassDeclaration(&names, CHECK_OK);
1758 break;
1759
1760 case Token::VAR:
1761 case Token::LET:
1762 case Token::CONST:
1763 result = ParseVariableStatement(kStatementListItem, &names, CHECK_OK);
1764 break;
1765
Ben Murdochc5610432016-08-08 18:44:38 +01001766 case Token::ASYNC:
1767 if (allow_harmony_async_await()) {
1768 Consume(Token::ASYNC);
1769 result = ParseAsyncFunctionDeclaration(&names, CHECK_OK);
1770 break;
1771 }
1772 /* falls through */
1773
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001774 default:
1775 *ok = false;
1776 ReportUnexpectedToken(scanner()->current_token());
1777 return NULL;
1778 }
1779
1780 // Extract declared names into export declarations.
1781 ModuleDescriptor* descriptor = scope_->module();
1782 for (int i = 0; i < names.length(); ++i) {
1783 descriptor->AddLocalExport(names[i], names[i], zone(), ok);
1784 if (!*ok) {
1785 // TODO(adamk): Possibly report this error at the right place.
1786 ParserTraits::ReportMessage(MessageTemplate::kDuplicateExport, names[i]);
1787 return NULL;
1788 }
1789 }
1790
1791 DCHECK_NOT_NULL(result);
1792 return result;
1793}
1794
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001795Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels,
Ben Murdochda12d292016-06-02 14:46:10 +01001796 AllowLabelledFunctionStatement allow_function,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001797 bool* ok) {
1798 // Statement ::
1799 // EmptyStatement
1800 // ...
1801
1802 if (peek() == Token::SEMICOLON) {
1803 Next();
1804 return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
1805 }
Ben Murdochda12d292016-06-02 14:46:10 +01001806 return ParseSubStatement(labels, allow_function, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001807}
1808
Ben Murdochda12d292016-06-02 14:46:10 +01001809Statement* Parser::ParseSubStatement(
1810 ZoneList<const AstRawString*>* labels,
1811 AllowLabelledFunctionStatement allow_function, bool* ok) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001812 // Statement ::
1813 // Block
1814 // VariableStatement
1815 // EmptyStatement
1816 // ExpressionStatement
1817 // IfStatement
1818 // IterationStatement
1819 // ContinueStatement
1820 // BreakStatement
1821 // ReturnStatement
1822 // WithStatement
1823 // LabelledStatement
1824 // SwitchStatement
1825 // ThrowStatement
1826 // TryStatement
1827 // DebuggerStatement
1828
1829 // Note: Since labels can only be used by 'break' and 'continue'
1830 // statements, which themselves are only valid within blocks,
1831 // iterations or 'switch' statements (i.e., BreakableStatements),
1832 // labels can be simply ignored in all other cases; except for
1833 // trivial labeled break statements 'label: break label' which is
1834 // parsed into an empty statement.
1835 switch (peek()) {
1836 case Token::LBRACE:
1837 return ParseBlock(labels, ok);
1838
1839 case Token::SEMICOLON:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001840 Next();
1841 return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
1842
1843 case Token::IF:
1844 return ParseIfStatement(labels, ok);
1845
1846 case Token::DO:
1847 return ParseDoWhileStatement(labels, ok);
1848
1849 case Token::WHILE:
1850 return ParseWhileStatement(labels, ok);
1851
1852 case Token::FOR:
1853 return ParseForStatement(labels, ok);
1854
1855 case Token::CONTINUE:
1856 case Token::BREAK:
1857 case Token::RETURN:
1858 case Token::THROW:
1859 case Token::TRY: {
1860 // These statements must have their labels preserved in an enclosing
1861 // block
1862 if (labels == NULL) {
1863 return ParseStatementAsUnlabelled(labels, ok);
1864 } else {
1865 Block* result =
1866 factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition);
1867 Target target(&this->target_stack_, result);
1868 Statement* statement = ParseStatementAsUnlabelled(labels, CHECK_OK);
1869 if (result) result->statements()->Add(statement, zone());
1870 return result;
1871 }
1872 }
1873
1874 case Token::WITH:
1875 return ParseWithStatement(labels, ok);
1876
1877 case Token::SWITCH:
1878 return ParseSwitchStatement(labels, ok);
1879
Ben Murdochda12d292016-06-02 14:46:10 +01001880 case Token::FUNCTION:
1881 // FunctionDeclaration only allowed as a StatementListItem, not in
1882 // an arbitrary Statement position. Exceptions such as
1883 // ES#sec-functiondeclarations-in-ifstatement-statement-clauses
1884 // are handled by calling ParseScopedStatement rather than
1885 // ParseSubStatement directly.
1886 ReportMessageAt(scanner()->peek_location(),
1887 is_strict(language_mode())
1888 ? MessageTemplate::kStrictFunction
1889 : MessageTemplate::kSloppyFunction);
1890 *ok = false;
1891 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001892
1893 case Token::DEBUGGER:
1894 return ParseDebuggerStatement(ok);
1895
1896 case Token::VAR:
1897 return ParseVariableStatement(kStatement, NULL, ok);
1898
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001899 default:
Ben Murdochda12d292016-06-02 14:46:10 +01001900 return ParseExpressionOrLabelledStatement(labels, allow_function, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001901 }
1902}
1903
1904Statement* Parser::ParseStatementAsUnlabelled(
1905 ZoneList<const AstRawString*>* labels, bool* ok) {
1906 switch (peek()) {
1907 case Token::CONTINUE:
1908 return ParseContinueStatement(ok);
1909
1910 case Token::BREAK:
1911 return ParseBreakStatement(labels, ok);
1912
1913 case Token::RETURN:
1914 return ParseReturnStatement(ok);
1915
1916 case Token::THROW:
1917 return ParseThrowStatement(ok);
1918
1919 case Token::TRY:
1920 return ParseTryStatement(ok);
1921
1922 default:
1923 UNREACHABLE();
1924 return NULL;
1925 }
1926}
1927
1928
1929VariableProxy* Parser::NewUnresolved(const AstRawString* name,
1930 VariableMode mode) {
1931 // If we are inside a function, a declaration of a var/const variable is a
1932 // truly local variable, and the scope of the variable is always the function
1933 // scope.
1934 // Let/const variables in harmony mode are always added to the immediately
1935 // enclosing scope.
1936 Scope* scope =
1937 IsLexicalVariableMode(mode) ? scope_ : scope_->DeclarationScope();
1938 return scope->NewUnresolved(factory(), name, Variable::NORMAL,
1939 scanner()->location().beg_pos,
1940 scanner()->location().end_pos);
1941}
1942
1943
1944Variable* Parser::Declare(Declaration* declaration,
1945 DeclarationDescriptor::Kind declaration_kind,
1946 bool resolve, bool* ok, Scope* scope) {
1947 VariableProxy* proxy = declaration->proxy();
1948 DCHECK(proxy->raw_name() != NULL);
1949 const AstRawString* name = proxy->raw_name();
1950 VariableMode mode = declaration->mode();
Ben Murdochc5610432016-08-08 18:44:38 +01001951 DCHECK(IsDeclaredVariableMode(mode) && mode != CONST_LEGACY);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001952 bool is_function_declaration = declaration->IsFunctionDeclaration();
1953 if (scope == nullptr) scope = scope_;
1954 Scope* declaration_scope =
1955 IsLexicalVariableMode(mode) ? scope : scope->DeclarationScope();
1956 Variable* var = NULL;
1957
1958 // If a suitable scope exists, then we can statically declare this
1959 // variable and also set its mode. In any case, a Declaration node
1960 // will be added to the scope so that the declaration can be added
1961 // to the corresponding activation frame at runtime if necessary.
1962 // For instance, var declarations inside a sloppy eval scope need
1963 // to be added to the calling function context. Similarly, strict
1964 // mode eval scope and lexical eval bindings do not leak variable
1965 // declarations to the caller's scope so we declare all locals, too.
1966 if (declaration_scope->is_function_scope() ||
1967 declaration_scope->is_block_scope() ||
1968 declaration_scope->is_module_scope() ||
1969 declaration_scope->is_script_scope() ||
1970 (declaration_scope->is_eval_scope() &&
1971 (is_strict(declaration_scope->language_mode()) ||
1972 IsLexicalVariableMode(mode)))) {
1973 // Declare the variable in the declaration scope.
1974 var = declaration_scope->LookupLocal(name);
1975 if (var == NULL) {
1976 // Declare the name.
1977 Variable::Kind kind = Variable::NORMAL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001978 if (is_function_declaration) {
1979 kind = Variable::FUNCTION;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001980 }
1981 var = declaration_scope->DeclareLocal(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001982 name, mode, declaration->initialization(), kind, kNotAssigned);
Ben Murdochc5610432016-08-08 18:44:38 +01001983 } else if (IsLexicalVariableMode(mode) ||
1984 IsLexicalVariableMode(var->mode())) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001985 // Allow duplicate function decls for web compat, see bug 4693.
Ben Murdoch61f157c2016-09-16 13:49:30 +01001986 bool duplicate_allowed = false;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001987 if (is_sloppy(language_mode()) && is_function_declaration &&
1988 var->is_function()) {
1989 DCHECK(IsLexicalVariableMode(mode) &&
1990 IsLexicalVariableMode(var->mode()));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001991 // If the duplication is allowed, then the var will show up
1992 // in the SloppyBlockFunctionMap and the new FunctionKind
1993 // will be a permitted duplicate.
1994 FunctionKind function_kind =
1995 declaration->AsFunctionDeclaration()->fun()->kind();
1996 duplicate_allowed =
1997 scope->DeclarationScope()->sloppy_block_function_map()->Lookup(
1998 const_cast<AstRawString*>(name), name->hash()) != nullptr &&
1999 !IsAsyncFunction(function_kind) &&
2000 !(allow_harmony_restrictive_generators() &&
2001 IsGeneratorFunction(function_kind));
2002 }
2003 if (duplicate_allowed) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002004 ++use_counts_[v8::Isolate::kSloppyModeBlockScopedFunctionRedefinition];
2005 } else {
2006 // The name was declared in this scope before; check for conflicting
2007 // re-declarations. We have a conflict if either of the declarations
2008 // is not a var (in script scope, we also have to ignore legacy const
2009 // for compatibility). There is similar code in runtime.cc in the
2010 // Declare functions. The function CheckConflictingVarDeclarations
2011 // checks for var and let bindings from different scopes whereas this
2012 // is a check for conflicting declarations within the same scope. This
2013 // check also covers the special case
2014 //
2015 // function () { let x; { var x; } }
2016 //
2017 // because the var declaration is hoisted to the function scope where
2018 // 'x' is already bound.
2019 DCHECK(IsDeclaredVariableMode(var->mode()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002020 // In harmony we treat re-declarations as early errors. See
2021 // ES5 16 for a definition of early errors.
2022 if (declaration_kind == DeclarationDescriptor::NORMAL) {
2023 ParserTraits::ReportMessage(MessageTemplate::kVarRedeclaration, name);
2024 } else {
2025 ParserTraits::ReportMessage(MessageTemplate::kParamDupe);
2026 }
2027 *ok = false;
2028 return nullptr;
2029 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002030 } else if (mode == VAR) {
2031 var->set_maybe_assigned();
2032 }
2033 } else if (declaration_scope->is_eval_scope() &&
2034 is_sloppy(declaration_scope->language_mode()) &&
2035 !IsLexicalVariableMode(mode)) {
2036 // In a var binding in a sloppy direct eval, pollute the enclosing scope
2037 // with this new binding by doing the following:
2038 // The proxy is bound to a lookup variable to force a dynamic declaration
Ben Murdoch61f157c2016-09-16 13:49:30 +01002039 // using the DeclareEvalVar or DeclareEvalFunction runtime functions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002040 Variable::Kind kind = Variable::NORMAL;
2041 // TODO(sigurds) figure out if kNotAssigned is OK here
2042 var = new (zone()) Variable(declaration_scope, name, mode, kind,
2043 declaration->initialization(), kNotAssigned);
2044 var->AllocateTo(VariableLocation::LOOKUP, -1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002045 resolve = true;
2046 }
2047
2048
2049 // We add a declaration node for every declaration. The compiler
2050 // will only generate code if necessary. In particular, declarations
2051 // for inner local variables that do not represent functions won't
2052 // result in any generated code.
2053 //
2054 // Note that we always add an unresolved proxy even if it's not
2055 // used, simply because we don't know in this method (w/o extra
2056 // parameters) if the proxy is needed or not. The proxy will be
2057 // bound during variable resolution time unless it was pre-bound
2058 // below.
2059 //
2060 // WARNING: This will lead to multiple declaration nodes for the
2061 // same variable if it is declared several times. This is not a
2062 // semantic issue as long as we keep the source order, but it may be
2063 // a performance issue since it may lead to repeated
Ben Murdoch61f157c2016-09-16 13:49:30 +01002064 // DeclareEvalVar or DeclareEvalFunction calls.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002065 declaration_scope->AddDeclaration(declaration);
2066
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002067 // If requested and we have a local variable, bind the proxy to the variable
2068 // at parse-time. This is used for functions (and consts) declared inside
2069 // statements: the corresponding function (or const) variable must be in the
2070 // function scope and not a statement-local scope, e.g. as provided with a
2071 // 'with' statement:
2072 //
2073 // with (obj) {
2074 // function f() {}
2075 // }
2076 //
2077 // which is translated into:
2078 //
2079 // with (obj) {
2080 // // in this case this is not: 'var f; f = function () {};'
2081 // var f = function () {};
2082 // }
2083 //
2084 // Note that if 'f' is accessed from inside the 'with' statement, it
2085 // will be allocated in the context (because we must be able to look
2086 // it up dynamically) but it will also be accessed statically, i.e.,
2087 // with a context slot index and a context chain length for this
2088 // initialization code. Thus, inside the 'with' statement, we need
2089 // both access to the static and the dynamic context chain; the
2090 // runtime needs to provide both.
2091 if (resolve && var != NULL) {
2092 proxy->BindTo(var);
2093 }
2094 return var;
2095}
2096
2097
2098// Language extension which is only enabled for source files loaded
2099// through the API's extension mechanism. A native function
2100// declaration is resolved by looking up the function through a
2101// callback provided by the extension.
2102Statement* Parser::ParseNativeDeclaration(bool* ok) {
2103 int pos = peek_position();
2104 Expect(Token::FUNCTION, CHECK_OK);
2105 // Allow "eval" or "arguments" for backward compatibility.
2106 const AstRawString* name =
2107 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
2108 Expect(Token::LPAREN, CHECK_OK);
2109 bool done = (peek() == Token::RPAREN);
2110 while (!done) {
2111 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
2112 done = (peek() == Token::RPAREN);
2113 if (!done) {
2114 Expect(Token::COMMA, CHECK_OK);
2115 }
2116 }
2117 Expect(Token::RPAREN, CHECK_OK);
2118 Expect(Token::SEMICOLON, CHECK_OK);
2119
2120 // Make sure that the function containing the native declaration
2121 // isn't lazily compiled. The extension structures are only
2122 // accessible while parsing the first time not when reparsing
2123 // because of lazy compilation.
2124 // TODO(adamk): Should this be ClosureScope()?
2125 scope_->DeclarationScope()->ForceEagerCompilation();
2126
2127 // TODO(1240846): It's weird that native function declarations are
2128 // introduced dynamically when we meet their declarations, whereas
2129 // other functions are set up when entering the surrounding scope.
2130 VariableProxy* proxy = NewUnresolved(name, VAR);
2131 Declaration* declaration =
2132 factory()->NewVariableDeclaration(proxy, VAR, scope_, pos);
2133 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
2134 NativeFunctionLiteral* lit = factory()->NewNativeFunctionLiteral(
2135 name, extension_, RelocInfo::kNoPosition);
2136 return factory()->NewExpressionStatement(
2137 factory()->NewAssignment(Token::INIT, proxy, lit, RelocInfo::kNoPosition),
2138 pos);
2139}
2140
2141
Ben Murdochc5610432016-08-08 18:44:38 +01002142Statement* Parser::ParseHoistableDeclaration(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002143 ZoneList<const AstRawString*>* names, bool* ok) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002144 Expect(Token::FUNCTION, CHECK_OK);
2145 int pos = position();
Ben Murdochc5610432016-08-08 18:44:38 +01002146 ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal;
2147 if (Check(Token::MUL)) {
2148 flags |= ParseFunctionFlags::kIsGenerator;
2149 }
2150 return ParseHoistableDeclaration(pos, flags, names, ok);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002151}
2152
Ben Murdochc5610432016-08-08 18:44:38 +01002153Statement* Parser::ParseAsyncFunctionDeclaration(
2154 ZoneList<const AstRawString*>* names, bool* ok) {
2155 DCHECK_EQ(scanner()->current_token(), Token::ASYNC);
2156 int pos = position();
2157 if (scanner()->HasAnyLineTerminatorBeforeNext()) {
2158 *ok = false;
2159 ReportUnexpectedToken(scanner()->current_token());
2160 return nullptr;
2161 }
2162 Expect(Token::FUNCTION, CHECK_OK);
2163 ParseFunctionFlags flags = ParseFunctionFlags::kIsAsync;
2164 return ParseHoistableDeclaration(pos, flags, names, ok);
2165}
Ben Murdoch097c5b22016-05-18 11:27:45 +01002166
Ben Murdochc5610432016-08-08 18:44:38 +01002167Statement* Parser::ParseHoistableDeclaration(
2168 int pos, ParseFunctionFlags flags, ZoneList<const AstRawString*>* names,
Ben Murdoch097c5b22016-05-18 11:27:45 +01002169 bool* ok) {
2170 // FunctionDeclaration ::
2171 // 'function' Identifier '(' FormalParameters ')' '{' FunctionBody '}'
2172 // GeneratorDeclaration ::
2173 // 'function' '*' Identifier '(' FormalParameters ')' '{' FunctionBody '}'
2174 //
2175 // 'function' and '*' (if present) have been consumed by the caller.
Ben Murdochc5610432016-08-08 18:44:38 +01002176 const bool is_generator = flags & ParseFunctionFlags::kIsGenerator;
2177 const bool is_async = flags & ParseFunctionFlags::kIsAsync;
2178 DCHECK(!is_generator || !is_async);
2179
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002180 bool is_strict_reserved = false;
2181 const AstRawString* name = ParseIdentifierOrStrictReservedWord(
2182 &is_strict_reserved, CHECK_OK);
2183
Ben Murdochc5610432016-08-08 18:44:38 +01002184 if (V8_UNLIKELY(is_async_function() && this->IsAwait(name))) {
2185 ReportMessageAt(scanner()->location(),
2186 MessageTemplate::kAwaitBindingIdentifier);
2187 *ok = false;
2188 return nullptr;
2189 }
2190
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002191 FuncNameInferrer::State fni_state(fni_);
2192 if (fni_ != NULL) fni_->PushEnclosingName(name);
2193 FunctionLiteral* fun = ParseFunctionLiteral(
2194 name, scanner()->location(),
2195 is_strict_reserved ? kFunctionNameIsStrictReserved
2196 : kFunctionNameValidityUnknown,
2197 is_generator ? FunctionKind::kGeneratorFunction
Ben Murdochc5610432016-08-08 18:44:38 +01002198 : is_async ? FunctionKind::kAsyncFunction
2199 : FunctionKind::kNormalFunction,
Ben Murdoch097c5b22016-05-18 11:27:45 +01002200 pos, FunctionLiteral::kDeclaration, language_mode(), CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002201
2202 // Even if we're not at the top-level of the global or a function
2203 // scope, we treat it as such and introduce the function with its
2204 // initial value upon entering the corresponding scope.
2205 // In ES6, a function behaves as a lexical binding, except in
2206 // a script scope, or the initial scope of eval or another function.
2207 VariableMode mode =
Ben Murdochc5610432016-08-08 18:44:38 +01002208 (!scope_->is_declaration_scope() || scope_->is_module_scope()) ? LET
2209 : VAR;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002210 VariableProxy* proxy = NewUnresolved(name, mode);
2211 Declaration* declaration =
2212 factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);
2213 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
2214 if (names) names->Add(name, zone());
2215 EmptyStatement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002216 // Async functions don't undergo sloppy mode block scoped hoisting, and don't
2217 // allow duplicates in a block. Both are represented by the
2218 // sloppy_block_function_map. Don't add them to the map for async functions.
2219 // Generators are also supposed to be prohibited; currently doing this behind
2220 // a flag and UseCounting violations to assess web compatibility.
2221 if (is_sloppy(language_mode()) && !scope_->is_declaration_scope() &&
2222 !is_async && !(allow_harmony_restrictive_generators() && is_generator)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002223 SloppyBlockFunctionStatement* delegate =
2224 factory()->NewSloppyBlockFunctionStatement(empty, scope_);
2225 scope_->DeclarationScope()->sloppy_block_function_map()->Declare(name,
2226 delegate);
2227 return delegate;
2228 }
2229 return empty;
2230}
2231
2232
2233Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
2234 bool* ok) {
2235 // ClassDeclaration ::
2236 // 'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}'
2237 //
Ben Murdoch097c5b22016-05-18 11:27:45 +01002238 // 'class' is expected to be consumed by the caller.
2239 //
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002240 // A ClassDeclaration
2241 //
2242 // class C { ... }
2243 //
2244 // has the same semantics as:
2245 //
2246 // let C = class C { ... };
2247 //
2248 // so rewrite it as such.
2249
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002250 int pos = position();
2251 bool is_strict_reserved = false;
2252 const AstRawString* name =
2253 ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
Ben Murdochda12d292016-06-02 14:46:10 +01002254 ClassLiteral* value = ParseClassLiteral(nullptr, name, scanner()->location(),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002255 is_strict_reserved, pos, CHECK_OK);
2256
Ben Murdochda12d292016-06-02 14:46:10 +01002257 VariableProxy* proxy = NewUnresolved(name, LET);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002258 Declaration* declaration =
Ben Murdochda12d292016-06-02 14:46:10 +01002259 factory()->NewVariableDeclaration(proxy, LET, scope_, pos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002260 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002261 proxy->var()->set_initializer_position(position());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002262 Assignment* assignment =
2263 factory()->NewAssignment(Token::INIT, proxy, value, pos);
2264 Statement* assignment_statement =
2265 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
2266 if (names) names->Add(name, zone());
2267 return assignment_statement;
2268}
2269
2270
2271Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels,
2272 bool finalize_block_scope, bool* ok) {
2273 // The harmony mode uses block elements instead of statements.
2274 //
2275 // Block ::
2276 // '{' StatementList '}'
2277
2278 // Construct block expecting 16 statements.
2279 Block* body =
2280 factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition);
2281 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
2282
2283 // Parse the statements and collect escaping labels.
2284 Expect(Token::LBRACE, CHECK_OK);
2285 block_scope->set_start_position(scanner()->location().beg_pos);
2286 { BlockState block_state(&scope_, block_scope);
2287 Target target(&this->target_stack_, body);
2288
2289 while (peek() != Token::RBRACE) {
2290 Statement* stat = ParseStatementListItem(CHECK_OK);
2291 if (stat && !stat->IsEmpty()) {
2292 body->statements()->Add(stat, zone());
2293 }
2294 }
2295 }
2296 Expect(Token::RBRACE, CHECK_OK);
2297 block_scope->set_end_position(scanner()->location().end_pos);
2298 if (finalize_block_scope) {
2299 block_scope = block_scope->FinalizeBlockScope();
2300 }
2301 body->set_scope(block_scope);
2302 return body;
2303}
2304
2305
2306Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) {
2307 return ParseBlock(labels, true, ok);
2308}
2309
2310
2311Block* Parser::DeclarationParsingResult::BuildInitializationBlock(
2312 ZoneList<const AstRawString*>* names, bool* ok) {
2313 Block* result = descriptor.parser->factory()->NewBlock(
2314 NULL, 1, true, descriptor.declaration_pos);
2315 for (auto declaration : declarations) {
2316 PatternRewriter::DeclareAndInitializeVariables(
2317 result, &descriptor, &declaration, names, CHECK_OK);
2318 }
2319 return result;
2320}
2321
2322
2323Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
2324 ZoneList<const AstRawString*>* names,
2325 bool* ok) {
2326 // VariableStatement ::
2327 // VariableDeclarations ';'
2328
2329 // The scope of a var/const declared variable anywhere inside a function
2330 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
2331 // transform a source-level var/const declaration into a (Function)
2332 // Scope declaration, and rewrite the source-level initialization into an
2333 // assignment statement. We use a block to collect multiple assignments.
2334 //
2335 // We mark the block as initializer block because we don't want the
2336 // rewriter to add a '.result' assignment to such a block (to get compliant
2337 // behavior for code such as print(eval('var x = 7')), and for cosmetic
2338 // reasons when pretty-printing. Also, unless an assignment (initialization)
2339 // is inside an initializer block, it is ignored.
2340
2341 DeclarationParsingResult parsing_result;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002342 Block* result =
2343 ParseVariableDeclarations(var_context, &parsing_result, names, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002344 ExpectSemicolon(CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002345 return result;
2346}
2347
Ben Murdoch097c5b22016-05-18 11:27:45 +01002348Block* Parser::ParseVariableDeclarations(
2349 VariableDeclarationContext var_context,
2350 DeclarationParsingResult* parsing_result,
2351 ZoneList<const AstRawString*>* names, bool* ok) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002352 // VariableDeclarations ::
2353 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
2354 //
2355 // The ES6 Draft Rev3 specifies the following grammar for const declarations
2356 //
2357 // ConstDeclaration ::
2358 // const ConstBinding (',' ConstBinding)* ';'
2359 // ConstBinding ::
2360 // Identifier '=' AssignmentExpression
2361 //
2362 // TODO(ES6):
2363 // ConstBinding ::
2364 // BindingPattern '=' AssignmentExpression
2365
2366 parsing_result->descriptor.parser = this;
2367 parsing_result->descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
2368 parsing_result->descriptor.declaration_pos = peek_position();
2369 parsing_result->descriptor.initialization_pos = peek_position();
2370 parsing_result->descriptor.mode = VAR;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002371
2372 Block* init_block = nullptr;
2373 if (var_context != kForStatement) {
2374 init_block = factory()->NewBlock(
2375 NULL, 1, true, parsing_result->descriptor.declaration_pos);
2376 }
2377
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002378 if (peek() == Token::VAR) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002379 Consume(Token::VAR);
Ben Murdochc5610432016-08-08 18:44:38 +01002380 } else if (peek() == Token::CONST) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002381 Consume(Token::CONST);
Ben Murdochda12d292016-06-02 14:46:10 +01002382 DCHECK(var_context != kStatement);
2383 parsing_result->descriptor.mode = CONST;
Ben Murdochc5610432016-08-08 18:44:38 +01002384 } else if (peek() == Token::LET) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002385 Consume(Token::LET);
2386 DCHECK(var_context != kStatement);
2387 parsing_result->descriptor.mode = LET;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002388 } else {
2389 UNREACHABLE(); // by current callers
2390 }
2391
2392 parsing_result->descriptor.scope = scope_;
2393 parsing_result->descriptor.hoist_scope = nullptr;
2394
2395
2396 bool first_declaration = true;
2397 int bindings_start = peek_position();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002398 do {
2399 FuncNameInferrer::State fni_state(fni_);
2400
2401 // Parse name.
2402 if (!first_declaration) Consume(Token::COMMA);
2403
2404 Expression* pattern;
2405 int decl_pos = peek_position();
2406 {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002407 ExpressionClassifier pattern_classifier(this);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002408 pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
2409 ValidateBindingPattern(&pattern_classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002410 if (IsLexicalVariableMode(parsing_result->descriptor.mode)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002411 ValidateLetPattern(&pattern_classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002412 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002413 }
2414
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002415 Scanner::Location variable_loc = scanner()->location();
2416 const AstRawString* single_name =
2417 pattern->IsVariableProxy() ? pattern->AsVariableProxy()->raw_name()
2418 : nullptr;
2419 if (single_name != nullptr) {
2420 if (fni_ != NULL) fni_->PushVariableName(single_name);
2421 }
2422
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002423 Expression* value = NULL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002424 int initializer_position = RelocInfo::kNoPosition;
2425 if (Check(Token::ASSIGN)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002426 ExpressionClassifier classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002427 value = ParseAssignmentExpression(var_context != kForStatement,
Ben Murdoch097c5b22016-05-18 11:27:45 +01002428 &classifier, CHECK_OK);
2429 RewriteNonPattern(&classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002430 variable_loc.end_pos = scanner()->location().end_pos;
2431
2432 if (!parsing_result->first_initializer_loc.IsValid()) {
2433 parsing_result->first_initializer_loc = variable_loc;
2434 }
2435
2436 // Don't infer if it is "a = function(){...}();"-like expression.
2437 if (single_name) {
2438 if (fni_ != NULL && value->AsCall() == NULL &&
2439 value->AsCallNew() == NULL) {
2440 fni_->Infer();
2441 } else {
2442 fni_->RemoveLastFunction();
2443 }
2444 }
2445
Ben Murdoch61f157c2016-09-16 13:49:30 +01002446 ParserTraits::SetFunctionNameFromIdentifierRef(value, pattern);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002447
2448 // End position of the initializer is after the assignment expression.
2449 initializer_position = scanner()->location().end_pos;
2450 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002451 // Initializers may be either required or implied unless this is a
2452 // for-in/of iteration variable.
2453 if (var_context != kForStatement || !PeekInOrOf()) {
2454 // ES6 'const' and binding patterns require initializers.
2455 if (parsing_result->descriptor.mode == CONST ||
2456 !pattern->IsVariableProxy()) {
2457 ParserTraits::ReportMessageAt(
2458 Scanner::Location(decl_pos, scanner()->location().end_pos),
2459 MessageTemplate::kDeclarationMissingInitializer,
2460 !pattern->IsVariableProxy() ? "destructuring" : "const");
2461 *ok = false;
2462 return nullptr;
2463 }
2464
Ben Murdochc5610432016-08-08 18:44:38 +01002465 // 'let x' initializes 'x' to undefined.
2466 if (parsing_result->descriptor.mode == LET) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002467 value = GetLiteralUndefined(position());
2468 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002469 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002470
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002471 // End position of the initializer is after the variable.
2472 initializer_position = position();
2473 }
2474
Ben Murdoch097c5b22016-05-18 11:27:45 +01002475 DeclarationParsingResult::Declaration decl(pattern, initializer_position,
2476 value);
2477 if (var_context == kForStatement) {
2478 // Save the declaration for further handling in ParseForStatement.
2479 parsing_result->declarations.Add(decl);
2480 } else {
2481 // Immediately declare the variable otherwise. This avoids O(N^2)
2482 // behavior (where N is the number of variables in a single
2483 // declaration) in the PatternRewriter having to do with removing
2484 // and adding VariableProxies to the Scope (see bug 4699).
2485 DCHECK_NOT_NULL(init_block);
2486 PatternRewriter::DeclareAndInitializeVariables(
2487 init_block, &parsing_result->descriptor, &decl, names, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002488 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002489 first_declaration = false;
2490 } while (peek() == Token::COMMA);
2491
2492 parsing_result->bindings_loc =
2493 Scanner::Location(bindings_start, scanner()->location().end_pos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002494
2495 DCHECK(*ok);
2496 return init_block;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002497}
2498
2499
2500static bool ContainsLabel(ZoneList<const AstRawString*>* labels,
2501 const AstRawString* label) {
2502 DCHECK(label != NULL);
2503 if (labels != NULL) {
2504 for (int i = labels->length(); i-- > 0; ) {
2505 if (labels->at(i) == label) {
2506 return true;
2507 }
2508 }
2509 }
2510 return false;
2511}
2512
Ben Murdochc5610432016-08-08 18:44:38 +01002513Statement* Parser::ParseFunctionDeclaration(bool* ok) {
2514 Consume(Token::FUNCTION);
2515 int pos = position();
2516 ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal;
2517 if (Check(Token::MUL)) {
2518 flags |= ParseFunctionFlags::kIsGenerator;
2519 if (allow_harmony_restrictive_declarations()) {
2520 ParserTraits::ReportMessageAt(scanner()->location(),
2521 MessageTemplate::kGeneratorInLegacyContext);
2522 *ok = false;
2523 return nullptr;
2524 }
2525 }
2526
2527 return ParseHoistableDeclaration(pos, flags, nullptr, CHECK_OK);
2528}
2529
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002530Statement* Parser::ParseExpressionOrLabelledStatement(
Ben Murdochda12d292016-06-02 14:46:10 +01002531 ZoneList<const AstRawString*>* labels,
2532 AllowLabelledFunctionStatement allow_function, bool* ok) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002533 // ExpressionStatement | LabelledStatement ::
2534 // Expression ';'
2535 // Identifier ':' Statement
2536 //
2537 // ExpressionStatement[Yield] :
2538 // [lookahead ∉ {{, function, class, let [}] Expression[In, ?Yield] ;
2539
2540 int pos = peek_position();
2541
2542 switch (peek()) {
2543 case Token::FUNCTION:
2544 case Token::LBRACE:
2545 UNREACHABLE(); // Always handled by the callers.
2546 case Token::CLASS:
2547 ReportUnexpectedToken(Next());
2548 *ok = false;
2549 return nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002550 default:
2551 break;
2552 }
2553
2554 bool starts_with_idenfifier = peek_any_identifier();
2555 Expression* expr = ParseExpression(true, CHECK_OK);
2556 if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL &&
2557 expr->AsVariableProxy() != NULL &&
2558 !expr->AsVariableProxy()->is_this()) {
2559 // Expression is a single identifier, and not, e.g., a parenthesized
2560 // identifier.
2561 VariableProxy* var = expr->AsVariableProxy();
2562 const AstRawString* label = var->raw_name();
2563 // TODO(1240780): We don't check for redeclaration of labels
2564 // during preparsing since keeping track of the set of active
2565 // labels requires nontrivial changes to the way scopes are
2566 // structured. However, these are probably changes we want to
2567 // make later anyway so we should go back and fix this then.
2568 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
2569 ParserTraits::ReportMessage(MessageTemplate::kLabelRedeclaration, label);
2570 *ok = false;
2571 return NULL;
2572 }
2573 if (labels == NULL) {
2574 labels = new(zone()) ZoneList<const AstRawString*>(4, zone());
2575 }
2576 labels->Add(label, zone());
2577 // Remove the "ghost" variable that turned out to be a label
2578 // from the top scope. This way, we don't try to resolve it
2579 // during the scope processing.
2580 scope_->RemoveUnresolved(var);
2581 Expect(Token::COLON, CHECK_OK);
Ben Murdochda12d292016-06-02 14:46:10 +01002582 // ES#sec-labelled-function-declarations Labelled Function Declarations
2583 if (peek() == Token::FUNCTION && is_sloppy(language_mode())) {
2584 if (allow_function == kAllowLabelledFunctionStatement) {
Ben Murdochc5610432016-08-08 18:44:38 +01002585 return ParseFunctionDeclaration(ok);
Ben Murdochda12d292016-06-02 14:46:10 +01002586 } else {
2587 return ParseScopedStatement(labels, true, ok);
2588 }
2589 }
2590 return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002591 }
2592
2593 // If we have an extension, we allow a native function declaration.
2594 // A native function declaration starts with "native function" with
2595 // no line-terminator between the two words.
2596 if (extension_ != NULL && peek() == Token::FUNCTION &&
2597 !scanner()->HasAnyLineTerminatorBeforeNext() && expr != NULL &&
2598 expr->AsVariableProxy() != NULL &&
2599 expr->AsVariableProxy()->raw_name() ==
2600 ast_value_factory()->native_string() &&
2601 !scanner()->literal_contains_escapes()) {
2602 return ParseNativeDeclaration(ok);
2603 }
2604
2605 // Parsed expression statement, followed by semicolon.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002606 ExpectSemicolon(CHECK_OK);
2607 return factory()->NewExpressionStatement(expr, pos);
2608}
2609
2610
2611IfStatement* Parser::ParseIfStatement(ZoneList<const AstRawString*>* labels,
2612 bool* ok) {
2613 // IfStatement ::
2614 // 'if' '(' Expression ')' Statement ('else' Statement)?
2615
2616 int pos = peek_position();
2617 Expect(Token::IF, CHECK_OK);
2618 Expect(Token::LPAREN, CHECK_OK);
2619 Expression* condition = ParseExpression(true, CHECK_OK);
2620 Expect(Token::RPAREN, CHECK_OK);
Ben Murdochda12d292016-06-02 14:46:10 +01002621 Statement* then_statement = ParseScopedStatement(labels, false, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002622 Statement* else_statement = NULL;
2623 if (peek() == Token::ELSE) {
2624 Next();
Ben Murdochda12d292016-06-02 14:46:10 +01002625 else_statement = ParseScopedStatement(labels, false, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002626 } else {
2627 else_statement = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
2628 }
2629 return factory()->NewIfStatement(
2630 condition, then_statement, else_statement, pos);
2631}
2632
2633
2634Statement* Parser::ParseContinueStatement(bool* ok) {
2635 // ContinueStatement ::
2636 // 'continue' Identifier? ';'
2637
2638 int pos = peek_position();
2639 Expect(Token::CONTINUE, CHECK_OK);
2640 const AstRawString* label = NULL;
2641 Token::Value tok = peek();
2642 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
2643 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
2644 // ECMA allows "eval" or "arguments" as labels even in strict mode.
2645 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
2646 }
2647 IterationStatement* target = LookupContinueTarget(label, CHECK_OK);
2648 if (target == NULL) {
2649 // Illegal continue statement.
2650 MessageTemplate::Template message = MessageTemplate::kIllegalContinue;
2651 if (label != NULL) {
2652 message = MessageTemplate::kUnknownLabel;
2653 }
2654 ParserTraits::ReportMessage(message, label);
2655 *ok = false;
2656 return NULL;
2657 }
2658 ExpectSemicolon(CHECK_OK);
2659 return factory()->NewContinueStatement(target, pos);
2660}
2661
2662
2663Statement* Parser::ParseBreakStatement(ZoneList<const AstRawString*>* labels,
2664 bool* ok) {
2665 // BreakStatement ::
2666 // 'break' Identifier? ';'
2667
2668 int pos = peek_position();
2669 Expect(Token::BREAK, CHECK_OK);
2670 const AstRawString* label = NULL;
2671 Token::Value tok = peek();
2672 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
2673 tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
2674 // ECMA allows "eval" or "arguments" as labels even in strict mode.
2675 label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
2676 }
2677 // Parse labeled break statements that target themselves into
2678 // empty statements, e.g. 'l1: l2: l3: break l2;'
2679 if (label != NULL && ContainsLabel(labels, label)) {
2680 ExpectSemicolon(CHECK_OK);
2681 return factory()->NewEmptyStatement(pos);
2682 }
2683 BreakableStatement* target = NULL;
2684 target = LookupBreakTarget(label, CHECK_OK);
2685 if (target == NULL) {
2686 // Illegal break statement.
2687 MessageTemplate::Template message = MessageTemplate::kIllegalBreak;
2688 if (label != NULL) {
2689 message = MessageTemplate::kUnknownLabel;
2690 }
2691 ParserTraits::ReportMessage(message, label);
2692 *ok = false;
2693 return NULL;
2694 }
2695 ExpectSemicolon(CHECK_OK);
2696 return factory()->NewBreakStatement(target, pos);
2697}
2698
2699
2700Statement* Parser::ParseReturnStatement(bool* ok) {
2701 // ReturnStatement ::
2702 // 'return' Expression? ';'
2703
2704 // Consume the return token. It is necessary to do that before
2705 // reporting any errors on it, because of the way errors are
2706 // reported (underlining).
2707 Expect(Token::RETURN, CHECK_OK);
2708 Scanner::Location loc = scanner()->location();
2709 function_state_->set_return_location(loc);
2710
2711 Token::Value tok = peek();
2712 Statement* result;
2713 Expression* return_value;
2714 if (scanner()->HasAnyLineTerminatorBeforeNext() ||
2715 tok == Token::SEMICOLON ||
2716 tok == Token::RBRACE ||
2717 tok == Token::EOS) {
2718 if (IsSubclassConstructor(function_state_->kind())) {
2719 return_value = ThisExpression(scope_, factory(), loc.beg_pos);
2720 } else {
2721 return_value = GetLiteralUndefined(position());
2722 }
2723 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002724 int pos = peek_position();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002725
2726 if (IsSubclassConstructor(function_state_->kind())) {
Ben Murdochc5610432016-08-08 18:44:38 +01002727 // Because of the return code rewriting that happens in case of a subclass
2728 // constructor we don't want to accept tail calls, therefore we don't set
2729 // ReturnExprScope to kInsideValidReturnStatement here.
2730 return_value = ParseExpression(true, CHECK_OK);
2731
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002732 // For subclass constructors we need to return this in case of undefined
Ben Murdoch097c5b22016-05-18 11:27:45 +01002733 // return a Smi (transformed into an exception in the ConstructStub)
2734 // for a non object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002735 //
2736 // return expr;
2737 //
2738 // Is rewritten as:
2739 //
2740 // return (temp = expr) === undefined ? this :
Ben Murdoch097c5b22016-05-18 11:27:45 +01002741 // %_IsJSReceiver(temp) ? temp : 1;
2742
2743 // temp = expr
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002744 Variable* temp = scope_->NewTemporary(
2745 ast_value_factory()->empty_string());
2746 Assignment* assign = factory()->NewAssignment(
2747 Token::ASSIGN, factory()->NewVariableProxy(temp), return_value, pos);
2748
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002749 // %_IsJSReceiver(temp)
2750 ZoneList<Expression*>* is_spec_object_args =
2751 new (zone()) ZoneList<Expression*>(1, zone());
2752 is_spec_object_args->Add(factory()->NewVariableProxy(temp), zone());
2753 Expression* is_spec_object_call = factory()->NewCallRuntime(
2754 Runtime::kInlineIsJSReceiver, is_spec_object_args, pos);
2755
Ben Murdoch61f157c2016-09-16 13:49:30 +01002756 // %_IsJSReceiver(temp) ? temp : 1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002757 Expression* is_object_conditional = factory()->NewConditional(
2758 is_spec_object_call, factory()->NewVariableProxy(temp),
Ben Murdoch097c5b22016-05-18 11:27:45 +01002759 factory()->NewSmiLiteral(1, pos), pos);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002760
2761 // temp === undefined
2762 Expression* is_undefined = factory()->NewCompareOperation(
2763 Token::EQ_STRICT, assign,
2764 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), pos);
2765
2766 // is_undefined ? this : is_object_conditional
2767 return_value = factory()->NewConditional(
2768 is_undefined, ThisExpression(scope_, factory(), pos),
2769 is_object_conditional, pos);
Ben Murdochc5610432016-08-08 18:44:38 +01002770 } else {
2771 ReturnExprScope maybe_allow_tail_calls(
2772 function_state_, ReturnExprContext::kInsideValidReturnStatement);
2773 return_value = ParseExpression(true, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002774
Ben Murdoch61f157c2016-09-16 13:49:30 +01002775 if (allow_tailcalls() && !is_sloppy(language_mode()) && !is_resumable()) {
Ben Murdochc5610432016-08-08 18:44:38 +01002776 // ES6 14.6.1 Static Semantics: IsInTailPosition
2777 function_state_->AddImplicitTailCallExpression(return_value);
2778 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002779 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002780 }
2781 ExpectSemicolon(CHECK_OK);
2782
2783 if (is_generator()) {
Ben Murdochda12d292016-06-02 14:46:10 +01002784 return_value = BuildIteratorResult(return_value, true);
Ben Murdochc5610432016-08-08 18:44:38 +01002785 } else if (is_async_function()) {
2786 return_value = BuildPromiseResolve(return_value, return_value->position());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002787 }
2788
Ben Murdochda12d292016-06-02 14:46:10 +01002789 result = factory()->NewReturnStatement(return_value, loc.beg_pos);
2790
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002791 Scope* decl_scope = scope_->DeclarationScope();
2792 if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) {
2793 ReportMessageAt(loc, MessageTemplate::kIllegalReturn);
2794 *ok = false;
2795 return NULL;
2796 }
2797 return result;
2798}
2799
2800
2801Statement* Parser::ParseWithStatement(ZoneList<const AstRawString*>* labels,
2802 bool* ok) {
2803 // WithStatement ::
2804 // 'with' '(' Expression ')' Statement
2805
2806 Expect(Token::WITH, CHECK_OK);
2807 int pos = position();
2808
2809 if (is_strict(language_mode())) {
2810 ReportMessage(MessageTemplate::kStrictWith);
2811 *ok = false;
2812 return NULL;
2813 }
2814
2815 Expect(Token::LPAREN, CHECK_OK);
2816 Expression* expr = ParseExpression(true, CHECK_OK);
2817 Expect(Token::RPAREN, CHECK_OK);
2818
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002819 Scope* with_scope = NewScope(scope_, WITH_SCOPE);
Ben Murdochda12d292016-06-02 14:46:10 +01002820 Statement* body;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002821 { BlockState block_state(&scope_, with_scope);
2822 with_scope->set_start_position(scanner()->peek_location().beg_pos);
Ben Murdochda12d292016-06-02 14:46:10 +01002823 body = ParseScopedStatement(labels, true, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002824 with_scope->set_end_position(scanner()->location().end_pos);
2825 }
2826 return factory()->NewWithStatement(with_scope, expr, body, pos);
2827}
2828
2829
2830CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
2831 // CaseClause ::
2832 // 'case' Expression ':' StatementList
2833 // 'default' ':' StatementList
2834
2835 Expression* label = NULL; // NULL expression indicates default case
2836 if (peek() == Token::CASE) {
2837 Expect(Token::CASE, CHECK_OK);
2838 label = ParseExpression(true, CHECK_OK);
2839 } else {
2840 Expect(Token::DEFAULT, CHECK_OK);
2841 if (*default_seen_ptr) {
2842 ReportMessage(MessageTemplate::kMultipleDefaultsInSwitch);
2843 *ok = false;
2844 return NULL;
2845 }
2846 *default_seen_ptr = true;
2847 }
2848 Expect(Token::COLON, CHECK_OK);
2849 int pos = position();
2850 ZoneList<Statement*>* statements =
2851 new(zone()) ZoneList<Statement*>(5, zone());
2852 Statement* stat = NULL;
2853 while (peek() != Token::CASE &&
2854 peek() != Token::DEFAULT &&
2855 peek() != Token::RBRACE) {
2856 stat = ParseStatementListItem(CHECK_OK);
2857 statements->Add(stat, zone());
2858 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002859 return factory()->NewCaseClause(label, statements, pos);
2860}
2861
2862
2863Statement* Parser::ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
2864 bool* ok) {
2865 // SwitchStatement ::
2866 // 'switch' '(' Expression ')' '{' CaseClause* '}'
2867 // In order to get the CaseClauses to execute in their own lexical scope,
2868 // but without requiring downstream code to have special scope handling
2869 // code for switch statements, desugar into blocks as follows:
2870 // { // To group the statements--harmless to evaluate Expression in scope
2871 // .tag_variable = Expression;
2872 // { // To give CaseClauses a scope
2873 // switch (.tag_variable) { CaseClause* }
2874 // }
2875 // }
2876
2877 Block* switch_block =
2878 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
2879 int switch_pos = peek_position();
2880
2881 Expect(Token::SWITCH, CHECK_OK);
2882 Expect(Token::LPAREN, CHECK_OK);
2883 Expression* tag = ParseExpression(true, CHECK_OK);
2884 Expect(Token::RPAREN, CHECK_OK);
2885
2886 Variable* tag_variable =
2887 scope_->NewTemporary(ast_value_factory()->dot_switch_tag_string());
2888 Assignment* tag_assign = factory()->NewAssignment(
2889 Token::ASSIGN, factory()->NewVariableProxy(tag_variable), tag,
2890 tag->position());
2891 Statement* tag_statement =
2892 factory()->NewExpressionStatement(tag_assign, RelocInfo::kNoPosition);
2893 switch_block->statements()->Add(tag_statement, zone());
2894
2895 // make statement: undefined;
2896 // This is needed so the tag isn't returned as the value, in case the switch
2897 // statements don't have a value.
2898 switch_block->statements()->Add(
2899 factory()->NewExpressionStatement(
2900 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
2901 RelocInfo::kNoPosition),
2902 zone());
2903
2904 Block* cases_block =
2905 factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
2906 Scope* cases_scope = NewScope(scope_, BLOCK_SCOPE);
2907 cases_scope->SetNonlinear();
2908
2909 SwitchStatement* switch_statement =
2910 factory()->NewSwitchStatement(labels, switch_pos);
2911
2912 cases_scope->set_start_position(scanner()->location().beg_pos);
2913 {
2914 BlockState cases_block_state(&scope_, cases_scope);
2915 Target target(&this->target_stack_, switch_statement);
2916
2917 Expression* tag_read = factory()->NewVariableProxy(tag_variable);
2918
2919 bool default_seen = false;
2920 ZoneList<CaseClause*>* cases =
2921 new (zone()) ZoneList<CaseClause*>(4, zone());
2922 Expect(Token::LBRACE, CHECK_OK);
2923 while (peek() != Token::RBRACE) {
2924 CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
2925 cases->Add(clause, zone());
2926 }
2927 switch_statement->Initialize(tag_read, cases);
2928 cases_block->statements()->Add(switch_statement, zone());
2929 }
2930 Expect(Token::RBRACE, CHECK_OK);
2931
2932 cases_scope->set_end_position(scanner()->location().end_pos);
2933 cases_scope = cases_scope->FinalizeBlockScope();
2934 cases_block->set_scope(cases_scope);
2935
2936 switch_block->statements()->Add(cases_block, zone());
2937
2938 return switch_block;
2939}
2940
2941
2942Statement* Parser::ParseThrowStatement(bool* ok) {
2943 // ThrowStatement ::
2944 // 'throw' Expression ';'
2945
2946 Expect(Token::THROW, CHECK_OK);
2947 int pos = position();
2948 if (scanner()->HasAnyLineTerminatorBeforeNext()) {
2949 ReportMessage(MessageTemplate::kNewlineAfterThrow);
2950 *ok = false;
2951 return NULL;
2952 }
2953 Expression* exception = ParseExpression(true, CHECK_OK);
2954 ExpectSemicolon(CHECK_OK);
2955
2956 return factory()->NewExpressionStatement(
2957 factory()->NewThrow(exception, pos), pos);
2958}
2959
2960
2961TryStatement* Parser::ParseTryStatement(bool* ok) {
2962 // TryStatement ::
2963 // 'try' Block Catch
2964 // 'try' Block Finally
2965 // 'try' Block Catch Finally
2966 //
2967 // Catch ::
2968 // 'catch' '(' Identifier ')' Block
2969 //
2970 // Finally ::
2971 // 'finally' Block
2972
2973 Expect(Token::TRY, CHECK_OK);
2974 int pos = position();
2975
Ben Murdoch097c5b22016-05-18 11:27:45 +01002976 Block* try_block;
2977 {
Ben Murdochc5610432016-08-08 18:44:38 +01002978 ReturnExprScope no_tail_calls(function_state_,
2979 ReturnExprContext::kInsideTryBlock);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002980 try_block = ParseBlock(NULL, CHECK_OK);
2981 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002982
2983 Token::Value tok = peek();
2984 if (tok != Token::CATCH && tok != Token::FINALLY) {
2985 ReportMessage(MessageTemplate::kNoCatchOrFinally);
2986 *ok = false;
2987 return NULL;
2988 }
2989
2990 Scope* catch_scope = NULL;
2991 Variable* catch_variable = NULL;
2992 Block* catch_block = NULL;
Ben Murdochc5610432016-08-08 18:44:38 +01002993 TailCallExpressionList tail_call_expressions_in_catch_block(zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002994 if (tok == Token::CATCH) {
2995 Consume(Token::CATCH);
2996
2997 Expect(Token::LPAREN, CHECK_OK);
2998 catch_scope = NewScope(scope_, CATCH_SCOPE);
2999 catch_scope->set_start_position(scanner()->location().beg_pos);
3000
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003001 {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003002 CollectExpressionsInTailPositionToListScope
Ben Murdochc5610432016-08-08 18:44:38 +01003003 collect_tail_call_expressions_scope(
3004 function_state_, &tail_call_expressions_in_catch_block);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003005 BlockState block_state(&scope_, catch_scope);
3006
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003007 catch_block =
3008 factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003009
Ben Murdoch61f157c2016-09-16 13:49:30 +01003010 // Create a block scope to hold any lexical declarations created
3011 // as part of destructuring the catch parameter.
3012 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003013 block_scope->set_start_position(scanner()->location().beg_pos);
3014 {
3015 BlockState block_state(&scope_, block_scope);
3016 Target target(&this->target_stack_, catch_block);
3017
Ben Murdoch61f157c2016-09-16 13:49:30 +01003018 ExpressionClassifier pattern_classifier(this);
3019 Expression* pattern =
3020 ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
3021 ValidateBindingPattern(&pattern_classifier, CHECK_OK);
3022
3023 const AstRawString* name = ast_value_factory()->dot_catch_string();
3024 bool is_simple = pattern->IsVariableProxy();
3025 if (is_simple) {
3026 auto proxy = pattern->AsVariableProxy();
3027 scope_->RemoveUnresolved(proxy);
3028 name = proxy->raw_name();
3029 }
3030 catch_variable = catch_scope->DeclareLocal(
3031 name, VAR, kCreatedInitialized, Variable::NORMAL);
3032
3033 Expect(Token::RPAREN, CHECK_OK);
3034
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003035 if (!is_simple) {
3036 DeclarationDescriptor descriptor;
3037 descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
3038 descriptor.parser = this;
3039 descriptor.scope = scope_;
3040 descriptor.hoist_scope = nullptr;
3041 descriptor.mode = LET;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003042 descriptor.declaration_pos = pattern->position();
3043 descriptor.initialization_pos = pattern->position();
3044
Ben Murdochc5610432016-08-08 18:44:38 +01003045 // Initializer position for variables declared by the pattern.
3046 const int initializer_position = position();
3047
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003048 DeclarationParsingResult::Declaration decl(
Ben Murdochc5610432016-08-08 18:44:38 +01003049 pattern, initializer_position,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003050 factory()->NewVariableProxy(catch_variable));
3051
Ben Murdochda12d292016-06-02 14:46:10 +01003052 Block* init_block =
3053 factory()->NewBlock(nullptr, 8, true, RelocInfo::kNoPosition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003054 PatternRewriter::DeclareAndInitializeVariables(
Ben Murdochda12d292016-06-02 14:46:10 +01003055 init_block, &descriptor, &decl, nullptr, CHECK_OK);
3056 catch_block->statements()->Add(init_block, zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003057 }
3058
Ben Murdoch61f157c2016-09-16 13:49:30 +01003059 // TODO(adamk): This should call ParseBlock in order to properly
3060 // add an additional block scope for the catch body.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003061 Expect(Token::LBRACE, CHECK_OK);
3062 while (peek() != Token::RBRACE) {
3063 Statement* stat = ParseStatementListItem(CHECK_OK);
3064 if (stat && !stat->IsEmpty()) {
3065 catch_block->statements()->Add(stat, zone());
3066 }
3067 }
3068 Consume(Token::RBRACE);
3069 }
3070 block_scope->set_end_position(scanner()->location().end_pos);
3071 block_scope = block_scope->FinalizeBlockScope();
3072 catch_block->set_scope(block_scope);
3073 }
3074
3075 catch_scope->set_end_position(scanner()->location().end_pos);
3076 tok = peek();
3077 }
3078
3079 Block* finally_block = NULL;
3080 DCHECK(tok == Token::FINALLY || catch_block != NULL);
3081 if (tok == Token::FINALLY) {
3082 Consume(Token::FINALLY);
3083 finally_block = ParseBlock(NULL, CHECK_OK);
3084 }
3085
3086 // Simplify the AST nodes by converting:
3087 // 'try B0 catch B1 finally B2'
3088 // to:
3089 // 'try { try B0 catch B1 } finally B2'
3090
3091 if (catch_block != NULL && finally_block != NULL) {
3092 // If we have both, create an inner try/catch.
3093 DCHECK(catch_scope != NULL && catch_variable != NULL);
3094 TryCatchStatement* statement =
3095 factory()->NewTryCatchStatement(try_block, catch_scope, catch_variable,
3096 catch_block, RelocInfo::kNoPosition);
3097 try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
3098 try_block->statements()->Add(statement, zone());
3099 catch_block = NULL; // Clear to indicate it's been handled.
3100 }
3101
3102 TryStatement* result = NULL;
3103 if (catch_block != NULL) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003104 // For a try-catch construct append return expressions from the catch block
3105 // to the list of return expressions.
Ben Murdochc5610432016-08-08 18:44:38 +01003106 function_state_->tail_call_expressions().Append(
3107 tail_call_expressions_in_catch_block);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003108
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003109 DCHECK(finally_block == NULL);
3110 DCHECK(catch_scope != NULL && catch_variable != NULL);
3111 result = factory()->NewTryCatchStatement(try_block, catch_scope,
3112 catch_variable, catch_block, pos);
3113 } else {
Ben Murdochc5610432016-08-08 18:44:38 +01003114 if (FLAG_harmony_explicit_tailcalls &&
3115 tail_call_expressions_in_catch_block.has_explicit_tail_calls()) {
3116 // TODO(ishell): update chapter number.
3117 // ES8 XX.YY.ZZ
3118 ReportMessageAt(tail_call_expressions_in_catch_block.location(),
3119 MessageTemplate::kUnexpectedTailCallInCatchBlock);
3120 *ok = false;
3121 return NULL;
3122 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003123 DCHECK(finally_block != NULL);
3124 result = factory()->NewTryFinallyStatement(try_block, finally_block, pos);
3125 }
3126
3127 return result;
3128}
3129
3130
3131DoWhileStatement* Parser::ParseDoWhileStatement(
3132 ZoneList<const AstRawString*>* labels, bool* ok) {
3133 // DoStatement ::
3134 // 'do' Statement 'while' '(' Expression ')' ';'
3135
3136 DoWhileStatement* loop =
3137 factory()->NewDoWhileStatement(labels, peek_position());
3138 Target target(&this->target_stack_, loop);
3139
3140 Expect(Token::DO, CHECK_OK);
Ben Murdochda12d292016-06-02 14:46:10 +01003141 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003142 Expect(Token::WHILE, CHECK_OK);
3143 Expect(Token::LPAREN, CHECK_OK);
3144
3145 Expression* cond = ParseExpression(true, CHECK_OK);
3146 Expect(Token::RPAREN, CHECK_OK);
3147
3148 // Allow do-statements to be terminated with and without
3149 // semi-colons. This allows code such as 'do;while(0)return' to
3150 // parse, which would not be the case if we had used the
3151 // ExpectSemicolon() functionality here.
3152 if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
3153
3154 if (loop != NULL) loop->Initialize(cond, body);
3155 return loop;
3156}
3157
3158
3159WhileStatement* Parser::ParseWhileStatement(
3160 ZoneList<const AstRawString*>* labels, bool* ok) {
3161 // WhileStatement ::
3162 // 'while' '(' Expression ')' Statement
3163
3164 WhileStatement* loop = factory()->NewWhileStatement(labels, peek_position());
3165 Target target(&this->target_stack_, loop);
3166
3167 Expect(Token::WHILE, CHECK_OK);
3168 Expect(Token::LPAREN, CHECK_OK);
3169 Expression* cond = ParseExpression(true, CHECK_OK);
3170 Expect(Token::RPAREN, CHECK_OK);
Ben Murdochda12d292016-06-02 14:46:10 +01003171 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003172
3173 if (loop != NULL) loop->Initialize(cond, body);
3174 return loop;
3175}
3176
3177
3178// !%_IsJSReceiver(result = iterator.next()) &&
3179// %ThrowIteratorResultNotAnObject(result)
3180Expression* Parser::BuildIteratorNextResult(Expression* iterator,
3181 Variable* result, int pos) {
3182 Expression* next_literal = factory()->NewStringLiteral(
3183 ast_value_factory()->next_string(), RelocInfo::kNoPosition);
3184 Expression* next_property =
3185 factory()->NewProperty(iterator, next_literal, RelocInfo::kNoPosition);
3186 ZoneList<Expression*>* next_arguments =
3187 new (zone()) ZoneList<Expression*>(0, zone());
3188 Expression* next_call =
3189 factory()->NewCall(next_property, next_arguments, pos);
3190 Expression* result_proxy = factory()->NewVariableProxy(result);
3191 Expression* left =
3192 factory()->NewAssignment(Token::ASSIGN, result_proxy, next_call, pos);
3193
3194 // %_IsJSReceiver(...)
3195 ZoneList<Expression*>* is_spec_object_args =
3196 new (zone()) ZoneList<Expression*>(1, zone());
3197 is_spec_object_args->Add(left, zone());
3198 Expression* is_spec_object_call = factory()->NewCallRuntime(
3199 Runtime::kInlineIsJSReceiver, is_spec_object_args, pos);
3200
3201 // %ThrowIteratorResultNotAnObject(result)
3202 Expression* result_proxy_again = factory()->NewVariableProxy(result);
3203 ZoneList<Expression*>* throw_arguments =
3204 new (zone()) ZoneList<Expression*>(1, zone());
3205 throw_arguments->Add(result_proxy_again, zone());
3206 Expression* throw_call = factory()->NewCallRuntime(
3207 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos);
3208
3209 return factory()->NewBinaryOperation(
3210 Token::AND,
3211 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos),
3212 throw_call, pos);
3213}
3214
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003215void Parser::InitializeForEachStatement(ForEachStatement* stmt,
3216 Expression* each, Expression* subject,
Ben Murdochc5610432016-08-08 18:44:38 +01003217 Statement* body, int each_keyword_pos) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003218 ForOfStatement* for_of = stmt->AsForOfStatement();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003219 if (for_of != NULL) {
Ben Murdochc5610432016-08-08 18:44:38 +01003220 InitializeForOfStatement(for_of, each, subject, body, each_keyword_pos);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003221 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01003222 if (each->IsArrayLiteral() || each->IsObjectLiteral()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003223 Variable* temp =
3224 scope_->NewTemporary(ast_value_factory()->empty_string());
3225 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
3226 Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment(
3227 this, factory()->NewAssignment(Token::ASSIGN, each, temp_proxy,
3228 RelocInfo::kNoPosition),
3229 scope_);
3230 auto block =
3231 factory()->NewBlock(nullptr, 2, false, RelocInfo::kNoPosition);
3232 block->statements()->Add(factory()->NewExpressionStatement(
3233 assign_each, RelocInfo::kNoPosition),
3234 zone());
3235 block->statements()->Add(body, zone());
3236 body = block;
3237 each = factory()->NewVariableProxy(temp);
3238 }
Ben Murdochc5610432016-08-08 18:44:38 +01003239 stmt->AsForInStatement()->Initialize(each, subject, body);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003240 }
3241}
3242
Ben Murdochda12d292016-06-02 14:46:10 +01003243void Parser::InitializeForOfStatement(ForOfStatement* for_of, Expression* each,
3244 Expression* iterable, Statement* body,
Ben Murdochc5610432016-08-08 18:44:38 +01003245 int next_result_pos) {
Ben Murdochda12d292016-06-02 14:46:10 +01003246 Variable* iterator =
3247 scope_->NewTemporary(ast_value_factory()->dot_iterator_string());
3248 Variable* result =
3249 scope_->NewTemporary(ast_value_factory()->dot_result_string());
3250
3251 Expression* assign_iterator;
3252 Expression* next_result;
3253 Expression* result_done;
3254 Expression* assign_each;
3255
Ben Murdochc5610432016-08-08 18:44:38 +01003256 int get_iterator_pos = iterable->position();
Ben Murdochda12d292016-06-02 14:46:10 +01003257
3258 // iterator = iterable[Symbol.iterator]()
3259 assign_iterator = factory()->NewAssignment(
3260 Token::ASSIGN, factory()->NewVariableProxy(iterator),
3261 GetIterator(iterable, factory(), get_iterator_pos), iterable->position());
3262
3263 // !%_IsJSReceiver(result = iterator.next()) &&
3264 // %ThrowIteratorResultNotAnObject(result)
3265 {
3266 // result = iterator.next()
3267 Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
3268 next_result =
3269 BuildIteratorNextResult(iterator_proxy, result, next_result_pos);
3270 }
3271
3272 // result.done
3273 {
3274 Expression* done_literal = factory()->NewStringLiteral(
3275 ast_value_factory()->done_string(), RelocInfo::kNoPosition);
3276 Expression* result_proxy = factory()->NewVariableProxy(result);
3277 result_done = factory()->NewProperty(result_proxy, done_literal,
3278 RelocInfo::kNoPosition);
3279 }
3280
3281 // each = result.value
3282 {
3283 Expression* value_literal = factory()->NewStringLiteral(
3284 ast_value_factory()->value_string(), RelocInfo::kNoPosition);
3285 Expression* result_proxy = factory()->NewVariableProxy(result);
3286 Expression* result_value = factory()->NewProperty(
3287 result_proxy, value_literal, RelocInfo::kNoPosition);
3288 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value,
3289 RelocInfo::kNoPosition);
3290 if (each->IsArrayLiteral() || each->IsObjectLiteral()) {
3291 assign_each = PatternRewriter::RewriteDestructuringAssignment(
3292 this, assign_each->AsAssignment(), scope_);
3293 }
3294 }
3295
Ben Murdochc5610432016-08-08 18:44:38 +01003296 for_of->Initialize(body, iterator, assign_iterator, next_result, result_done,
3297 assign_each);
Ben Murdochda12d292016-06-02 14:46:10 +01003298}
3299
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003300Statement* Parser::DesugarLexicalBindingsInForStatement(
Ben Murdoch097c5b22016-05-18 11:27:45 +01003301 Scope* inner_scope, VariableMode mode, ZoneList<const AstRawString*>* names,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003302 ForStatement* loop, Statement* init, Expression* cond, Statement* next,
3303 Statement* body, bool* ok) {
3304 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are
3305 // copied into a new environment. Moreover, the "next" statement must be
3306 // evaluated not in the environment of the just completed iteration but in
3307 // that of the upcoming one. We achieve this with the following desugaring.
3308 // Extra care is needed to preserve the completion value of the original loop.
3309 //
3310 // We are given a for statement of the form
3311 //
3312 // labels: for (let/const x = i; cond; next) body
3313 //
3314 // and rewrite it as follows. Here we write {{ ... }} for init-blocks, ie.,
3315 // blocks whose ignore_completion_value_ flag is set.
3316 //
3317 // {
3318 // let/const x = i;
3319 // temp_x = x;
3320 // first = 1;
3321 // undefined;
3322 // outer: for (;;) {
3323 // let/const x = temp_x;
3324 // {{ if (first == 1) {
3325 // first = 0;
3326 // } else {
3327 // next;
3328 // }
3329 // flag = 1;
3330 // if (!cond) break;
3331 // }}
3332 // labels: for (; flag == 1; flag = 0, temp_x = x) {
3333 // body
3334 // }
3335 // {{ if (flag == 1) // Body used break.
3336 // break;
3337 // }}
3338 // }
3339 // }
3340
3341 DCHECK(names->length() > 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003342 ZoneList<Variable*> temps(names->length(), zone());
3343
3344 Block* outer_block = factory()->NewBlock(NULL, names->length() + 4, false,
3345 RelocInfo::kNoPosition);
3346
3347 // Add statement: let/const x = i.
3348 outer_block->statements()->Add(init, zone());
3349
3350 const AstRawString* temp_name = ast_value_factory()->dot_for_string();
3351
3352 // For each lexical variable x:
3353 // make statement: temp_x = x.
3354 for (int i = 0; i < names->length(); i++) {
3355 VariableProxy* proxy = NewUnresolved(names->at(i), LET);
3356 Variable* temp = scope_->NewTemporary(temp_name);
3357 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
3358 Assignment* assignment = factory()->NewAssignment(
3359 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition);
3360 Statement* assignment_statement = factory()->NewExpressionStatement(
3361 assignment, RelocInfo::kNoPosition);
3362 outer_block->statements()->Add(assignment_statement, zone());
3363 temps.Add(temp, zone());
3364 }
3365
3366 Variable* first = NULL;
3367 // Make statement: first = 1.
3368 if (next) {
3369 first = scope_->NewTemporary(temp_name);
3370 VariableProxy* first_proxy = factory()->NewVariableProxy(first);
3371 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
3372 Assignment* assignment = factory()->NewAssignment(
3373 Token::ASSIGN, first_proxy, const1, RelocInfo::kNoPosition);
3374 Statement* assignment_statement =
3375 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
3376 outer_block->statements()->Add(assignment_statement, zone());
3377 }
3378
3379 // make statement: undefined;
3380 outer_block->statements()->Add(
3381 factory()->NewExpressionStatement(
3382 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
3383 RelocInfo::kNoPosition),
3384 zone());
3385
3386 // Make statement: outer: for (;;)
3387 // Note that we don't actually create the label, or set this loop up as an
3388 // explicit break target, instead handing it directly to those nodes that
3389 // need to know about it. This should be safe because we don't run any code
3390 // in this function that looks up break targets.
3391 ForStatement* outer_loop =
3392 factory()->NewForStatement(NULL, RelocInfo::kNoPosition);
3393 outer_block->statements()->Add(outer_loop, zone());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003394 outer_block->set_scope(scope_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003395
3396 Block* inner_block =
3397 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003398 {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003399 BlockState block_state(&scope_, inner_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003400
Ben Murdoch097c5b22016-05-18 11:27:45 +01003401 Block* ignore_completion_block = factory()->NewBlock(
3402 NULL, names->length() + 3, true, RelocInfo::kNoPosition);
3403 ZoneList<Variable*> inner_vars(names->length(), zone());
3404 // For each let variable x:
3405 // make statement: let/const x = temp_x.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003406 for (int i = 0; i < names->length(); i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003407 VariableProxy* proxy = NewUnresolved(names->at(i), mode);
3408 Declaration* declaration = factory()->NewVariableDeclaration(
3409 proxy, mode, scope_, RelocInfo::kNoPosition);
3410 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
3411 inner_vars.Add(declaration->proxy()->var(), zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003412 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003413 Assignment* assignment = factory()->NewAssignment(
Ben Murdoch097c5b22016-05-18 11:27:45 +01003414 Token::INIT, proxy, temp_proxy, RelocInfo::kNoPosition);
3415 Statement* assignment_statement =
3416 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
3417 DCHECK(init->position() != RelocInfo::kNoPosition);
3418 proxy->var()->set_initializer_position(init->position());
3419 ignore_completion_block->statements()->Add(assignment_statement, zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003420 }
3421
Ben Murdoch097c5b22016-05-18 11:27:45 +01003422 // Make statement: if (first == 1) { first = 0; } else { next; }
3423 if (next) {
3424 DCHECK(first);
3425 Expression* compare = NULL;
3426 // Make compare expression: first == 1.
3427 {
3428 Expression* const1 =
3429 factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
3430 VariableProxy* first_proxy = factory()->NewVariableProxy(first);
3431 compare = factory()->NewCompareOperation(Token::EQ, first_proxy, const1,
3432 RelocInfo::kNoPosition);
3433 }
3434 Statement* clear_first = NULL;
3435 // Make statement: first = 0.
3436 {
3437 VariableProxy* first_proxy = factory()->NewVariableProxy(first);
3438 Expression* const0 =
3439 factory()->NewSmiLiteral(0, RelocInfo::kNoPosition);
3440 Assignment* assignment = factory()->NewAssignment(
3441 Token::ASSIGN, first_proxy, const0, RelocInfo::kNoPosition);
3442 clear_first = factory()->NewExpressionStatement(assignment,
3443 RelocInfo::kNoPosition);
3444 }
3445 Statement* clear_first_or_next = factory()->NewIfStatement(
3446 compare, clear_first, next, RelocInfo::kNoPosition);
3447 ignore_completion_block->statements()->Add(clear_first_or_next, zone());
3448 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003449
Ben Murdoch097c5b22016-05-18 11:27:45 +01003450 Variable* flag = scope_->NewTemporary(temp_name);
3451 // Make statement: flag = 1.
3452 {
3453 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
3454 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
3455 Assignment* assignment = factory()->NewAssignment(
3456 Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition);
3457 Statement* assignment_statement =
3458 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
3459 ignore_completion_block->statements()->Add(assignment_statement, zone());
3460 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003461
Ben Murdoch097c5b22016-05-18 11:27:45 +01003462 // Make statement: if (!cond) break.
3463 if (cond) {
3464 Statement* stop =
3465 factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition);
3466 Statement* noop = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
3467 ignore_completion_block->statements()->Add(
3468 factory()->NewIfStatement(cond, noop, stop, cond->position()),
3469 zone());
3470 }
3471
3472 inner_block->statements()->Add(ignore_completion_block, zone());
3473 // Make cond expression for main loop: flag == 1.
3474 Expression* flag_cond = NULL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003475 {
3476 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
3477 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003478 flag_cond = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
3479 RelocInfo::kNoPosition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003480 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003481
Ben Murdoch097c5b22016-05-18 11:27:45 +01003482 // Create chain of expressions "flag = 0, temp_x = x, ..."
3483 Statement* compound_next_statement = NULL;
3484 {
3485 Expression* compound_next = NULL;
3486 // Make expression: flag = 0.
3487 {
3488 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
3489 Expression* const0 =
3490 factory()->NewSmiLiteral(0, RelocInfo::kNoPosition);
3491 compound_next = factory()->NewAssignment(
3492 Token::ASSIGN, flag_proxy, const0, RelocInfo::kNoPosition);
3493 }
3494
3495 // Make the comma-separated list of temp_x = x assignments.
3496 int inner_var_proxy_pos = scanner()->location().beg_pos;
3497 for (int i = 0; i < names->length(); i++) {
3498 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
3499 VariableProxy* proxy =
3500 factory()->NewVariableProxy(inner_vars.at(i), inner_var_proxy_pos);
3501 Assignment* assignment = factory()->NewAssignment(
3502 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition);
3503 compound_next = factory()->NewBinaryOperation(
3504 Token::COMMA, compound_next, assignment, RelocInfo::kNoPosition);
3505 }
3506
3507 compound_next_statement = factory()->NewExpressionStatement(
3508 compound_next, RelocInfo::kNoPosition);
3509 }
3510
3511 // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x)
3512 // Note that we re-use the original loop node, which retains its labels
3513 // and ensures that any break or continue statements in body point to
3514 // the right place.
3515 loop->Initialize(NULL, flag_cond, compound_next_statement, body);
3516 inner_block->statements()->Add(loop, zone());
3517
3518 // Make statement: {{if (flag == 1) break;}}
3519 {
3520 Expression* compare = NULL;
3521 // Make compare expresion: flag == 1.
3522 {
3523 Expression* const1 =
3524 factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
3525 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
3526 compare = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
3527 RelocInfo::kNoPosition);
3528 }
3529 Statement* stop =
3530 factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition);
3531 Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
3532 Statement* if_flag_break = factory()->NewIfStatement(
3533 compare, stop, empty, RelocInfo::kNoPosition);
3534 Block* ignore_completion_block =
3535 factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
3536 ignore_completion_block->statements()->Add(if_flag_break, zone());
3537 inner_block->statements()->Add(ignore_completion_block, zone());
3538 }
3539
3540 inner_scope->set_end_position(scanner()->location().end_pos);
3541 inner_block->set_scope(inner_scope);
3542 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003543
3544 outer_loop->Initialize(NULL, NULL, NULL, inner_block);
3545 return outer_block;
3546}
3547
Ben Murdochda12d292016-06-02 14:46:10 +01003548Statement* Parser::ParseScopedStatement(ZoneList<const AstRawString*>* labels,
3549 bool legacy, bool* ok) {
3550 if (is_strict(language_mode()) || peek() != Token::FUNCTION ||
3551 (legacy && allow_harmony_restrictive_declarations())) {
3552 return ParseSubStatement(labels, kDisallowLabelledFunctionStatement, ok);
3553 } else {
3554 if (legacy) {
3555 ++use_counts_[v8::Isolate::kLegacyFunctionDeclaration];
3556 }
3557 // Make a block around the statement for a lexical binding
3558 // is introduced by a FunctionDeclaration.
3559 Scope* body_scope = NewScope(scope_, BLOCK_SCOPE);
Ben Murdochc5610432016-08-08 18:44:38 +01003560 body_scope->set_start_position(scanner()->location().beg_pos);
Ben Murdochda12d292016-06-02 14:46:10 +01003561 BlockState block_state(&scope_, body_scope);
3562 Block* block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
Ben Murdochc5610432016-08-08 18:44:38 +01003563 Statement* body = ParseFunctionDeclaration(CHECK_OK);
Ben Murdochda12d292016-06-02 14:46:10 +01003564 block->statements()->Add(body, zone());
3565 body_scope->set_end_position(scanner()->location().end_pos);
3566 body_scope = body_scope->FinalizeBlockScope();
3567 block->set_scope(body_scope);
3568 return block;
3569 }
3570}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003571
3572Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
3573 bool* ok) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003574 int stmt_pos = peek_position();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003575 Statement* init = NULL;
3576 ZoneList<const AstRawString*> lexical_bindings(1, zone());
3577
3578 // Create an in-between scope for let-bound iteration variables.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003579 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003580
3581 BlockState block_state(&scope_, for_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003582 Expect(Token::FOR, CHECK_OK);
3583 Expect(Token::LPAREN, CHECK_OK);
3584 for_scope->set_start_position(scanner()->location().beg_pos);
Ben Murdochc5610432016-08-08 18:44:38 +01003585 for_scope->set_is_hidden();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003586 DeclarationParsingResult parsing_result;
3587 if (peek() != Token::SEMICOLON) {
Ben Murdochc5610432016-08-08 18:44:38 +01003588 if (peek() == Token::VAR || peek() == Token::CONST ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003589 (peek() == Token::LET && IsNextLetKeyword())) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003590 ParseVariableDeclarations(kForStatement, &parsing_result, nullptr,
3591 CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003592
Ben Murdochda12d292016-06-02 14:46:10 +01003593 ForEachStatement::VisitMode mode = ForEachStatement::ENUMERATE;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003594 int each_beg_pos = scanner()->location().beg_pos;
3595 int each_end_pos = scanner()->location().end_pos;
3596
Ben Murdoch097c5b22016-05-18 11:27:45 +01003597 if (CheckInOrOf(&mode, ok)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003598 if (!*ok) return nullptr;
Ben Murdoch097c5b22016-05-18 11:27:45 +01003599 if (parsing_result.declarations.length() != 1) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003600 ParserTraits::ReportMessageAt(
3601 parsing_result.bindings_loc,
Ben Murdoch097c5b22016-05-18 11:27:45 +01003602 MessageTemplate::kForInOfLoopMultiBindings,
3603 ForEachStatement::VisitModeString(mode));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003604 *ok = false;
3605 return nullptr;
3606 }
3607 DeclarationParsingResult::Declaration& decl =
3608 parsing_result.declarations[0];
3609 if (parsing_result.first_initializer_loc.IsValid() &&
3610 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE ||
3611 IsLexicalVariableMode(parsing_result.descriptor.mode) ||
Ben Murdochc5610432016-08-08 18:44:38 +01003612 !decl.pattern->IsVariableProxy() || allow_harmony_for_in())) {
3613 // Only increment the use count if we would have let this through
3614 // without the flag.
3615 if (allow_harmony_for_in()) {
3616 ++use_counts_[v8::Isolate::kForInInitializer];
3617 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01003618 ParserTraits::ReportMessageAt(
3619 parsing_result.first_initializer_loc,
3620 MessageTemplate::kForInOfLoopInitializer,
3621 ForEachStatement::VisitModeString(mode));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003622 *ok = false;
3623 return nullptr;
3624 }
3625
3626 Block* init_block = nullptr;
3627
3628 // special case for legacy for (var/const x =.... in)
3629 if (!IsLexicalVariableMode(parsing_result.descriptor.mode) &&
3630 decl.pattern->IsVariableProxy() && decl.initializer != nullptr) {
Ben Murdochc5610432016-08-08 18:44:38 +01003631 DCHECK(!allow_harmony_for_in());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003632 ++use_counts_[v8::Isolate::kForInInitializer];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003633 const AstRawString* name =
3634 decl.pattern->AsVariableProxy()->raw_name();
3635 VariableProxy* single_var = scope_->NewUnresolved(
3636 factory(), name, Variable::NORMAL, each_beg_pos, each_end_pos);
3637 init_block = factory()->NewBlock(
3638 nullptr, 2, true, parsing_result.descriptor.declaration_pos);
3639 init_block->statements()->Add(
3640 factory()->NewExpressionStatement(
3641 factory()->NewAssignment(Token::ASSIGN, single_var,
3642 decl.initializer,
3643 RelocInfo::kNoPosition),
3644 RelocInfo::kNoPosition),
3645 zone());
3646 }
3647
3648 // Rewrite a for-in/of statement of the form
3649 //
3650 // for (let/const/var x in/of e) b
3651 //
3652 // into
3653 //
3654 // {
3655 // <let x' be a temporary variable>
3656 // for (x' in/of e) {
3657 // let/const/var x;
3658 // x = x';
3659 // b;
3660 // }
3661 // let x; // for TDZ
3662 // }
3663
Ben Murdoch097c5b22016-05-18 11:27:45 +01003664 Variable* temp =
3665 scope_->NewTemporary(ast_value_factory()->dot_for_string());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003666 ForEachStatement* loop =
3667 factory()->NewForEachStatement(mode, labels, stmt_pos);
3668 Target target(&this->target_stack_, loop);
3669
Ben Murdochc5610432016-08-08 18:44:38 +01003670 int each_keyword_position = scanner()->location().beg_pos;
3671
Ben Murdoch097c5b22016-05-18 11:27:45 +01003672 Expression* enumerable;
3673 if (mode == ForEachStatement::ITERATE) {
3674 ExpressionClassifier classifier(this);
3675 enumerable = ParseAssignmentExpression(true, &classifier, CHECK_OK);
3676 RewriteNonPattern(&classifier, CHECK_OK);
3677 } else {
3678 enumerable = ParseExpression(true, CHECK_OK);
3679 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003680
3681 Expect(Token::RPAREN, CHECK_OK);
3682
3683 Scope* body_scope = NewScope(scope_, BLOCK_SCOPE);
3684 body_scope->set_start_position(scanner()->location().beg_pos);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003685
3686 Block* body_block =
3687 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
3688
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003689 {
Ben Murdochc5610432016-08-08 18:44:38 +01003690 ReturnExprScope no_tail_calls(function_state_,
3691 ReturnExprContext::kInsideForInOfBody);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003692 BlockState block_state(&scope_, body_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003693
Ben Murdochda12d292016-06-02 14:46:10 +01003694 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003695
3696 auto each_initialization_block =
3697 factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
3698 {
3699 auto descriptor = parsing_result.descriptor;
3700 descriptor.declaration_pos = RelocInfo::kNoPosition;
3701 descriptor.initialization_pos = RelocInfo::kNoPosition;
3702 decl.initializer = factory()->NewVariableProxy(temp);
3703
3704 PatternRewriter::DeclareAndInitializeVariables(
3705 each_initialization_block, &descriptor, &decl,
3706 IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings
3707 : nullptr,
3708 CHECK_OK);
3709 }
3710
3711 body_block->statements()->Add(each_initialization_block, zone());
3712 body_block->statements()->Add(body, zone());
3713 VariableProxy* temp_proxy =
3714 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos);
Ben Murdochc5610432016-08-08 18:44:38 +01003715 InitializeForEachStatement(loop, temp_proxy, enumerable, body_block,
3716 each_keyword_position);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003717 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003718 body_scope->set_end_position(scanner()->location().end_pos);
3719 body_scope = body_scope->FinalizeBlockScope();
Ben Murdoch097c5b22016-05-18 11:27:45 +01003720 body_block->set_scope(body_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003721
3722 // Create a TDZ for any lexically-bound names.
3723 if (IsLexicalVariableMode(parsing_result.descriptor.mode)) {
3724 DCHECK_NULL(init_block);
3725
3726 init_block =
3727 factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition);
3728
3729 for (int i = 0; i < lexical_bindings.length(); ++i) {
3730 // TODO(adamk): This needs to be some sort of special
3731 // INTERNAL variable that's invisible to the debugger
3732 // but visible to everything else.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003733 VariableProxy* tdz_proxy =
3734 NewUnresolved(lexical_bindings[i], LET);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003735 Declaration* tdz_decl = factory()->NewVariableDeclaration(
3736 tdz_proxy, LET, scope_, RelocInfo::kNoPosition);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003737 Variable* tdz_var = Declare(
3738 tdz_decl, DeclarationDescriptor::NORMAL, true, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003739 tdz_var->set_initializer_position(position());
3740 }
3741 }
3742
Ben Murdoch097c5b22016-05-18 11:27:45 +01003743 Statement* final_loop = loop->IsForOfStatement()
3744 ? FinalizeForOfStatement(
3745 loop->AsForOfStatement(), RelocInfo::kNoPosition)
3746 : loop;
3747
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003748 for_scope->set_end_position(scanner()->location().end_pos);
3749 for_scope = for_scope->FinalizeBlockScope();
3750 // Parsed for-in loop w/ variable declarations.
3751 if (init_block != nullptr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003752 init_block->statements()->Add(final_loop, zone());
3753 init_block->set_scope(for_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003754 return init_block;
3755 } else {
3756 DCHECK_NULL(for_scope);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003757 return final_loop;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003758 }
3759 } else {
3760 init = parsing_result.BuildInitializationBlock(
3761 IsLexicalVariableMode(parsing_result.descriptor.mode)
3762 ? &lexical_bindings
3763 : nullptr,
3764 CHECK_OK);
3765 }
3766 } else {
3767 int lhs_beg_pos = peek_position();
Ben Murdoch097c5b22016-05-18 11:27:45 +01003768 ExpressionClassifier classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003769 Expression* expression = ParseExpression(false, &classifier, CHECK_OK);
3770 int lhs_end_pos = scanner()->location().end_pos;
Ben Murdochda12d292016-06-02 14:46:10 +01003771 ForEachStatement::VisitMode mode = ForEachStatement::ENUMERATE;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003772
3773 bool is_for_each = CheckInOrOf(&mode, ok);
3774 if (!*ok) return nullptr;
Ben Murdochda12d292016-06-02 14:46:10 +01003775 bool is_destructuring = is_for_each && (expression->IsArrayLiteral() ||
3776 expression->IsObjectLiteral());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003777
3778 if (is_destructuring) {
3779 ValidateAssignmentPattern(&classifier, CHECK_OK);
3780 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003781 RewriteNonPattern(&classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003782 }
3783
3784 if (is_for_each) {
3785 if (!is_destructuring) {
3786 expression = this->CheckAndRewriteReferenceExpression(
3787 expression, lhs_beg_pos, lhs_end_pos,
3788 MessageTemplate::kInvalidLhsInFor, kSyntaxError, CHECK_OK);
3789 }
3790
3791 ForEachStatement* loop =
3792 factory()->NewForEachStatement(mode, labels, stmt_pos);
3793 Target target(&this->target_stack_, loop);
3794
Ben Murdochc5610432016-08-08 18:44:38 +01003795 int each_keyword_position = scanner()->location().beg_pos;
3796
Ben Murdoch097c5b22016-05-18 11:27:45 +01003797 Expression* enumerable;
3798 if (mode == ForEachStatement::ITERATE) {
3799 ExpressionClassifier classifier(this);
3800 enumerable = ParseAssignmentExpression(true, &classifier, CHECK_OK);
3801 RewriteNonPattern(&classifier, CHECK_OK);
3802 } else {
3803 enumerable = ParseExpression(true, CHECK_OK);
3804 }
3805
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003806 Expect(Token::RPAREN, CHECK_OK);
3807
Ben Murdochda12d292016-06-02 14:46:10 +01003808 // For legacy compat reasons, give for loops similar treatment to
3809 // if statements in allowing a function declaration for a body
3810 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
Ben Murdochc5610432016-08-08 18:44:38 +01003811 InitializeForEachStatement(loop, expression, enumerable, body,
3812 each_keyword_position);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003813
3814 Statement* final_loop = loop->IsForOfStatement()
3815 ? FinalizeForOfStatement(
3816 loop->AsForOfStatement(), RelocInfo::kNoPosition)
3817 : loop;
3818
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003819 for_scope->set_end_position(scanner()->location().end_pos);
3820 for_scope = for_scope->FinalizeBlockScope();
3821 DCHECK(for_scope == nullptr);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003822 return final_loop;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003823
3824 } else {
3825 init = factory()->NewExpressionStatement(expression, lhs_beg_pos);
3826 }
3827 }
3828 }
3829
3830 // Standard 'for' loop
3831 ForStatement* loop = factory()->NewForStatement(labels, stmt_pos);
3832 Target target(&this->target_stack_, loop);
3833
3834 // Parsed initializer at this point.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003835 Expect(Token::SEMICOLON, CHECK_OK);
3836
Ben Murdoch097c5b22016-05-18 11:27:45 +01003837 Expression* cond = NULL;
3838 Statement* next = NULL;
3839 Statement* body = NULL;
3840
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003841 // If there are let bindings, then condition and the next statement of the
3842 // for loop must be parsed in a new scope.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003843 Scope* inner_scope = scope_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003844 if (lexical_bindings.length() > 0) {
3845 inner_scope = NewScope(for_scope, BLOCK_SCOPE);
3846 inner_scope->set_start_position(scanner()->location().beg_pos);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003847 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01003848 {
3849 BlockState block_state(&scope_, inner_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003850
Ben Murdoch097c5b22016-05-18 11:27:45 +01003851 if (peek() != Token::SEMICOLON) {
3852 cond = ParseExpression(true, CHECK_OK);
3853 }
3854 Expect(Token::SEMICOLON, CHECK_OK);
3855
3856 if (peek() != Token::RPAREN) {
3857 Expression* exp = ParseExpression(true, CHECK_OK);
3858 next = factory()->NewExpressionStatement(exp, exp->position());
3859 }
3860 Expect(Token::RPAREN, CHECK_OK);
3861
Ben Murdochda12d292016-06-02 14:46:10 +01003862 body = ParseScopedStatement(NULL, true, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003863 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003864
3865 Statement* result = NULL;
3866 if (lexical_bindings.length() > 0) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003867 BlockState block_state(&scope_, for_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003868 result = DesugarLexicalBindingsInForStatement(
Ben Murdoch097c5b22016-05-18 11:27:45 +01003869 inner_scope, parsing_result.descriptor.mode, &lexical_bindings, loop,
3870 init, cond, next, body, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003871 for_scope->set_end_position(scanner()->location().end_pos);
3872 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003873 for_scope->set_end_position(scanner()->location().end_pos);
3874 for_scope = for_scope->FinalizeBlockScope();
3875 if (for_scope) {
3876 // Rewrite a for statement of the form
3877 // for (const x = i; c; n) b
3878 //
3879 // into
3880 //
3881 // {
3882 // const x = i;
3883 // for (; c; n) b
3884 // }
3885 //
3886 // or, desugar
3887 // for (; c; n) b
3888 // into
3889 // {
3890 // for (; c; n) b
3891 // }
3892 // just in case b introduces a lexical binding some other way, e.g., if b
3893 // is a FunctionDeclaration.
3894 Block* block =
3895 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
3896 if (init != nullptr) {
3897 block->statements()->Add(init, zone());
3898 }
3899 block->statements()->Add(loop, zone());
3900 block->set_scope(for_scope);
3901 loop->Initialize(NULL, cond, next, body);
3902 result = block;
3903 } else {
3904 loop->Initialize(init, cond, next, body);
3905 result = loop;
3906 }
3907 }
3908 return result;
3909}
3910
3911
3912DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
3913 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
3914 // contexts this is used as a statement which invokes the debugger as i a
3915 // break point is present.
3916 // DebuggerStatement ::
3917 // 'debugger' ';'
3918
3919 int pos = peek_position();
3920 Expect(Token::DEBUGGER, CHECK_OK);
3921 ExpectSemicolon(CHECK_OK);
3922 return factory()->NewDebuggerStatement(pos);
3923}
3924
3925
3926bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
3927 if (expression->IsLiteral()) return true;
3928 MaterializedLiteral* lit = expression->AsMaterializedLiteral();
3929 return lit != NULL && lit->is_simple();
3930}
3931
3932
3933Handle<FixedArray> CompileTimeValue::GetValue(Isolate* isolate,
3934 Expression* expression) {
3935 Factory* factory = isolate->factory();
3936 DCHECK(IsCompileTimeValue(expression));
3937 Handle<FixedArray> result = factory->NewFixedArray(2, TENURED);
3938 ObjectLiteral* object_literal = expression->AsObjectLiteral();
3939 if (object_literal != NULL) {
3940 DCHECK(object_literal->is_simple());
3941 if (object_literal->fast_elements()) {
3942 result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
3943 } else {
3944 result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
3945 }
3946 result->set(kElementsSlot, *object_literal->constant_properties());
3947 } else {
3948 ArrayLiteral* array_literal = expression->AsArrayLiteral();
3949 DCHECK(array_literal != NULL && array_literal->is_simple());
3950 result->set(kLiteralTypeSlot, Smi::FromInt(ARRAY_LITERAL));
3951 result->set(kElementsSlot, *array_literal->constant_elements());
3952 }
3953 return result;
3954}
3955
3956
3957CompileTimeValue::LiteralType CompileTimeValue::GetLiteralType(
3958 Handle<FixedArray> value) {
3959 Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot));
3960 return static_cast<LiteralType>(literal_type->value());
3961}
3962
3963
3964Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
3965 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3966}
3967
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003968void ParserTraits::ParseArrowFunctionFormalParameters(
Ben Murdochc5610432016-08-08 18:44:38 +01003969 ParserFormalParameters* parameters, Expression* expr, int end_pos,
3970 bool* ok) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003971 // ArrowFunctionFormals ::
3972 // Binary(Token::COMMA, NonTailArrowFunctionFormals, Tail)
3973 // Tail
3974 // NonTailArrowFunctionFormals ::
3975 // Binary(Token::COMMA, NonTailArrowFunctionFormals, VariableProxy)
3976 // VariableProxy
3977 // Tail ::
3978 // VariableProxy
3979 // Spread(VariableProxy)
3980 //
3981 // As we need to visit the parameters in left-to-right order, we recurse on
3982 // the left-hand side of comma expressions.
3983 //
3984 if (expr->IsBinaryOperation()) {
3985 BinaryOperation* binop = expr->AsBinaryOperation();
3986 // The classifier has already run, so we know that the expression is a valid
3987 // arrow function formals production.
3988 DCHECK_EQ(binop->op(), Token::COMMA);
3989 Expression* left = binop->left();
3990 Expression* right = binop->right();
Ben Murdochc5610432016-08-08 18:44:38 +01003991 int comma_pos = binop->position();
3992 ParseArrowFunctionFormalParameters(parameters, left, comma_pos, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003993 if (!*ok) return;
3994 // LHS of comma expression should be unparenthesized.
3995 expr = right;
3996 }
3997
3998 // Only the right-most expression may be a rest parameter.
3999 DCHECK(!parameters->has_rest);
4000
4001 bool is_rest = expr->IsSpread();
4002 if (is_rest) {
4003 expr = expr->AsSpread()->expression();
4004 parameters->has_rest = true;
4005 }
4006 if (parameters->is_simple) {
4007 parameters->is_simple = !is_rest && expr->IsVariableProxy();
4008 }
4009
4010 Expression* initializer = nullptr;
4011 if (expr->IsVariableProxy()) {
4012 // When the formal parameter was originally seen, it was parsed as a
4013 // VariableProxy and recorded as unresolved in the scope. Here we undo that
4014 // parse-time side-effect for parameters that are single-names (not
4015 // patterns; for patterns that happens uniformly in
4016 // PatternRewriter::VisitVariableProxy).
4017 parser_->scope_->RemoveUnresolved(expr->AsVariableProxy());
4018 } else if (expr->IsAssignment()) {
4019 Assignment* assignment = expr->AsAssignment();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004020 DCHECK(!assignment->is_compound());
4021 initializer = assignment->value();
4022 expr = assignment->target();
4023
4024 // TODO(adamk): Only call this if necessary.
4025 RewriteParameterInitializerScope(parser_->stack_limit(), initializer,
4026 parser_->scope_, parameters->scope);
4027 }
4028
Ben Murdochc5610432016-08-08 18:44:38 +01004029 AddFormalParameter(parameters, expr, initializer, end_pos, is_rest);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004030}
4031
Ben Murdochc5610432016-08-08 18:44:38 +01004032void ParserTraits::ParseAsyncArrowSingleExpressionBody(
4033 ZoneList<Statement*>* body, bool accept_IN,
4034 Type::ExpressionClassifier* classifier, int pos, bool* ok) {
4035 parser_->DesugarAsyncFunctionBody(
4036 parser_->ast_value_factory()->empty_string(), parser_->scope_, body,
4037 classifier, kAsyncArrowFunction, FunctionBody::SingleExpression,
4038 accept_IN, pos, ok);
4039}
4040
4041void Parser::DesugarAsyncFunctionBody(const AstRawString* function_name,
4042 Scope* scope, ZoneList<Statement*>* body,
4043 ExpressionClassifier* classifier,
4044 FunctionKind kind, FunctionBody body_type,
4045 bool accept_IN, int pos, bool* ok) {
4046 // function async_function() {
4047 // try {
4048 // .generator_object = %CreateGeneratorObject();
4049 // ... function body ...
4050 // } catch (e) {
4051 // return Promise.reject(e);
4052 // }
4053 // }
4054 scope->ForceContextAllocation();
4055 Variable* temp =
4056 scope_->NewTemporary(ast_value_factory()->dot_generator_object_string());
4057 function_state_->set_generator_object_variable(temp);
4058
4059 Expression* init_generator_variable = factory()->NewAssignment(
4060 Token::INIT, factory()->NewVariableProxy(temp),
4061 BuildCreateJSGeneratorObject(pos, kind), RelocInfo::kNoPosition);
4062 body->Add(factory()->NewExpressionStatement(init_generator_variable,
4063 RelocInfo::kNoPosition),
4064 zone());
4065
4066 Block* try_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition);
4067
4068 ZoneList<Statement*>* inner_body = try_block->statements();
4069
4070 Expression* return_value = nullptr;
4071 if (body_type == FunctionBody::Normal) {
4072 ParseStatementList(inner_body, Token::RBRACE, ok);
4073 if (!*ok) return;
4074 return_value = factory()->NewUndefinedLiteral(RelocInfo::kNoPosition);
4075 } else {
4076 return_value = ParseAssignmentExpression(accept_IN, classifier, ok);
4077 if (!*ok) return;
4078 ParserTraits::RewriteNonPattern(classifier, ok);
4079 if (!*ok) return;
4080 }
4081
4082 return_value = BuildPromiseResolve(return_value, return_value->position());
4083 inner_body->Add(
4084 factory()->NewReturnStatement(return_value, return_value->position()),
4085 zone());
4086 body->Add(BuildRejectPromiseOnException(try_block), zone());
4087 scope->set_end_position(scanner()->location().end_pos);
4088}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004089
4090DoExpression* Parser::ParseDoExpression(bool* ok) {
4091 // AssignmentExpression ::
4092 // do '{' StatementList '}'
4093 int pos = peek_position();
4094
4095 Expect(Token::DO, CHECK_OK);
4096 Variable* result =
4097 scope_->NewTemporary(ast_value_factory()->dot_result_string());
4098 Block* block = ParseBlock(nullptr, false, CHECK_OK);
4099 DoExpression* expr = factory()->NewDoExpression(block, result, pos);
4100 if (!Rewriter::Rewrite(this, expr, ast_value_factory())) {
4101 *ok = false;
4102 return nullptr;
4103 }
4104 block->set_scope(block->scope()->FinalizeBlockScope());
4105 return expr;
4106}
4107
4108
4109void ParserTraits::ParseArrowFunctionFormalParameterList(
4110 ParserFormalParameters* parameters, Expression* expr,
4111 const Scanner::Location& params_loc,
4112 Scanner::Location* duplicate_loc, bool* ok) {
4113 if (expr->IsEmptyParentheses()) return;
4114
Ben Murdochc5610432016-08-08 18:44:38 +01004115 ParseArrowFunctionFormalParameters(parameters, expr, params_loc.end_pos, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004116 if (!*ok) return;
4117
Ben Murdochc5610432016-08-08 18:44:38 +01004118 if (parameters->Arity() > Code::kMaxArguments) {
4119 ReportMessageAt(params_loc, MessageTemplate::kMalformedArrowFunParamList);
4120 *ok = false;
4121 return;
4122 }
4123
Ben Murdoch097c5b22016-05-18 11:27:45 +01004124 Type::ExpressionClassifier classifier(parser_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004125 if (!parameters->is_simple) {
4126 classifier.RecordNonSimpleParameter();
4127 }
4128 for (int i = 0; i < parameters->Arity(); ++i) {
4129 auto parameter = parameters->at(i);
4130 DeclareFormalParameter(parameters->scope, parameter, &classifier);
4131 if (!duplicate_loc->IsValid()) {
4132 *duplicate_loc = classifier.duplicate_formal_parameter_error().location;
4133 }
4134 }
4135 DCHECK_EQ(parameters->is_simple, parameters->scope->has_simple_parameters());
4136}
4137
4138
4139void ParserTraits::ReindexLiterals(const ParserFormalParameters& parameters) {
4140 if (parser_->function_state_->materialized_literal_count() > 0) {
4141 AstLiteralReindexer reindexer;
4142
4143 for (const auto p : parameters.params) {
4144 if (p.pattern != nullptr) reindexer.Reindex(p.pattern);
4145 if (p.initializer != nullptr) reindexer.Reindex(p.initializer);
4146 }
4147
4148 DCHECK(reindexer.count() <=
4149 parser_->function_state_->materialized_literal_count());
4150 }
4151}
4152
4153
4154FunctionLiteral* Parser::ParseFunctionLiteral(
4155 const AstRawString* function_name, Scanner::Location function_name_location,
4156 FunctionNameValidity function_name_validity, FunctionKind kind,
4157 int function_token_pos, FunctionLiteral::FunctionType function_type,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004158 LanguageMode language_mode, bool* ok) {
4159 // Function ::
4160 // '(' FormalParameterList? ')' '{' FunctionBody '}'
4161 //
4162 // Getter ::
4163 // '(' ')' '{' FunctionBody '}'
4164 //
4165 // Setter ::
4166 // '(' PropertySetParameterList ')' '{' FunctionBody '}'
4167
4168 int pos = function_token_pos == RelocInfo::kNoPosition
4169 ? peek_position() : function_token_pos;
4170
4171 bool is_generator = IsGeneratorFunction(kind);
4172
4173 // Anonymous functions were passed either the empty symbol or a null
4174 // handle as the function name. Remember if we were passed a non-empty
4175 // handle to decide whether to invoke function name inference.
4176 bool should_infer_name = function_name == NULL;
4177
4178 // We want a non-null handle as the function name.
4179 if (should_infer_name) {
4180 function_name = ast_value_factory()->empty_string();
4181 }
4182
Ben Murdochc5610432016-08-08 18:44:38 +01004183 Scope* scope = NewScope(scope_, FUNCTION_SCOPE, kind);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004184 SetLanguageMode(scope, language_mode);
4185 ZoneList<Statement*>* body = NULL;
4186 int arity = -1;
4187 int materialized_literal_count = -1;
4188 int expected_property_count = -1;
4189 DuplicateFinder duplicate_finder(scanner()->unicode_cache());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004190 bool should_be_used_once_hint = false;
Ben Murdoch097c5b22016-05-18 11:27:45 +01004191 bool has_duplicate_parameters;
Ben Murdochc5610432016-08-08 18:44:38 +01004192 FunctionLiteral::EagerCompileHint eager_compile_hint;
4193
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004194 // Parse function.
4195 {
4196 AstNodeFactory function_factory(ast_value_factory());
4197 FunctionState function_state(&function_state_, &scope_, scope, kind,
4198 &function_factory);
4199 scope_->SetScopeName(function_name);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004200 ExpressionClassifier formals_classifier(this, &duplicate_finder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004201
Ben Murdochc5610432016-08-08 18:44:38 +01004202 eager_compile_hint = function_state_->this_function_is_parenthesized()
4203 ? FunctionLiteral::kShouldEagerCompile
4204 : FunctionLiteral::kShouldLazyCompile;
4205
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004206 if (is_generator) {
4207 // For generators, allocating variables in contexts is currently a win
4208 // because it minimizes the work needed to suspend and resume an
Ben Murdochda12d292016-06-02 14:46:10 +01004209 // activation. The machine code produced for generators (by full-codegen)
4210 // relies on this forced context allocation, but not in an essential way.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004211 scope_->ForceContextAllocation();
4212
4213 // Calling a generator returns a generator object. That object is stored
4214 // in a temporary variable, a definition that is used by "yield"
4215 // expressions. This also marks the FunctionState as a generator.
4216 Variable* temp = scope_->NewTemporary(
4217 ast_value_factory()->dot_generator_object_string());
4218 function_state.set_generator_object_variable(temp);
4219 }
4220
4221 Expect(Token::LPAREN, CHECK_OK);
4222 int start_position = scanner()->location().beg_pos;
4223 scope_->set_start_position(start_position);
4224 ParserFormalParameters formals(scope);
4225 ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK);
4226 arity = formals.Arity();
4227 Expect(Token::RPAREN, CHECK_OK);
4228 int formals_end_position = scanner()->location().end_pos;
4229
Ben Murdoch097c5b22016-05-18 11:27:45 +01004230 CheckArityRestrictions(arity, kind, formals.has_rest, start_position,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004231 formals_end_position, CHECK_OK);
4232 Expect(Token::LBRACE, CHECK_OK);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004233 // Don't include the rest parameter into the function's formal parameter
4234 // count (esp. the SharedFunctionInfo::internal_formal_parameter_count,
4235 // which says whether we need to create an arguments adaptor frame).
4236 if (formals.has_rest) arity--;
4237
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004238 // Determine if the function can be parsed lazily. Lazy parsing is different
4239 // from lazy compilation; we need to parse more eagerly than we compile.
4240
4241 // We can only parse lazily if we also compile lazily. The heuristics for
4242 // lazy compilation are:
4243 // - It must not have been prohibited by the caller to Parse (some callers
4244 // need a full AST).
4245 // - The outer scope must allow lazy compilation of inner functions.
4246 // - The function mustn't be a function expression with an open parenthesis
4247 // before; we consider that a hint that the function will be called
4248 // immediately, and it would be a waste of time to make it lazily
4249 // compiled.
4250 // These are all things we can know at this point, without looking at the
4251 // function itself.
4252
4253 // In addition, we need to distinguish between these cases:
4254 // (function foo() {
4255 // bar = function() { return 1; }
4256 // })();
4257 // and
4258 // (function foo() {
4259 // var a = 1;
4260 // bar = function() { return a; }
4261 // })();
4262
4263 // Now foo will be parsed eagerly and compiled eagerly (optimization: assume
4264 // parenthesis before the function means that it will be called
4265 // immediately). The inner function *must* be parsed eagerly to resolve the
4266 // possible reference to the variable in foo's scope. However, it's possible
4267 // that it will be compiled lazily.
4268
4269 // To make this additional case work, both Parser and PreParser implement a
4270 // logic where only top-level functions will be parsed lazily.
4271 bool is_lazily_parsed = mode() == PARSE_LAZILY &&
4272 scope_->AllowsLazyParsing() &&
Ben Murdochc5610432016-08-08 18:44:38 +01004273 !function_state_->this_function_is_parenthesized();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004274
4275 // Eager or lazy parse?
4276 // If is_lazily_parsed, we'll parse lazy. If we can set a bookmark, we'll
4277 // pass it to SkipLazyFunctionBody, which may use it to abort lazy
4278 // parsing if it suspect that wasn't a good idea. If so, or if we didn't
4279 // try to lazy parse in the first place, we'll have to parse eagerly.
4280 Scanner::BookmarkScope bookmark(scanner());
4281 if (is_lazily_parsed) {
4282 Scanner::BookmarkScope* maybe_bookmark =
4283 bookmark.Set() ? &bookmark : nullptr;
4284 SkipLazyFunctionBody(&materialized_literal_count,
4285 &expected_property_count, /*CHECK_OK*/ ok,
4286 maybe_bookmark);
4287
4288 materialized_literal_count += formals.materialized_literals_count +
4289 function_state.materialized_literal_count();
4290
4291 if (bookmark.HasBeenReset()) {
4292 // Trigger eager (re-)parsing, just below this block.
4293 is_lazily_parsed = false;
4294
4295 // This is probably an initialization function. Inform the compiler it
4296 // should also eager-compile this function, and that we expect it to be
4297 // used once.
4298 eager_compile_hint = FunctionLiteral::kShouldEagerCompile;
4299 should_be_used_once_hint = true;
4300 }
4301 }
4302 if (!is_lazily_parsed) {
4303 // Determine whether the function body can be discarded after parsing.
4304 // The preconditions are:
4305 // - Lazy compilation has to be enabled.
4306 // - Neither V8 natives nor native function declarations can be allowed,
4307 // since parsing one would retroactively force the function to be
4308 // eagerly compiled.
4309 // - The invoker of this parser can't depend on the AST being eagerly
4310 // built (either because the function is about to be compiled, or
4311 // because the AST is going to be inspected for some reason).
4312 // - Because of the above, we can't be attempting to parse a
4313 // FunctionExpression; even without enclosing parentheses it might be
4314 // immediately invoked.
4315 // - The function literal shouldn't be hinted to eagerly compile.
Ben Murdochc5610432016-08-08 18:44:38 +01004316 // - For asm.js functions the body needs to be available when module
4317 // validation is active, because we examine the entire module at once.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004318 bool use_temp_zone =
4319 FLAG_lazy && !allow_natives() && extension_ == NULL && allow_lazy() &&
4320 function_type == FunctionLiteral::kDeclaration &&
Ben Murdochc5610432016-08-08 18:44:38 +01004321 eager_compile_hint != FunctionLiteral::kShouldEagerCompile &&
4322 !(FLAG_validate_asm && scope->asm_function());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004323 // Open a new BodyScope, which sets our AstNodeFactory to allocate in the
4324 // new temporary zone if the preconditions are satisfied, and ensures that
4325 // the previous zone is always restored after parsing the body.
4326 // For the purpose of scope analysis, some ZoneObjects allocated by the
4327 // factory must persist after the function body is thrown away and
4328 // temp_zone is deallocated. These objects are instead allocated in a
4329 // parser-persistent zone (see parser_zone_ in AstNodeFactory).
4330 {
Ben Murdochda12d292016-06-02 14:46:10 +01004331 Zone temp_zone(zone()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004332 AstNodeFactory::BodyScope inner(factory(), &temp_zone, use_temp_zone);
4333
4334 body = ParseEagerFunctionBody(function_name, pos, formals, kind,
4335 function_type, CHECK_OK);
4336 }
4337 materialized_literal_count = function_state.materialized_literal_count();
4338 expected_property_count = function_state.expected_property_count();
4339 if (use_temp_zone) {
4340 // If the preconditions are correct the function body should never be
4341 // accessed, but do this anyway for better behaviour if they're wrong.
4342 body = NULL;
4343 }
4344 }
4345
4346 // Parsing the body may change the language mode in our scope.
4347 language_mode = scope->language_mode();
4348
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004349 // Validate name and parameter names. We can do this only after parsing the
4350 // function, since the function can declare itself strict.
4351 CheckFunctionName(language_mode, function_name, function_name_validity,
4352 function_name_location, CHECK_OK);
4353 const bool allow_duplicate_parameters =
4354 is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind);
4355 ValidateFormalParameters(&formals_classifier, language_mode,
4356 allow_duplicate_parameters, CHECK_OK);
4357
4358 if (is_strict(language_mode)) {
4359 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(),
4360 CHECK_OK);
Ben Murdochc5610432016-08-08 18:44:38 +01004361 CheckDecimalLiteralWithLeadingZero(use_counts_, scope->start_position(),
4362 scope->end_position());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004363 }
Ben Murdochc5610432016-08-08 18:44:38 +01004364 if (is_sloppy(language_mode)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004365 InsertSloppyBlockFunctionVarBindings(scope, CHECK_OK);
4366 }
Ben Murdochda12d292016-06-02 14:46:10 +01004367 CheckConflictingVarDeclarations(scope, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004368
4369 if (body) {
4370 // If body can be inspected, rewrite queued destructuring assignments
4371 ParserTraits::RewriteDestructuringAssignments();
4372 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01004373 has_duplicate_parameters =
4374 !formals_classifier.is_valid_formal_parameter_list_without_duplicates();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004375 }
4376
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004377 FunctionLiteral::ParameterFlag duplicate_parameters =
4378 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters
4379 : FunctionLiteral::kNoDuplicateParameters;
4380
4381 FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
4382 function_name, scope, body, materialized_literal_count,
4383 expected_property_count, arity, duplicate_parameters, function_type,
4384 eager_compile_hint, kind, pos);
4385 function_literal->set_function_token_position(function_token_pos);
4386 if (should_be_used_once_hint)
4387 function_literal->set_should_be_used_once_hint();
4388
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004389 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
4390 return function_literal;
4391}
4392
Ben Murdochc5610432016-08-08 18:44:38 +01004393Expression* Parser::ParseAsyncFunctionExpression(bool* ok) {
4394 // AsyncFunctionDeclaration ::
4395 // async [no LineTerminator here] function ( FormalParameters[Await] )
4396 // { AsyncFunctionBody }
4397 //
4398 // async [no LineTerminator here] function BindingIdentifier[Await]
4399 // ( FormalParameters[Await] ) { AsyncFunctionBody }
4400 DCHECK_EQ(scanner()->current_token(), Token::ASYNC);
4401 int pos = position();
4402 Expect(Token::FUNCTION, CHECK_OK);
4403 bool is_strict_reserved = false;
4404 const AstRawString* name = nullptr;
4405 FunctionLiteral::FunctionType type = FunctionLiteral::kAnonymousExpression;
4406
4407 if (peek_any_identifier()) {
4408 type = FunctionLiteral::kNamedExpression;
4409 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
4410 if (this->IsAwait(name)) {
4411 ReportMessageAt(scanner()->location(),
4412 MessageTemplate::kAwaitBindingIdentifier);
4413 *ok = false;
4414 return nullptr;
4415 }
4416 }
4417 return ParseFunctionLiteral(name, scanner()->location(),
4418 is_strict_reserved ? kFunctionNameIsStrictReserved
4419 : kFunctionNameValidityUnknown,
4420 FunctionKind::kAsyncFunction, pos, type,
4421 language_mode(), CHECK_OK);
4422}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004423
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();
Ben Murdochc5610432016-08-08 18:44:38 +01004613 param_scope->set_start_position(descriptor.initialization_pos);
4614 param_scope->set_end_position(parameter.initializer_end_position);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004615 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_;
Ben Murdochc5610432016-08-08 18:44:38 +01004619 // Pass the appropriate scope in so that PatternRewriter can appropriately
4620 // rewrite inner initializers of the pattern to param_scope
4621 descriptor.scope = param_scope;
4622 // Rewrite the outer initializer to point to param_scope
4623 RewriteParameterInitializerScope(stack_limit(), initial_value, scope_,
4624 param_scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004625 }
4626
4627 {
4628 BlockState block_state(&scope_, param_scope);
4629 DeclarationParsingResult::Declaration decl(
4630 parameter.pattern, initializer_position, initial_value);
4631 PatternRewriter::DeclareAndInitializeVariables(param_block, &descriptor,
4632 &decl, nullptr, CHECK_OK);
4633 }
4634
4635 if (!parameter.is_simple() && scope_->calls_sloppy_eval()) {
4636 param_scope = param_scope->FinalizeBlockScope();
4637 if (param_scope != nullptr) {
4638 CheckConflictingVarDeclarations(param_scope, CHECK_OK);
4639 }
4640 init_block->statements()->Add(param_block, zone());
4641 }
4642 }
4643 return init_block;
4644}
4645
Ben Murdochc5610432016-08-08 18:44:38 +01004646Block* Parser::BuildRejectPromiseOnException(Block* block) {
4647 // try { <block> } catch (error) { return Promise.reject(error); }
4648 Block* try_block = block;
4649 Scope* catch_scope = NewScope(scope_, CATCH_SCOPE);
4650 catch_scope->set_is_hidden();
4651 Variable* catch_variable =
4652 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR,
4653 kCreatedInitialized, Variable::NORMAL);
4654 Block* catch_block =
4655 factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
4656
4657 Expression* promise_reject = BuildPromiseReject(
4658 factory()->NewVariableProxy(catch_variable), RelocInfo::kNoPosition);
4659
4660 ReturnStatement* return_promise_reject =
4661 factory()->NewReturnStatement(promise_reject, RelocInfo::kNoPosition);
4662 catch_block->statements()->Add(return_promise_reject, zone());
4663 TryStatement* try_catch_statement =
4664 factory()->NewTryCatchStatement(try_block, catch_scope, catch_variable,
4665 catch_block, RelocInfo::kNoPosition);
4666
4667 block = factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
4668 block->statements()->Add(try_catch_statement, zone());
4669 return block;
4670}
4671
4672Expression* Parser::BuildCreateJSGeneratorObject(int pos, FunctionKind kind) {
4673 DCHECK_NOT_NULL(function_state_->generator_object_variable());
4674 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
4675 args->Add(factory()->NewThisFunction(pos), zone());
4676 args->Add(IsArrowFunction(kind)
4677 ? GetLiteralUndefined(pos)
4678 : ThisExpression(scope_, factory(), RelocInfo::kNoPosition),
4679 zone());
4680 return factory()->NewCallRuntime(Runtime::kCreateJSGeneratorObject, args,
4681 pos);
4682}
4683
4684Expression* Parser::BuildPromiseResolve(Expression* value, int pos) {
4685 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
4686 args->Add(value, zone());
4687 return factory()->NewCallRuntime(Context::PROMISE_CREATE_RESOLVED_INDEX, args,
4688 pos);
4689}
4690
4691Expression* Parser::BuildPromiseReject(Expression* value, int pos) {
4692 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
4693 args->Add(value, zone());
4694 return factory()->NewCallRuntime(Context::PROMISE_CREATE_REJECTED_INDEX, args,
4695 pos);
4696}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004697
4698ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
4699 const AstRawString* function_name, int pos,
4700 const ParserFormalParameters& parameters, FunctionKind kind,
4701 FunctionLiteral::FunctionType function_type, bool* ok) {
4702 // Everything inside an eagerly parsed function will be parsed eagerly
4703 // (see comment above).
4704 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
4705 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone());
4706
4707 static const int kFunctionNameAssignmentIndex = 0;
4708 if (function_type == FunctionLiteral::kNamedExpression) {
4709 DCHECK(function_name != NULL);
4710 // If we have a named function expression, we add a local variable
4711 // declaration to the body of the function with the name of the
4712 // function and let it refer to the function itself (closure).
4713 // Not having parsed the function body, the language mode may still change,
4714 // so we reserve a spot and create the actual const assignment later.
4715 DCHECK_EQ(kFunctionNameAssignmentIndex, result->length());
4716 result->Add(NULL, zone());
4717 }
4718
4719 ZoneList<Statement*>* body = result;
4720 Scope* inner_scope = scope_;
4721 Block* inner_block = nullptr;
4722 if (!parameters.is_simple) {
4723 inner_scope = NewScope(scope_, BLOCK_SCOPE);
4724 inner_scope->set_is_declaration_scope();
4725 inner_scope->set_start_position(scanner()->location().beg_pos);
4726 inner_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition);
4727 inner_block->set_scope(inner_scope);
4728 body = inner_block->statements();
4729 }
4730
4731 {
4732 BlockState block_state(&scope_, inner_scope);
4733
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004734 if (IsGeneratorFunction(kind)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004735 // We produce:
4736 //
Ben Murdochda12d292016-06-02 14:46:10 +01004737 // try { InitialYield; ...body...; return {value: undefined, done: true} }
Ben Murdoch61f157c2016-09-16 13:49:30 +01004738 // finally { %_GeneratorClose(generator) }
Ben Murdoch097c5b22016-05-18 11:27:45 +01004739 //
4740 // - InitialYield yields the actual generator object.
Ben Murdochda12d292016-06-02 14:46:10 +01004741 // - Any return statement inside the body will have its argument wrapped
4742 // in a "done" iterator result object.
Ben Murdoch097c5b22016-05-18 11:27:45 +01004743 // - If the generator terminates for whatever reason, we must close it.
4744 // Hence the finally clause.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004745
Ben Murdoch097c5b22016-05-18 11:27:45 +01004746 Block* try_block =
4747 factory()->NewBlock(nullptr, 3, false, RelocInfo::kNoPosition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004748
Ben Murdoch097c5b22016-05-18 11:27:45 +01004749 {
Ben Murdochc5610432016-08-08 18:44:38 +01004750 Expression* allocation = BuildCreateJSGeneratorObject(pos, kind);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004751 VariableProxy* init_proxy = factory()->NewVariableProxy(
4752 function_state_->generator_object_variable());
4753 Assignment* assignment = factory()->NewAssignment(
4754 Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition);
4755 VariableProxy* get_proxy = factory()->NewVariableProxy(
4756 function_state_->generator_object_variable());
Ben Murdoch61f157c2016-09-16 13:49:30 +01004757 // The position of the yield is important for reporting the exception
4758 // caused by calling the .throw method on a generator suspended at the
4759 // initial yield (i.e. right after generator instantiation).
4760 Yield* yield = factory()->NewYield(get_proxy, assignment,
4761 scope_->start_position());
Ben Murdoch097c5b22016-05-18 11:27:45 +01004762 try_block->statements()->Add(
4763 factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition),
4764 zone());
4765 }
4766
4767 ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK);
4768
Ben Murdochda12d292016-06-02 14:46:10 +01004769 Statement* final_return = factory()->NewReturnStatement(
4770 BuildIteratorResult(nullptr, true), RelocInfo::kNoPosition);
4771 try_block->statements()->Add(final_return, zone());
Ben Murdoch097c5b22016-05-18 11:27:45 +01004772
4773 Block* finally_block =
4774 factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition);
4775 ZoneList<Expression*>* args =
4776 new (zone()) ZoneList<Expression*>(1, zone());
4777 VariableProxy* call_proxy = factory()->NewVariableProxy(
4778 function_state_->generator_object_variable());
4779 args->Add(call_proxy, zone());
4780 Expression* call = factory()->NewCallRuntime(
Ben Murdoch61f157c2016-09-16 13:49:30 +01004781 Runtime::kInlineGeneratorClose, args, RelocInfo::kNoPosition);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004782 finally_block->statements()->Add(
4783 factory()->NewExpressionStatement(call, RelocInfo::kNoPosition),
4784 zone());
4785
4786 body->Add(factory()->NewTryFinallyStatement(try_block, finally_block,
4787 RelocInfo::kNoPosition),
4788 zone());
Ben Murdochc5610432016-08-08 18:44:38 +01004789 } else if (IsAsyncFunction(kind)) {
4790 const bool accept_IN = true;
4791 DesugarAsyncFunctionBody(function_name, inner_scope, body, nullptr, kind,
4792 FunctionBody::Normal, accept_IN, pos, CHECK_OK);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004793 } else {
4794 ParseStatementList(body, Token::RBRACE, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004795 }
4796
4797 if (IsSubclassConstructor(kind)) {
4798 body->Add(
4799 factory()->NewReturnStatement(
4800 this->ThisExpression(scope_, factory(), RelocInfo::kNoPosition),
4801 RelocInfo::kNoPosition),
4802 zone());
4803 }
4804 }
4805
4806 Expect(Token::RBRACE, CHECK_OK);
4807 scope_->set_end_position(scanner()->location().end_pos);
4808
4809 if (!parameters.is_simple) {
4810 DCHECK_NOT_NULL(inner_scope);
4811 DCHECK_EQ(body, inner_block->statements());
4812 SetLanguageMode(scope_, inner_scope->language_mode());
4813 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK);
Ben Murdochc5610432016-08-08 18:44:38 +01004814
4815 if (IsAsyncFunction(kind)) {
4816 init_block = BuildRejectPromiseOnException(init_block);
4817 }
4818
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004819 DCHECK_NOT_NULL(init_block);
4820
4821 inner_scope->set_end_position(scanner()->location().end_pos);
4822 inner_scope = inner_scope->FinalizeBlockScope();
4823 if (inner_scope != nullptr) {
4824 CheckConflictingVarDeclarations(inner_scope, CHECK_OK);
4825 InsertShadowingVarBindingInitializers(inner_block);
4826 }
4827
4828 result->Add(init_block, zone());
4829 result->Add(inner_block, zone());
4830 }
4831
4832 if (function_type == FunctionLiteral::kNamedExpression) {
4833 // Now that we know the language mode, we can create the const assignment
4834 // in the previously reserved spot.
4835 // NOTE: We create a proxy and resolve it here so that in the
4836 // future we can change the AST to only refer to VariableProxies
4837 // instead of Variables and Proxies as is the case now.
4838 VariableMode fvar_mode = is_strict(language_mode()) ? CONST : CONST_LEGACY;
4839 Variable* fvar = new (zone())
4840 Variable(scope_, function_name, fvar_mode, Variable::NORMAL,
4841 kCreatedInitialized, kNotAssigned);
4842 VariableProxy* proxy = factory()->NewVariableProxy(fvar);
4843 VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
4844 proxy, fvar_mode, scope_, RelocInfo::kNoPosition);
4845 scope_->DeclareFunctionVar(fvar_declaration);
4846
4847 VariableProxy* fproxy = factory()->NewVariableProxy(fvar);
4848 result->Set(kFunctionNameAssignmentIndex,
4849 factory()->NewExpressionStatement(
4850 factory()->NewAssignment(Token::INIT, fproxy,
4851 factory()->NewThisFunction(pos),
4852 RelocInfo::kNoPosition),
4853 RelocInfo::kNoPosition));
4854 }
4855
Ben Murdochc5610432016-08-08 18:44:38 +01004856 MarkCollectedTailCallExpressions();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004857 return result;
4858}
4859
4860
4861PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
4862 SingletonLogger* logger, Scanner::BookmarkScope* bookmark) {
4863 // This function may be called on a background thread too; record only the
4864 // main thread preparse times.
4865 if (pre_parse_timer_ != NULL) {
4866 pre_parse_timer_->Start();
4867 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01004868 TRACE_EVENT0("v8", "V8.PreParse");
4869
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004870 DCHECK_EQ(Token::LBRACE, scanner()->current_token());
4871
4872 if (reusable_preparser_ == NULL) {
4873 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(),
4874 NULL, stack_limit_);
4875 reusable_preparser_->set_allow_lazy(true);
4876#define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name());
4877 SET_ALLOW(natives);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004878 SET_ALLOW(harmony_do_expressions);
Ben Murdochc5610432016-08-08 18:44:38 +01004879 SET_ALLOW(harmony_for_in);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004880 SET_ALLOW(harmony_function_sent);
Ben Murdochda12d292016-06-02 14:46:10 +01004881 SET_ALLOW(harmony_exponentiation_operator);
4882 SET_ALLOW(harmony_restrictive_declarations);
Ben Murdochc5610432016-08-08 18:44:38 +01004883 SET_ALLOW(harmony_async_await);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004884#undef SET_ALLOW
4885 }
4886 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
4887 language_mode(), function_state_->kind(), scope_->has_simple_parameters(),
Ben Murdochc5610432016-08-08 18:44:38 +01004888 parsing_module_, logger, bookmark, use_counts_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004889 if (pre_parse_timer_ != NULL) {
4890 pre_parse_timer_->Stop();
4891 }
4892 return result;
4893}
4894
Ben Murdochda12d292016-06-02 14:46:10 +01004895ClassLiteral* Parser::ParseClassLiteral(ExpressionClassifier* classifier,
4896 const AstRawString* name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004897 Scanner::Location class_name_location,
4898 bool name_is_strict_reserved, int pos,
4899 bool* ok) {
4900 // All parts of a ClassDeclaration and ClassExpression are strict code.
4901 if (name_is_strict_reserved) {
4902 ReportMessageAt(class_name_location,
4903 MessageTemplate::kUnexpectedStrictReserved);
4904 *ok = false;
4905 return NULL;
4906 }
4907 if (IsEvalOrArguments(name)) {
4908 ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments);
4909 *ok = false;
4910 return NULL;
4911 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004912
4913 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
4914 BlockState block_state(&scope_, block_scope);
4915 RaiseLanguageMode(STRICT);
4916 scope_->SetScopeName(name);
4917
4918 VariableProxy* proxy = NULL;
4919 if (name != NULL) {
4920 proxy = NewUnresolved(name, CONST);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004921 Declaration* declaration =
4922 factory()->NewVariableDeclaration(proxy, CONST, block_scope, pos);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004923 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
4924 }
4925
4926 Expression* extends = NULL;
4927 if (Check(Token::EXTENDS)) {
4928 block_scope->set_start_position(scanner()->location().end_pos);
Ben Murdochda12d292016-06-02 14:46:10 +01004929 ExpressionClassifier extends_classifier(this);
4930 extends = ParseLeftHandSideExpression(&extends_classifier, CHECK_OK);
Ben Murdochc5610432016-08-08 18:44:38 +01004931 CheckNoTailCallExpressions(&extends_classifier, CHECK_OK);
Ben Murdochda12d292016-06-02 14:46:10 +01004932 RewriteNonPattern(&extends_classifier, CHECK_OK);
4933 if (classifier != nullptr) {
4934 classifier->Accumulate(&extends_classifier,
4935 ExpressionClassifier::ExpressionProductions);
4936 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004937 } else {
4938 block_scope->set_start_position(scanner()->location().end_pos);
4939 }
4940
4941
4942 ClassLiteralChecker checker(this);
4943 ZoneList<ObjectLiteral::Property*>* properties = NewPropertyList(4, zone());
4944 FunctionLiteral* constructor = NULL;
4945 bool has_seen_constructor = false;
4946
4947 Expect(Token::LBRACE, CHECK_OK);
4948
4949 const bool has_extends = extends != nullptr;
4950 while (peek() != Token::RBRACE) {
4951 if (Check(Token::SEMICOLON)) continue;
4952 FuncNameInferrer::State fni_state(fni_);
4953 const bool in_class = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004954 bool is_computed_name = false; // Classes do not care about computed
4955 // property names here.
Ben Murdochda12d292016-06-02 14:46:10 +01004956 ExpressionClassifier property_classifier(this);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004957 const AstRawString* property_name = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004958 ObjectLiteral::Property* property = ParsePropertyDefinition(
Ben Murdochc5610432016-08-08 18:44:38 +01004959 &checker, in_class, has_extends, MethodKind::Normal, &is_computed_name,
Ben Murdochda12d292016-06-02 14:46:10 +01004960 &has_seen_constructor, &property_classifier, &property_name, CHECK_OK);
4961 RewriteNonPattern(&property_classifier, CHECK_OK);
4962 if (classifier != nullptr) {
4963 classifier->Accumulate(&property_classifier,
4964 ExpressionClassifier::ExpressionProductions);
4965 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004966
4967 if (has_seen_constructor && constructor == NULL) {
4968 constructor = GetPropertyValue(property)->AsFunctionLiteral();
4969 DCHECK_NOT_NULL(constructor);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004970 constructor->set_raw_name(
4971 name != nullptr ? name : ast_value_factory()->empty_string());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004972 } else {
4973 properties->Add(property, zone());
4974 }
4975
4976 if (fni_ != NULL) fni_->Infer();
4977
Ben Murdoch61f157c2016-09-16 13:49:30 +01004978 if (property_name != ast_value_factory()->constructor_string()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004979 SetFunctionNameFromPropertyName(property, property_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004980 }
4981 }
4982
4983 Expect(Token::RBRACE, CHECK_OK);
4984 int end_pos = scanner()->location().end_pos;
4985
4986 if (constructor == NULL) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01004987 constructor = DefaultConstructor(name, has_extends, block_scope, pos,
Ben Murdoch097c5b22016-05-18 11:27:45 +01004988 end_pos, block_scope->language_mode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004989 }
4990
Ben Murdochda12d292016-06-02 14:46:10 +01004991 // Note that we do not finalize this block scope because it is
4992 // used as a sentinel value indicating an anonymous class.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004993 block_scope->set_end_position(end_pos);
4994
4995 if (name != NULL) {
4996 DCHECK_NOT_NULL(proxy);
4997 proxy->var()->set_initializer_position(end_pos);
4998 }
4999
Ben Murdoch097c5b22016-05-18 11:27:45 +01005000 return factory()->NewClassLiteral(block_scope, proxy, extends, constructor,
5001 properties, pos, end_pos);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005002}
5003
5004
5005Expression* Parser::ParseV8Intrinsic(bool* ok) {
5006 // CallRuntime ::
5007 // '%' Identifier Arguments
5008
5009 int pos = peek_position();
5010 Expect(Token::MOD, CHECK_OK);
5011 // Allow "eval" or "arguments" for backward compatibility.
5012 const AstRawString* name = ParseIdentifier(kAllowRestrictedIdentifiers,
5013 CHECK_OK);
5014 Scanner::Location spread_pos;
Ben Murdoch097c5b22016-05-18 11:27:45 +01005015 ExpressionClassifier classifier(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005016 ZoneList<Expression*>* args =
5017 ParseArguments(&spread_pos, &classifier, CHECK_OK);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005018
5019 DCHECK(!spread_pos.IsValid());
5020
5021 if (extension_ != NULL) {
5022 // The extension structures are only accessible while parsing the
5023 // very first time not when reparsing because of lazy compilation.
5024 scope_->DeclarationScope()->ForceEagerCompilation();
5025 }
5026
5027 const Runtime::Function* function = Runtime::FunctionForName(name->string());
5028
5029 if (function != NULL) {
5030 // Check for possible name clash.
5031 DCHECK_EQ(Context::kNotFound,
5032 Context::IntrinsicIndexForName(name->string()));
5033 // Check for built-in IS_VAR macro.
5034 if (function->function_id == Runtime::kIS_VAR) {
5035 DCHECK_EQ(Runtime::RUNTIME, function->intrinsic_type);
5036 // %IS_VAR(x) evaluates to x if x is a variable,
5037 // leads to a parse error otherwise. Could be implemented as an
5038 // inline function %_IS_VAR(x) to eliminate this special case.
5039 if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
5040 return args->at(0);
5041 } else {
5042 ReportMessage(MessageTemplate::kNotIsvar);
5043 *ok = false;
5044 return NULL;
5045 }
5046 }
5047
5048 // Check that the expected number of arguments are being passed.
5049 if (function->nargs != -1 && function->nargs != args->length()) {
Ben Murdochda12d292016-06-02 14:46:10 +01005050 ReportMessage(MessageTemplate::kRuntimeWrongNumArgs);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005051 *ok = false;
5052 return NULL;
5053 }
5054
5055 return factory()->NewCallRuntime(function, args, pos);
5056 }
5057
5058 int context_index = Context::IntrinsicIndexForName(name->string());
5059
5060 // Check that the function is defined.
5061 if (context_index == Context::kNotFound) {
5062 ParserTraits::ReportMessage(MessageTemplate::kNotDefined, name);
5063 *ok = false;
5064 return NULL;
5065 }
5066
5067 return factory()->NewCallRuntime(context_index, args, pos);
5068}
5069
5070
5071Literal* Parser::GetLiteralUndefined(int position) {
5072 return factory()->NewUndefinedLiteral(position);
5073}
5074
5075
5076void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
5077 Declaration* decl = scope->CheckConflictingVarDeclarations();
5078 if (decl != NULL) {
5079 // In ES6, conflicting variable bindings are early errors.
5080 const AstRawString* name = decl->proxy()->raw_name();
5081 int position = decl->proxy()->position();
5082 Scanner::Location location = position == RelocInfo::kNoPosition
5083 ? Scanner::Location::invalid()
5084 : Scanner::Location(position, position + 1);
5085 ParserTraits::ReportMessageAt(location, MessageTemplate::kVarRedeclaration,
5086 name);
5087 *ok = false;
5088 }
5089}
5090
5091
5092void Parser::InsertShadowingVarBindingInitializers(Block* inner_block) {
5093 // For each var-binding that shadows a parameter, insert an assignment
5094 // initializing the variable with the parameter.
5095 Scope* inner_scope = inner_block->scope();
5096 DCHECK(inner_scope->is_declaration_scope());
5097 Scope* function_scope = inner_scope->outer_scope();
5098 DCHECK(function_scope->is_function_scope());
5099 ZoneList<Declaration*>* decls = inner_scope->declarations();
5100 for (int i = 0; i < decls->length(); ++i) {
5101 Declaration* decl = decls->at(i);
5102 if (decl->mode() != VAR || !decl->IsVariableDeclaration()) continue;
5103 const AstRawString* name = decl->proxy()->raw_name();
5104 Variable* parameter = function_scope->LookupLocal(name);
5105 if (parameter == nullptr) continue;
5106 VariableProxy* to = inner_scope->NewUnresolved(factory(), name);
5107 VariableProxy* from = factory()->NewVariableProxy(parameter);
5108 Expression* assignment = factory()->NewAssignment(
5109 Token::ASSIGN, to, from, RelocInfo::kNoPosition);
5110 Statement* statement = factory()->NewExpressionStatement(
5111 assignment, RelocInfo::kNoPosition);
5112 inner_block->statements()->InsertAt(0, statement, zone());
5113 }
5114}
5115
5116
5117void Parser::InsertSloppyBlockFunctionVarBindings(Scope* scope, bool* ok) {
5118 // For each variable which is used as a function declaration in a sloppy
5119 // block,
5120 DCHECK(scope->is_declaration_scope());
5121 SloppyBlockFunctionMap* map = scope->sloppy_block_function_map();
5122 for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
5123 AstRawString* name = static_cast<AstRawString*>(p->key);
5124 // If the variable wouldn't conflict with a lexical declaration,
5125 Variable* var = scope->LookupLocal(name);
5126 if (var == nullptr || !IsLexicalVariableMode(var->mode())) {
5127 // Declare a var-style binding for the function in the outer scope
5128 VariableProxy* proxy = scope->NewUnresolved(factory(), name);
5129 Declaration* declaration = factory()->NewVariableDeclaration(
5130 proxy, VAR, scope, RelocInfo::kNoPosition);
5131 Declare(declaration, DeclarationDescriptor::NORMAL, true, ok, scope);
5132 DCHECK(ok); // Based on the preceding check, this should not fail
5133 if (!ok) return;
5134
5135 // Write in assignments to var for each block-scoped function declaration
5136 auto delegates = static_cast<SloppyBlockFunctionMap::Vector*>(p->value);
5137 for (SloppyBlockFunctionStatement* delegate : *delegates) {
5138 // Read from the local lexical scope and write to the function scope
5139 VariableProxy* to = scope->NewUnresolved(factory(), name);
5140 VariableProxy* from = delegate->scope()->NewUnresolved(factory(), name);
5141 Expression* assignment = factory()->NewAssignment(
5142 Token::ASSIGN, to, from, RelocInfo::kNoPosition);
5143 Statement* statement = factory()->NewExpressionStatement(
5144 assignment, RelocInfo::kNoPosition);
5145 delegate->set_statement(statement);
5146 }
5147 }
5148 }
5149}
5150
5151
5152// ----------------------------------------------------------------------------
5153// Parser support
5154
5155bool Parser::TargetStackContainsLabel(const AstRawString* label) {
5156 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
5157 if (ContainsLabel(t->statement()->labels(), label)) return true;
5158 }
5159 return false;
5160}
5161
5162
5163BreakableStatement* Parser::LookupBreakTarget(const AstRawString* label,
5164 bool* ok) {
5165 bool anonymous = label == NULL;
5166 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
5167 BreakableStatement* stat = t->statement();
5168 if ((anonymous && stat->is_target_for_anonymous()) ||
5169 (!anonymous && ContainsLabel(stat->labels(), label))) {
5170 return stat;
5171 }
5172 }
5173 return NULL;
5174}
5175
5176
5177IterationStatement* Parser::LookupContinueTarget(const AstRawString* label,
5178 bool* ok) {
5179 bool anonymous = label == NULL;
5180 for (Target* t = target_stack_; t != NULL; t = t->previous()) {
5181 IterationStatement* stat = t->statement()->AsIterationStatement();
5182 if (stat == NULL) continue;
5183
5184 DCHECK(stat->is_target_for_anonymous());
5185 if (anonymous || ContainsLabel(stat->labels(), label)) {
5186 return stat;
5187 }
5188 }
5189 return NULL;
5190}
5191
5192
5193void Parser::HandleSourceURLComments(Isolate* isolate, Handle<Script> script) {
5194 if (scanner_.source_url()->length() > 0) {
5195 Handle<String> source_url = scanner_.source_url()->Internalize(isolate);
5196 script->set_source_url(*source_url);
5197 }
5198 if (scanner_.source_mapping_url()->length() > 0) {
5199 Handle<String> source_mapping_url =
5200 scanner_.source_mapping_url()->Internalize(isolate);
5201 script->set_source_mapping_url(*source_mapping_url);
5202 }
5203}
5204
5205
5206void Parser::Internalize(Isolate* isolate, Handle<Script> script, bool error) {
5207 // Internalize strings.
5208 ast_value_factory()->Internalize(isolate);
5209
5210 // Error processing.
5211 if (error) {
5212 if (stack_overflow()) {
5213 isolate->StackOverflow();
5214 } else {
5215 DCHECK(pending_error_handler_.has_pending_error());
5216 pending_error_handler_.ThrowPendingError(isolate, script);
5217 }
5218 }
5219
5220 // Move statistics to Isolate.
5221 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
5222 ++feature) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01005223 if (use_counts_[feature] > 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005224 isolate->CountUsage(v8::Isolate::UseCounterFeature(feature));
5225 }
5226 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01005227 if (scanner_.FoundHtmlComment()) {
5228 isolate->CountUsage(v8::Isolate::kHtmlComment);
5229 if (script->line_offset() == 0 && script->column_offset() == 0) {
5230 isolate->CountUsage(v8::Isolate::kHtmlCommentInExternalScript);
5231 }
5232 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005233 isolate->counters()->total_preparse_skipped()->Increment(
5234 total_preparse_skipped_);
5235}
5236
5237
5238// ----------------------------------------------------------------------------
5239// The Parser interface.
5240
5241
5242bool Parser::ParseStatic(ParseInfo* info) {
5243 Parser parser(info);
5244 if (parser.Parse(info)) {
5245 info->set_language_mode(info->literal()->language_mode());
5246 return true;
5247 }
5248 return false;
5249}
5250
5251
5252bool Parser::Parse(ParseInfo* info) {
5253 DCHECK(info->literal() == NULL);
5254 FunctionLiteral* result = NULL;
5255 // Ok to use Isolate here; this function is only called in the main thread.
5256 DCHECK(parsing_on_main_thread_);
5257 Isolate* isolate = info->isolate();
5258 pre_parse_timer_ = isolate->counters()->pre_parse();
5259 if (FLAG_trace_parse || allow_natives() || extension_ != NULL) {
5260 // If intrinsics are allowed, the Parser cannot operate independent of the
5261 // V8 heap because of Runtime. Tell the string table to internalize strings
5262 // and values right after they're created.
5263 ast_value_factory()->Internalize(isolate);
5264 }
5265
5266 if (info->is_lazy()) {
5267 DCHECK(!info->is_eval());
5268 if (info->shared_info()->is_function()) {
5269 result = ParseLazy(isolate, info);
5270 } else {
5271 result = ParseProgram(isolate, info);
5272 }
5273 } else {
5274 SetCachedData(info);
5275 result = ParseProgram(isolate, info);
5276 }
5277 info->set_literal(result);
5278
5279 Internalize(isolate, info->script(), result == NULL);
5280 DCHECK(ast_value_factory()->IsInternalized());
5281 return (result != NULL);
5282}
5283
5284
5285void Parser::ParseOnBackground(ParseInfo* info) {
5286 parsing_on_main_thread_ = false;
5287
5288 DCHECK(info->literal() == NULL);
5289 FunctionLiteral* result = NULL;
5290 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
5291
5292 CompleteParserRecorder recorder;
5293 if (produce_cached_parse_data()) log_ = &recorder;
5294
5295 DCHECK(info->source_stream() != NULL);
5296 ExternalStreamingStream stream(info->source_stream(),
5297 info->source_stream_encoding());
5298 scanner_.Initialize(&stream);
5299 DCHECK(info->context().is_null() || info->context()->IsNativeContext());
5300
5301 // When streaming, we don't know the length of the source until we have parsed
5302 // it. The raw data can be UTF-8, so we wouldn't know the source length until
5303 // we have decoded it anyway even if we knew the raw data length (which we
5304 // don't). We work around this by storing all the scopes which need their end
5305 // position set at the end of the script (the top scope and possible eval
5306 // scopes) and set their end position after we know the script length.
5307 result = DoParseProgram(info);
5308
5309 info->set_literal(result);
5310
5311 // We cannot internalize on a background thread; a foreground task will take
5312 // care of calling Parser::Internalize just before compilation.
5313
5314 if (produce_cached_parse_data()) {
5315 if (result != NULL) *info->cached_data() = recorder.GetScriptData();
5316 log_ = NULL;
5317 }
5318}
5319
5320
5321ParserTraits::TemplateLiteralState Parser::OpenTemplateLiteral(int pos) {
5322 return new (zone()) ParserTraits::TemplateLiteral(zone(), pos);
5323}
5324
5325
5326void Parser::AddTemplateSpan(TemplateLiteralState* state, bool tail) {
5327 int pos = scanner()->location().beg_pos;
5328 int end = scanner()->location().end_pos - (tail ? 1 : 2);
5329 const AstRawString* tv = scanner()->CurrentSymbol(ast_value_factory());
5330 const AstRawString* trv = scanner()->CurrentRawSymbol(ast_value_factory());
5331 Literal* cooked = factory()->NewStringLiteral(tv, pos);
5332 Literal* raw = factory()->NewStringLiteral(trv, pos);
5333 (*state)->AddTemplateSpan(cooked, raw, end, zone());
5334}
5335
5336
5337void Parser::AddTemplateExpression(TemplateLiteralState* state,
5338 Expression* expression) {
5339 (*state)->AddExpression(expression, zone());
5340}
5341
5342
5343Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start,
5344 Expression* tag) {
5345 TemplateLiteral* lit = *state;
5346 int pos = lit->position();
5347 const ZoneList<Expression*>* cooked_strings = lit->cooked();
5348 const ZoneList<Expression*>* raw_strings = lit->raw();
5349 const ZoneList<Expression*>* expressions = lit->expressions();
5350 DCHECK_EQ(cooked_strings->length(), raw_strings->length());
5351 DCHECK_EQ(cooked_strings->length(), expressions->length() + 1);
5352
5353 if (!tag) {
5354 // Build tree of BinaryOps to simplify code-generation
5355 Expression* expr = cooked_strings->at(0);
5356 int i = 0;
5357 while (i < expressions->length()) {
5358 Expression* sub = expressions->at(i++);
5359 Expression* cooked_str = cooked_strings->at(i);
5360
5361 // Let middle be ToString(sub).
5362 ZoneList<Expression*>* args =
5363 new (zone()) ZoneList<Expression*>(1, zone());
5364 args->Add(sub, zone());
5365 Expression* middle = factory()->NewCallRuntime(Runtime::kInlineToString,
5366 args, sub->position());
5367
5368 expr = factory()->NewBinaryOperation(
5369 Token::ADD, factory()->NewBinaryOperation(
5370 Token::ADD, expr, middle, expr->position()),
5371 cooked_str, sub->position());
5372 }
5373 return expr;
5374 } else {
5375 uint32_t hash = ComputeTemplateLiteralHash(lit);
5376
5377 int cooked_idx = function_state_->NextMaterializedLiteralIndex();
5378 int raw_idx = function_state_->NextMaterializedLiteralIndex();
5379
5380 // $getTemplateCallSite
5381 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(4, zone());
5382 args->Add(factory()->NewArrayLiteral(
5383 const_cast<ZoneList<Expression*>*>(cooked_strings),
Ben Murdochda12d292016-06-02 14:46:10 +01005384 cooked_idx, pos),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005385 zone());
5386 args->Add(
5387 factory()->NewArrayLiteral(
Ben Murdochda12d292016-06-02 14:46:10 +01005388 const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx, pos),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005389 zone());
5390
5391 // Ensure hash is suitable as a Smi value
5392 Smi* hash_obj = Smi::cast(Internals::IntToSmi(static_cast<int>(hash)));
5393 args->Add(factory()->NewSmiLiteral(hash_obj->value(), pos), zone());
5394
5395 Expression* call_site = factory()->NewCallRuntime(
5396 Context::GET_TEMPLATE_CALL_SITE_INDEX, args, start);
5397
5398 // Call TagFn
5399 ZoneList<Expression*>* call_args =
5400 new (zone()) ZoneList<Expression*>(expressions->length() + 1, zone());
5401 call_args->Add(call_site, zone());
5402 call_args->AddAll(*expressions, zone());
5403 return factory()->NewCall(tag, call_args, pos);
5404 }
5405}
5406
5407
5408uint32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) {
5409 const ZoneList<Expression*>* raw_strings = lit->raw();
5410 int total = raw_strings->length();
5411 DCHECK(total);
5412
5413 uint32_t running_hash = 0;
5414
5415 for (int index = 0; index < total; ++index) {
5416 if (index) {
5417 running_hash = StringHasher::ComputeRunningHashOneByte(
5418 running_hash, "${}", 3);
5419 }
5420
5421 const AstRawString* raw_string =
5422 raw_strings->at(index)->AsLiteral()->raw_value()->AsString();
5423 if (raw_string->is_one_byte()) {
5424 const char* data = reinterpret_cast<const char*>(raw_string->raw_data());
5425 running_hash = StringHasher::ComputeRunningHashOneByte(
5426 running_hash, data, raw_string->length());
5427 } else {
5428 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data());
5429 running_hash = StringHasher::ComputeRunningHash(running_hash, data,
5430 raw_string->length());
5431 }
5432 }
5433
5434 return running_hash;
5435}
5436
5437
5438ZoneList<v8::internal::Expression*>* Parser::PrepareSpreadArguments(
5439 ZoneList<v8::internal::Expression*>* list) {
5440 ZoneList<v8::internal::Expression*>* args =
5441 new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
5442 if (list->length() == 1) {
5443 // Spread-call with single spread argument produces an InternalArray
5444 // containing the values from the array.
5445 //
5446 // Function is called or constructed with the produced array of arguments
5447 //
5448 // EG: Apply(Func, Spread(spread0))
5449 ZoneList<Expression*>* spread_list =
5450 new (zone()) ZoneList<Expression*>(0, zone());
5451 spread_list->Add(list->at(0)->AsSpread()->expression(), zone());
5452 args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX,
5453 spread_list, RelocInfo::kNoPosition),
5454 zone());
5455 return args;
5456 } else {
5457 // Spread-call with multiple arguments produces array literals for each
5458 // sequences of unspread arguments, and converts each spread iterable to
5459 // an Internal array. Finally, all of these produced arrays are flattened
5460 // into a single InternalArray, containing the arguments for the call.
5461 //
5462 // EG: Apply(Func, Flatten([unspread0, unspread1], Spread(spread0),
5463 // Spread(spread1), [unspread2, unspread3]))
5464 int i = 0;
5465 int n = list->length();
5466 while (i < n) {
5467 if (!list->at(i)->IsSpread()) {
5468 ZoneList<v8::internal::Expression*>* unspread =
5469 new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
5470
5471 // Push array of unspread parameters
5472 while (i < n && !list->at(i)->IsSpread()) {
5473 unspread->Add(list->at(i++), zone());
5474 }
5475 int literal_index = function_state_->NextMaterializedLiteralIndex();
5476 args->Add(factory()->NewArrayLiteral(unspread, literal_index,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005477 RelocInfo::kNoPosition),
5478 zone());
5479
5480 if (i == n) break;
5481 }
5482
5483 // Push eagerly spread argument
5484 ZoneList<v8::internal::Expression*>* spread_list =
5485 new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
5486 spread_list->Add(list->at(i++)->AsSpread()->expression(), zone());
5487 args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX,
5488 spread_list, RelocInfo::kNoPosition),
5489 zone());
5490 }
5491
5492 list = new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
5493 list->Add(factory()->NewCallRuntime(Context::SPREAD_ARGUMENTS_INDEX, args,
5494 RelocInfo::kNoPosition),
5495 zone());
5496 return list;
5497 }
5498 UNREACHABLE();
5499}
5500
5501
5502Expression* Parser::SpreadCall(Expression* function,
5503 ZoneList<v8::internal::Expression*>* args,
5504 int pos) {
5505 if (function->IsSuperCallReference()) {
5506 // Super calls
5507 // $super_constructor = %_GetSuperConstructor(<this-function>)
5508 // %reflect_construct($super_constructor, args, new.target)
5509 ZoneList<Expression*>* tmp = new (zone()) ZoneList<Expression*>(1, zone());
5510 tmp->Add(function->AsSuperCallReference()->this_function_var(), zone());
5511 Expression* super_constructor = factory()->NewCallRuntime(
5512 Runtime::kInlineGetSuperConstructor, tmp, pos);
5513 args->InsertAt(0, super_constructor, zone());
5514 args->Add(function->AsSuperCallReference()->new_target_var(), zone());
5515 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args,
5516 pos);
5517 } else {
5518 if (function->IsProperty()) {
5519 // Method calls
5520 if (function->AsProperty()->IsSuperAccess()) {
5521 Expression* home =
5522 ThisExpression(scope_, factory(), RelocInfo::kNoPosition);
5523 args->InsertAt(0, function, zone());
5524 args->InsertAt(1, home, zone());
5525 } else {
5526 Variable* temp =
5527 scope_->NewTemporary(ast_value_factory()->empty_string());
5528 VariableProxy* obj = factory()->NewVariableProxy(temp);
5529 Assignment* assign_obj = factory()->NewAssignment(
5530 Token::ASSIGN, obj, function->AsProperty()->obj(),
5531 RelocInfo::kNoPosition);
5532 function = factory()->NewProperty(
5533 assign_obj, function->AsProperty()->key(), RelocInfo::kNoPosition);
5534 args->InsertAt(0, function, zone());
5535 obj = factory()->NewVariableProxy(temp);
5536 args->InsertAt(1, obj, zone());
5537 }
5538 } else {
5539 // Non-method calls
5540 args->InsertAt(0, function, zone());
5541 args->InsertAt(1, factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
5542 zone());
5543 }
5544 return factory()->NewCallRuntime(Context::REFLECT_APPLY_INDEX, args, pos);
5545 }
5546}
5547
5548
5549Expression* Parser::SpreadCallNew(Expression* function,
5550 ZoneList<v8::internal::Expression*>* args,
5551 int pos) {
5552 args->InsertAt(0, function, zone());
5553
5554 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos);
5555}
5556
5557
5558void Parser::SetLanguageMode(Scope* scope, LanguageMode mode) {
5559 v8::Isolate::UseCounterFeature feature;
5560 if (is_sloppy(mode))
5561 feature = v8::Isolate::kSloppyMode;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005562 else if (is_strict(mode))
5563 feature = v8::Isolate::kStrictMode;
5564 else
5565 UNREACHABLE();
5566 ++use_counts_[feature];
5567 scope->SetLanguageMode(mode);
5568}
5569
5570
5571void Parser::RaiseLanguageMode(LanguageMode mode) {
Ben Murdochda12d292016-06-02 14:46:10 +01005572 LanguageMode old = scope_->language_mode();
5573 SetLanguageMode(scope_, old > mode ? old : mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005574}
5575
Ben Murdochc5610432016-08-08 18:44:38 +01005576void Parser::MarkCollectedTailCallExpressions() {
5577 const ZoneList<Expression*>& tail_call_expressions =
5578 function_state_->tail_call_expressions().expressions();
5579 for (int i = 0; i < tail_call_expressions.length(); ++i) {
5580 Expression* expression = tail_call_expressions[i];
5581 // If only FLAG_harmony_explicit_tailcalls is enabled then expression
5582 // must be a Call expression.
5583 DCHECK(FLAG_harmony_tailcalls || !FLAG_harmony_explicit_tailcalls ||
5584 expression->IsCall());
5585 MarkTailPosition(expression);
5586 }
5587}
5588
5589Expression* ParserTraits::ExpressionListToExpression(
5590 ZoneList<Expression*>* args) {
5591 AstNodeFactory* factory = parser_->factory();
5592 Expression* expr = args->at(0);
5593 for (int i = 1; i < args->length(); ++i) {
5594 expr = factory->NewBinaryOperation(Token::COMMA, expr, args->at(i),
5595 expr->position());
5596 }
5597 return expr;
5598}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005599
5600void ParserTraits::RewriteDestructuringAssignments() {
5601 parser_->RewriteDestructuringAssignments();
5602}
5603
Ben Murdochda12d292016-06-02 14:46:10 +01005604Expression* ParserTraits::RewriteExponentiation(Expression* left,
5605 Expression* right, int pos) {
5606 return parser_->RewriteExponentiation(left, right, pos);
5607}
5608
5609Expression* ParserTraits::RewriteAssignExponentiation(Expression* left,
5610 Expression* right,
5611 int pos) {
5612 return parser_->RewriteAssignExponentiation(left, right, pos);
5613}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005614
Ben Murdoch097c5b22016-05-18 11:27:45 +01005615void ParserTraits::RewriteNonPattern(Type::ExpressionClassifier* classifier,
5616 bool* ok) {
5617 parser_->RewriteNonPattern(classifier, ok);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005618}
5619
Ben Murdoch61f157c2016-09-16 13:49:30 +01005620Expression* ParserTraits::RewriteAwaitExpression(Expression* value,
5621 int await_pos) {
Ben Murdochc5610432016-08-08 18:44:38 +01005622 // yield %AsyncFunctionAwait(.generator_object, <operand>)
5623 Variable* generator_object_variable =
5624 parser_->function_state_->generator_object_variable();
5625
5626 // If generator_object_variable is null,
5627 if (!generator_object_variable) return value;
5628
Ben Murdoch61f157c2016-09-16 13:49:30 +01005629 auto factory = parser_->factory();
5630 const int nopos = RelocInfo::kNoPosition;
5631
5632 Variable* temp_var = parser_->scope_->NewTemporary(
5633 parser_->ast_value_factory()->empty_string());
5634 VariableProxy* temp_proxy = factory->NewVariableProxy(temp_var);
5635 Block* do_block = factory->NewBlock(nullptr, 2, false, nopos);
5636
5637 // Wrap value evaluation to provide a break location.
5638 Expression* value_assignment =
5639 factory->NewAssignment(Token::ASSIGN, temp_proxy, value, nopos);
5640 do_block->statements()->Add(
5641 factory->NewExpressionStatement(value_assignment, value->position()),
5642 zone());
Ben Murdochc5610432016-08-08 18:44:38 +01005643
5644 ZoneList<Expression*>* async_function_await_args =
5645 new (zone()) ZoneList<Expression*>(2, zone());
Ben Murdoch61f157c2016-09-16 13:49:30 +01005646 Expression* generator_object =
5647 factory->NewVariableProxy(generator_object_variable);
Ben Murdochc5610432016-08-08 18:44:38 +01005648 async_function_await_args->Add(generator_object, zone());
Ben Murdoch61f157c2016-09-16 13:49:30 +01005649 async_function_await_args->Add(temp_proxy, zone());
Ben Murdochc5610432016-08-08 18:44:38 +01005650 Expression* async_function_await = parser_->factory()->NewCallRuntime(
Ben Murdoch61f157c2016-09-16 13:49:30 +01005651 Context::ASYNC_FUNCTION_AWAIT_INDEX, async_function_await_args, nopos);
5652 // Wrap await to provide a break location between value evaluation and yield.
5653 Expression* await_assignment = factory->NewAssignment(
5654 Token::ASSIGN, temp_proxy, async_function_await, nopos);
5655 do_block->statements()->Add(
5656 factory->NewExpressionStatement(await_assignment, await_pos), zone());
5657 Expression* do_expr = factory->NewDoExpression(do_block, temp_var, nopos);
Ben Murdochc5610432016-08-08 18:44:38 +01005658
Ben Murdoch61f157c2016-09-16 13:49:30 +01005659 generator_object = factory->NewVariableProxy(generator_object_variable);
5660 return factory->NewYield(generator_object, do_expr, nopos);
Ben Murdochc5610432016-08-08 18:44:38 +01005661}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005662
Ben Murdoch097c5b22016-05-18 11:27:45 +01005663ZoneList<Expression*>* ParserTraits::GetNonPatternList() const {
5664 return parser_->function_state_->non_patterns_to_rewrite();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005665}
5666
5667
Ben Murdoch61f157c2016-09-16 13:49:30 +01005668ZoneList<typename ParserTraits::Type::ExpressionClassifier::Error>*
5669ParserTraits::GetReportedErrorList() const {
5670 return parser_->function_state_->GetReportedErrorList();
5671}
5672
5673
5674Zone* ParserTraits::zone() const {
5675 return parser_->function_state_->scope()->zone();
5676}
5677
5678
Ben Murdoch097c5b22016-05-18 11:27:45 +01005679class NonPatternRewriter : public AstExpressionRewriter {
5680 public:
5681 NonPatternRewriter(uintptr_t stack_limit, Parser* parser)
5682 : AstExpressionRewriter(stack_limit), parser_(parser) {}
5683 ~NonPatternRewriter() override {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005684
Ben Murdoch097c5b22016-05-18 11:27:45 +01005685 private:
5686 bool RewriteExpression(Expression* expr) override {
5687 if (expr->IsRewritableExpression()) return true;
5688 // Rewrite only what could have been a pattern but is not.
5689 if (expr->IsArrayLiteral()) {
5690 // Spread rewriting in array literals.
5691 ArrayLiteral* lit = expr->AsArrayLiteral();
5692 VisitExpressions(lit->values());
5693 replacement_ = parser_->RewriteSpreads(lit);
5694 return false;
5695 }
5696 if (expr->IsObjectLiteral()) {
5697 return true;
5698 }
5699 if (expr->IsBinaryOperation() &&
5700 expr->AsBinaryOperation()->op() == Token::COMMA) {
5701 return true;
5702 }
5703 // Everything else does not need rewriting.
5704 return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005705 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01005706
5707 void VisitObjectLiteralProperty(ObjectLiteralProperty* property) override {
5708 if (property == nullptr) return;
5709 // Do not rewrite (computed) key expressions
5710 AST_REWRITE_PROPERTY(Expression, property, value);
5711 }
5712
5713 Parser* parser_;
5714};
5715
5716
5717void Parser::RewriteNonPattern(ExpressionClassifier* classifier, bool* ok) {
5718 ValidateExpression(classifier, ok);
5719 if (!*ok) return;
5720 auto non_patterns_to_rewrite = function_state_->non_patterns_to_rewrite();
5721 int begin = classifier->GetNonPatternBegin();
5722 int end = non_patterns_to_rewrite->length();
5723 if (begin < end) {
5724 NonPatternRewriter rewriter(stack_limit_, this);
5725 for (int i = begin; i < end; i++) {
5726 DCHECK(non_patterns_to_rewrite->at(i)->IsRewritableExpression());
5727 rewriter.Rewrite(non_patterns_to_rewrite->at(i));
5728 }
5729 non_patterns_to_rewrite->Rewind(begin);
5730 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005731}
5732
5733
5734void Parser::RewriteDestructuringAssignments() {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005735 const auto& assignments =
5736 function_state_->destructuring_assignments_to_rewrite();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005737 for (int i = assignments.length() - 1; i >= 0; --i) {
5738 // Rewrite list in reverse, so that nested assignment patterns are rewritten
5739 // correctly.
Ben Murdoch097c5b22016-05-18 11:27:45 +01005740 const DestructuringAssignment& pair = assignments.at(i);
5741 RewritableExpression* to_rewrite =
5742 pair.assignment->AsRewritableExpression();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005743 DCHECK_NOT_NULL(to_rewrite);
5744 if (!to_rewrite->is_rewritten()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005745 PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite,
5746 pair.scope);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005747 }
5748 }
5749}
5750
Ben Murdochda12d292016-06-02 14:46:10 +01005751Expression* Parser::RewriteExponentiation(Expression* left, Expression* right,
5752 int pos) {
5753 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
5754 args->Add(left, zone());
5755 args->Add(right, zone());
5756 return factory()->NewCallRuntime(Context::MATH_POW_METHOD_INDEX, args, pos);
5757}
5758
5759Expression* Parser::RewriteAssignExponentiation(Expression* left,
5760 Expression* right, int pos) {
5761 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
5762 if (left->IsVariableProxy()) {
5763 VariableProxy* lhs = left->AsVariableProxy();
5764
5765 Expression* result;
5766 DCHECK_NOT_NULL(lhs->raw_name());
5767 result =
5768 this->ExpressionFromIdentifier(lhs->raw_name(), lhs->position(),
5769 lhs->end_position(), scope_, factory());
5770 args->Add(left, zone());
5771 args->Add(right, zone());
5772 Expression* call =
5773 factory()->NewCallRuntime(Context::MATH_POW_METHOD_INDEX, args, pos);
5774 return factory()->NewAssignment(Token::ASSIGN, result, call, pos);
5775 } else if (left->IsProperty()) {
5776 Property* prop = left->AsProperty();
5777 auto temp_obj = scope_->NewTemporary(ast_value_factory()->empty_string());
5778 auto temp_key = scope_->NewTemporary(ast_value_factory()->empty_string());
5779 Expression* assign_obj = factory()->NewAssignment(
5780 Token::ASSIGN, factory()->NewVariableProxy(temp_obj), prop->obj(),
5781 RelocInfo::kNoPosition);
5782 Expression* assign_key = factory()->NewAssignment(
5783 Token::ASSIGN, factory()->NewVariableProxy(temp_key), prop->key(),
5784 RelocInfo::kNoPosition);
5785 args->Add(factory()->NewProperty(factory()->NewVariableProxy(temp_obj),
5786 factory()->NewVariableProxy(temp_key),
5787 left->position()),
5788 zone());
5789 args->Add(right, zone());
5790 Expression* call =
5791 factory()->NewCallRuntime(Context::MATH_POW_METHOD_INDEX, args, pos);
5792 Expression* target = factory()->NewProperty(
5793 factory()->NewVariableProxy(temp_obj),
5794 factory()->NewVariableProxy(temp_key), RelocInfo::kNoPosition);
5795 Expression* assign =
5796 factory()->NewAssignment(Token::ASSIGN, target, call, pos);
5797 return factory()->NewBinaryOperation(
5798 Token::COMMA, assign_obj,
5799 factory()->NewBinaryOperation(Token::COMMA, assign_key, assign, pos),
5800 pos);
5801 }
5802 UNREACHABLE();
5803 return nullptr;
5804}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005805
Ben Murdoch097c5b22016-05-18 11:27:45 +01005806Expression* Parser::RewriteSpreads(ArrayLiteral* lit) {
5807 // Array literals containing spreads are rewritten using do expressions, e.g.
5808 // [1, 2, 3, ...x, 4, ...y, 5]
5809 // is roughly rewritten as:
5810 // do {
5811 // $R = [1, 2, 3];
5812 // for ($i of x) %AppendElement($R, $i);
5813 // %AppendElement($R, 4);
5814 // for ($j of y) %AppendElement($R, $j);
5815 // %AppendElement($R, 5);
5816 // $R
5817 // }
5818 // where $R, $i and $j are fresh temporary variables.
5819 ZoneList<Expression*>::iterator s = lit->FirstSpread();
5820 if (s == lit->EndValue()) return nullptr; // no spread, no rewriting...
5821 Variable* result =
5822 scope_->NewTemporary(ast_value_factory()->dot_result_string());
5823 // NOTE: The value assigned to R is the whole original array literal,
5824 // spreads included. This will be fixed before the rewritten AST is returned.
5825 // $R = lit
5826 Expression* init_result =
5827 factory()->NewAssignment(Token::INIT, factory()->NewVariableProxy(result),
5828 lit, RelocInfo::kNoPosition);
5829 Block* do_block =
5830 factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition);
5831 do_block->statements()->Add(
5832 factory()->NewExpressionStatement(init_result, RelocInfo::kNoPosition),
5833 zone());
5834 // Traverse the array literal starting from the first spread.
5835 while (s != lit->EndValue()) {
5836 Expression* value = *s++;
5837 Spread* spread = value->AsSpread();
5838 if (spread == nullptr) {
5839 // If the element is not a spread, we're adding a single:
5840 // %AppendElement($R, value)
5841 ZoneList<Expression*>* append_element_args = NewExpressionList(2, zone());
5842 append_element_args->Add(factory()->NewVariableProxy(result), zone());
5843 append_element_args->Add(value, zone());
5844 do_block->statements()->Add(
5845 factory()->NewExpressionStatement(
5846 factory()->NewCallRuntime(Runtime::kAppendElement,
5847 append_element_args,
5848 RelocInfo::kNoPosition),
5849 RelocInfo::kNoPosition),
5850 zone());
5851 } else {
5852 // If it's a spread, we're adding a for/of loop iterating through it.
5853 Variable* each =
5854 scope_->NewTemporary(ast_value_factory()->dot_for_string());
5855 Expression* subject = spread->expression();
Ben Murdoch097c5b22016-05-18 11:27:45 +01005856 // %AppendElement($R, each)
5857 Statement* append_body;
5858 {
5859 ZoneList<Expression*>* append_element_args =
5860 NewExpressionList(2, zone());
5861 append_element_args->Add(factory()->NewVariableProxy(result), zone());
5862 append_element_args->Add(factory()->NewVariableProxy(each), zone());
5863 append_body = factory()->NewExpressionStatement(
5864 factory()->NewCallRuntime(Runtime::kAppendElement,
5865 append_element_args,
5866 RelocInfo::kNoPosition),
5867 RelocInfo::kNoPosition);
5868 }
5869 // for (each of spread) %AppendElement($R, each)
5870 ForEachStatement* loop = factory()->NewForEachStatement(
5871 ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition);
Ben Murdochda12d292016-06-02 14:46:10 +01005872 InitializeForOfStatement(loop->AsForOfStatement(),
5873 factory()->NewVariableProxy(each), subject,
Ben Murdochc5610432016-08-08 18:44:38 +01005874 append_body);
Ben Murdochda12d292016-06-02 14:46:10 +01005875 do_block->statements()->Add(loop, zone());
Ben Murdoch097c5b22016-05-18 11:27:45 +01005876 }
5877 }
5878 // Now, rewind the original array literal to truncate everything from the
5879 // first spread (included) until the end. This fixes $R's initialization.
5880 lit->RewindSpreads();
5881 return factory()->NewDoExpression(do_block, result, lit->position());
5882}
5883
5884
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005885void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005886 DCHECK(expr->IsRewritableExpression());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005887 parser_->function_state_->AddDestructuringAssignment(
5888 Parser::DestructuringAssignment(expr, parser_->scope_));
5889}
5890
5891
Ben Murdoch61f157c2016-09-16 13:49:30 +01005892void ParserTraits::QueueNonPatternForRewriting(Expression* expr, bool* ok) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005893 DCHECK(expr->IsRewritableExpression());
Ben Murdoch61f157c2016-09-16 13:49:30 +01005894 parser_->function_state_->AddNonPatternForRewriting(expr, ok);
Ben Murdoch097c5b22016-05-18 11:27:45 +01005895}
5896
5897
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005898void ParserTraits::SetFunctionNameFromPropertyName(
5899 ObjectLiteralProperty* property, const AstRawString* name) {
5900 Expression* value = property->value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005901
Ben Murdoch097c5b22016-05-18 11:27:45 +01005902 // Computed name setting must happen at runtime.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005903 if (property->is_computed_name()) return;
Ben Murdoch097c5b22016-05-18 11:27:45 +01005904
5905 // Getter and setter names are handled here because their names
5906 // change in ES2015, even though they are not anonymous.
5907 auto function = value->AsFunctionLiteral();
5908 if (function != nullptr) {
5909 bool is_getter = property->kind() == ObjectLiteralProperty::GETTER;
5910 bool is_setter = property->kind() == ObjectLiteralProperty::SETTER;
5911 if (is_getter || is_setter) {
5912 DCHECK_NOT_NULL(name);
5913 const AstRawString* prefix =
5914 is_getter ? parser_->ast_value_factory()->get_space_string()
5915 : parser_->ast_value_factory()->set_space_string();
5916 function->set_raw_name(
5917 parser_->ast_value_factory()->NewConsString(prefix, name));
5918 return;
5919 }
5920 }
5921
5922 if (!value->IsAnonymousFunctionDefinition()) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005923 DCHECK_NOT_NULL(name);
5924
5925 // Ignore "__proto__" as a name when it's being used to set the [[Prototype]]
5926 // of an object literal.
5927 if (property->kind() == ObjectLiteralProperty::PROTOTYPE) return;
5928
Ben Murdoch097c5b22016-05-18 11:27:45 +01005929 if (function != nullptr) {
5930 function->set_raw_name(name);
5931 DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005932 } else {
5933 DCHECK(value->IsClassLiteral());
5934 DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind());
Ben Murdoch097c5b22016-05-18 11:27:45 +01005935 value->AsClassLiteral()->constructor()->set_raw_name(name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005936 }
5937}
5938
5939
5940void ParserTraits::SetFunctionNameFromIdentifierRef(Expression* value,
5941 Expression* identifier) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005942 if (!value->IsAnonymousFunctionDefinition()) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005943 if (!identifier->IsVariableProxy()) return;
5944
5945 auto name = identifier->AsVariableProxy()->raw_name();
5946 DCHECK_NOT_NULL(name);
5947
Ben Murdoch097c5b22016-05-18 11:27:45 +01005948 auto function = value->AsFunctionLiteral();
5949 if (function != nullptr) {
5950 function->set_raw_name(name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005951 } else {
5952 DCHECK(value->IsClassLiteral());
Ben Murdoch097c5b22016-05-18 11:27:45 +01005953 value->AsClassLiteral()->constructor()->set_raw_name(name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005954 }
5955}
5956
5957
Ben Murdoch097c5b22016-05-18 11:27:45 +01005958// Desugaring of yield*
5959// ====================
5960//
5961// With the help of do-expressions and function.sent, we desugar yield* into a
5962// loop containing a "raw" yield (a yield that doesn't wrap an iterator result
5963// object around its argument). Concretely, "yield* iterable" turns into
5964// roughly the following code:
5965//
5966// do {
5967// const kNext = 0;
5968// const kReturn = 1;
5969// const kThrow = 2;
5970//
5971// let input = function.sent;
5972// let mode = kNext;
5973// let output = undefined;
5974//
5975// let iterator = iterable[Symbol.iterator]();
5976// if (!IS_RECEIVER(iterator)) throw MakeTypeError(kSymbolIteratorInvalid);
5977//
5978// while (true) {
5979// // From the generator to the iterator:
5980// // Forward input according to resume mode and obtain output.
5981// switch (mode) {
5982// case kNext:
5983// output = iterator.next(input);
5984// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
5985// break;
5986// case kReturn:
5987// IteratorClose(iterator, input, output); // See below.
5988// break;
5989// case kThrow:
5990// let iteratorThrow = iterator.throw;
5991// if (IS_NULL_OR_UNDEFINED(iteratorThrow)) {
5992// IteratorClose(iterator); // See below.
5993// throw MakeTypeError(kThrowMethodMissing);
5994// }
5995// output = %_Call(iteratorThrow, iterator, input);
5996// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
5997// break;
5998// }
5999// if (output.done) break;
6000//
6001// // From the generator to its user:
6002// // Forward output, receive new input, and determine resume mode.
6003// mode = kReturn;
6004// try {
6005// try {
6006// RawYield(output); // See explanation above.
6007// mode = kNext;
6008// } catch (error) {
6009// mode = kThrow;
6010// }
6011// } finally {
6012// input = function.sent;
6013// continue;
6014// }
6015// }
6016//
Ben Murdochc5610432016-08-08 18:44:38 +01006017// if (mode === kReturn) {
6018// return {value: output.value, done: true};
6019// }
6020// output.value
Ben Murdoch097c5b22016-05-18 11:27:45 +01006021// }
6022//
6023// IteratorClose(iterator) expands to the following:
6024//
6025// let iteratorReturn = iterator.return;
Ben Murdochc5610432016-08-08 18:44:38 +01006026// if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
6027// let output = %_Call(iteratorReturn, iterator);
6028// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
6029// }
Ben Murdoch097c5b22016-05-18 11:27:45 +01006030//
6031// IteratorClose(iterator, input, output) expands to the following:
6032//
6033// let iteratorReturn = iterator.return;
6034// if (IS_NULL_OR_UNDEFINED(iteratorReturn)) return input;
6035// output = %_Call(iteratorReturn, iterator, input);
6036// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
6037
Ben Murdoch097c5b22016-05-18 11:27:45 +01006038Expression* ParserTraits::RewriteYieldStar(
6039 Expression* generator, Expression* iterable, int pos) {
6040
6041 const int nopos = RelocInfo::kNoPosition;
6042
6043 auto factory = parser_->factory();
6044 auto avfactory = parser_->ast_value_factory();
6045 auto scope = parser_->scope_;
6046 auto zone = parser_->zone();
6047
6048
6049 // Forward definition for break/continue statements.
6050 WhileStatement* loop = factory->NewWhileStatement(nullptr, nopos);
6051
6052
6053 // let input = undefined;
6054 Variable* var_input = scope->NewTemporary(avfactory->empty_string());
6055 Statement* initialize_input;
6056 {
6057 Expression* input_proxy = factory->NewVariableProxy(var_input);
6058 Expression* assignment = factory->NewAssignment(
6059 Token::ASSIGN, input_proxy, factory->NewUndefinedLiteral(nopos), nopos);
6060 initialize_input = factory->NewExpressionStatement(assignment, nopos);
6061 }
6062
6063
6064 // let mode = kNext;
6065 Variable* var_mode = scope->NewTemporary(avfactory->empty_string());
6066 Statement* initialize_mode;
6067 {
6068 Expression* mode_proxy = factory->NewVariableProxy(var_mode);
Ben Murdochc5610432016-08-08 18:44:38 +01006069 Expression* knext = factory->NewSmiLiteral(JSGeneratorObject::kNext, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006070 Expression* assignment =
6071 factory->NewAssignment(Token::ASSIGN, mode_proxy, knext, nopos);
6072 initialize_mode = factory->NewExpressionStatement(assignment, nopos);
6073 }
6074
6075
6076 // let output = undefined;
6077 Variable* var_output = scope->NewTemporary(avfactory->empty_string());
6078 Statement* initialize_output;
6079 {
6080 Expression* output_proxy = factory->NewVariableProxy(var_output);
6081 Expression* assignment = factory->NewAssignment(
6082 Token::ASSIGN, output_proxy, factory->NewUndefinedLiteral(nopos),
6083 nopos);
6084 initialize_output = factory->NewExpressionStatement(assignment, nopos);
6085 }
6086
6087
6088 // let iterator = iterable[Symbol.iterator];
6089 Variable* var_iterator = scope->NewTemporary(avfactory->empty_string());
6090 Statement* get_iterator;
6091 {
6092 Expression* iterator = GetIterator(iterable, factory, nopos);
6093 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator);
6094 Expression* assignment = factory->NewAssignment(
6095 Token::ASSIGN, iterator_proxy, iterator, nopos);
6096 get_iterator = factory->NewExpressionStatement(assignment, nopos);
6097 }
6098
6099
6100 // if (!IS_RECEIVER(iterator)) throw MakeTypeError(kSymbolIteratorInvalid);
6101 Statement* validate_iterator;
6102 {
6103 Expression* is_receiver_call;
6104 {
6105 auto args = new (zone) ZoneList<Expression*>(1, zone);
6106 args->Add(factory->NewVariableProxy(var_iterator), zone);
6107 is_receiver_call =
6108 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
6109 }
6110
6111 Statement* throw_call;
6112 {
6113 Expression* call = NewThrowTypeError(
6114 MessageTemplate::kSymbolIteratorInvalid, avfactory->empty_string(),
6115 nopos);
6116 throw_call = factory->NewExpressionStatement(call, nopos);
6117 }
6118
6119 validate_iterator = factory->NewIfStatement(
6120 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
6121 }
6122
6123
6124 // output = iterator.next(input);
6125 Statement* call_next;
6126 {
6127 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator);
6128 Expression* literal =
6129 factory->NewStringLiteral(avfactory->next_string(), nopos);
6130 Expression* next_property =
6131 factory->NewProperty(iterator_proxy, literal, nopos);
6132 Expression* input_proxy = factory->NewVariableProxy(var_input);
6133 auto args = new (zone) ZoneList<Expression*>(1, zone);
6134 args->Add(input_proxy, zone);
6135 Expression* call = factory->NewCall(next_property, args, nopos);
6136 Expression* output_proxy = factory->NewVariableProxy(var_output);
6137 Expression* assignment =
6138 factory->NewAssignment(Token::ASSIGN, output_proxy, call, nopos);
6139 call_next = factory->NewExpressionStatement(assignment, nopos);
6140 }
6141
6142
6143 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
6144 Statement* validate_next_output;
6145 {
6146 Expression* is_receiver_call;
6147 {
6148 auto args = new (zone) ZoneList<Expression*>(1, zone);
6149 args->Add(factory->NewVariableProxy(var_output), zone);
6150 is_receiver_call =
6151 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
6152 }
6153
6154 Statement* throw_call;
6155 {
6156 auto args = new (zone) ZoneList<Expression*>(1, zone);
6157 args->Add(factory->NewVariableProxy(var_output), zone);
6158 Expression* call = factory->NewCallRuntime(
6159 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
6160 throw_call = factory->NewExpressionStatement(call, nopos);
6161 }
6162
6163 validate_next_output = factory->NewIfStatement(
6164 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
6165 }
6166
6167
6168 // let iteratorThrow = iterator.throw;
6169 Variable* var_throw = scope->NewTemporary(avfactory->empty_string());
6170 Statement* get_throw;
6171 {
6172 Expression* iterator_proxy = factory->NewVariableProxy(var_iterator);
6173 Expression* literal =
6174 factory->NewStringLiteral(avfactory->throw_string(), nopos);
6175 Expression* property =
6176 factory->NewProperty(iterator_proxy, literal, nopos);
6177 Expression* throw_proxy = factory->NewVariableProxy(var_throw);
6178 Expression* assignment = factory->NewAssignment(
6179 Token::ASSIGN, throw_proxy, property, nopos);
6180 get_throw = factory->NewExpressionStatement(assignment, nopos);
6181 }
6182
6183
6184 // if (IS_NULL_OR_UNDEFINED(iteratorThrow) {
6185 // IteratorClose(iterator);
6186 // throw MakeTypeError(kThrowMethodMissing);
6187 // }
6188 Statement* check_throw;
6189 {
6190 Expression* condition = factory->NewCompareOperation(
6191 Token::EQ, factory->NewVariableProxy(var_throw),
6192 factory->NewNullLiteral(nopos), nopos);
6193
6194 Expression* call = NewThrowTypeError(
6195 MessageTemplate::kThrowMethodMissing,
6196 avfactory->empty_string(), nopos);
6197 Statement* throw_call = factory->NewExpressionStatement(call, nopos);
6198
6199 Block* then = factory->NewBlock(nullptr, 4+1, false, nopos);
Ben Murdochc5610432016-08-08 18:44:38 +01006200 parser_->BuildIteratorCloseForCompletion(
6201 then->statements(), var_iterator,
6202 factory->NewSmiLiteral(Parser::kNormalCompletion, nopos));
Ben Murdoch097c5b22016-05-18 11:27:45 +01006203 then->statements()->Add(throw_call, zone);
6204 check_throw = factory->NewIfStatement(
6205 condition, then, factory->NewEmptyStatement(nopos), nopos);
6206 }
6207
6208
6209 // output = %_Call(iteratorThrow, iterator, input);
6210 Statement* call_throw;
6211 {
6212 auto args = new (zone) ZoneList<Expression*>(3, zone);
6213 args->Add(factory->NewVariableProxy(var_throw), zone);
6214 args->Add(factory->NewVariableProxy(var_iterator), zone);
6215 args->Add(factory->NewVariableProxy(var_input), zone);
6216 Expression* call =
6217 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
6218 Expression* assignment = factory->NewAssignment(
6219 Token::ASSIGN, factory->NewVariableProxy(var_output), call, nopos);
6220 call_throw = factory->NewExpressionStatement(assignment, nopos);
6221 }
6222
6223
6224 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
6225 Statement* validate_throw_output;
6226 {
6227 Expression* is_receiver_call;
6228 {
6229 auto args = new (zone) ZoneList<Expression*>(1, zone);
6230 args->Add(factory->NewVariableProxy(var_output), zone);
6231 is_receiver_call =
6232 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
6233 }
6234
6235 Statement* throw_call;
6236 {
6237 auto args = new (zone) ZoneList<Expression*>(1, zone);
6238 args->Add(factory->NewVariableProxy(var_output), zone);
6239 Expression* call = factory->NewCallRuntime(
6240 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
6241 throw_call = factory->NewExpressionStatement(call, nopos);
6242 }
6243
6244 validate_throw_output = factory->NewIfStatement(
6245 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
6246 }
6247
6248
6249 // if (output.done) break;
6250 Statement* if_done;
6251 {
6252 Expression* output_proxy = factory->NewVariableProxy(var_output);
6253 Expression* literal =
6254 factory->NewStringLiteral(avfactory->done_string(), nopos);
6255 Expression* property = factory->NewProperty(output_proxy, literal, nopos);
6256 BreakStatement* break_loop = factory->NewBreakStatement(loop, nopos);
6257 if_done = factory->NewIfStatement(
6258 property, break_loop, factory->NewEmptyStatement(nopos), nopos);
6259 }
6260
6261
6262 // mode = kReturn;
6263 Statement* set_mode_return;
6264 {
6265 Expression* mode_proxy = factory->NewVariableProxy(var_mode);
6266 Expression* kreturn =
Ben Murdochc5610432016-08-08 18:44:38 +01006267 factory->NewSmiLiteral(JSGeneratorObject::kReturn, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006268 Expression* assignment =
6269 factory->NewAssignment(Token::ASSIGN, mode_proxy, kreturn, nopos);
6270 set_mode_return = factory->NewExpressionStatement(assignment, nopos);
6271 }
6272
Ben Murdochda12d292016-06-02 14:46:10 +01006273 // Yield(output);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006274 Statement* yield_output;
6275 {
6276 Expression* output_proxy = factory->NewVariableProxy(var_output);
Ben Murdochda12d292016-06-02 14:46:10 +01006277 Yield* yield = factory->NewYield(generator, output_proxy, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006278 yield_output = factory->NewExpressionStatement(yield, nopos);
6279 }
6280
6281
6282 // mode = kNext;
6283 Statement* set_mode_next;
6284 {
6285 Expression* mode_proxy = factory->NewVariableProxy(var_mode);
Ben Murdochc5610432016-08-08 18:44:38 +01006286 Expression* knext = factory->NewSmiLiteral(JSGeneratorObject::kNext, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006287 Expression* assignment =
6288 factory->NewAssignment(Token::ASSIGN, mode_proxy, knext, nopos);
6289 set_mode_next = factory->NewExpressionStatement(assignment, nopos);
6290 }
6291
6292
6293 // mode = kThrow;
6294 Statement* set_mode_throw;
6295 {
6296 Expression* mode_proxy = factory->NewVariableProxy(var_mode);
6297 Expression* kthrow =
Ben Murdochc5610432016-08-08 18:44:38 +01006298 factory->NewSmiLiteral(JSGeneratorObject::kThrow, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006299 Expression* assignment =
6300 factory->NewAssignment(Token::ASSIGN, mode_proxy, kthrow, nopos);
6301 set_mode_throw = factory->NewExpressionStatement(assignment, nopos);
6302 }
6303
6304
6305 // input = function.sent;
6306 Statement* get_input;
6307 {
6308 Expression* function_sent = FunctionSentExpression(scope, factory, nopos);
6309 Expression* input_proxy = factory->NewVariableProxy(var_input);
6310 Expression* assignment = factory->NewAssignment(
6311 Token::ASSIGN, input_proxy, function_sent, nopos);
6312 get_input = factory->NewExpressionStatement(assignment, nopos);
6313 }
6314
6315
Ben Murdochc5610432016-08-08 18:44:38 +01006316 // if (mode === kReturn) {
6317 // return {value: output.value, done: true};
6318 // }
6319 Statement* maybe_return_value;
6320 {
6321 Expression* mode_proxy = factory->NewVariableProxy(var_mode);
6322 Expression* kreturn =
6323 factory->NewSmiLiteral(JSGeneratorObject::kReturn, nopos);
6324 Expression* condition = factory->NewCompareOperation(
6325 Token::EQ_STRICT, mode_proxy, kreturn, nopos);
6326
6327 Expression* output_proxy = factory->NewVariableProxy(var_output);
6328 Expression* literal =
6329 factory->NewStringLiteral(avfactory->value_string(), nopos);
6330 Expression* property = factory->NewProperty(output_proxy, literal, nopos);
6331 Statement* return_value =
6332 factory->NewReturnStatement(BuildIteratorResult(property, true), nopos);
6333
6334 maybe_return_value = factory->NewIfStatement(
6335 condition, return_value, factory->NewEmptyStatement(nopos), nopos);
6336 }
6337
6338
6339 // output.value
Ben Murdoch097c5b22016-05-18 11:27:45 +01006340 Statement* get_value;
6341 {
6342 Expression* output_proxy = factory->NewVariableProxy(var_output);
6343 Expression* literal =
6344 factory->NewStringLiteral(avfactory->value_string(), nopos);
6345 Expression* property = factory->NewProperty(output_proxy, literal, nopos);
6346 get_value = factory->NewExpressionStatement(property, nopos);
6347 }
6348
6349
6350 // Now put things together.
6351
6352
6353 // try { ... } catch(e) { ... }
6354 Statement* try_catch;
6355 {
6356 Block* try_block = factory->NewBlock(nullptr, 2, false, nopos);
6357 try_block->statements()->Add(yield_output, zone);
6358 try_block->statements()->Add(set_mode_next, zone);
6359
6360 Block* catch_block = factory->NewBlock(nullptr, 1, false, nopos);
6361 catch_block->statements()->Add(set_mode_throw, zone);
6362
6363 Scope* catch_scope = NewScope(scope, CATCH_SCOPE);
Ben Murdochc5610432016-08-08 18:44:38 +01006364 catch_scope->set_is_hidden();
Ben Murdoch097c5b22016-05-18 11:27:45 +01006365 const AstRawString* name = avfactory->dot_catch_string();
6366 Variable* catch_variable =
6367 catch_scope->DeclareLocal(name, VAR, kCreatedInitialized,
6368 Variable::NORMAL);
6369
6370 try_catch = factory->NewTryCatchStatement(
6371 try_block, catch_scope, catch_variable, catch_block, nopos);
6372 }
6373
6374
6375 // try { ... } finally { ... }
6376 Statement* try_finally;
6377 {
6378 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
6379 try_block->statements()->Add(try_catch, zone);
6380
6381 Block* finally = factory->NewBlock(nullptr, 2, false, nopos);
6382 finally->statements()->Add(get_input, zone);
6383 finally->statements()->Add(
6384 factory->NewContinueStatement(loop, nopos), zone);
6385
6386 try_finally = factory->NewTryFinallyStatement(try_block, finally, nopos);
6387 }
6388
6389
6390 // switch (mode) { ... }
6391 SwitchStatement* switch_mode = factory->NewSwitchStatement(nullptr, nopos);
6392 {
6393 auto case_next = new (zone) ZoneList<Statement*>(3, zone);
6394 case_next->Add(call_next, zone);
6395 case_next->Add(validate_next_output, zone);
6396 case_next->Add(factory->NewBreakStatement(switch_mode, nopos), zone);
6397
6398 auto case_return = new (zone) ZoneList<Statement*>(5, zone);
Ben Murdochc5610432016-08-08 18:44:38 +01006399 BuildIteratorClose(case_return, var_iterator, var_input, var_output);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006400 case_return->Add(factory->NewBreakStatement(switch_mode, nopos), zone);
6401
6402 auto case_throw = new (zone) ZoneList<Statement*>(5, zone);
6403 case_throw->Add(get_throw, zone);
6404 case_throw->Add(check_throw, zone);
6405 case_throw->Add(call_throw, zone);
6406 case_throw->Add(validate_throw_output, zone);
6407 case_throw->Add(factory->NewBreakStatement(switch_mode, nopos), zone);
6408
6409 auto cases = new (zone) ZoneList<CaseClause*>(3, zone);
Ben Murdochc5610432016-08-08 18:44:38 +01006410 Expression* knext = factory->NewSmiLiteral(JSGeneratorObject::kNext, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006411 Expression* kreturn =
Ben Murdochc5610432016-08-08 18:44:38 +01006412 factory->NewSmiLiteral(JSGeneratorObject::kReturn, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006413 Expression* kthrow =
Ben Murdochc5610432016-08-08 18:44:38 +01006414 factory->NewSmiLiteral(JSGeneratorObject::kThrow, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006415 cases->Add(factory->NewCaseClause(knext, case_next, nopos), zone);
6416 cases->Add(factory->NewCaseClause(kreturn, case_return, nopos), zone);
6417 cases->Add(factory->NewCaseClause(kthrow, case_throw, nopos), zone);
6418
6419 switch_mode->Initialize(factory->NewVariableProxy(var_mode), cases);
6420 }
6421
6422
6423 // while (true) { ... }
6424 // Already defined earlier: WhileStatement* loop = ...
6425 {
6426 Block* loop_body = factory->NewBlock(nullptr, 4, false, nopos);
6427 loop_body->statements()->Add(switch_mode, zone);
6428 loop_body->statements()->Add(if_done, zone);
6429 loop_body->statements()->Add(set_mode_return, zone);
6430 loop_body->statements()->Add(try_finally, zone);
6431
6432 loop->Initialize(factory->NewBooleanLiteral(true, nopos), loop_body);
6433 }
6434
6435
6436 // do { ... }
6437 DoExpression* yield_star;
6438 {
6439 // The rewriter needs to process the get_value statement only, hence we
6440 // put the preceding statements into an init block.
6441
Ben Murdochc5610432016-08-08 18:44:38 +01006442 Block* do_block_ = factory->NewBlock(nullptr, 7, true, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006443 do_block_->statements()->Add(initialize_input, zone);
6444 do_block_->statements()->Add(initialize_mode, zone);
6445 do_block_->statements()->Add(initialize_output, zone);
6446 do_block_->statements()->Add(get_iterator, zone);
6447 do_block_->statements()->Add(validate_iterator, zone);
6448 do_block_->statements()->Add(loop, zone);
Ben Murdochc5610432016-08-08 18:44:38 +01006449 do_block_->statements()->Add(maybe_return_value, zone);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006450
6451 Block* do_block = factory->NewBlock(nullptr, 2, false, nopos);
6452 do_block->statements()->Add(do_block_, zone);
6453 do_block->statements()->Add(get_value, zone);
6454
6455 Variable* dot_result = scope->NewTemporary(avfactory->dot_result_string());
6456 yield_star = factory->NewDoExpression(do_block, dot_result, nopos);
6457 Rewriter::Rewrite(parser_, yield_star, avfactory);
6458 }
6459
6460 return yield_star;
6461}
6462
Ben Murdochda12d292016-06-02 14:46:10 +01006463Statement* ParserTraits::CheckCallable(Variable* var, Expression* error,
6464 int pos) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01006465 auto factory = parser_->factory();
6466 auto avfactory = parser_->ast_value_factory();
6467 const int nopos = RelocInfo::kNoPosition;
6468 Statement* validate_var;
6469 {
6470 Expression* type_of = factory->NewUnaryOperation(
6471 Token::TYPEOF, factory->NewVariableProxy(var), nopos);
6472 Expression* function_literal =
6473 factory->NewStringLiteral(avfactory->function_string(), nopos);
6474 Expression* condition = factory->NewCompareOperation(
6475 Token::EQ_STRICT, type_of, function_literal, nopos);
6476
Ben Murdochda12d292016-06-02 14:46:10 +01006477 Statement* throw_call = factory->NewExpressionStatement(error, pos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006478
6479 validate_var = factory->NewIfStatement(
6480 condition, factory->NewEmptyStatement(nopos), throw_call, nopos);
6481 }
6482 return validate_var;
6483}
6484
6485void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements,
Ben Murdochc5610432016-08-08 18:44:38 +01006486 Variable* iterator, Variable* input,
Ben Murdoch097c5b22016-05-18 11:27:45 +01006487 Variable* var_output) {
6488 //
6489 // This function adds four statements to [statements], corresponding to the
6490 // following code:
6491 //
6492 // let iteratorReturn = iterator.return;
Ben Murdochc5610432016-08-08 18:44:38 +01006493 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) {
6494 // return {value: input, done: true};
6495 // }
6496 // output = %_Call(iteratorReturn, iterator, input);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006497 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
6498 //
6499
6500 const int nopos = RelocInfo::kNoPosition;
6501 auto factory = parser_->factory();
6502 auto avfactory = parser_->ast_value_factory();
6503 auto zone = parser_->zone();
6504
6505 // let iteratorReturn = iterator.return;
6506 Variable* var_return = var_output; // Reusing the output variable.
6507 Statement* get_return;
6508 {
6509 Expression* iterator_proxy = factory->NewVariableProxy(iterator);
6510 Expression* literal =
6511 factory->NewStringLiteral(avfactory->return_string(), nopos);
6512 Expression* property =
6513 factory->NewProperty(iterator_proxy, literal, nopos);
6514 Expression* return_proxy = factory->NewVariableProxy(var_return);
6515 Expression* assignment = factory->NewAssignment(
6516 Token::ASSIGN, return_proxy, property, nopos);
6517 get_return = factory->NewExpressionStatement(assignment, nopos);
6518 }
6519
Ben Murdochc5610432016-08-08 18:44:38 +01006520 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) {
6521 // return {value: input, done: true};
6522 // }
Ben Murdoch097c5b22016-05-18 11:27:45 +01006523 Statement* check_return;
6524 {
6525 Expression* condition = factory->NewCompareOperation(
6526 Token::EQ, factory->NewVariableProxy(var_return),
6527 factory->NewNullLiteral(nopos), nopos);
6528
Ben Murdochc5610432016-08-08 18:44:38 +01006529 Expression* value = factory->NewVariableProxy(input);
Ben Murdochda12d292016-06-02 14:46:10 +01006530
Ben Murdochc5610432016-08-08 18:44:38 +01006531 Statement* return_input =
6532 factory->NewReturnStatement(BuildIteratorResult(value, true), nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006533
6534 check_return = factory->NewIfStatement(
6535 condition, return_input, factory->NewEmptyStatement(nopos), nopos);
6536 }
6537
Ben Murdochc5610432016-08-08 18:44:38 +01006538 // output = %_Call(iteratorReturn, iterator, input);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006539 Statement* call_return;
6540 {
6541 auto args = new (zone) ZoneList<Expression*>(3, zone);
6542 args->Add(factory->NewVariableProxy(var_return), zone);
6543 args->Add(factory->NewVariableProxy(iterator), zone);
Ben Murdochc5610432016-08-08 18:44:38 +01006544 args->Add(factory->NewVariableProxy(input), zone);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006545
6546 Expression* call =
6547 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
6548 Expression* output_proxy = factory->NewVariableProxy(var_output);
6549 Expression* assignment = factory->NewAssignment(
6550 Token::ASSIGN, output_proxy, call, nopos);
6551 call_return = factory->NewExpressionStatement(assignment, nopos);
6552 }
6553
6554 // if (!IS_RECEIVER(output)) %ThrowIteratorResultNotAnObject(output);
6555 Statement* validate_output;
6556 {
6557 Expression* is_receiver_call;
6558 {
6559 auto args = new (zone) ZoneList<Expression*>(1, zone);
6560 args->Add(factory->NewVariableProxy(var_output), zone);
6561 is_receiver_call =
6562 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
6563 }
6564
6565 Statement* throw_call;
6566 {
6567 auto args = new (zone) ZoneList<Expression*>(1, zone);
6568 args->Add(factory->NewVariableProxy(var_output), zone);
6569 Expression* call = factory->NewCallRuntime(
6570 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
6571 throw_call = factory->NewExpressionStatement(call, nopos);
6572 }
6573
6574 validate_output = factory->NewIfStatement(
6575 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
6576 }
6577
6578 statements->Add(get_return, zone);
6579 statements->Add(check_return, zone);
6580 statements->Add(call_return, zone);
6581 statements->Add(validate_output, zone);
6582}
6583
Ben Murdochda12d292016-06-02 14:46:10 +01006584void ParserTraits::FinalizeIteratorUse(Variable* completion,
6585 Expression* condition, Variable* iter,
6586 Block* iterator_use, Block* target) {
Ben Murdochda12d292016-06-02 14:46:10 +01006587 //
6588 // This function adds two statements to [target], corresponding to the
6589 // following code:
6590 //
6591 // completion = kNormalCompletion;
6592 // try {
6593 // try {
6594 // iterator_use
6595 // } catch(e) {
6596 // if (completion === kAbruptCompletion) completion = kThrowCompletion;
6597 // %ReThrow(e);
6598 // }
6599 // } finally {
6600 // if (condition) {
6601 // #BuildIteratorCloseForCompletion(iter, completion)
6602 // }
6603 // }
6604 //
6605
6606 const int nopos = RelocInfo::kNoPosition;
6607 auto factory = parser_->factory();
6608 auto avfactory = parser_->ast_value_factory();
6609 auto scope = parser_->scope_;
6610 auto zone = parser_->zone();
6611
6612 // completion = kNormalCompletion;
6613 Statement* initialize_completion;
6614 {
6615 Expression* proxy = factory->NewVariableProxy(completion);
6616 Expression* assignment = factory->NewAssignment(
6617 Token::ASSIGN, proxy,
6618 factory->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
6619 initialize_completion = factory->NewExpressionStatement(assignment, nopos);
6620 }
6621
6622 // if (completion === kAbruptCompletion) completion = kThrowCompletion;
6623 Statement* set_completion_throw;
6624 {
6625 Expression* condition = factory->NewCompareOperation(
6626 Token::EQ_STRICT, factory->NewVariableProxy(completion),
6627 factory->NewSmiLiteral(Parser::kAbruptCompletion, nopos), nopos);
6628
6629 Expression* proxy = factory->NewVariableProxy(completion);
6630 Expression* assignment = factory->NewAssignment(
6631 Token::ASSIGN, proxy,
6632 factory->NewSmiLiteral(Parser::kThrowCompletion, nopos), nopos);
6633 Statement* statement = factory->NewExpressionStatement(assignment, nopos);
6634 set_completion_throw = factory->NewIfStatement(
6635 condition, statement, factory->NewEmptyStatement(nopos), nopos);
6636 }
6637
6638 // if (condition) {
6639 // #BuildIteratorCloseForCompletion(iter, completion)
6640 // }
6641 Block* maybe_close;
6642 {
6643 Block* block = factory->NewBlock(nullptr, 2, true, nopos);
Ben Murdochc5610432016-08-08 18:44:38 +01006644 Expression* proxy = factory->NewVariableProxy(completion);
6645 parser_->BuildIteratorCloseForCompletion(block->statements(), iter, proxy);
Ben Murdochda12d292016-06-02 14:46:10 +01006646 DCHECK(block->statements()->length() == 2);
6647
6648 maybe_close = factory->NewBlock(nullptr, 1, true, nopos);
6649 maybe_close->statements()->Add(
6650 factory->NewIfStatement(condition, block,
6651 factory->NewEmptyStatement(nopos), nopos),
6652 zone);
6653 }
6654
6655 // try { #try_block }
6656 // catch(e) {
6657 // #set_completion_throw;
6658 // %ReThrow(e);
6659 // }
6660 Statement* try_catch;
6661 {
6662 Scope* catch_scope = parser_->NewScope(scope, CATCH_SCOPE);
6663 Variable* catch_variable =
6664 catch_scope->DeclareLocal(avfactory->dot_catch_string(), VAR,
6665 kCreatedInitialized, Variable::NORMAL);
Ben Murdochc5610432016-08-08 18:44:38 +01006666 catch_scope->set_is_hidden();
Ben Murdochda12d292016-06-02 14:46:10 +01006667
6668 Statement* rethrow;
6669 // We use %ReThrow rather than the ordinary throw because we want to
6670 // preserve the original exception message. This is also why we create a
6671 // TryCatchStatementForReThrow below (which does not clear the pending
6672 // message), rather than a TryCatchStatement.
6673 {
6674 auto args = new (zone) ZoneList<Expression*>(1, zone);
6675 args->Add(factory->NewVariableProxy(catch_variable), zone);
6676 rethrow = factory->NewExpressionStatement(
6677 factory->NewCallRuntime(Runtime::kReThrow, args, nopos), nopos);
6678 }
6679
6680 Block* catch_block = factory->NewBlock(nullptr, 2, false, nopos);
6681 catch_block->statements()->Add(set_completion_throw, zone);
6682 catch_block->statements()->Add(rethrow, zone);
6683
6684 try_catch = factory->NewTryCatchStatementForReThrow(
6685 iterator_use, catch_scope, catch_variable, catch_block, nopos);
6686 }
6687
6688 // try { #try_catch } finally { #maybe_close }
6689 Statement* try_finally;
6690 {
6691 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
6692 try_block->statements()->Add(try_catch, zone);
6693
6694 try_finally =
6695 factory->NewTryFinallyStatement(try_block, maybe_close, nopos);
6696 }
6697
6698 target->statements()->Add(initialize_completion, zone);
6699 target->statements()->Add(try_finally, zone);
6700}
Ben Murdoch097c5b22016-05-18 11:27:45 +01006701
6702void ParserTraits::BuildIteratorCloseForCompletion(
6703 ZoneList<Statement*>* statements, Variable* iterator,
Ben Murdochc5610432016-08-08 18:44:38 +01006704 Expression* completion) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01006705 //
6706 // This function adds two statements to [statements], corresponding to the
6707 // following code:
6708 //
6709 // let iteratorReturn = iterator.return;
6710 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
Ben Murdochda12d292016-06-02 14:46:10 +01006711 // if (completion === kThrowCompletion) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01006712 // if (!IS_CALLABLE(iteratorReturn)) {
6713 // throw MakeTypeError(kReturnMethodNotCallable);
6714 // }
Ben Murdochda12d292016-06-02 14:46:10 +01006715 // try { %_Call(iteratorReturn, iterator) } catch (_) { }
Ben Murdoch097c5b22016-05-18 11:27:45 +01006716 // } else {
Ben Murdochda12d292016-06-02 14:46:10 +01006717 // let output = %_Call(iteratorReturn, iterator);
6718 // if (!IS_RECEIVER(output)) {
6719 // %ThrowIterResultNotAnObject(output);
6720 // }
Ben Murdoch097c5b22016-05-18 11:27:45 +01006721 // }
Ben Murdoch097c5b22016-05-18 11:27:45 +01006722 // }
6723 //
6724
6725 const int nopos = RelocInfo::kNoPosition;
6726 auto factory = parser_->factory();
6727 auto avfactory = parser_->ast_value_factory();
6728 auto scope = parser_->scope_;
6729 auto zone = parser_->zone();
6730
Ben Murdoch097c5b22016-05-18 11:27:45 +01006731
6732 // let iteratorReturn = iterator.return;
Ben Murdochda12d292016-06-02 14:46:10 +01006733 Variable* var_return = scope->NewTemporary(avfactory->empty_string());
Ben Murdoch097c5b22016-05-18 11:27:45 +01006734 Statement* get_return;
6735 {
6736 Expression* iterator_proxy = factory->NewVariableProxy(iterator);
6737 Expression* literal =
6738 factory->NewStringLiteral(avfactory->return_string(), nopos);
6739 Expression* property =
6740 factory->NewProperty(iterator_proxy, literal, nopos);
6741 Expression* return_proxy = factory->NewVariableProxy(var_return);
6742 Expression* assignment = factory->NewAssignment(
6743 Token::ASSIGN, return_proxy, property, nopos);
6744 get_return = factory->NewExpressionStatement(assignment, nopos);
6745 }
6746
6747 // if (!IS_CALLABLE(iteratorReturn)) {
6748 // throw MakeTypeError(kReturnMethodNotCallable);
6749 // }
6750 Statement* check_return_callable;
6751 {
6752 Expression* throw_expr = NewThrowTypeError(
6753 MessageTemplate::kReturnMethodNotCallable,
6754 avfactory->empty_string(), nopos);
Ben Murdochda12d292016-06-02 14:46:10 +01006755 check_return_callable = CheckCallable(var_return, throw_expr, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006756 }
6757
Ben Murdochda12d292016-06-02 14:46:10 +01006758 // try { %_Call(iteratorReturn, iterator) } catch (_) { }
Ben Murdoch097c5b22016-05-18 11:27:45 +01006759 Statement* try_call_return;
6760 {
6761 auto args = new (zone) ZoneList<Expression*>(2, zone);
6762 args->Add(factory->NewVariableProxy(var_return), zone);
6763 args->Add(factory->NewVariableProxy(iterator), zone);
6764
6765 Expression* call =
6766 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006767
6768 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
Ben Murdochda12d292016-06-02 14:46:10 +01006769 try_block->statements()->Add(factory->NewExpressionStatement(call, nopos),
6770 zone);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006771
6772 Block* catch_block = factory->NewBlock(nullptr, 0, false, nopos);
6773
6774 Scope* catch_scope = NewScope(scope, CATCH_SCOPE);
6775 Variable* catch_variable = catch_scope->DeclareLocal(
6776 avfactory->dot_catch_string(), VAR, kCreatedInitialized,
6777 Variable::NORMAL);
Ben Murdochc5610432016-08-08 18:44:38 +01006778 catch_scope->set_is_hidden();
Ben Murdoch097c5b22016-05-18 11:27:45 +01006779
6780 try_call_return = factory->NewTryCatchStatement(
6781 try_block, catch_scope, catch_variable, catch_block, nopos);
6782 }
6783
Ben Murdochda12d292016-06-02 14:46:10 +01006784 // let output = %_Call(iteratorReturn, iterator);
6785 // if (!IS_RECEIVER(output)) {
6786 // %ThrowIteratorResultNotAnObject(output);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006787 // }
Ben Murdochda12d292016-06-02 14:46:10 +01006788 Block* validate_return;
Ben Murdoch097c5b22016-05-18 11:27:45 +01006789 {
Ben Murdochda12d292016-06-02 14:46:10 +01006790 Variable* var_output = scope->NewTemporary(avfactory->empty_string());
6791 Statement* call_return;
6792 {
6793 auto args = new (zone) ZoneList<Expression*>(2, zone);
6794 args->Add(factory->NewVariableProxy(var_return), zone);
6795 args->Add(factory->NewVariableProxy(iterator), zone);
6796 Expression* call =
6797 factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006798
Ben Murdochda12d292016-06-02 14:46:10 +01006799 Expression* output_proxy = factory->NewVariableProxy(var_output);
6800 Expression* assignment =
6801 factory->NewAssignment(Token::ASSIGN, output_proxy, call, nopos);
6802 call_return = factory->NewExpressionStatement(assignment, nopos);
6803 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01006804
Ben Murdoch097c5b22016-05-18 11:27:45 +01006805 Expression* is_receiver_call;
6806 {
6807 auto args = new (zone) ZoneList<Expression*>(1, zone);
6808 args->Add(factory->NewVariableProxy(var_output), zone);
6809 is_receiver_call =
6810 factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
6811 }
6812
6813 Statement* throw_call;
6814 {
6815 auto args = new (zone) ZoneList<Expression*>(1, zone);
6816 args->Add(factory->NewVariableProxy(var_output), zone);
6817 Expression* call = factory->NewCallRuntime(
6818 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
6819 throw_call = factory->NewExpressionStatement(call, nopos);
6820 }
6821
Ben Murdochda12d292016-06-02 14:46:10 +01006822 Statement* check_return = factory->NewIfStatement(
Ben Murdoch097c5b22016-05-18 11:27:45 +01006823 is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
Ben Murdochda12d292016-06-02 14:46:10 +01006824
6825 validate_return = factory->NewBlock(nullptr, 2, false, nopos);
6826 validate_return->statements()->Add(call_return, zone);
6827 validate_return->statements()->Add(check_return, zone);
6828 }
6829
6830 // if (completion === kThrowCompletion) {
6831 // #check_return_callable;
6832 // #try_call_return;
6833 // } else {
6834 // #validate_return;
6835 // }
6836 Statement* call_return_carefully;
6837 {
6838 Expression* condition = factory->NewCompareOperation(
Ben Murdochc5610432016-08-08 18:44:38 +01006839 Token::EQ_STRICT, completion,
Ben Murdochda12d292016-06-02 14:46:10 +01006840 factory->NewSmiLiteral(Parser::kThrowCompletion, nopos), nopos);
6841
6842 Block* then_block = factory->NewBlock(nullptr, 2, false, nopos);
6843 then_block->statements()->Add(check_return_callable, zone);
6844 then_block->statements()->Add(try_call_return, zone);
6845
6846 call_return_carefully =
6847 factory->NewIfStatement(condition, then_block, validate_return, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006848 }
6849
6850 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { ... }
6851 Statement* maybe_call_return;
6852 {
6853 Expression* condition = factory->NewCompareOperation(
6854 Token::EQ, factory->NewVariableProxy(var_return),
6855 factory->NewNullLiteral(nopos), nopos);
6856
Ben Murdochda12d292016-06-02 14:46:10 +01006857 maybe_call_return =
6858 factory->NewIfStatement(condition, factory->NewEmptyStatement(nopos),
6859 call_return_carefully, nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006860 }
6861
6862
6863 statements->Add(get_return, zone);
6864 statements->Add(maybe_call_return, zone);
6865}
6866
6867
6868Statement* ParserTraits::FinalizeForOfStatement(ForOfStatement* loop, int pos) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01006869 //
6870 // This function replaces the loop with the following wrapping:
6871 //
Ben Murdochda12d292016-06-02 14:46:10 +01006872 // let each;
6873 // let completion = kNormalCompletion;
Ben Murdoch097c5b22016-05-18 11:27:45 +01006874 // try {
Ben Murdochda12d292016-06-02 14:46:10 +01006875 // try {
6876 // #loop;
6877 // } catch(e) {
6878 // if (completion === kAbruptCompletion) completion = kThrowCompletion;
6879 // %ReThrow(e);
6880 // }
Ben Murdoch097c5b22016-05-18 11:27:45 +01006881 // } finally {
Ben Murdochda12d292016-06-02 14:46:10 +01006882 // if (!(completion === kNormalCompletion || IS_UNDEFINED(#iterator))) {
6883 // #BuildIteratorCloseForCompletion(#iterator, completion)
Ben Murdoch097c5b22016-05-18 11:27:45 +01006884 // }
6885 // }
6886 //
6887 // where the loop's body is wrapped as follows:
6888 //
6889 // {
Ben Murdoch097c5b22016-05-18 11:27:45 +01006890 // #loop-body
Ben Murdochda12d292016-06-02 14:46:10 +01006891 // {{completion = kNormalCompletion;}}
Ben Murdoch097c5b22016-05-18 11:27:45 +01006892 // }
Ben Murdochda12d292016-06-02 14:46:10 +01006893 //
6894 // and the loop's assign_each is wrapped as follows
6895 //
6896 // do {
6897 // {{completion = kAbruptCompletion;}}
6898 // #assign-each
6899 // }
6900 //
Ben Murdoch097c5b22016-05-18 11:27:45 +01006901
6902 const int nopos = RelocInfo::kNoPosition;
6903 auto factory = parser_->factory();
6904 auto avfactory = parser_->ast_value_factory();
6905 auto scope = parser_->scope_;
6906 auto zone = parser_->zone();
6907
Ben Murdoch097c5b22016-05-18 11:27:45 +01006908 Variable* var_completion = scope->NewTemporary(avfactory->empty_string());
Ben Murdochda12d292016-06-02 14:46:10 +01006909
6910 // let each;
6911 Variable* var_each = scope->NewTemporary(avfactory->empty_string());
6912 Statement* initialize_each;
Ben Murdoch097c5b22016-05-18 11:27:45 +01006913 {
Ben Murdochda12d292016-06-02 14:46:10 +01006914 Expression* proxy = factory->NewVariableProxy(var_each);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006915 Expression* assignment = factory->NewAssignment(
6916 Token::ASSIGN, proxy,
Ben Murdochda12d292016-06-02 14:46:10 +01006917 factory->NewUndefinedLiteral(nopos), nopos);
6918 initialize_each =
Ben Murdoch097c5b22016-05-18 11:27:45 +01006919 factory->NewExpressionStatement(assignment, nopos);
6920 }
6921
Ben Murdochda12d292016-06-02 14:46:10 +01006922 // !(completion === kNormalCompletion || IS_UNDEFINED(#iterator))
6923 Expression* closing_condition;
Ben Murdoch097c5b22016-05-18 11:27:45 +01006924 {
Ben Murdochda12d292016-06-02 14:46:10 +01006925 Expression* lhs = factory->NewCompareOperation(
Ben Murdoch097c5b22016-05-18 11:27:45 +01006926 Token::EQ_STRICT, factory->NewVariableProxy(var_completion),
Ben Murdochda12d292016-06-02 14:46:10 +01006927 factory->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
6928 Expression* rhs = factory->NewCompareOperation(
Ben Murdoch097c5b22016-05-18 11:27:45 +01006929 Token::EQ_STRICT, factory->NewVariableProxy(loop->iterator()),
6930 factory->NewUndefinedLiteral(nopos), nopos);
Ben Murdochda12d292016-06-02 14:46:10 +01006931 closing_condition = factory->NewUnaryOperation(
6932 Token::NOT, factory->NewBinaryOperation(Token::OR, lhs, rhs, nopos),
6933 nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006934 }
6935
Ben Murdochda12d292016-06-02 14:46:10 +01006936 // {{completion = kNormalCompletion;}}
Ben Murdoch097c5b22016-05-18 11:27:45 +01006937 Statement* set_completion_normal;
6938 {
6939 Expression* proxy = factory->NewVariableProxy(var_completion);
6940 Expression* assignment = factory->NewAssignment(
Ben Murdochda12d292016-06-02 14:46:10 +01006941 Token::ASSIGN, proxy,
6942 factory->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
Ben Murdoch097c5b22016-05-18 11:27:45 +01006943
6944 Block* block = factory->NewBlock(nullptr, 1, true, nopos);
6945 block->statements()->Add(
6946 factory->NewExpressionStatement(assignment, nopos), zone);
6947 set_completion_normal = block;
6948 }
6949
Ben Murdochda12d292016-06-02 14:46:10 +01006950 // {{completion = kAbruptCompletion;}}
6951 Statement* set_completion_abrupt;
6952 {
6953 Expression* proxy = factory->NewVariableProxy(var_completion);
6954 Expression* assignment = factory->NewAssignment(
6955 Token::ASSIGN, proxy,
6956 factory->NewSmiLiteral(Parser::kAbruptCompletion, nopos), nopos);
6957
6958 Block* block = factory->NewBlock(nullptr, 1, true, nopos);
6959 block->statements()->Add(factory->NewExpressionStatement(assignment, nopos),
6960 zone);
6961 set_completion_abrupt = block;
6962 }
6963
6964 // { #loop-body; #set_completion_normal }
Ben Murdoch097c5b22016-05-18 11:27:45 +01006965 Block* new_body = factory->NewBlock(nullptr, 2, false, nopos);
Ben Murdochda12d292016-06-02 14:46:10 +01006966 {
6967 new_body->statements()->Add(loop->body(), zone);
6968 new_body->statements()->Add(set_completion_normal, zone);
6969 }
6970
6971 // { #set_completion_abrupt; #assign-each }
6972 Block* new_assign_each = factory->NewBlock(nullptr, 2, false, nopos);
6973 {
6974 new_assign_each->statements()->Add(set_completion_abrupt, zone);
6975 new_assign_each->statements()->Add(
6976 factory->NewExpressionStatement(loop->assign_each(), nopos), zone);
6977 }
6978
6979 // Now put things together.
Ben Murdoch097c5b22016-05-18 11:27:45 +01006980
6981 loop->set_body(new_body);
Ben Murdochda12d292016-06-02 14:46:10 +01006982 loop->set_assign_each(
6983 factory->NewDoExpression(new_assign_each, var_each, nopos));
6984
6985 Statement* final_loop;
6986 {
6987 Block* target = factory->NewBlock(nullptr, 3, false, nopos);
6988 target->statements()->Add(initialize_each, zone);
6989
6990 Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
6991 try_block->statements()->Add(loop, zone);
6992
6993 FinalizeIteratorUse(var_completion, closing_condition, loop->iterator(),
6994 try_block, target);
6995 final_loop = target;
6996 }
6997
Ben Murdoch097c5b22016-05-18 11:27:45 +01006998 return final_loop;
6999}
7000
7001
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007002} // namespace internal
7003} // namespace v8