1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/parsing/parser.h"
6
7 #include <memory>
8
9 #include "src/api.h"
10 #include "src/ast/ast-expression-rewriter.h"
11 #include "src/ast/ast-literal-reindexer.h"
12 #include "src/ast/ast-traversal-visitor.h"
13 #include "src/ast/ast.h"
14 #include "src/bailout-reason.h"
15 #include "src/base/platform/platform.h"
16 #include "src/char-predicates-inl.h"
17 #include "src/messages.h"
18 #include "src/parsing/duplicate-finder.h"
19 #include "src/parsing/parameter-initializer-rewriter.h"
20 #include "src/parsing/parse-info.h"
21 #include "src/parsing/rewriter.h"
22 #include "src/parsing/scanner-character-streams.h"
23 #include "src/runtime/runtime.h"
24 #include "src/string-stream.h"
25 #include "src/tracing/trace-event.h"
26
27 namespace v8 {
28 namespace internal {
29
ScriptData(const byte * data,int length)30 ScriptData::ScriptData(const byte* data, int length)
31 : owns_data_(false), rejected_(false), data_(data), length_(length) {
32 if (!IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment)) {
33 byte* copy = NewArray<byte>(length);
34 DCHECK(IsAligned(reinterpret_cast<intptr_t>(copy), kPointerAlignment));
35 CopyBytes(copy, data, length);
36 data_ = copy;
37 AcquireDataOwnership();
38 }
39 }
40
GetFunctionEntry(int start)41 FunctionEntry ParseData::GetFunctionEntry(int start) {
42 // The current pre-data entry must be a FunctionEntry with the given
43 // start position.
44 if ((function_index_ + FunctionEntry::kSize <= Length()) &&
45 (static_cast<int>(Data()[function_index_]) == start)) {
46 int index = function_index_;
47 function_index_ += FunctionEntry::kSize;
48 Vector<unsigned> subvector(&(Data()[index]), FunctionEntry::kSize);
49 return FunctionEntry(subvector);
50 }
51 return FunctionEntry();
52 }
53
54
FunctionCount()55 int ParseData::FunctionCount() {
56 int functions_size = FunctionsSize();
57 if (functions_size < 0) return 0;
58 if (functions_size % FunctionEntry::kSize != 0) return 0;
59 return functions_size / FunctionEntry::kSize;
60 }
61
62
IsSane()63 bool ParseData::IsSane() {
64 if (!IsAligned(script_data_->length(), sizeof(unsigned))) return false;
65 // Check that the header data is valid and doesn't specify
66 // point to positions outside the store.
67 int data_length = Length();
68 if (data_length < PreparseDataConstants::kHeaderSize) return false;
69 if (Magic() != PreparseDataConstants::kMagicNumber) return false;
70 if (Version() != PreparseDataConstants::kCurrentVersion) return false;
71 // Check that the space allocated for function entries is sane.
72 int functions_size = FunctionsSize();
73 if (functions_size < 0) return false;
74 if (functions_size % FunctionEntry::kSize != 0) return false;
75 // Check that the total size has room for header and function entries.
76 int minimum_size =
77 PreparseDataConstants::kHeaderSize + functions_size;
78 if (data_length < minimum_size) return false;
79 return true;
80 }
81
82
Initialize()83 void ParseData::Initialize() {
84 // Prepares state for use.
85 int data_length = Length();
86 if (data_length >= PreparseDataConstants::kHeaderSize) {
87 function_index_ = PreparseDataConstants::kHeaderSize;
88 }
89 }
90
91
Magic()92 unsigned ParseData::Magic() {
93 return Data()[PreparseDataConstants::kMagicOffset];
94 }
95
96
Version()97 unsigned ParseData::Version() {
98 return Data()[PreparseDataConstants::kVersionOffset];
99 }
100
101
FunctionsSize()102 int ParseData::FunctionsSize() {
103 return static_cast<int>(Data()[PreparseDataConstants::kFunctionsSizeOffset]);
104 }
105
106 // Helper for putting parts of the parse results into a temporary zone when
107 // parsing inner function bodies.
108 class DiscardableZoneScope {
109 public:
DiscardableZoneScope(Parser * parser,Zone * temp_zone,bool use_temp_zone)110 DiscardableZoneScope(Parser* parser, Zone* temp_zone, bool use_temp_zone)
111 : ast_node_factory_scope_(parser->factory(), temp_zone, use_temp_zone),
112 fni_(parser->ast_value_factory_, temp_zone),
113 parser_(parser),
114 prev_fni_(parser->fni_),
115 prev_zone_(parser->zone_) {
116 if (use_temp_zone) {
117 parser_->fni_ = &fni_;
118 parser_->zone_ = temp_zone;
119 if (parser_->reusable_preparser_ != nullptr) {
120 parser_->reusable_preparser_->zone_ = temp_zone;
121 parser_->reusable_preparser_->factory()->set_zone(temp_zone);
122 }
123 }
124 }
Reset()125 void Reset() {
126 parser_->fni_ = prev_fni_;
127 parser_->zone_ = prev_zone_;
128 if (parser_->reusable_preparser_ != nullptr) {
129 parser_->reusable_preparser_->zone_ = prev_zone_;
130 parser_->reusable_preparser_->factory()->set_zone(prev_zone_);
131 }
132 ast_node_factory_scope_.Reset();
133 }
~DiscardableZoneScope()134 ~DiscardableZoneScope() { Reset(); }
135
136 private:
137 AstNodeFactory::BodyScope ast_node_factory_scope_;
138 FuncNameInferrer fni_;
139 Parser* parser_;
140 FuncNameInferrer* prev_fni_;
141 Zone* prev_zone_;
142
143 DISALLOW_COPY_AND_ASSIGN(DiscardableZoneScope);
144 };
145
SetCachedData(ParseInfo * info)146 void Parser::SetCachedData(ParseInfo* info) {
147 DCHECK_NULL(cached_parse_data_);
148 if (consume_cached_parse_data()) {
149 cached_parse_data_ = ParseData::FromCachedData(*info->cached_data());
150 if (cached_parse_data_ == nullptr) {
151 compile_options_ = ScriptCompiler::kNoCompileOptions;
152 }
153 }
154 }
155
CallClassFieldInitializer(Scope * scope,Expression * this_expr)156 Expression* Parser::CallClassFieldInitializer(Scope* scope,
157 Expression* this_expr) {
158 // This produces the expression
159 // `.class_field_intializer(this_expr)`, where '.class_field_intializer' is
160 // the name
161 // of a synthetic variable.
162 // 'this_expr' will be 'this' in a base constructor and the result of calling
163 // 'super' in a derived one.
164 const AstRawString* init_fn_name =
165 ast_value_factory()->dot_class_field_init_string();
166 VariableProxy* init_fn_proxy = scope->NewUnresolved(factory(), init_fn_name);
167 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
168 args->Add(init_fn_proxy, zone());
169 args->Add(this_expr, zone());
170 return factory()->NewCallRuntime(Runtime::kInlineCall, args,
171 kNoSourcePosition);
172 }
173
RewriteSuperCall(Expression * super_call)174 Expression* Parser::RewriteSuperCall(Expression* super_call) {
175 // TODO(bakkot) find a way to avoid this for classes without fields.
176 if (!allow_harmony_class_fields()) {
177 return super_call;
178 }
179 // This turns a super call `super()` into a do expression of the form
180 // do {
181 // tmp x = super();
182 // if (.class-field-init)
183 // .class-field-init(x)
184 // x; // This isn't actually present; our do-expression representation
185 // allows specifying that the expression returns x directly.
186 // }
187 Variable* var_tmp =
188 scope()->NewTemporary(ast_value_factory()->empty_string());
189 Block* block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
190 Assignment* assignment = factory()->NewAssignment(
191 Token::ASSIGN, factory()->NewVariableProxy(var_tmp), super_call,
192 kNoSourcePosition);
193 block->statements()->Add(
194 factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone());
195 const AstRawString* init_fn_name =
196 ast_value_factory()->dot_class_field_init_string();
197 VariableProxy* init_fn_proxy =
198 scope()->NewUnresolved(factory(), init_fn_name);
199 Expression* condition = init_fn_proxy;
200 Statement* initialize = factory()->NewExpressionStatement(
201 CallClassFieldInitializer(scope(), factory()->NewVariableProxy(var_tmp)),
202 kNoSourcePosition);
203 IfStatement* if_statement = factory()->NewIfStatement(
204 condition, initialize, factory()->NewEmptyStatement(kNoSourcePosition),
205 kNoSourcePosition);
206 block->statements()->Add(if_statement, zone());
207 return factory()->NewDoExpression(block, var_tmp, kNoSourcePosition);
208 }
209
DefaultConstructor(const AstRawString * name,bool call_super,bool requires_class_field_init,int pos,int end_pos,LanguageMode language_mode)210 FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name,
211 bool call_super,
212 bool requires_class_field_init,
213 int pos, int end_pos,
214 LanguageMode language_mode) {
215 int materialized_literal_count = -1;
216 int expected_property_count = -1;
217 const int parameter_count = 0;
218 if (name == nullptr) name = ast_value_factory()->empty_string();
219
220 FunctionKind kind = call_super ? FunctionKind::kDefaultSubclassConstructor
221 : FunctionKind::kDefaultBaseConstructor;
222 DeclarationScope* function_scope = NewFunctionScope(kind);
223 SetLanguageMode(function_scope,
224 static_cast<LanguageMode>(language_mode | STRICT));
225 // Set start and end position to the same value
226 function_scope->set_start_position(pos);
227 function_scope->set_end_position(pos);
228 ZoneList<Statement*>* body = NULL;
229
230 {
231 FunctionState function_state(&function_state_, &scope_state_,
232 function_scope);
233
234 body = new (zone()) ZoneList<Statement*>(call_super ? 2 : 1, zone());
235 if (call_super) {
236 // $super_constructor = %_GetSuperConstructor(<this-function>)
237 // %reflect_construct(
238 // $super_constructor, InternalArray(...args), new.target)
239 auto constructor_args_name = ast_value_factory()->empty_string();
240 bool is_duplicate;
241 bool is_rest = true;
242 bool is_optional = false;
243 Variable* constructor_args = function_scope->DeclareParameter(
244 constructor_args_name, TEMPORARY, is_optional, is_rest, &is_duplicate,
245 ast_value_factory());
246
247 ZoneList<Expression*>* args =
248 new (zone()) ZoneList<Expression*>(2, zone());
249 VariableProxy* this_function_proxy =
250 NewUnresolved(ast_value_factory()->this_function_string(), pos);
251 ZoneList<Expression*>* tmp =
252 new (zone()) ZoneList<Expression*>(1, zone());
253 tmp->Add(this_function_proxy, zone());
254 Expression* super_constructor = factory()->NewCallRuntime(
255 Runtime::kInlineGetSuperConstructor, tmp, pos);
256 args->Add(super_constructor, zone());
257 Spread* spread_args = factory()->NewSpread(
258 factory()->NewVariableProxy(constructor_args), pos, pos);
259 ZoneList<Expression*>* spread_args_expr =
260 new (zone()) ZoneList<Expression*>(1, zone());
261 spread_args_expr->Add(spread_args, zone());
262 args->AddAll(*PrepareSpreadArguments(spread_args_expr), zone());
263 VariableProxy* new_target_proxy =
264 NewUnresolved(ast_value_factory()->new_target_string(), pos);
265 args->Add(new_target_proxy, zone());
266 Expression* call = factory()->NewCallRuntime(
267 Context::REFLECT_CONSTRUCT_INDEX, args, pos);
268 if (requires_class_field_init) {
269 call = CallClassFieldInitializer(scope(), call);
270 }
271 body->Add(factory()->NewReturnStatement(call, pos), zone());
272 }
273
274 materialized_literal_count = function_state.materialized_literal_count();
275 expected_property_count = function_state.expected_property_count();
276 }
277
278 FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
279 name, function_scope, body, materialized_literal_count,
280 expected_property_count, parameter_count, parameter_count,
281 FunctionLiteral::kNoDuplicateParameters,
282 FunctionLiteral::kAnonymousExpression, default_eager_compile_hint(), pos,
283 true);
284
285 function_literal->set_requires_class_field_init(requires_class_field_init);
286
287 return function_literal;
288 }
289
290 // ----------------------------------------------------------------------------
291 // The CHECK_OK macro is a convenient macro to enforce error
292 // handling for functions that may fail (by returning !*ok).
293 //
294 // CAUTION: This macro appends extra statements after a call,
295 // thus it must never be used where only a single statement
296 // is correct (e.g. an if statement branch w/o braces)!
297
298 #define CHECK_OK_VALUE(x) ok); \
299 if (!*ok) return x; \
300 ((void)0
301 #define DUMMY ) // to make indentation work
302 #undef DUMMY
303
304 #define CHECK_OK CHECK_OK_VALUE(nullptr)
305 #define CHECK_OK_VOID CHECK_OK_VALUE(this->Void())
306
307 #define CHECK_FAILED /**/); \
308 if (failed_) return nullptr; \
309 ((void)0
310 #define DUMMY ) // to make indentation work
311 #undef DUMMY
312
313 // ----------------------------------------------------------------------------
314 // Implementation of Parser
315
ShortcutNumericLiteralBinaryExpression(Expression ** x,Expression * y,Token::Value op,int pos)316 bool Parser::ShortcutNumericLiteralBinaryExpression(Expression** x,
317 Expression* y,
318 Token::Value op, int pos) {
319 if ((*x)->AsLiteral() && (*x)->AsLiteral()->raw_value()->IsNumber() &&
320 y->AsLiteral() && y->AsLiteral()->raw_value()->IsNumber()) {
321 double x_val = (*x)->AsLiteral()->raw_value()->AsNumber();
322 double y_val = y->AsLiteral()->raw_value()->AsNumber();
323 bool x_has_dot = (*x)->AsLiteral()->raw_value()->ContainsDot();
324 bool y_has_dot = y->AsLiteral()->raw_value()->ContainsDot();
325 bool has_dot = x_has_dot || y_has_dot;
326 switch (op) {
327 case Token::ADD:
328 *x = factory()->NewNumberLiteral(x_val + y_val, pos, has_dot);
329 return true;
330 case Token::SUB:
331 *x = factory()->NewNumberLiteral(x_val - y_val, pos, has_dot);
332 return true;
333 case Token::MUL:
334 *x = factory()->NewNumberLiteral(x_val * y_val, pos, has_dot);
335 return true;
336 case Token::DIV:
337 *x = factory()->NewNumberLiteral(x_val / y_val, pos, has_dot);
338 return true;
339 case Token::BIT_OR: {
340 int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
341 *x = factory()->NewNumberLiteral(value, pos, has_dot);
342 return true;
343 }
344 case Token::BIT_AND: {
345 int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
346 *x = factory()->NewNumberLiteral(value, pos, has_dot);
347 return true;
348 }
349 case Token::BIT_XOR: {
350 int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
351 *x = factory()->NewNumberLiteral(value, pos, has_dot);
352 return true;
353 }
354 case Token::SHL: {
355 int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
356 *x = factory()->NewNumberLiteral(value, pos, has_dot);
357 return true;
358 }
359 case Token::SHR: {
360 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
361 uint32_t value = DoubleToUint32(x_val) >> shift;
362 *x = factory()->NewNumberLiteral(value, pos, has_dot);
363 return true;
364 }
365 case Token::SAR: {
366 uint32_t shift = DoubleToInt32(y_val) & 0x1f;
367 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
368 *x = factory()->NewNumberLiteral(value, pos, has_dot);
369 return true;
370 }
371 case Token::EXP: {
372 double value = Pow(x_val, y_val);
373 int int_value = static_cast<int>(value);
374 *x = factory()->NewNumberLiteral(
375 int_value == value && value != -0.0 ? int_value : value, pos,
376 has_dot);
377 return true;
378 }
379 default:
380 break;
381 }
382 }
383 return false;
384 }
385
BuildUnaryExpression(Expression * expression,Token::Value op,int pos)386 Expression* Parser::BuildUnaryExpression(Expression* expression,
387 Token::Value op, int pos) {
388 DCHECK(expression != NULL);
389 if (expression->IsLiteral()) {
390 const AstValue* literal = expression->AsLiteral()->raw_value();
391 if (op == Token::NOT) {
392 // Convert the literal to a boolean condition and negate it.
393 bool condition = literal->BooleanValue();
394 return factory()->NewBooleanLiteral(!condition, pos);
395 } else if (literal->IsNumber()) {
396 // Compute some expressions involving only number literals.
397 double value = literal->AsNumber();
398 bool has_dot = literal->ContainsDot();
399 switch (op) {
400 case Token::ADD:
401 return expression;
402 case Token::SUB:
403 return factory()->NewNumberLiteral(-value, pos, has_dot);
404 case Token::BIT_NOT:
405 return factory()->NewNumberLiteral(~DoubleToInt32(value), pos,
406 has_dot);
407 default:
408 break;
409 }
410 }
411 }
412 // Desugar '+foo' => 'foo*1'
413 if (op == Token::ADD) {
414 return factory()->NewBinaryOperation(
415 Token::MUL, expression, factory()->NewNumberLiteral(1, pos, true), pos);
416 }
417 // The same idea for '-foo' => 'foo*(-1)'.
418 if (op == Token::SUB) {
419 return factory()->NewBinaryOperation(
420 Token::MUL, expression, factory()->NewNumberLiteral(-1, pos), pos);
421 }
422 // ...and one more time for '~foo' => 'foo^(~0)'.
423 if (op == Token::BIT_NOT) {
424 return factory()->NewBinaryOperation(
425 Token::BIT_XOR, expression, factory()->NewNumberLiteral(~0, pos), pos);
426 }
427 return factory()->NewUnaryOperation(op, expression, pos);
428 }
429
BuildIteratorResult(Expression * value,bool done)430 Expression* Parser::BuildIteratorResult(Expression* value, bool done) {
431 int pos = kNoSourcePosition;
432
433 if (value == nullptr) value = factory()->NewUndefinedLiteral(pos);
434
435 auto args = new (zone()) ZoneList<Expression*>(2, zone());
436 args->Add(value, zone());
437 args->Add(factory()->NewBooleanLiteral(done, pos), zone());
438
439 return factory()->NewCallRuntime(Runtime::kInlineCreateIterResultObject, args,
440 pos);
441 }
442
NewThrowError(Runtime::FunctionId id,MessageTemplate::Template message,const AstRawString * arg,int pos)443 Expression* Parser::NewThrowError(Runtime::FunctionId id,
444 MessageTemplate::Template message,
445 const AstRawString* arg, int pos) {
446 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
447 args->Add(factory()->NewSmiLiteral(message, pos), zone());
448 args->Add(factory()->NewStringLiteral(arg, pos), zone());
449 CallRuntime* call_constructor = factory()->NewCallRuntime(id, args, pos);
450 return factory()->NewThrow(call_constructor, pos);
451 }
452
NewSuperPropertyReference(int pos)453 Expression* Parser::NewSuperPropertyReference(int pos) {
454 // this_function[home_object_symbol]
455 VariableProxy* this_function_proxy =
456 NewUnresolved(ast_value_factory()->this_function_string(), pos);
457 Expression* home_object_symbol_literal =
458 factory()->NewSymbolLiteral("home_object_symbol", kNoSourcePosition);
459 Expression* home_object = factory()->NewProperty(
460 this_function_proxy, home_object_symbol_literal, pos);
461 return factory()->NewSuperPropertyReference(
462 ThisExpression(pos)->AsVariableProxy(), home_object, pos);
463 }
464
NewSuperCallReference(int pos)465 Expression* Parser::NewSuperCallReference(int pos) {
466 VariableProxy* new_target_proxy =
467 NewUnresolved(ast_value_factory()->new_target_string(), pos);
468 VariableProxy* this_function_proxy =
469 NewUnresolved(ast_value_factory()->this_function_string(), pos);
470 return factory()->NewSuperCallReference(
471 ThisExpression(pos)->AsVariableProxy(), new_target_proxy,
472 this_function_proxy, pos);
473 }
474
NewTargetExpression(int pos)475 Expression* Parser::NewTargetExpression(int pos) {
476 auto proxy = NewUnresolved(ast_value_factory()->new_target_string(), pos);
477 proxy->set_is_new_target();
478 return proxy;
479 }
480
FunctionSentExpression(int pos)481 Expression* Parser::FunctionSentExpression(int pos) {
482 // We desugar function.sent into %_GeneratorGetInputOrDebugPos(generator).
483 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
484 VariableProxy* generator =
485 factory()->NewVariableProxy(function_state_->generator_object_variable());
486 args->Add(generator, zone());
487 return factory()->NewCallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos,
488 args, pos);
489 }
490
ExpressionFromLiteral(Token::Value token,int pos)491 Literal* Parser::ExpressionFromLiteral(Token::Value token, int pos) {
492 switch (token) {
493 case Token::NULL_LITERAL:
494 return factory()->NewNullLiteral(pos);
495 case Token::TRUE_LITERAL:
496 return factory()->NewBooleanLiteral(true, pos);
497 case Token::FALSE_LITERAL:
498 return factory()->NewBooleanLiteral(false, pos);
499 case Token::SMI: {
500 uint32_t value = scanner()->smi_value();
501 return factory()->NewSmiLiteral(value, pos);
502 }
503 case Token::NUMBER: {
504 bool has_dot = scanner()->ContainsDot();
505 double value = scanner()->DoubleValue();
506 return factory()->NewNumberLiteral(value, pos, has_dot);
507 }
508 default:
509 DCHECK(false);
510 }
511 return NULL;
512 }
513
GetIterator(Expression * iterable,int pos)514 Expression* Parser::GetIterator(Expression* iterable, int pos) {
515 Expression* iterator_symbol_literal =
516 factory()->NewSymbolLiteral("iterator_symbol", kNoSourcePosition);
517 Expression* prop =
518 factory()->NewProperty(iterable, iterator_symbol_literal, pos);
519 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(0, zone());
520 return factory()->NewCall(prop, args, pos);
521 }
522
MarkTailPosition(Expression * expression)523 void Parser::MarkTailPosition(Expression* expression) {
524 expression->MarkTail();
525 }
526
NewV8Intrinsic(const AstRawString * name,ZoneList<Expression * > * args,int pos,bool * ok)527 Expression* Parser::NewV8Intrinsic(const AstRawString* name,
528 ZoneList<Expression*>* args, int pos,
529 bool* ok) {
530 if (extension_ != nullptr) {
531 // The extension structures are only accessible while parsing the
532 // very first time, not when reparsing because of lazy compilation.
533 GetClosureScope()->ForceEagerCompilation();
534 }
535
536 DCHECK(name->is_one_byte());
537 const Runtime::Function* function =
538 Runtime::FunctionForName(name->raw_data(), name->length());
539
540 if (function != nullptr) {
541 // Check for possible name clash.
542 DCHECK_EQ(Context::kNotFound,
543 Context::IntrinsicIndexForName(name->raw_data(), name->length()));
544 // Check for built-in IS_VAR macro.
545 if (function->function_id == Runtime::kIS_VAR) {
546 DCHECK_EQ(Runtime::RUNTIME, function->intrinsic_type);
547 // %IS_VAR(x) evaluates to x if x is a variable,
548 // leads to a parse error otherwise. Could be implemented as an
549 // inline function %_IS_VAR(x) to eliminate this special case.
550 if (args->length() == 1 && args->at(0)->AsVariableProxy() != nullptr) {
551 return args->at(0);
552 } else {
553 ReportMessage(MessageTemplate::kNotIsvar);
554 *ok = false;
555 return nullptr;
556 }
557 }
558
559 // Check that the expected number of arguments are being passed.
560 if (function->nargs != -1 && function->nargs != args->length()) {
561 ReportMessage(MessageTemplate::kRuntimeWrongNumArgs);
562 *ok = false;
563 return nullptr;
564 }
565
566 return factory()->NewCallRuntime(function, args, pos);
567 }
568
569 int context_index =
570 Context::IntrinsicIndexForName(name->raw_data(), name->length());
571
572 // Check that the function is defined.
573 if (context_index == Context::kNotFound) {
574 ReportMessage(MessageTemplate::kNotDefined, name);
575 *ok = false;
576 return nullptr;
577 }
578
579 return factory()->NewCallRuntime(context_index, args, pos);
580 }
581
Parser(ParseInfo * info)582 Parser::Parser(ParseInfo* info)
583 : ParserBase<Parser>(info->zone(), &scanner_, info->stack_limit(),
584 info->extension(), info->ast_value_factory(),
585 info->isolate()->counters()->runtime_call_stats()),
586 scanner_(info->unicode_cache()),
587 reusable_preparser_(nullptr),
588 original_scope_(nullptr),
589 mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
590 target_stack_(nullptr),
591 compile_options_(info->compile_options()),
592 cached_parse_data_(nullptr),
593 total_preparse_skipped_(0),
594 parsing_on_main_thread_(true),
595 log_(nullptr) {
596 // Even though we were passed ParseInfo, we should not store it in
597 // Parser - this makes sure that Isolate is not accidentally accessed via
598 // ParseInfo during background parsing.
599 DCHECK(!info->script().is_null() || info->source_stream() != nullptr ||
600 info->character_stream() != nullptr);
601 // Determine if functions can be lazily compiled. This is necessary to
602 // allow some of our builtin JS files to be lazily compiled. These
603 // builtins cannot be handled lazily by the parser, since we have to know
604 // if a function uses the special natives syntax, which is something the
605 // parser records.
606 // If the debugger requests compilation for break points, we cannot be
607 // aggressive about lazy compilation, because it might trigger compilation
608 // of functions without an outer context when setting a breakpoint through
609 // Debug::FindSharedFunctionInfoInScript
610 bool can_compile_lazily = FLAG_lazy && !info->is_debug();
611
612 // Consider compiling eagerly when targeting the code cache.
613 can_compile_lazily &= !(FLAG_serialize_eager && info->will_serialize());
614
615 set_default_eager_compile_hint(can_compile_lazily
616 ? FunctionLiteral::kShouldLazyCompile
617 : FunctionLiteral::kShouldEagerCompile);
618 set_allow_lazy(FLAG_lazy && info->allow_lazy_parsing() &&
619 !info->is_native() && info->extension() == nullptr &&
620 can_compile_lazily);
621 set_allow_natives(FLAG_allow_natives_syntax || info->is_native());
622 set_allow_tailcalls(FLAG_harmony_tailcalls && !info->is_native() &&
623 info->isolate()->is_tail_call_elimination_enabled());
624 set_allow_harmony_do_expressions(FLAG_harmony_do_expressions);
625 set_allow_harmony_function_sent(FLAG_harmony_function_sent);
626 set_allow_harmony_async_await(FLAG_harmony_async_await);
627 set_allow_harmony_restrictive_generators(FLAG_harmony_restrictive_generators);
628 set_allow_harmony_trailing_commas(FLAG_harmony_trailing_commas);
629 set_allow_harmony_class_fields(FLAG_harmony_class_fields);
630 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
631 ++feature) {
632 use_counts_[feature] = 0;
633 }
634 if (info->ast_value_factory() == NULL) {
635 // info takes ownership of AstValueFactory.
636 info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed()));
637 info->set_ast_value_factory_owned();
638 ast_value_factory_ = info->ast_value_factory();
639 ast_node_factory_.set_ast_value_factory(ast_value_factory_);
640 }
641 }
642
DeserializeScopeChain(ParseInfo * info,MaybeHandle<ScopeInfo> maybe_outer_scope_info)643 void Parser::DeserializeScopeChain(
644 ParseInfo* info, MaybeHandle<ScopeInfo> maybe_outer_scope_info) {
645 DCHECK(ThreadId::Current().Equals(info->isolate()->thread_id()));
646 // TODO(wingo): Add an outer SCRIPT_SCOPE corresponding to the native
647 // context, which will have the "this" binding for script scopes.
648 DeclarationScope* script_scope = NewScriptScope();
649 info->set_script_scope(script_scope);
650 Scope* scope = script_scope;
651 Handle<ScopeInfo> outer_scope_info;
652 if (maybe_outer_scope_info.ToHandle(&outer_scope_info)) {
653 scope = Scope::DeserializeScopeChain(
654 info->isolate(), zone(), *outer_scope_info, script_scope,
655 ast_value_factory(), Scope::DeserializationMode::kScopesOnly);
656 DCHECK(!info->is_module() || scope->is_module_scope());
657 }
658 original_scope_ = scope;
659 }
660
ParseProgram(Isolate * isolate,ParseInfo * info)661 FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {
662 // TODO(bmeurer): We temporarily need to pass allow_nesting = true here,
663 // see comment for HistogramTimerScope class.
664
665 // It's OK to use the Isolate & counters here, since this function is only
666 // called in the main thread.
667 DCHECK(parsing_on_main_thread_);
668
669 RuntimeCallTimerScope runtime_timer(
670 runtime_call_stats_, info->is_eval() ? &RuntimeCallStats::ParseEval
671 : &RuntimeCallStats::ParseProgram);
672 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseProgram");
673 Handle<String> source(String::cast(info->script()->source()));
674 isolate->counters()->total_parse_size()->Increment(source->length());
675 base::ElapsedTimer timer;
676 if (FLAG_trace_parse) {
677 timer.Start();
678 }
679 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
680
681 // Initialize parser state.
682 ParserLogger logger;
683
684 if (produce_cached_parse_data()) {
685 log_ = &logger;
686 } else if (consume_cached_parse_data()) {
687 cached_parse_data_->Initialize();
688 }
689
690 DeserializeScopeChain(info, info->maybe_outer_scope_info());
691
692 source = String::Flatten(source);
693 FunctionLiteral* result;
694
695 {
696 std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For(source));
697 scanner_.Initialize(stream.get());
698 result = DoParseProgram(info);
699 }
700 if (result != NULL) {
701 DCHECK_EQ(scanner_.peek_location().beg_pos, source->length());
702 }
703 HandleSourceURLComments(isolate, info->script());
704
705 if (FLAG_trace_parse && result != nullptr) {
706 double ms = timer.Elapsed().InMillisecondsF();
707 if (info->is_eval()) {
708 PrintF("[parsing eval");
709 } else if (info->script()->name()->IsString()) {
710 String* name = String::cast(info->script()->name());
711 std::unique_ptr<char[]> name_chars = name->ToCString();
712 PrintF("[parsing script: %s", name_chars.get());
713 } else {
714 PrintF("[parsing script");
715 }
716 PrintF(" - took %0.3f ms]\n", ms);
717 }
718 if (produce_cached_parse_data() && result != nullptr) {
719 *info->cached_data() = logger.GetScriptData();
720 }
721 log_ = nullptr;
722 return result;
723 }
724
725
DoParseProgram(ParseInfo * info)726 FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
727 // Note that this function can be called from the main thread or from a
728 // background thread. We should not access anything Isolate / heap dependent
729 // via ParseInfo, and also not pass it forward.
730 DCHECK_NULL(scope_state_);
731 DCHECK_NULL(target_stack_);
732
733 ParsingModeScope mode(this, allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY);
734
735 FunctionLiteral* result = NULL;
736 {
737 Scope* outer = original_scope_;
738 DCHECK_NOT_NULL(outer);
739 parsing_module_ = info->is_module();
740 if (info->is_eval()) {
741 outer = NewEvalScope(outer);
742 } else if (parsing_module_) {
743 DCHECK_EQ(outer, info->script_scope());
744 outer = NewModuleScope(info->script_scope());
745 }
746
747 DeclarationScope* scope = outer->AsDeclarationScope();
748
749 scope->set_start_position(0);
750
751 FunctionState function_state(&function_state_, &scope_state_, scope);
752
753 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
754 bool ok = true;
755 int beg_pos = scanner()->location().beg_pos;
756 if (parsing_module_) {
757 // Declare the special module parameter.
758 auto name = ast_value_factory()->empty_string();
759 bool is_duplicate;
760 bool is_rest = false;
761 bool is_optional = false;
762 auto var = scope->DeclareParameter(name, VAR, is_optional, is_rest,
763 &is_duplicate, ast_value_factory());
764 DCHECK(!is_duplicate);
765 var->AllocateTo(VariableLocation::PARAMETER, 0);
766
767 PrepareGeneratorVariables(&function_state);
768 Expression* initial_yield =
769 BuildInitialYield(kNoSourcePosition, kGeneratorFunction);
770 body->Add(
771 factory()->NewExpressionStatement(initial_yield, kNoSourcePosition),
772 zone());
773
774 ParseModuleItemList(body, &ok);
775 ok = ok &&
776 module()->Validate(this->scope()->AsModuleScope(),
777 &pending_error_handler_, zone());
778 } else {
779 // Don't count the mode in the use counters--give the program a chance
780 // to enable script-wide strict mode below.
781 this->scope()->SetLanguageMode(info->language_mode());
782 ParseStatementList(body, Token::EOS, &ok);
783 }
784
785 // The parser will peek but not consume EOS. Our scope logically goes all
786 // the way to the EOS, though.
787 scope->set_end_position(scanner()->peek_location().beg_pos);
788
789 if (ok && is_strict(language_mode())) {
790 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
791 CheckDecimalLiteralWithLeadingZero(beg_pos,
792 scanner()->location().end_pos);
793 }
794 if (ok && is_sloppy(language_mode())) {
795 // TODO(littledan): Function bindings on the global object that modify
796 // pre-existing bindings should be made writable, enumerable and
797 // nonconfigurable if possible, whereas this code will leave attributes
798 // unchanged if the property already exists.
799 InsertSloppyBlockFunctionVarBindings(scope);
800 }
801 if (ok) {
802 CheckConflictingVarDeclarations(scope, &ok);
803 }
804
805 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) {
806 if (body->length() != 1 ||
807 !body->at(0)->IsExpressionStatement() ||
808 !body->at(0)->AsExpressionStatement()->
809 expression()->IsFunctionLiteral()) {
810 ReportMessage(MessageTemplate::kSingleFunctionLiteral);
811 ok = false;
812 }
813 }
814
815 if (ok) {
816 RewriteDestructuringAssignments();
817 int parameter_count = parsing_module_ ? 1 : 0;
818 result = factory()->NewScriptOrEvalFunctionLiteral(
819 scope, body, function_state.materialized_literal_count(),
820 function_state.expected_property_count(), parameter_count);
821 }
822 }
823
824 // Make sure the target stack is empty.
825 DCHECK(target_stack_ == NULL);
826
827 return result;
828 }
829
ParseFunction(Isolate * isolate,ParseInfo * info)830 FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info) {
831 // It's OK to use the Isolate & counters here, since this function is only
832 // called in the main thread.
833 DCHECK(parsing_on_main_thread_);
834 RuntimeCallTimerScope runtime_timer(runtime_call_stats_,
835 &RuntimeCallStats::ParseFunction);
836 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseFunction");
837 Handle<String> source(String::cast(info->script()->source()));
838 isolate->counters()->total_parse_size()->Increment(source->length());
839 base::ElapsedTimer timer;
840 if (FLAG_trace_parse) {
841 timer.Start();
842 }
843 Handle<SharedFunctionInfo> shared_info = info->shared_info();
844 DeserializeScopeChain(info, info->maybe_outer_scope_info());
845
846 // Initialize parser state.
847 source = String::Flatten(source);
848 FunctionLiteral* result;
849 {
850 std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For(
851 source, shared_info->start_position(), shared_info->end_position()));
852 Handle<String> name(String::cast(shared_info->name()));
853 result = DoParseFunction(info, ast_value_factory()->GetString(name),
854 stream.get());
855 if (result != nullptr) {
856 Handle<String> inferred_name(shared_info->inferred_name());
857 result->set_inferred_name(inferred_name);
858 }
859 }
860
861 if (FLAG_trace_parse && result != NULL) {
862 double ms = timer.Elapsed().InMillisecondsF();
863 // We need to make sure that the debug-name is available.
864 ast_value_factory()->Internalize(isolate);
865 std::unique_ptr<char[]> name_chars = result->debug_name()->ToCString();
866 PrintF("[parsing function: %s - took %0.3f ms]\n", name_chars.get(), ms);
867 }
868 return result;
869 }
870
ComputeFunctionType(ParseInfo * info)871 static FunctionLiteral::FunctionType ComputeFunctionType(ParseInfo* info) {
872 if (info->is_declaration()) {
873 return FunctionLiteral::kDeclaration;
874 } else if (info->is_named_expression()) {
875 return FunctionLiteral::kNamedExpression;
876 } else if (IsConciseMethod(info->function_kind()) ||
877 IsAccessorFunction(info->function_kind())) {
878 return FunctionLiteral::kAccessorOrMethod;
879 }
880 return FunctionLiteral::kAnonymousExpression;
881 }
882
DoParseFunction(ParseInfo * info,const AstRawString * raw_name,Utf16CharacterStream * source)883 FunctionLiteral* Parser::DoParseFunction(ParseInfo* info,
884 const AstRawString* raw_name,
885 Utf16CharacterStream* source) {
886 scanner_.Initialize(source);
887 DCHECK_NULL(scope_state_);
888 DCHECK_NULL(target_stack_);
889
890 DCHECK(ast_value_factory());
891 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
892 fni_->PushEnclosingName(raw_name);
893
894 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
895
896 // Place holder for the result.
897 FunctionLiteral* result = nullptr;
898
899 {
900 // Parse the function literal.
901 Scope* outer = original_scope_;
902 DeclarationScope* outer_function = outer->GetClosureScope();
903 DCHECK(outer);
904 FunctionState function_state(&function_state_, &scope_state_,
905 outer_function);
906 BlockState block_state(&scope_state_, outer);
907 DCHECK(is_sloppy(outer->language_mode()) ||
908 is_strict(info->language_mode()));
909 FunctionLiteral::FunctionType function_type = ComputeFunctionType(info);
910 FunctionKind kind = info->function_kind();
911 bool ok = true;
912
913 if (IsArrowFunction(kind)) {
914 if (allow_harmony_async_await() && IsAsyncFunction(kind)) {
915 DCHECK(!scanner()->HasAnyLineTerminatorAfterNext());
916 if (!Check(Token::ASYNC)) {
917 CHECK(stack_overflow());
918 return nullptr;
919 }
920 if (!(peek_any_identifier() || peek() == Token::LPAREN)) {
921 CHECK(stack_overflow());
922 return nullptr;
923 }
924 }
925
926 // TODO(adamk): We should construct this scope from the ScopeInfo.
927 DeclarationScope* scope = NewFunctionScope(kind);
928
929 // These two bits only need to be explicitly set because we're
930 // not passing the ScopeInfo to the Scope constructor.
931 // TODO(adamk): Remove these calls once the above NewScope call
932 // passes the ScopeInfo.
933 if (info->calls_eval()) {
934 scope->RecordEvalCall();
935 }
936 SetLanguageMode(scope, info->language_mode());
937
938 scope->set_start_position(info->start_position());
939 ExpressionClassifier formals_classifier(this);
940 ParserFormalParameters formals(scope);
941 Checkpoint checkpoint(this);
942 {
943 // Parsing patterns as variable reference expression creates
944 // NewUnresolved references in current scope. Entrer arrow function
945 // scope for formal parameter parsing.
946 BlockState block_state(&scope_state_, scope);
947 if (Check(Token::LPAREN)) {
948 // '(' StrictFormalParameters ')'
949 ParseFormalParameterList(&formals, &ok);
950 if (ok) ok = Check(Token::RPAREN);
951 } else {
952 // BindingIdentifier
953 ParseFormalParameter(&formals, &ok);
954 if (ok) DeclareFormalParameter(formals.scope, formals.at(0));
955 }
956 }
957
958 if (ok) {
959 checkpoint.Restore(&formals.materialized_literals_count);
960 // Pass `accept_IN=true` to ParseArrowFunctionLiteral --- This should
961 // not be observable, or else the preparser would have failed.
962 Expression* expression = ParseArrowFunctionLiteral(true, formals, &ok);
963 if (ok) {
964 // Scanning must end at the same position that was recorded
965 // previously. If not, parsing has been interrupted due to a stack
966 // overflow, at which point the partially parsed arrow function
967 // concise body happens to be a valid expression. This is a problem
968 // only for arrow functions with single expression bodies, since there
969 // is no end token such as "}" for normal functions.
970 if (scanner()->location().end_pos == info->end_position()) {
971 // The pre-parser saw an arrow function here, so the full parser
972 // must produce a FunctionLiteral.
973 DCHECK(expression->IsFunctionLiteral());
974 result = expression->AsFunctionLiteral();
975 } else {
976 ok = false;
977 }
978 }
979 }
980 } else if (IsDefaultConstructor(kind)) {
981 DCHECK_EQ(scope(), outer);
982 bool is_subclass_constructor = IsSubclassConstructor(kind);
983 result = DefaultConstructor(
984 raw_name, is_subclass_constructor, info->requires_class_field_init(),
985 info->start_position(), info->end_position(), info->language_mode());
986 if (!is_subclass_constructor && info->requires_class_field_init()) {
987 result = InsertClassFieldInitializer(result);
988 }
989 } else if (info->is_class_field_initializer()) {
990 Handle<SharedFunctionInfo> shared_info = info->shared_info();
991 DCHECK(!shared_info.is_null());
992 if (shared_info->length() == 0) {
993 result = ParseClassFieldForInitializer(
994 info->start_position() != info->end_position(), &ok);
995 } else {
996 result = SynthesizeClassFieldInitializer(shared_info->length());
997 }
998 } else {
999 result = ParseFunctionLiteral(
1000 raw_name, Scanner::Location::invalid(), kSkipFunctionNameCheck, kind,
1001 kNoSourcePosition, function_type, info->language_mode(), &ok);
1002 if (info->requires_class_field_init()) {
1003 result = InsertClassFieldInitializer(result);
1004 }
1005 }
1006 // Make sure the results agree.
1007 DCHECK(ok == (result != nullptr));
1008 }
1009
1010 // Make sure the target stack is empty.
1011 DCHECK_NULL(target_stack_);
1012 return result;
1013 }
1014
ParseModuleItem(bool * ok)1015 Statement* Parser::ParseModuleItem(bool* ok) {
1016 // ecma262/#prod-ModuleItem
1017 // ModuleItem :
1018 // ImportDeclaration
1019 // ExportDeclaration
1020 // StatementListItem
1021
1022 switch (peek()) {
1023 case Token::IMPORT:
1024 ParseImportDeclaration(CHECK_OK);
1025 return factory()->NewEmptyStatement(kNoSourcePosition);
1026 case Token::EXPORT:
1027 return ParseExportDeclaration(ok);
1028 default:
1029 return ParseStatementListItem(ok);
1030 }
1031 }
1032
1033
ParseModuleItemList(ZoneList<Statement * > * body,bool * ok)1034 void Parser::ParseModuleItemList(ZoneList<Statement*>* body, bool* ok) {
1035 // ecma262/#prod-Module
1036 // Module :
1037 // ModuleBody?
1038 //
1039 // ecma262/#prod-ModuleItemList
1040 // ModuleBody :
1041 // ModuleItem*
1042
1043 DCHECK(scope()->is_module_scope());
1044 while (peek() != Token::EOS) {
1045 Statement* stat = ParseModuleItem(CHECK_OK_VOID);
1046 if (stat && !stat->IsEmpty()) {
1047 body->Add(stat, zone());
1048 }
1049 }
1050 }
1051
1052
ParseModuleSpecifier(bool * ok)1053 const AstRawString* Parser::ParseModuleSpecifier(bool* ok) {
1054 // ModuleSpecifier :
1055 // StringLiteral
1056
1057 Expect(Token::STRING, CHECK_OK);
1058 return GetSymbol();
1059 }
1060
1061
ParseExportClause(ZoneList<const AstRawString * > * export_names,ZoneList<Scanner::Location> * export_locations,ZoneList<const AstRawString * > * local_names,Scanner::Location * reserved_loc,bool * ok)1062 void Parser::ParseExportClause(ZoneList<const AstRawString*>* export_names,
1063 ZoneList<Scanner::Location>* export_locations,
1064 ZoneList<const AstRawString*>* local_names,
1065 Scanner::Location* reserved_loc, bool* ok) {
1066 // ExportClause :
1067 // '{' '}'
1068 // '{' ExportsList '}'
1069 // '{' ExportsList ',' '}'
1070 //
1071 // ExportsList :
1072 // ExportSpecifier
1073 // ExportsList ',' ExportSpecifier
1074 //
1075 // ExportSpecifier :
1076 // IdentifierName
1077 // IdentifierName 'as' IdentifierName
1078
1079 Expect(Token::LBRACE, CHECK_OK_VOID);
1080
1081 Token::Value name_tok;
1082 while ((name_tok = peek()) != Token::RBRACE) {
1083 // Keep track of the first reserved word encountered in case our
1084 // caller needs to report an error.
1085 if (!reserved_loc->IsValid() &&
1086 !Token::IsIdentifier(name_tok, STRICT, false, parsing_module_)) {
1087 *reserved_loc = scanner()->location();
1088 }
1089 const AstRawString* local_name = ParseIdentifierName(CHECK_OK_VOID);
1090 const AstRawString* export_name = NULL;
1091 Scanner::Location location = scanner()->location();
1092 if (CheckContextualKeyword(CStrVector("as"))) {
1093 export_name = ParseIdentifierName(CHECK_OK_VOID);
1094 // Set the location to the whole "a as b" string, so that it makes sense
1095 // both for errors due to "a" and for errors due to "b".
1096 location.end_pos = scanner()->location().end_pos;
1097 }
1098 if (export_name == NULL) {
1099 export_name = local_name;
1100 }
1101 export_names->Add(export_name, zone());
1102 local_names->Add(local_name, zone());
1103 export_locations->Add(location, zone());
1104 if (peek() == Token::RBRACE) break;
1105 Expect(Token::COMMA, CHECK_OK_VOID);
1106 }
1107
1108 Expect(Token::RBRACE, CHECK_OK_VOID);
1109 }
1110
1111
ParseNamedImports(int pos,bool * ok)1112 ZoneList<const Parser::NamedImport*>* Parser::ParseNamedImports(
1113 int pos, bool* ok) {
1114 // NamedImports :
1115 // '{' '}'
1116 // '{' ImportsList '}'
1117 // '{' ImportsList ',' '}'
1118 //
1119 // ImportsList :
1120 // ImportSpecifier
1121 // ImportsList ',' ImportSpecifier
1122 //
1123 // ImportSpecifier :
1124 // BindingIdentifier
1125 // IdentifierName 'as' BindingIdentifier
1126
1127 Expect(Token::LBRACE, CHECK_OK);
1128
1129 auto result = new (zone()) ZoneList<const NamedImport*>(1, zone());
1130 while (peek() != Token::RBRACE) {
1131 const AstRawString* import_name = ParseIdentifierName(CHECK_OK);
1132 const AstRawString* local_name = import_name;
1133 Scanner::Location location = scanner()->location();
1134 // In the presence of 'as', the left-side of the 'as' can
1135 // be any IdentifierName. But without 'as', it must be a valid
1136 // BindingIdentifier.
1137 if (CheckContextualKeyword(CStrVector("as"))) {
1138 local_name = ParseIdentifierName(CHECK_OK);
1139 }
1140 if (!Token::IsIdentifier(scanner()->current_token(), STRICT, false,
1141 parsing_module_)) {
1142 *ok = false;
1143 ReportMessage(MessageTemplate::kUnexpectedReserved);
1144 return nullptr;
1145 } else if (IsEvalOrArguments(local_name)) {
1146 *ok = false;
1147 ReportMessage(MessageTemplate::kStrictEvalArguments);
1148 return nullptr;
1149 }
1150
1151 DeclareVariable(local_name, CONST, kNeedsInitialization, position(),
1152 CHECK_OK);
1153
1154 NamedImport* import =
1155 new (zone()) NamedImport(import_name, local_name, location);
1156 result->Add(import, zone());
1157
1158 if (peek() == Token::RBRACE) break;
1159 Expect(Token::COMMA, CHECK_OK);
1160 }
1161
1162 Expect(Token::RBRACE, CHECK_OK);
1163 return result;
1164 }
1165
1166
ParseImportDeclaration(bool * ok)1167 void Parser::ParseImportDeclaration(bool* ok) {
1168 // ImportDeclaration :
1169 // 'import' ImportClause 'from' ModuleSpecifier ';'
1170 // 'import' ModuleSpecifier ';'
1171 //
1172 // ImportClause :
1173 // ImportedDefaultBinding
1174 // NameSpaceImport
1175 // NamedImports
1176 // ImportedDefaultBinding ',' NameSpaceImport
1177 // ImportedDefaultBinding ',' NamedImports
1178 //
1179 // NameSpaceImport :
1180 // '*' 'as' ImportedBinding
1181
1182 int pos = peek_position();
1183 Expect(Token::IMPORT, CHECK_OK_VOID);
1184
1185 Token::Value tok = peek();
1186
1187 // 'import' ModuleSpecifier ';'
1188 if (tok == Token::STRING) {
1189 const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK_VOID);
1190 ExpectSemicolon(CHECK_OK_VOID);
1191 module()->AddEmptyImport(module_specifier);
1192 return;
1193 }
1194
1195 // Parse ImportedDefaultBinding if present.
1196 const AstRawString* import_default_binding = nullptr;
1197 Scanner::Location import_default_binding_loc;
1198 if (tok != Token::MUL && tok != Token::LBRACE) {
1199 import_default_binding =
1200 ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK_VOID);
1201 import_default_binding_loc = scanner()->location();
1202 DeclareVariable(import_default_binding, CONST, kNeedsInitialization, pos,
1203 CHECK_OK_VOID);
1204 }
1205
1206 // Parse NameSpaceImport or NamedImports if present.
1207 const AstRawString* module_namespace_binding = nullptr;
1208 Scanner::Location module_namespace_binding_loc;
1209 const ZoneList<const NamedImport*>* named_imports = nullptr;
1210 if (import_default_binding == nullptr || Check(Token::COMMA)) {
1211 switch (peek()) {
1212 case Token::MUL: {
1213 Consume(Token::MUL);
1214 ExpectContextualKeyword(CStrVector("as"), CHECK_OK_VOID);
1215 module_namespace_binding =
1216 ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK_VOID);
1217 module_namespace_binding_loc = scanner()->location();
1218 DeclareVariable(module_namespace_binding, CONST, kCreatedInitialized,
1219 pos, CHECK_OK_VOID);
1220 break;
1221 }
1222
1223 case Token::LBRACE:
1224 named_imports = ParseNamedImports(pos, CHECK_OK_VOID);
1225 break;
1226
1227 default:
1228 *ok = false;
1229 ReportUnexpectedToken(scanner()->current_token());
1230 return;
1231 }
1232 }
1233
1234 ExpectContextualKeyword(CStrVector("from"), CHECK_OK_VOID);
1235 const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK_VOID);
1236 ExpectSemicolon(CHECK_OK_VOID);
1237
1238 // Now that we have all the information, we can make the appropriate
1239 // declarations.
1240
1241 // TODO(neis): Would prefer to call DeclareVariable for each case below rather
1242 // than above and in ParseNamedImports, but then a possible error message
1243 // would point to the wrong location. Maybe have a DeclareAt version of
1244 // Declare that takes a location?
1245
1246 if (module_namespace_binding != nullptr) {
1247 module()->AddStarImport(module_namespace_binding, module_specifier,
1248 module_namespace_binding_loc, zone());
1249 }
1250
1251 if (import_default_binding != nullptr) {
1252 module()->AddImport(ast_value_factory()->default_string(),
1253 import_default_binding, module_specifier,
1254 import_default_binding_loc, zone());
1255 }
1256
1257 if (named_imports != nullptr) {
1258 if (named_imports->length() == 0) {
1259 module()->AddEmptyImport(module_specifier);
1260 } else {
1261 for (int i = 0; i < named_imports->length(); ++i) {
1262 const NamedImport* import = named_imports->at(i);
1263 module()->AddImport(import->import_name, import->local_name,
1264 module_specifier, import->location, zone());
1265 }
1266 }
1267 }
1268 }
1269
1270
ParseExportDefault(bool * ok)1271 Statement* Parser::ParseExportDefault(bool* ok) {
1272 // Supports the following productions, starting after the 'default' token:
1273 // 'export' 'default' HoistableDeclaration
1274 // 'export' 'default' ClassDeclaration
1275 // 'export' 'default' AssignmentExpression[In] ';'
1276
1277 Expect(Token::DEFAULT, CHECK_OK);
1278 Scanner::Location default_loc = scanner()->location();
1279
1280 ZoneList<const AstRawString*> local_names(1, zone());
1281 Statement* result = nullptr;
1282 switch (peek()) {
1283 case Token::FUNCTION:
1284 result = ParseHoistableDeclaration(&local_names, true, CHECK_OK);
1285 break;
1286
1287 case Token::CLASS:
1288 Consume(Token::CLASS);
1289 result = ParseClassDeclaration(&local_names, true, CHECK_OK);
1290 break;
1291
1292 case Token::ASYNC:
1293 if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION &&
1294 !scanner()->HasAnyLineTerminatorAfterNext()) {
1295 Consume(Token::ASYNC);
1296 result = ParseAsyncFunctionDeclaration(&local_names, true, CHECK_OK);
1297 break;
1298 }
1299 /* falls through */
1300
1301 default: {
1302 int pos = position();
1303 ExpressionClassifier classifier(this);
1304 Expression* value = ParseAssignmentExpression(true, CHECK_OK);
1305 RewriteNonPattern(CHECK_OK);
1306 SetFunctionName(value, ast_value_factory()->default_string());
1307
1308 const AstRawString* local_name =
1309 ast_value_factory()->star_default_star_string();
1310 local_names.Add(local_name, zone());
1311
1312 // It's fine to declare this as CONST because the user has no way of
1313 // writing to it.
1314 Declaration* decl = DeclareVariable(local_name, CONST, pos, CHECK_OK);
1315 decl->proxy()->var()->set_initializer_position(position());
1316
1317 Assignment* assignment = factory()->NewAssignment(
1318 Token::INIT, decl->proxy(), value, kNoSourcePosition);
1319 result = factory()->NewExpressionStatement(assignment, kNoSourcePosition);
1320
1321 ExpectSemicolon(CHECK_OK);
1322 break;
1323 }
1324 }
1325
1326 DCHECK_EQ(local_names.length(), 1);
1327 module()->AddExport(local_names.first(),
1328 ast_value_factory()->default_string(), default_loc,
1329 zone());
1330
1331 DCHECK_NOT_NULL(result);
1332 return result;
1333 }
1334
ParseExportDeclaration(bool * ok)1335 Statement* Parser::ParseExportDeclaration(bool* ok) {
1336 // ExportDeclaration:
1337 // 'export' '*' 'from' ModuleSpecifier ';'
1338 // 'export' ExportClause ('from' ModuleSpecifier)? ';'
1339 // 'export' VariableStatement
1340 // 'export' Declaration
1341 // 'export' 'default' ... (handled in ParseExportDefault)
1342
1343 Expect(Token::EXPORT, CHECK_OK);
1344 int pos = position();
1345
1346 Statement* result = nullptr;
1347 ZoneList<const AstRawString*> names(1, zone());
1348 Scanner::Location loc = scanner()->peek_location();
1349 switch (peek()) {
1350 case Token::DEFAULT:
1351 return ParseExportDefault(ok);
1352
1353 case Token::MUL: {
1354 Consume(Token::MUL);
1355 loc = scanner()->location();
1356 ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
1357 const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
1358 ExpectSemicolon(CHECK_OK);
1359 module()->AddStarExport(module_specifier, loc, zone());
1360 return factory()->NewEmptyStatement(pos);
1361 }
1362
1363 case Token::LBRACE: {
1364 // There are two cases here:
1365 //
1366 // 'export' ExportClause ';'
1367 // and
1368 // 'export' ExportClause FromClause ';'
1369 //
1370 // In the first case, the exported identifiers in ExportClause must
1371 // not be reserved words, while in the latter they may be. We
1372 // pass in a location that gets filled with the first reserved word
1373 // encountered, and then throw a SyntaxError if we are in the
1374 // non-FromClause case.
1375 Scanner::Location reserved_loc = Scanner::Location::invalid();
1376 ZoneList<const AstRawString*> export_names(1, zone());
1377 ZoneList<Scanner::Location> export_locations(1, zone());
1378 ZoneList<const AstRawString*> original_names(1, zone());
1379 ParseExportClause(&export_names, &export_locations, &original_names,
1380 &reserved_loc, CHECK_OK);
1381 const AstRawString* module_specifier = nullptr;
1382 if (CheckContextualKeyword(CStrVector("from"))) {
1383 module_specifier = ParseModuleSpecifier(CHECK_OK);
1384 } else if (reserved_loc.IsValid()) {
1385 // No FromClause, so reserved words are invalid in ExportClause.
1386 *ok = false;
1387 ReportMessageAt(reserved_loc, MessageTemplate::kUnexpectedReserved);
1388 return nullptr;
1389 }
1390 ExpectSemicolon(CHECK_OK);
1391 const int length = export_names.length();
1392 DCHECK_EQ(length, original_names.length());
1393 DCHECK_EQ(length, export_locations.length());
1394 if (module_specifier == nullptr) {
1395 for (int i = 0; i < length; ++i) {
1396 module()->AddExport(original_names[i], export_names[i],
1397 export_locations[i], zone());
1398 }
1399 } else if (length == 0) {
1400 module()->AddEmptyImport(module_specifier);
1401 } else {
1402 for (int i = 0; i < length; ++i) {
1403 module()->AddExport(original_names[i], export_names[i],
1404 module_specifier, export_locations[i], zone());
1405 }
1406 }
1407 return factory()->NewEmptyStatement(pos);
1408 }
1409
1410 case Token::FUNCTION:
1411 result = ParseHoistableDeclaration(&names, false, CHECK_OK);
1412 break;
1413
1414 case Token::CLASS:
1415 Consume(Token::CLASS);
1416 result = ParseClassDeclaration(&names, false, CHECK_OK);
1417 break;
1418
1419 case Token::VAR:
1420 case Token::LET:
1421 case Token::CONST:
1422 result = ParseVariableStatement(kStatementListItem, &names, CHECK_OK);
1423 break;
1424
1425 case Token::ASYNC:
1426 if (allow_harmony_async_await()) {
1427 // TODO(neis): Why don't we have the same check here as in
1428 // ParseStatementListItem?
1429 Consume(Token::ASYNC);
1430 result = ParseAsyncFunctionDeclaration(&names, false, CHECK_OK);
1431 break;
1432 }
1433 /* falls through */
1434
1435 default:
1436 *ok = false;
1437 ReportUnexpectedToken(scanner()->current_token());
1438 return nullptr;
1439 }
1440 loc.end_pos = scanner()->location().end_pos;
1441
1442 ModuleDescriptor* descriptor = module();
1443 for (int i = 0; i < names.length(); ++i) {
1444 descriptor->AddExport(names[i], names[i], loc, zone());
1445 }
1446
1447 DCHECK_NOT_NULL(result);
1448 return result;
1449 }
1450
NewUnresolved(const AstRawString * name,int begin_pos,VariableKind kind)1451 VariableProxy* Parser::NewUnresolved(const AstRawString* name, int begin_pos,
1452 VariableKind kind) {
1453 return scope()->NewUnresolved(factory(), name, begin_pos, kind);
1454 }
1455
NewUnresolved(const AstRawString * name)1456 VariableProxy* Parser::NewUnresolved(const AstRawString* name) {
1457 return scope()->NewUnresolved(factory(), name, scanner()->location().beg_pos);
1458 }
1459
DeclareVariable(const AstRawString * name,VariableMode mode,int pos,bool * ok)1460 Declaration* Parser::DeclareVariable(const AstRawString* name,
1461 VariableMode mode, int pos, bool* ok) {
1462 return DeclareVariable(name, mode, Variable::DefaultInitializationFlag(mode),
1463 pos, ok);
1464 }
1465
DeclareVariable(const AstRawString * name,VariableMode mode,InitializationFlag init,int pos,bool * ok)1466 Declaration* Parser::DeclareVariable(const AstRawString* name,
1467 VariableMode mode, InitializationFlag init,
1468 int pos, bool* ok) {
1469 DCHECK_NOT_NULL(name);
1470 VariableProxy* proxy = factory()->NewVariableProxy(
1471 name, NORMAL_VARIABLE, scanner()->location().beg_pos);
1472 Declaration* declaration =
1473 factory()->NewVariableDeclaration(proxy, this->scope(), pos);
1474 Declare(declaration, DeclarationDescriptor::NORMAL, mode, init, ok, nullptr,
1475 scanner()->location().end_pos);
1476 if (!*ok) return nullptr;
1477 return declaration;
1478 }
1479
Declare(Declaration * declaration,DeclarationDescriptor::Kind declaration_kind,VariableMode mode,InitializationFlag init,bool * ok,Scope * scope,int var_end_pos)1480 Variable* Parser::Declare(Declaration* declaration,
1481 DeclarationDescriptor::Kind declaration_kind,
1482 VariableMode mode, InitializationFlag init, bool* ok,
1483 Scope* scope, int var_end_pos) {
1484 if (scope == nullptr) {
1485 scope = this->scope();
1486 }
1487 bool sloppy_mode_block_scope_function_redefinition = false;
1488 Variable* variable = scope->DeclareVariable(
1489 declaration, mode, init, allow_harmony_restrictive_generators(),
1490 &sloppy_mode_block_scope_function_redefinition, ok);
1491 if (!*ok) {
1492 // If we only have the start position of a proxy, we can't highlight the
1493 // whole variable name. Pretend its length is 1 so that we highlight at
1494 // least the first character.
1495 Scanner::Location loc(declaration->proxy()->position(),
1496 var_end_pos != kNoSourcePosition
1497 ? var_end_pos
1498 : declaration->proxy()->position() + 1);
1499 if (declaration_kind == DeclarationDescriptor::NORMAL) {
1500 ReportMessageAt(loc, MessageTemplate::kVarRedeclaration,
1501 declaration->proxy()->raw_name());
1502 } else {
1503 ReportMessageAt(loc, MessageTemplate::kParamDupe);
1504 }
1505 return nullptr;
1506 }
1507 if (sloppy_mode_block_scope_function_redefinition) {
1508 ++use_counts_[v8::Isolate::kSloppyModeBlockScopedFunctionRedefinition];
1509 }
1510 return variable;
1511 }
1512
BuildInitializationBlock(DeclarationParsingResult * parsing_result,ZoneList<const AstRawString * > * names,bool * ok)1513 Block* Parser::BuildInitializationBlock(
1514 DeclarationParsingResult* parsing_result,
1515 ZoneList<const AstRawString*>* names, bool* ok) {
1516 Block* result = factory()->NewBlock(
1517 NULL, 1, true, parsing_result->descriptor.declaration_pos);
1518 for (auto declaration : parsing_result->declarations) {
1519 PatternRewriter::DeclareAndInitializeVariables(
1520 this, result, &(parsing_result->descriptor), &declaration, names,
1521 CHECK_OK);
1522 }
1523 return result;
1524 }
1525
DeclareAndInitializeVariables(Block * block,const DeclarationDescriptor * declaration_descriptor,const DeclarationParsingResult::Declaration * declaration,ZoneList<const AstRawString * > * names,bool * ok)1526 void Parser::DeclareAndInitializeVariables(
1527 Block* block, const DeclarationDescriptor* declaration_descriptor,
1528 const DeclarationParsingResult::Declaration* declaration,
1529 ZoneList<const AstRawString*>* names, bool* ok) {
1530 DCHECK_NOT_NULL(block);
1531 PatternRewriter::DeclareAndInitializeVariables(
1532 this, block, declaration_descriptor, declaration, names, ok);
1533 }
1534
DeclareFunction(const AstRawString * variable_name,FunctionLiteral * function,int pos,bool is_generator,bool is_async,ZoneList<const AstRawString * > * names,bool * ok)1535 Statement* Parser::DeclareFunction(const AstRawString* variable_name,
1536 FunctionLiteral* function, int pos,
1537 bool is_generator, bool is_async,
1538 ZoneList<const AstRawString*>* names,
1539 bool* ok) {
1540 // In ES6, a function behaves as a lexical binding, except in
1541 // a script scope, or the initial scope of eval or another function.
1542 VariableMode mode =
1543 (!scope()->is_declaration_scope() || scope()->is_module_scope()) ? LET
1544 : VAR;
1545 VariableProxy* proxy =
1546 factory()->NewVariableProxy(variable_name, NORMAL_VARIABLE);
1547 Declaration* declaration =
1548 factory()->NewFunctionDeclaration(proxy, function, scope(), pos);
1549 Declare(declaration, DeclarationDescriptor::NORMAL, mode, kCreatedInitialized,
1550 CHECK_OK);
1551 if (names) names->Add(variable_name, zone());
1552 // Async functions don't undergo sloppy mode block scoped hoisting, and don't
1553 // allow duplicates in a block. Both are represented by the
1554 // sloppy_block_function_map. Don't add them to the map for async functions.
1555 // Generators are also supposed to be prohibited; currently doing this behind
1556 // a flag and UseCounting violations to assess web compatibility.
1557 if (is_sloppy(language_mode()) && !scope()->is_declaration_scope() &&
1558 !is_async && !(allow_harmony_restrictive_generators() && is_generator)) {
1559 SloppyBlockFunctionStatement* delegate =
1560 factory()->NewSloppyBlockFunctionStatement(scope());
1561 DeclarationScope* target_scope = GetDeclarationScope();
1562 target_scope->DeclareSloppyBlockFunction(variable_name, delegate);
1563 return delegate;
1564 }
1565 return factory()->NewEmptyStatement(kNoSourcePosition);
1566 }
1567
DeclareClass(const AstRawString * variable_name,Expression * value,ZoneList<const AstRawString * > * names,int class_token_pos,int end_pos,bool * ok)1568 Statement* Parser::DeclareClass(const AstRawString* variable_name,
1569 Expression* value,
1570 ZoneList<const AstRawString*>* names,
1571 int class_token_pos, int end_pos, bool* ok) {
1572 Declaration* decl =
1573 DeclareVariable(variable_name, LET, class_token_pos, CHECK_OK);
1574 decl->proxy()->var()->set_initializer_position(end_pos);
1575 Assignment* assignment = factory()->NewAssignment(Token::INIT, decl->proxy(),
1576 value, class_token_pos);
1577 Statement* assignment_statement =
1578 factory()->NewExpressionStatement(assignment, kNoSourcePosition);
1579 if (names) names->Add(variable_name, zone());
1580 return assignment_statement;
1581 }
1582
DeclareNative(const AstRawString * name,int pos,bool * ok)1583 Statement* Parser::DeclareNative(const AstRawString* name, int pos, bool* ok) {
1584 // Make sure that the function containing the native declaration
1585 // isn't lazily compiled. The extension structures are only
1586 // accessible while parsing the first time not when reparsing
1587 // because of lazy compilation.
1588 GetClosureScope()->ForceEagerCompilation();
1589
1590 // TODO(1240846): It's weird that native function declarations are
1591 // introduced dynamically when we meet their declarations, whereas
1592 // other functions are set up when entering the surrounding scope.
1593 Declaration* decl = DeclareVariable(name, VAR, pos, CHECK_OK);
1594 NativeFunctionLiteral* lit =
1595 factory()->NewNativeFunctionLiteral(name, extension_, kNoSourcePosition);
1596 return factory()->NewExpressionStatement(
1597 factory()->NewAssignment(Token::INIT, decl->proxy(), lit,
1598 kNoSourcePosition),
1599 pos);
1600 }
1601
DeclareLabel(ZoneList<const AstRawString * > * labels,VariableProxy * var,bool * ok)1602 ZoneList<const AstRawString*>* Parser::DeclareLabel(
1603 ZoneList<const AstRawString*>* labels, VariableProxy* var, bool* ok) {
1604 const AstRawString* label = var->raw_name();
1605 // TODO(1240780): We don't check for redeclaration of labels
1606 // during preparsing since keeping track of the set of active
1607 // labels requires nontrivial changes to the way scopes are
1608 // structured. However, these are probably changes we want to
1609 // make later anyway so we should go back and fix this then.
1610 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
1611 ReportMessage(MessageTemplate::kLabelRedeclaration, label);
1612 *ok = false;
1613 return nullptr;
1614 }
1615 if (labels == nullptr) {
1616 labels = new (zone()) ZoneList<const AstRawString*>(1, zone());
1617 }
1618 labels->Add(label, zone());
1619 // Remove the "ghost" variable that turned out to be a label
1620 // from the top scope. This way, we don't try to resolve it
1621 // during the scope processing.
1622 scope()->RemoveUnresolved(var);
1623 return labels;
1624 }
1625
ContainsLabel(ZoneList<const AstRawString * > * labels,const AstRawString * label)1626 bool Parser::ContainsLabel(ZoneList<const AstRawString*>* labels,
1627 const AstRawString* label) {
1628 DCHECK_NOT_NULL(label);
1629 if (labels != nullptr) {
1630 for (int i = labels->length(); i-- > 0;) {
1631 if (labels->at(i) == label) return true;
1632 }
1633 }
1634 return false;
1635 }
1636
RewriteReturn(Expression * return_value,int pos)1637 Expression* Parser::RewriteReturn(Expression* return_value, int pos) {
1638 if (IsSubclassConstructor(function_state_->kind())) {
1639 // For subclass constructors we need to return this in case of undefined
1640 // return a Smi (transformed into an exception in the ConstructStub)
1641 // for a non object.
1642 //
1643 // return expr;
1644 //
1645 // Is rewritten as:
1646 //
1647 // return (temp = expr) === undefined ? this :
1648 // %_IsJSReceiver(temp) ? temp : 1;
1649
1650 // temp = expr
1651 Variable* temp = NewTemporary(ast_value_factory()->empty_string());
1652 Assignment* assign = factory()->NewAssignment(
1653 Token::ASSIGN, factory()->NewVariableProxy(temp), return_value, pos);
1654
1655 // %_IsJSReceiver(temp)
1656 ZoneList<Expression*>* is_spec_object_args =
1657 new (zone()) ZoneList<Expression*>(1, zone());
1658 is_spec_object_args->Add(factory()->NewVariableProxy(temp), zone());
1659 Expression* is_spec_object_call = factory()->NewCallRuntime(
1660 Runtime::kInlineIsJSReceiver, is_spec_object_args, pos);
1661
1662 // %_IsJSReceiver(temp) ? temp : 1;
1663 Expression* is_object_conditional = factory()->NewConditional(
1664 is_spec_object_call, factory()->NewVariableProxy(temp),
1665 factory()->NewSmiLiteral(1, pos), pos);
1666
1667 // temp === undefined
1668 Expression* is_undefined = factory()->NewCompareOperation(
1669 Token::EQ_STRICT, assign,
1670 factory()->NewUndefinedLiteral(kNoSourcePosition), pos);
1671
1672 // is_undefined ? this : is_object_conditional
1673 return_value = factory()->NewConditional(is_undefined, ThisExpression(pos),
1674 is_object_conditional, pos);
1675 }
1676 if (is_generator()) {
1677 return_value = BuildIteratorResult(return_value, true);
1678 } else if (is_async_function()) {
1679 return_value = BuildResolvePromise(return_value, return_value->position());
1680 }
1681 return return_value;
1682 }
1683
RewriteDoExpression(Block * body,int pos,bool * ok)1684 Expression* Parser::RewriteDoExpression(Block* body, int pos, bool* ok) {
1685 Variable* result = NewTemporary(ast_value_factory()->dot_result_string());
1686 DoExpression* expr = factory()->NewDoExpression(body, result, pos);
1687 if (!Rewriter::Rewrite(this, GetClosureScope(), expr, ast_value_factory())) {
1688 *ok = false;
1689 return nullptr;
1690 }
1691 return expr;
1692 }
1693
RewriteSwitchStatement(Expression * tag,SwitchStatement * switch_statement,ZoneList<CaseClause * > * cases,Scope * scope)1694 Statement* Parser::RewriteSwitchStatement(Expression* tag,
1695 SwitchStatement* switch_statement,
1696 ZoneList<CaseClause*>* cases,
1697 Scope* scope) {
1698 // In order to get the CaseClauses to execute in their own lexical scope,
1699 // but without requiring downstream code to have special scope handling
1700 // code for switch statements, desugar into blocks as follows:
1701 // { // To group the statements--harmless to evaluate Expression in scope
1702 // .tag_variable = Expression;
1703 // { // To give CaseClauses a scope
1704 // switch (.tag_variable) { CaseClause* }
1705 // }
1706 // }
1707
1708 Block* switch_block = factory()->NewBlock(NULL, 2, false, kNoSourcePosition);
1709
1710 Variable* tag_variable =
1711 NewTemporary(ast_value_factory()->dot_switch_tag_string());
1712 Assignment* tag_assign = factory()->NewAssignment(
1713 Token::ASSIGN, factory()->NewVariableProxy(tag_variable), tag,
1714 tag->position());
1715 Statement* tag_statement =
1716 factory()->NewExpressionStatement(tag_assign, kNoSourcePosition);
1717 switch_block->statements()->Add(tag_statement, zone());
1718
1719 // make statement: undefined;
1720 // This is needed so the tag isn't returned as the value, in case the switch
1721 // statements don't have a value.
1722 switch_block->statements()->Add(
1723 factory()->NewExpressionStatement(
1724 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition),
1725 zone());
1726
1727 Expression* tag_read = factory()->NewVariableProxy(tag_variable);
1728 switch_statement->Initialize(tag_read, cases);
1729 Block* cases_block = factory()->NewBlock(NULL, 1, false, kNoSourcePosition);
1730 cases_block->statements()->Add(switch_statement, zone());
1731 cases_block->set_scope(scope);
1732 switch_block->statements()->Add(cases_block, zone());
1733 return switch_block;
1734 }
1735
RewriteCatchPattern(CatchInfo * catch_info,bool * ok)1736 void Parser::RewriteCatchPattern(CatchInfo* catch_info, bool* ok) {
1737 if (catch_info->name == nullptr) {
1738 DCHECK_NOT_NULL(catch_info->pattern);
1739 catch_info->name = ast_value_factory()->dot_catch_string();
1740 }
1741 catch_info->variable = catch_info->scope->DeclareLocal(
1742 catch_info->name, VAR, kCreatedInitialized, NORMAL_VARIABLE);
1743 if (catch_info->pattern != nullptr) {
1744 DeclarationDescriptor descriptor;
1745 descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
1746 descriptor.scope = scope();
1747 descriptor.hoist_scope = nullptr;
1748 descriptor.mode = LET;
1749 descriptor.declaration_pos = catch_info->pattern->position();
1750 descriptor.initialization_pos = catch_info->pattern->position();
1751
1752 // Initializer position for variables declared by the pattern.
1753 const int initializer_position = position();
1754
1755 DeclarationParsingResult::Declaration decl(
1756 catch_info->pattern, initializer_position,
1757 factory()->NewVariableProxy(catch_info->variable));
1758
1759 catch_info->init_block =
1760 factory()->NewBlock(nullptr, 8, true, kNoSourcePosition);
1761 PatternRewriter::DeclareAndInitializeVariables(
1762 this, catch_info->init_block, &descriptor, &decl,
1763 &catch_info->bound_names, ok);
1764 } else {
1765 catch_info->bound_names.Add(catch_info->name, zone());
1766 }
1767 }
1768
ValidateCatchBlock(const CatchInfo & catch_info,bool * ok)1769 void Parser::ValidateCatchBlock(const CatchInfo& catch_info, bool* ok) {
1770 // Check for `catch(e) { let e; }` and similar errors.
1771 Scope* inner_block_scope = catch_info.inner_block->scope();
1772 if (inner_block_scope != nullptr) {
1773 Declaration* decl = inner_block_scope->CheckLexDeclarationsConflictingWith(
1774 catch_info.bound_names);
1775 if (decl != nullptr) {
1776 const AstRawString* name = decl->proxy()->raw_name();
1777 int position = decl->proxy()->position();
1778 Scanner::Location location =
1779 position == kNoSourcePosition
1780 ? Scanner::Location::invalid()
1781 : Scanner::Location(position, position + 1);
1782 ReportMessageAt(location, MessageTemplate::kVarRedeclaration, name);
1783 *ok = false;
1784 }
1785 }
1786 }
1787
RewriteTryStatement(Block * try_block,Block * catch_block,Block * finally_block,const CatchInfo & catch_info,int pos)1788 Statement* Parser::RewriteTryStatement(Block* try_block, Block* catch_block,
1789 Block* finally_block,
1790 const CatchInfo& catch_info, int pos) {
1791 // Simplify the AST nodes by converting:
1792 // 'try B0 catch B1 finally B2'
1793 // to:
1794 // 'try { try B0 catch B1 } finally B2'
1795
1796 if (catch_block != nullptr && finally_block != nullptr) {
1797 // If we have both, create an inner try/catch.
1798 DCHECK_NOT_NULL(catch_info.scope);
1799 DCHECK_NOT_NULL(catch_info.variable);
1800 TryCatchStatement* statement;
1801 if (catch_info.for_promise_reject) {
1802 statement = factory()->NewTryCatchStatementForPromiseReject(
1803 try_block, catch_info.scope, catch_info.variable, catch_block,
1804 kNoSourcePosition);
1805 } else {
1806 statement = factory()->NewTryCatchStatement(
1807 try_block, catch_info.scope, catch_info.variable, catch_block,
1808 kNoSourcePosition);
1809 }
1810
1811 try_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
1812 try_block->statements()->Add(statement, zone());
1813 catch_block = nullptr; // Clear to indicate it's been handled.
1814 }
1815
1816 if (catch_block != nullptr) {
1817 // For a try-catch construct append return expressions from the catch block
1818 // to the list of return expressions.
1819 function_state_->tail_call_expressions().Append(
1820 catch_info.tail_call_expressions);
1821
1822 DCHECK_NULL(finally_block);
1823 DCHECK_NOT_NULL(catch_info.scope);
1824 DCHECK_NOT_NULL(catch_info.variable);
1825 return factory()->NewTryCatchStatement(
1826 try_block, catch_info.scope, catch_info.variable, catch_block, pos);
1827 } else {
1828 DCHECK_NOT_NULL(finally_block);
1829 return factory()->NewTryFinallyStatement(try_block, finally_block, pos);
1830 }
1831 }
1832
1833 // !%_IsJSReceiver(result = iterator.next()) &&
1834 // %ThrowIteratorResultNotAnObject(result)
BuildIteratorNextResult(Expression * iterator,Variable * result,int pos)1835 Expression* Parser::BuildIteratorNextResult(Expression* iterator,
1836 Variable* result, int pos) {
1837 Expression* next_literal = factory()->NewStringLiteral(
1838 ast_value_factory()->next_string(), kNoSourcePosition);
1839 Expression* next_property =
1840 factory()->NewProperty(iterator, next_literal, kNoSourcePosition);
1841 ZoneList<Expression*>* next_arguments =
1842 new (zone()) ZoneList<Expression*>(0, zone());
1843 Expression* next_call =
1844 factory()->NewCall(next_property, next_arguments, pos);
1845 Expression* result_proxy = factory()->NewVariableProxy(result);
1846 Expression* left =
1847 factory()->NewAssignment(Token::ASSIGN, result_proxy, next_call, pos);
1848
1849 // %_IsJSReceiver(...)
1850 ZoneList<Expression*>* is_spec_object_args =
1851 new (zone()) ZoneList<Expression*>(1, zone());
1852 is_spec_object_args->Add(left, zone());
1853 Expression* is_spec_object_call = factory()->NewCallRuntime(
1854 Runtime::kInlineIsJSReceiver, is_spec_object_args, pos);
1855
1856 // %ThrowIteratorResultNotAnObject(result)
1857 Expression* result_proxy_again = factory()->NewVariableProxy(result);
1858 ZoneList<Expression*>* throw_arguments =
1859 new (zone()) ZoneList<Expression*>(1, zone());
1860 throw_arguments->Add(result_proxy_again, zone());
1861 Expression* throw_call = factory()->NewCallRuntime(
1862 Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos);
1863
1864 return factory()->NewBinaryOperation(
1865 Token::AND,
1866 factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos),
1867 throw_call, pos);
1868 }
1869
InitializeForEachStatement(ForEachStatement * stmt,Expression * each,Expression * subject,Statement * body,int each_keyword_pos)1870 Statement* Parser::InitializeForEachStatement(ForEachStatement* stmt,
1871 Expression* each,
1872 Expression* subject,
1873 Statement* body,
1874 int each_keyword_pos) {
1875 ForOfStatement* for_of = stmt->AsForOfStatement();
1876 if (for_of != NULL) {
1877 const bool finalize = true;
1878 return InitializeForOfStatement(for_of, each, subject, body, finalize,
1879 each_keyword_pos);
1880 } else {
1881 if (each->IsArrayLiteral() || each->IsObjectLiteral()) {
1882 Variable* temp = NewTemporary(ast_value_factory()->empty_string());
1883 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
1884 Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment(
1885 this, factory()->NewAssignment(Token::ASSIGN, each, temp_proxy,
1886 kNoSourcePosition),
1887 scope());
1888 auto block = factory()->NewBlock(nullptr, 2, false, kNoSourcePosition);
1889 block->statements()->Add(
1890 factory()->NewExpressionStatement(assign_each, kNoSourcePosition),
1891 zone());
1892 block->statements()->Add(body, zone());
1893 body = block;
1894 each = factory()->NewVariableProxy(temp);
1895 }
1896 stmt->AsForInStatement()->Initialize(each, subject, body);
1897 }
1898 return stmt;
1899 }
1900
1901 // Special case for legacy for
1902 //
1903 // for (var x = initializer in enumerable) body
1904 //
1905 // An initialization block of the form
1906 //
1907 // {
1908 // x = initializer;
1909 // }
1910 //
1911 // is returned in this case. It has reserved space for two statements,
1912 // so that (later on during parsing), the equivalent of
1913 //
1914 // for (x in enumerable) body
1915 //
1916 // is added as a second statement to it.
RewriteForVarInLegacy(const ForInfo & for_info)1917 Block* Parser::RewriteForVarInLegacy(const ForInfo& for_info) {
1918 const DeclarationParsingResult::Declaration& decl =
1919 for_info.parsing_result.declarations[0];
1920 if (!IsLexicalVariableMode(for_info.parsing_result.descriptor.mode) &&
1921 decl.pattern->IsVariableProxy() && decl.initializer != nullptr) {
1922 ++use_counts_[v8::Isolate::kForInInitializer];
1923 const AstRawString* name = decl.pattern->AsVariableProxy()->raw_name();
1924 VariableProxy* single_var = NewUnresolved(name);
1925 Block* init_block = factory()->NewBlock(
1926 nullptr, 2, true, for_info.parsing_result.descriptor.declaration_pos);
1927 init_block->statements()->Add(
1928 factory()->NewExpressionStatement(
1929 factory()->NewAssignment(Token::ASSIGN, single_var,
1930 decl.initializer, kNoSourcePosition),
1931 kNoSourcePosition),
1932 zone());
1933 return init_block;
1934 }
1935 return nullptr;
1936 }
1937
1938 // Rewrite a for-in/of statement of the form
1939 //
1940 // for (let/const/var x in/of e) b
1941 //
1942 // into
1943 //
1944 // {
1945 // <let x' be a temporary variable>
1946 // for (x' in/of e) {
1947 // let/const/var x;
1948 // x = x';
1949 // b;
1950 // }
1951 // let x; // for TDZ
1952 // }
DesugarBindingInForEachStatement(ForInfo * for_info,Block ** body_block,Expression ** each_variable,bool * ok)1953 void Parser::DesugarBindingInForEachStatement(ForInfo* for_info,
1954 Block** body_block,
1955 Expression** each_variable,
1956 bool* ok) {
1957 DeclarationParsingResult::Declaration& decl =
1958 for_info->parsing_result.declarations[0];
1959 Variable* temp = NewTemporary(ast_value_factory()->dot_for_string());
1960 auto each_initialization_block =
1961 factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
1962 {
1963 auto descriptor = for_info->parsing_result.descriptor;
1964 descriptor.declaration_pos = kNoSourcePosition;
1965 descriptor.initialization_pos = kNoSourcePosition;
1966 decl.initializer = factory()->NewVariableProxy(temp);
1967
1968 bool is_for_var_of =
1969 for_info->mode == ForEachStatement::ITERATE &&
1970 for_info->parsing_result.descriptor.mode == VariableMode::VAR;
1971
1972 PatternRewriter::DeclareAndInitializeVariables(
1973 this, each_initialization_block, &descriptor, &decl,
1974 (IsLexicalVariableMode(for_info->parsing_result.descriptor.mode) ||
1975 is_for_var_of)
1976 ? &for_info->bound_names
1977 : nullptr,
1978 CHECK_OK_VOID);
1979
1980 // Annex B.3.5 prohibits the form
1981 // `try {} catch(e) { for (var e of {}); }`
1982 // So if we are parsing a statement like `for (var ... of ...)`
1983 // we need to walk up the scope chain and look for catch scopes
1984 // which have a simple binding, then compare their binding against
1985 // all of the names declared in the init of the for-of we're
1986 // parsing.
1987 if (is_for_var_of) {
1988 Scope* catch_scope = scope();
1989 while (catch_scope != nullptr && !catch_scope->is_declaration_scope()) {
1990 if (catch_scope->is_catch_scope()) {
1991 auto name = catch_scope->catch_variable_name();
1992 // If it's a simple binding and the name is declared in the for loop.
1993 if (name != ast_value_factory()->dot_catch_string() &&
1994 for_info->bound_names.Contains(name)) {
1995 ReportMessageAt(for_info->parsing_result.bindings_loc,
1996 MessageTemplate::kVarRedeclaration, name);
1997 *ok = false;
1998 return;
1999 }
2000 }
2001 catch_scope = catch_scope->outer_scope();
2002 }
2003 }
2004 }
2005
2006 *body_block = factory()->NewBlock(nullptr, 3, false, kNoSourcePosition);
2007 (*body_block)->statements()->Add(each_initialization_block, zone());
2008 *each_variable = factory()->NewVariableProxy(temp, for_info->position);
2009 }
2010
2011 // Create a TDZ for any lexically-bound names in for in/of statements.
CreateForEachStatementTDZ(Block * init_block,const ForInfo & for_info,bool * ok)2012 Block* Parser::CreateForEachStatementTDZ(Block* init_block,
2013 const ForInfo& for_info, bool* ok) {
2014 if (IsLexicalVariableMode(for_info.parsing_result.descriptor.mode)) {
2015 DCHECK_NULL(init_block);
2016
2017 init_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
2018
2019 for (int i = 0; i < for_info.bound_names.length(); ++i) {
2020 // TODO(adamk): This needs to be some sort of special
2021 // INTERNAL variable that's invisible to the debugger
2022 // but visible to everything else.
2023 Declaration* tdz_decl = DeclareVariable(for_info.bound_names[i], LET,
2024 kNoSourcePosition, CHECK_OK);
2025 tdz_decl->proxy()->var()->set_initializer_position(position());
2026 }
2027 }
2028 return init_block;
2029 }
2030
InitializeForOfStatement(ForOfStatement * for_of,Expression * each,Expression * iterable,Statement * body,bool finalize,int next_result_pos)2031 Statement* Parser::InitializeForOfStatement(ForOfStatement* for_of,
2032 Expression* each,
2033 Expression* iterable,
2034 Statement* body, bool finalize,
2035 int next_result_pos) {
2036 // Create the auxiliary expressions needed for iterating over the iterable,
2037 // and initialize the given ForOfStatement with them.
2038 // If finalize is true, also instrument the loop with code that performs the
2039 // proper ES6 iterator finalization. In that case, the result is not
2040 // immediately a ForOfStatement.
2041
2042 const int nopos = kNoSourcePosition;
2043 auto avfactory = ast_value_factory();
2044
2045 Variable* iterator = NewTemporary(ast_value_factory()->dot_iterator_string());
2046 Variable* result = NewTemporary(ast_value_factory()->dot_result_string());
2047 Variable* completion = NewTemporary(avfactory->empty_string());
2048
2049 // iterator = iterable[Symbol.iterator]()
2050 Expression* assign_iterator;
2051 {
2052 assign_iterator = factory()->NewAssignment(
2053 Token::ASSIGN, factory()->NewVariableProxy(iterator),
2054 GetIterator(iterable, iterable->position()), iterable->position());
2055 }
2056
2057 // !%_IsJSReceiver(result = iterator.next()) &&
2058 // %ThrowIteratorResultNotAnObject(result)
2059 Expression* next_result;
2060 {
2061 Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
2062 next_result =
2063 BuildIteratorNextResult(iterator_proxy, result, next_result_pos);
2064 }
2065
2066 // result.done
2067 Expression* result_done;
2068 {
2069 Expression* done_literal = factory()->NewStringLiteral(
2070 ast_value_factory()->done_string(), kNoSourcePosition);
2071 Expression* result_proxy = factory()->NewVariableProxy(result);
2072 result_done =
2073 factory()->NewProperty(result_proxy, done_literal, kNoSourcePosition);
2074 }
2075
2076 // result.value
2077 Expression* result_value;
2078 {
2079 Expression* value_literal =
2080 factory()->NewStringLiteral(avfactory->value_string(), nopos);
2081 Expression* result_proxy = factory()->NewVariableProxy(result);
2082 result_value = factory()->NewProperty(result_proxy, value_literal, nopos);
2083 }
2084
2085 // {{completion = kAbruptCompletion;}}
2086 Statement* set_completion_abrupt;
2087 if (finalize) {
2088 Expression* proxy = factory()->NewVariableProxy(completion);
2089 Expression* assignment = factory()->NewAssignment(
2090 Token::ASSIGN, proxy,
2091 factory()->NewSmiLiteral(Parser::kAbruptCompletion, nopos), nopos);
2092
2093 Block* block = factory()->NewBlock(nullptr, 1, true, nopos);
2094 block->statements()->Add(
2095 factory()->NewExpressionStatement(assignment, nopos), zone());
2096 set_completion_abrupt = block;
2097 }
2098
2099 // do { let tmp = #result_value; #set_completion_abrupt; tmp }
2100 // Expression* result_value (gets overwritten)
2101 if (finalize) {
2102 Variable* var_tmp = NewTemporary(avfactory->empty_string());
2103 Expression* tmp = factory()->NewVariableProxy(var_tmp);
2104 Expression* assignment =
2105 factory()->NewAssignment(Token::ASSIGN, tmp, result_value, nopos);
2106
2107 Block* block = factory()->NewBlock(nullptr, 2, false, nopos);
2108 block->statements()->Add(
2109 factory()->NewExpressionStatement(assignment, nopos), zone());
2110 block->statements()->Add(set_completion_abrupt, zone());
2111
2112 result_value = factory()->NewDoExpression(block, var_tmp, nopos);
2113 }
2114
2115 // each = #result_value;
2116 Expression* assign_each;
2117 {
2118 assign_each =
2119 factory()->NewAssignment(Token::ASSIGN, each, result_value, nopos);
2120 if (each->IsArrayLiteral() || each->IsObjectLiteral()) {
2121 assign_each = PatternRewriter::RewriteDestructuringAssignment(
2122 this, assign_each->AsAssignment(), scope());
2123 }
2124 }
2125
2126 // {{completion = kNormalCompletion;}}
2127 Statement* set_completion_normal;
2128 if (finalize) {
2129 Expression* proxy = factory()->NewVariableProxy(completion);
2130 Expression* assignment = factory()->NewAssignment(
2131 Token::ASSIGN, proxy,
2132 factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
2133
2134 Block* block = factory()->NewBlock(nullptr, 1, true, nopos);
2135 block->statements()->Add(
2136 factory()->NewExpressionStatement(assignment, nopos), zone());
2137 set_completion_normal = block;
2138 }
2139
2140 // { #loop-body; #set_completion_normal }
2141 // Statement* body (gets overwritten)
2142 if (finalize) {
2143 Block* block = factory()->NewBlock(nullptr, 2, false, nopos);
2144 block->statements()->Add(body, zone());
2145 block->statements()->Add(set_completion_normal, zone());
2146 body = block;
2147 }
2148
2149 for_of->Initialize(body, iterator, assign_iterator, next_result, result_done,
2150 assign_each);
2151 return finalize ? FinalizeForOfStatement(for_of, completion, nopos) : for_of;
2152 }
2153
DesugarLexicalBindingsInForStatement(ForStatement * loop,Statement * init,Expression * cond,Statement * next,Statement * body,Scope * inner_scope,const ForInfo & for_info,bool * ok)2154 Statement* Parser::DesugarLexicalBindingsInForStatement(
2155 ForStatement* loop, Statement* init, Expression* cond, Statement* next,
2156 Statement* body, Scope* inner_scope, const ForInfo& for_info, bool* ok) {
2157 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are
2158 // copied into a new environment. Moreover, the "next" statement must be
2159 // evaluated not in the environment of the just completed iteration but in
2160 // that of the upcoming one. We achieve this with the following desugaring.
2161 // Extra care is needed to preserve the completion value of the original loop.
2162 //
2163 // We are given a for statement of the form
2164 //
2165 // labels: for (let/const x = i; cond; next) body
2166 //
2167 // and rewrite it as follows. Here we write {{ ... }} for init-blocks, ie.,
2168 // blocks whose ignore_completion_value_ flag is set.
2169 //
2170 // {
2171 // let/const x = i;
2172 // temp_x = x;
2173 // first = 1;
2174 // undefined;
2175 // outer: for (;;) {
2176 // let/const x = temp_x;
2177 // {{ if (first == 1) {
2178 // first = 0;
2179 // } else {
2180 // next;
2181 // }
2182 // flag = 1;
2183 // if (!cond) break;
2184 // }}
2185 // labels: for (; flag == 1; flag = 0, temp_x = x) {
2186 // body
2187 // }
2188 // {{ if (flag == 1) // Body used break.
2189 // break;
2190 // }}
2191 // }
2192 // }
2193
2194 DCHECK(for_info.bound_names.length() > 0);
2195 ZoneList<Variable*> temps(for_info.bound_names.length(), zone());
2196
2197 Block* outer_block = factory()->NewBlock(
2198 nullptr, for_info.bound_names.length() + 4, false, kNoSourcePosition);
2199
2200 // Add statement: let/const x = i.
2201 outer_block->statements()->Add(init, zone());
2202
2203 const AstRawString* temp_name = ast_value_factory()->dot_for_string();
2204
2205 // For each lexical variable x:
2206 // make statement: temp_x = x.
2207 for (int i = 0; i < for_info.bound_names.length(); i++) {
2208 VariableProxy* proxy = NewUnresolved(for_info.bound_names[i]);
2209 Variable* temp = NewTemporary(temp_name);
2210 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
2211 Assignment* assignment = factory()->NewAssignment(Token::ASSIGN, temp_proxy,
2212 proxy, kNoSourcePosition);
2213 Statement* assignment_statement =
2214 factory()->NewExpressionStatement(assignment, kNoSourcePosition);
2215 outer_block->statements()->Add(assignment_statement, zone());
2216 temps.Add(temp, zone());
2217 }
2218
2219 Variable* first = NULL;
2220 // Make statement: first = 1.
2221 if (next) {
2222 first = NewTemporary(temp_name);
2223 VariableProxy* first_proxy = factory()->NewVariableProxy(first);
2224 Expression* const1 = factory()->NewSmiLiteral(1, kNoSourcePosition);
2225 Assignment* assignment = factory()->NewAssignment(
2226 Token::ASSIGN, first_proxy, const1, kNoSourcePosition);
2227 Statement* assignment_statement =
2228 factory()->NewExpressionStatement(assignment, kNoSourcePosition);
2229 outer_block->statements()->Add(assignment_statement, zone());
2230 }
2231
2232 // make statement: undefined;
2233 outer_block->statements()->Add(
2234 factory()->NewExpressionStatement(
2235 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition),
2236 zone());
2237
2238 // Make statement: outer: for (;;)
2239 // Note that we don't actually create the label, or set this loop up as an
2240 // explicit break target, instead handing it directly to those nodes that
2241 // need to know about it. This should be safe because we don't run any code
2242 // in this function that looks up break targets.
2243 ForStatement* outer_loop =
2244 factory()->NewForStatement(NULL, kNoSourcePosition);
2245 outer_block->statements()->Add(outer_loop, zone());
2246 outer_block->set_scope(scope());
2247
2248 Block* inner_block = factory()->NewBlock(NULL, 3, false, kNoSourcePosition);
2249 {
2250 BlockState block_state(&scope_state_, inner_scope);
2251
2252 Block* ignore_completion_block = factory()->NewBlock(
2253 nullptr, for_info.bound_names.length() + 3, true, kNoSourcePosition);
2254 ZoneList<Variable*> inner_vars(for_info.bound_names.length(), zone());
2255 // For each let variable x:
2256 // make statement: let/const x = temp_x.
2257 for (int i = 0; i < for_info.bound_names.length(); i++) {
2258 Declaration* decl = DeclareVariable(
2259 for_info.bound_names[i], for_info.parsing_result.descriptor.mode,
2260 kNoSourcePosition, CHECK_OK);
2261 inner_vars.Add(decl->proxy()->var(), zone());
2262 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
2263 Assignment* assignment = factory()->NewAssignment(
2264 Token::INIT, decl->proxy(), temp_proxy, kNoSourcePosition);
2265 Statement* assignment_statement =
2266 factory()->NewExpressionStatement(assignment, kNoSourcePosition);
2267 DCHECK(init->position() != kNoSourcePosition);
2268 decl->proxy()->var()->set_initializer_position(init->position());
2269 ignore_completion_block->statements()->Add(assignment_statement, zone());
2270 }
2271
2272 // Make statement: if (first == 1) { first = 0; } else { next; }
2273 if (next) {
2274 DCHECK(first);
2275 Expression* compare = NULL;
2276 // Make compare expression: first == 1.
2277 {
2278 Expression* const1 = factory()->NewSmiLiteral(1, kNoSourcePosition);
2279 VariableProxy* first_proxy = factory()->NewVariableProxy(first);
2280 compare = factory()->NewCompareOperation(Token::EQ, first_proxy, const1,
2281 kNoSourcePosition);
2282 }
2283 Statement* clear_first = NULL;
2284 // Make statement: first = 0.
2285 {
2286 VariableProxy* first_proxy = factory()->NewVariableProxy(first);
2287 Expression* const0 = factory()->NewSmiLiteral(0, kNoSourcePosition);
2288 Assignment* assignment = factory()->NewAssignment(
2289 Token::ASSIGN, first_proxy, const0, kNoSourcePosition);
2290 clear_first =
2291 factory()->NewExpressionStatement(assignment, kNoSourcePosition);
2292 }
2293 Statement* clear_first_or_next = factory()->NewIfStatement(
2294 compare, clear_first, next, kNoSourcePosition);
2295 ignore_completion_block->statements()->Add(clear_first_or_next, zone());
2296 }
2297
2298 Variable* flag = NewTemporary(temp_name);
2299 // Make statement: flag = 1.
2300 {
2301 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
2302 Expression* const1 = factory()->NewSmiLiteral(1, kNoSourcePosition);
2303 Assignment* assignment = factory()->NewAssignment(
2304 Token::ASSIGN, flag_proxy, const1, kNoSourcePosition);
2305 Statement* assignment_statement =
2306 factory()->NewExpressionStatement(assignment, kNoSourcePosition);
2307 ignore_completion_block->statements()->Add(assignment_statement, zone());
2308 }
2309
2310 // Make statement: if (!cond) break.
2311 if (cond) {
2312 Statement* stop =
2313 factory()->NewBreakStatement(outer_loop, kNoSourcePosition);
2314 Statement* noop = factory()->NewEmptyStatement(kNoSourcePosition);
2315 ignore_completion_block->statements()->Add(
2316 factory()->NewIfStatement(cond, noop, stop, cond->position()),
2317 zone());
2318 }
2319
2320 inner_block->statements()->Add(ignore_completion_block, zone());
2321 // Make cond expression for main loop: flag == 1.
2322 Expression* flag_cond = NULL;
2323 {
2324 Expression* const1 = factory()->NewSmiLiteral(1, kNoSourcePosition);
2325 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
2326 flag_cond = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
2327 kNoSourcePosition);
2328 }
2329
2330 // Create chain of expressions "flag = 0, temp_x = x, ..."
2331 Statement* compound_next_statement = NULL;
2332 {
2333 Expression* compound_next = NULL;
2334 // Make expression: flag = 0.
2335 {
2336 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
2337 Expression* const0 = factory()->NewSmiLiteral(0, kNoSourcePosition);
2338 compound_next = factory()->NewAssignment(Token::ASSIGN, flag_proxy,
2339 const0, kNoSourcePosition);
2340 }
2341
2342 // Make the comma-separated list of temp_x = x assignments.
2343 int inner_var_proxy_pos = scanner()->location().beg_pos;
2344 for (int i = 0; i < for_info.bound_names.length(); i++) {
2345 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
2346 VariableProxy* proxy =
2347 factory()->NewVariableProxy(inner_vars.at(i), inner_var_proxy_pos);
2348 Assignment* assignment = factory()->NewAssignment(
2349 Token::ASSIGN, temp_proxy, proxy, kNoSourcePosition);
2350 compound_next = factory()->NewBinaryOperation(
2351 Token::COMMA, compound_next, assignment, kNoSourcePosition);
2352 }
2353
2354 compound_next_statement =
2355 factory()->NewExpressionStatement(compound_next, kNoSourcePosition);
2356 }
2357
2358 // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x)
2359 // Note that we re-use the original loop node, which retains its labels
2360 // and ensures that any break or continue statements in body point to
2361 // the right place.
2362 loop->Initialize(NULL, flag_cond, compound_next_statement, body);
2363 inner_block->statements()->Add(loop, zone());
2364
2365 // Make statement: {{if (flag == 1) break;}}
2366 {
2367 Expression* compare = NULL;
2368 // Make compare expresion: flag == 1.
2369 {
2370 Expression* const1 = factory()->NewSmiLiteral(1, kNoSourcePosition);
2371 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
2372 compare = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
2373 kNoSourcePosition);
2374 }
2375 Statement* stop =
2376 factory()->NewBreakStatement(outer_loop, kNoSourcePosition);
2377 Statement* empty = factory()->NewEmptyStatement(kNoSourcePosition);
2378 Statement* if_flag_break =
2379 factory()->NewIfStatement(compare, stop, empty, kNoSourcePosition);
2380 Block* ignore_completion_block =
2381 factory()->NewBlock(NULL, 1, true, kNoSourcePosition);
2382 ignore_completion_block->statements()->Add(if_flag_break, zone());
2383 inner_block->statements()->Add(ignore_completion_block, zone());
2384 }
2385
2386 inner_scope->set_end_position(scanner()->location().end_pos);
2387 inner_block->set_scope(inner_scope);
2388 }
2389
2390 outer_loop->Initialize(NULL, NULL, NULL, inner_block);
2391 return outer_block;
2392 }
2393
AddArrowFunctionFormalParameters(ParserFormalParameters * parameters,Expression * expr,int end_pos,bool * ok)2394 void Parser::AddArrowFunctionFormalParameters(
2395 ParserFormalParameters* parameters, Expression* expr, int end_pos,
2396 bool* ok) {
2397 // ArrowFunctionFormals ::
2398 // Binary(Token::COMMA, NonTailArrowFunctionFormals, Tail)
2399 // Tail
2400 // NonTailArrowFunctionFormals ::
2401 // Binary(Token::COMMA, NonTailArrowFunctionFormals, VariableProxy)
2402 // VariableProxy
2403 // Tail ::
2404 // VariableProxy
2405 // Spread(VariableProxy)
2406 //
2407 // As we need to visit the parameters in left-to-right order, we recurse on
2408 // the left-hand side of comma expressions.
2409 //
2410 if (expr->IsBinaryOperation()) {
2411 BinaryOperation* binop = expr->AsBinaryOperation();
2412 // The classifier has already run, so we know that the expression is a valid
2413 // arrow function formals production.
2414 DCHECK_EQ(binop->op(), Token::COMMA);
2415 Expression* left = binop->left();
2416 Expression* right = binop->right();
2417 int comma_pos = binop->position();
2418 AddArrowFunctionFormalParameters(parameters, left, comma_pos,
2419 CHECK_OK_VOID);
2420 // LHS of comma expression should be unparenthesized.
2421 expr = right;
2422 }
2423
2424 // Only the right-most expression may be a rest parameter.
2425 DCHECK(!parameters->has_rest);
2426
2427 bool is_rest = expr->IsSpread();
2428 if (is_rest) {
2429 expr = expr->AsSpread()->expression();
2430 parameters->has_rest = true;
2431 }
2432 if (parameters->is_simple) {
2433 parameters->is_simple = !is_rest && expr->IsVariableProxy();
2434 }
2435
2436 Expression* initializer = nullptr;
2437 if (expr->IsAssignment()) {
2438 Assignment* assignment = expr->AsAssignment();
2439 DCHECK(!assignment->is_compound());
2440 initializer = assignment->value();
2441 expr = assignment->target();
2442 }
2443
2444 AddFormalParameter(parameters, expr, initializer, end_pos, is_rest);
2445 }
2446
DeclareArrowFunctionFormalParameters(ParserFormalParameters * parameters,Expression * expr,const Scanner::Location & params_loc,Scanner::Location * duplicate_loc,bool * ok)2447 void Parser::DeclareArrowFunctionFormalParameters(
2448 ParserFormalParameters* parameters, Expression* expr,
2449 const Scanner::Location& params_loc, Scanner::Location* duplicate_loc,
2450 bool* ok) {
2451 if (expr->IsEmptyParentheses()) return;
2452
2453 AddArrowFunctionFormalParameters(parameters, expr, params_loc.end_pos,
2454 CHECK_OK_VOID);
2455
2456 if (parameters->arity > Code::kMaxArguments) {
2457 ReportMessageAt(params_loc, MessageTemplate::kMalformedArrowFunParamList);
2458 *ok = false;
2459 return;
2460 }
2461
2462 ExpressionClassifier classifier(this);
2463 if (!parameters->is_simple) {
2464 this->classifier()->RecordNonSimpleParameter();
2465 }
2466 for (int i = 0; i < parameters->arity; ++i) {
2467 auto parameter = parameters->at(i);
2468 DeclareFormalParameter(parameters->scope, parameter);
2469 if (!this->classifier()
2470 ->is_valid_formal_parameter_list_without_duplicates() &&
2471 !duplicate_loc->IsValid()) {
2472 *duplicate_loc =
2473 this->classifier()->duplicate_formal_parameter_error().location;
2474 }
2475 }
2476 DCHECK_EQ(parameters->is_simple, parameters->scope->has_simple_parameters());
2477 }
2478
ReindexLiterals(const ParserFormalParameters & parameters)2479 void Parser::ReindexLiterals(const ParserFormalParameters& parameters) {
2480 if (function_state_->materialized_literal_count() > 0) {
2481 AstLiteralReindexer reindexer;
2482
2483 for (const auto p : parameters.params) {
2484 if (p.pattern != nullptr) reindexer.Reindex(p.pattern);
2485 if (p.initializer != nullptr) reindexer.Reindex(p.initializer);
2486 }
2487
2488 DCHECK(reindexer.count() <= function_state_->materialized_literal_count());
2489 }
2490 }
2491
PrepareGeneratorVariables(FunctionState * function_state)2492 void Parser::PrepareGeneratorVariables(FunctionState* function_state) {
2493 // For generators, allocating variables in contexts is currently a win
2494 // because it minimizes the work needed to suspend and resume an
2495 // activation. The machine code produced for generators (by full-codegen)
2496 // relies on this forced context allocation, but not in an essential way.
2497 scope()->ForceContextAllocation();
2498
2499 // Calling a generator returns a generator object. That object is stored
2500 // in a temporary variable, a definition that is used by "yield"
2501 // expressions.
2502 Variable* temp =
2503 NewTemporary(ast_value_factory()->dot_generator_object_string());
2504 function_state->set_generator_object_variable(temp);
2505 }
2506
ParseFunctionLiteral(const AstRawString * function_name,Scanner::Location function_name_location,FunctionNameValidity function_name_validity,FunctionKind kind,int function_token_pos,FunctionLiteral::FunctionType function_type,LanguageMode language_mode,bool * ok)2507 FunctionLiteral* Parser::ParseFunctionLiteral(
2508 const AstRawString* function_name, Scanner::Location function_name_location,
2509 FunctionNameValidity function_name_validity, FunctionKind kind,
2510 int function_token_pos, FunctionLiteral::FunctionType function_type,
2511 LanguageMode language_mode, bool* ok) {
2512 // Function ::
2513 // '(' FormalParameterList? ')' '{' FunctionBody '}'
2514 //
2515 // Getter ::
2516 // '(' ')' '{' FunctionBody '}'
2517 //
2518 // Setter ::
2519 // '(' PropertySetParameterList ')' '{' FunctionBody '}'
2520
2521 int pos = function_token_pos == kNoSourcePosition ? peek_position()
2522 : function_token_pos;
2523
2524 // Anonymous functions were passed either the empty symbol or a null
2525 // handle as the function name. Remember if we were passed a non-empty
2526 // handle to decide whether to invoke function name inference.
2527 bool should_infer_name = function_name == NULL;
2528
2529 // We want a non-null handle as the function name.
2530 if (should_infer_name) {
2531 function_name = ast_value_factory()->empty_string();
2532 }
2533
2534 FunctionLiteral::EagerCompileHint eager_compile_hint =
2535 function_state_->next_function_is_parenthesized()
2536 ? FunctionLiteral::kShouldEagerCompile
2537 : default_eager_compile_hint();
2538
2539 // Determine if the function can be parsed lazily. Lazy parsing is
2540 // different from lazy compilation; we need to parse more eagerly than we
2541 // compile.
2542
2543 // We can only parse lazily if we also compile lazily. The heuristics for lazy
2544 // compilation are:
2545 // - It must not have been prohibited by the caller to Parse (some callers
2546 // need a full AST).
2547 // - The outer scope must allow lazy compilation of inner functions.
2548 // - The function mustn't be a function expression with an open parenthesis
2549 // before; we consider that a hint that the function will be called
2550 // immediately, and it would be a waste of time to make it lazily
2551 // compiled.
2552 // These are all things we can know at this point, without looking at the
2553 // function itself.
2554
2555 // We separate between lazy parsing top level functions and lazy parsing inner
2556 // functions, because the latter needs to do more work. In particular, we need
2557 // to track unresolved variables to distinguish between these cases:
2558 // (function foo() {
2559 // bar = function() { return 1; }
2560 // })();
2561 // and
2562 // (function foo() {
2563 // var a = 1;
2564 // bar = function() { return a; }
2565 // })();
2566
2567 // Now foo will be parsed eagerly and compiled eagerly (optimization: assume
2568 // parenthesis before the function means that it will be called
2569 // immediately). bar can be parsed lazily, but we need to parse it in a mode
2570 // that tracks unresolved variables.
2571 DCHECK_IMPLIES(parse_lazily(), FLAG_lazy);
2572 DCHECK_IMPLIES(parse_lazily(), allow_lazy());
2573 DCHECK_IMPLIES(parse_lazily(), extension_ == nullptr);
2574
2575 bool can_preparse = parse_lazily() &&
2576 eager_compile_hint == FunctionLiteral::kShouldLazyCompile;
2577
2578 bool is_lazy_top_level_function =
2579 can_preparse && impl()->AllowsLazyParsingWithoutUnresolvedVariables();
2580
2581 RuntimeCallTimerScope runtime_timer(runtime_call_stats_,
2582 &RuntimeCallStats::ParseFunctionLiteral);
2583
2584 // Determine whether we can still lazy parse the inner function.
2585 // The preconditions are:
2586 // - Lazy compilation has to be enabled.
2587 // - Neither V8 natives nor native function declarations can be allowed,
2588 // since parsing one would retroactively force the function to be
2589 // eagerly compiled.
2590 // - The invoker of this parser can't depend on the AST being eagerly
2591 // built (either because the function is about to be compiled, or
2592 // because the AST is going to be inspected for some reason).
2593 // - Because of the above, we can't be attempting to parse a
2594 // FunctionExpression; even without enclosing parentheses it might be
2595 // immediately invoked.
2596 // - The function literal shouldn't be hinted to eagerly compile.
2597 // - For asm.js functions the body needs to be available when module
2598 // validation is active, because we examine the entire module at once.
2599
2600 // Inner functions will be parsed using a temporary Zone. After parsing, we
2601 // will migrate unresolved variable into a Scope in the main Zone.
2602 // TODO(marja): Refactor parsing modes: simplify this.
2603 bool use_temp_zone =
2604 (FLAG_lazy_inner_functions
2605 ? can_preparse
2606 : (is_lazy_top_level_function ||
2607 (allow_lazy() && function_type == FunctionLiteral::kDeclaration &&
2608 eager_compile_hint == FunctionLiteral::kShouldLazyCompile))) &&
2609 !(FLAG_validate_asm && scope()->IsAsmModule());
2610 bool is_lazy_inner_function =
2611 use_temp_zone && FLAG_lazy_inner_functions && !is_lazy_top_level_function;
2612
2613 // This Scope lives in the main zone. We'll migrate data into that zone later.
2614 DeclarationScope* scope = NewFunctionScope(kind);
2615 SetLanguageMode(scope, language_mode);
2616 #ifdef DEBUG
2617 scope->SetScopeName(function_name);
2618 #endif
2619
2620 ZoneList<Statement*>* body = nullptr;
2621 int materialized_literal_count = -1;
2622 int expected_property_count = -1;
2623 bool should_be_used_once_hint = false;
2624 int num_parameters = -1;
2625 int function_length = -1;
2626 bool has_duplicate_parameters = false;
2627
2628 Expect(Token::LPAREN, CHECK_OK);
2629 scope->set_start_position(scanner()->location().beg_pos);
2630
2631 {
2632 // Temporary zones can nest. When we migrate free variables (see below), we
2633 // need to recreate them in the previous Zone.
2634 AstNodeFactory previous_zone_ast_node_factory(ast_value_factory());
2635 previous_zone_ast_node_factory.set_zone(zone());
2636
2637 // Open a new zone scope, which sets our AstNodeFactory to allocate in the
2638 // new temporary zone if the preconditions are satisfied, and ensures that
2639 // the previous zone is always restored after parsing the body. To be able
2640 // to do scope analysis correctly after full parsing, we migrate needed
2641 // information when the function is parsed.
2642 Zone temp_zone(zone()->allocator(), ZONE_NAME);
2643 DiscardableZoneScope zone_scope(this, &temp_zone, use_temp_zone);
2644 #ifdef DEBUG
2645 if (use_temp_zone) scope->set_needs_migration();
2646 #endif
2647
2648 // Eager or lazy parse? If is_lazy_top_level_function, we'll parse
2649 // lazily. We'll call SkipFunction, which may decide to
2650 // abort lazy parsing if it suspects that wasn't a good idea. If so (in
2651 // which case the parser is expected to have backtracked), or if we didn't
2652 // try to lazy parse in the first place, we'll have to parse eagerly.
2653 if (is_lazy_top_level_function || is_lazy_inner_function) {
2654 Scanner::BookmarkScope bookmark(scanner());
2655 bookmark.Set();
2656 LazyParsingResult result =
2657 SkipFunction(kind, scope, &num_parameters, &function_length,
2658 &has_duplicate_parameters, &materialized_literal_count,
2659 &expected_property_count, is_lazy_inner_function,
2660 is_lazy_top_level_function, CHECK_OK);
2661
2662 if (result == kLazyParsingAborted) {
2663 DCHECK(is_lazy_top_level_function);
2664 bookmark.Apply();
2665 // Trigger eager (re-)parsing, just below this block.
2666 is_lazy_top_level_function = false;
2667
2668 // This is probably an initialization function. Inform the compiler it
2669 // should also eager-compile this function, and that we expect it to be
2670 // used once.
2671 eager_compile_hint = FunctionLiteral::kShouldEagerCompile;
2672 should_be_used_once_hint = true;
2673 scope->ResetAfterPreparsing(ast_value_factory(), true);
2674 zone_scope.Reset();
2675 use_temp_zone = false;
2676 }
2677 }
2678
2679 if (!is_lazy_top_level_function && !is_lazy_inner_function) {
2680 body = ParseFunction(
2681 function_name, pos, kind, function_type, scope, &num_parameters,
2682 &function_length, &has_duplicate_parameters,
2683 &materialized_literal_count, &expected_property_count, CHECK_OK);
2684 }
2685
2686 DCHECK(use_temp_zone || !is_lazy_top_level_function);
2687 if (use_temp_zone) {
2688 // If the preconditions are correct the function body should never be
2689 // accessed, but do this anyway for better behaviour if they're wrong.
2690 body = nullptr;
2691 scope->AnalyzePartially(&previous_zone_ast_node_factory);
2692 }
2693
2694 if (FLAG_trace_preparse) {
2695 PrintF(" [%s]: %i-%i %.*s\n",
2696 is_lazy_top_level_function
2697 ? "Preparse no-resolution"
2698 : (use_temp_zone ? "Preparse resolution" : "Full parse"),
2699 scope->start_position(), scope->end_position(),
2700 function_name->byte_length(), function_name->raw_data());
2701 if (is_lazy_top_level_function) {
2702 CHANGE_CURRENT_RUNTIME_COUNTER(runtime_call_stats_,
2703 PreParseNoVariableResolution);
2704 } else if (use_temp_zone) {
2705 CHANGE_CURRENT_RUNTIME_COUNTER(runtime_call_stats_,
2706 PreParseWithVariableResolution);
2707 }
2708 }
2709
2710 // Validate function name. We can do this only after parsing the function,
2711 // since the function can declare itself strict.
2712 language_mode = scope->language_mode();
2713 CheckFunctionName(language_mode, function_name, function_name_validity,
2714 function_name_location, CHECK_OK);
2715
2716 if (is_strict(language_mode)) {
2717 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(),
2718 CHECK_OK);
2719 CheckDecimalLiteralWithLeadingZero(scope->start_position(),
2720 scope->end_position());
2721 }
2722 CheckConflictingVarDeclarations(scope, CHECK_OK);
2723 } // DiscardableZoneScope goes out of scope.
2724
2725 FunctionLiteral::ParameterFlag duplicate_parameters =
2726 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters
2727 : FunctionLiteral::kNoDuplicateParameters;
2728
2729 // Note that the FunctionLiteral needs to be created in the main Zone again.
2730 FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
2731 function_name, scope, body, materialized_literal_count,
2732 expected_property_count, num_parameters, function_length,
2733 duplicate_parameters, function_type, eager_compile_hint, pos, true);
2734 function_literal->set_function_token_position(function_token_pos);
2735 if (should_be_used_once_hint)
2736 function_literal->set_should_be_used_once_hint();
2737
2738 if (should_infer_name) {
2739 DCHECK_NOT_NULL(fni_);
2740 fni_->AddFunction(function_literal);
2741 }
2742 return function_literal;
2743 }
2744
SkipFunction(FunctionKind kind,DeclarationScope * function_scope,int * num_parameters,int * function_length,bool * has_duplicate_parameters,int * materialized_literal_count,int * expected_property_count,bool is_inner_function,bool may_abort,bool * ok)2745 Parser::LazyParsingResult Parser::SkipFunction(
2746 FunctionKind kind, DeclarationScope* function_scope, int* num_parameters,
2747 int* function_length, bool* has_duplicate_parameters,
2748 int* materialized_literal_count, int* expected_property_count,
2749 bool is_inner_function, bool may_abort, bool* ok) {
2750 DCHECK_NE(kNoSourcePosition, function_scope->start_position());
2751 if (produce_cached_parse_data()) CHECK(log_);
2752
2753 DCHECK_IMPLIES(IsArrowFunction(kind),
2754 scanner()->current_token() == Token::ARROW);
2755
2756 // Inner functions are not part of the cached data.
2757 if (!is_inner_function && consume_cached_parse_data() &&
2758 !cached_parse_data_->rejected()) {
2759 // If we have cached data, we use it to skip parsing the function. The data
2760 // contains the information we need to construct the lazy function.
2761 FunctionEntry entry =
2762 cached_parse_data_->GetFunctionEntry(function_scope->start_position());
2763 // Check that cached data is valid. If not, mark it as invalid (the embedder
2764 // handles it). Note that end position greater than end of stream is safe,
2765 // and hard to check.
2766 if (entry.is_valid() &&
2767 entry.end_pos() > function_scope->start_position()) {
2768 total_preparse_skipped_ += entry.end_pos() - position();
2769 function_scope->set_end_position(entry.end_pos());
2770 scanner()->SeekForward(entry.end_pos() - 1);
2771 Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
2772 *num_parameters = entry.num_parameters();
2773 *function_length = entry.function_length();
2774 *has_duplicate_parameters = entry.has_duplicate_parameters();
2775 *materialized_literal_count = entry.literal_count();
2776 *expected_property_count = entry.property_count();
2777 SetLanguageMode(function_scope, entry.language_mode());
2778 if (entry.uses_super_property())
2779 function_scope->RecordSuperPropertyUsage();
2780 if (entry.calls_eval()) function_scope->RecordEvalCall();
2781 return kLazyParsingComplete;
2782 }
2783 cached_parse_data_->Reject();
2784 }
2785
2786 // With no cached data, we partially parse the function, without building an
2787 // AST. This gathers the data needed to build a lazy function.
2788 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse");
2789
2790 if (reusable_preparser_ == NULL) {
2791 reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(),
2792 &pending_error_handler_,
2793 runtime_call_stats_, stack_limit_);
2794 reusable_preparser_->set_allow_lazy(true);
2795 #define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name());
2796 SET_ALLOW(natives);
2797 SET_ALLOW(harmony_do_expressions);
2798 SET_ALLOW(harmony_function_sent);
2799 SET_ALLOW(harmony_async_await);
2800 SET_ALLOW(harmony_trailing_commas);
2801 SET_ALLOW(harmony_class_fields);
2802 #undef SET_ALLOW
2803 }
2804 // Aborting inner function preparsing would leave scopes in an inconsistent
2805 // state; we don't parse inner functions in the abortable mode anyway.
2806 DCHECK(!is_inner_function || !may_abort);
2807
2808 PreParser::PreParseResult result = reusable_preparser_->PreParseFunction(
2809 kind, function_scope, parsing_module_, is_inner_function, may_abort,
2810 use_counts_);
2811
2812 // Return immediately if pre-parser decided to abort parsing.
2813 if (result == PreParser::kPreParseAbort) return kLazyParsingAborted;
2814 if (result == PreParser::kPreParseStackOverflow) {
2815 // Propagate stack overflow.
2816 set_stack_overflow();
2817 *ok = false;
2818 return kLazyParsingComplete;
2819 }
2820 if (pending_error_handler_.has_pending_error()) {
2821 *ok = false;
2822 return kLazyParsingComplete;
2823 }
2824 PreParserLogger* logger = reusable_preparser_->logger();
2825 function_scope->set_end_position(logger->end());
2826 Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
2827 total_preparse_skipped_ +=
2828 function_scope->end_position() - function_scope->start_position();
2829 *num_parameters = logger->num_parameters();
2830 *function_length = logger->function_length();
2831 *has_duplicate_parameters = logger->has_duplicate_parameters();
2832 *materialized_literal_count = logger->literals();
2833 *expected_property_count = logger->properties();
2834 if (!is_inner_function && produce_cached_parse_data()) {
2835 DCHECK(log_);
2836 log_->LogFunction(
2837 function_scope->start_position(), function_scope->end_position(),
2838 *num_parameters, *function_length, *has_duplicate_parameters,
2839 *materialized_literal_count, *expected_property_count, language_mode(),
2840 function_scope->uses_super_property(), function_scope->calls_eval());
2841 }
2842 return kLazyParsingComplete;
2843 }
2844
2845
BuildAssertIsCoercible(Variable * var)2846 Statement* Parser::BuildAssertIsCoercible(Variable* var) {
2847 // if (var === null || var === undefined)
2848 // throw /* type error kNonCoercible) */;
2849
2850 Expression* condition = factory()->NewBinaryOperation(
2851 Token::OR,
2852 factory()->NewCompareOperation(
2853 Token::EQ_STRICT, factory()->NewVariableProxy(var),
2854 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition),
2855 factory()->NewCompareOperation(
2856 Token::EQ_STRICT, factory()->NewVariableProxy(var),
2857 factory()->NewNullLiteral(kNoSourcePosition), kNoSourcePosition),
2858 kNoSourcePosition);
2859 Expression* throw_type_error =
2860 NewThrowTypeError(MessageTemplate::kNonCoercible,
2861 ast_value_factory()->empty_string(), kNoSourcePosition);
2862 IfStatement* if_statement = factory()->NewIfStatement(
2863 condition,
2864 factory()->NewExpressionStatement(throw_type_error, kNoSourcePosition),
2865 factory()->NewEmptyStatement(kNoSourcePosition), kNoSourcePosition);
2866 return if_statement;
2867 }
2868
2869
2870 class InitializerRewriter final
2871 : public AstTraversalVisitor<InitializerRewriter> {
2872 public:
InitializerRewriter(uintptr_t stack_limit,Expression * root,Parser * parser,Scope * scope)2873 InitializerRewriter(uintptr_t stack_limit, Expression* root, Parser* parser,
2874 Scope* scope)
2875 : AstTraversalVisitor(stack_limit, root),
2876 parser_(parser),
2877 scope_(scope) {}
2878
2879 private:
2880 // This is required so that the overriden Visit* methods can be
2881 // called by the base class (template).
2882 friend class AstTraversalVisitor<InitializerRewriter>;
2883
2884 // Just rewrite destructuring assignments wrapped in RewritableExpressions.
VisitRewritableExpression(RewritableExpression * to_rewrite)2885 void VisitRewritableExpression(RewritableExpression* to_rewrite) {
2886 if (to_rewrite->is_rewritten()) return;
2887 Parser::PatternRewriter::RewriteDestructuringAssignment(parser_, to_rewrite,
2888 scope_);
2889 }
2890
2891 // Code in function literals does not need to be eagerly rewritten, it will be
2892 // rewritten when scheduled.
VisitFunctionLiteral(FunctionLiteral * expr)2893 void VisitFunctionLiteral(FunctionLiteral* expr) {}
2894
2895 Parser* parser_;
2896 Scope* scope_;
2897 };
2898
2899
RewriteParameterInitializer(Expression * expr,Scope * scope)2900 void Parser::RewriteParameterInitializer(Expression* expr, Scope* scope) {
2901 InitializerRewriter rewriter(stack_limit_, expr, this, scope);
2902 rewriter.Run();
2903 }
2904
2905
BuildParameterInitializationBlock(const ParserFormalParameters & parameters,bool * ok)2906 Block* Parser::BuildParameterInitializationBlock(
2907 const ParserFormalParameters& parameters, bool* ok) {
2908 DCHECK(!parameters.is_simple);
2909 DCHECK(scope()->is_function_scope());
2910 Block* init_block = factory()->NewBlock(NULL, 1, true, kNoSourcePosition);
2911 for (int i = 0; i < parameters.params.length(); ++i) {
2912 auto parameter = parameters.params[i];
2913 if (parameter.is_rest && parameter.pattern->IsVariableProxy()) break;
2914 DeclarationDescriptor descriptor;
2915 descriptor.declaration_kind = DeclarationDescriptor::PARAMETER;
2916 descriptor.scope = scope();
2917 descriptor.hoist_scope = nullptr;
2918 descriptor.mode = LET;
2919 descriptor.declaration_pos = parameter.pattern->position();
2920 // The position that will be used by the AssignmentExpression
2921 // which copies from the temp parameter to the pattern.
2922 //
2923 // TODO(adamk): Should this be kNoSourcePosition, since
2924 // it's just copying from a temp var to the real param var?
2925 descriptor.initialization_pos = parameter.pattern->position();
2926 Expression* initial_value =
2927 factory()->NewVariableProxy(parameters.scope->parameter(i));
2928 if (parameter.initializer != nullptr) {
2929 // IS_UNDEFINED($param) ? initializer : $param
2930
2931 // Ensure initializer is rewritten
2932 RewriteParameterInitializer(parameter.initializer, scope());
2933
2934 auto condition = factory()->NewCompareOperation(
2935 Token::EQ_STRICT,
2936 factory()->NewVariableProxy(parameters.scope->parameter(i)),
2937 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
2938 initial_value = factory()->NewConditional(
2939 condition, parameter.initializer, initial_value, kNoSourcePosition);
2940 descriptor.initialization_pos = parameter.initializer->position();
2941 }
2942
2943 Scope* param_scope = scope();
2944 Block* param_block = init_block;
2945 if (!parameter.is_simple() && scope()->calls_sloppy_eval()) {
2946 param_scope = NewVarblockScope();
2947 param_scope->set_start_position(descriptor.initialization_pos);
2948 param_scope->set_end_position(parameter.initializer_end_position);
2949 param_scope->RecordEvalCall();
2950 param_block = factory()->NewBlock(NULL, 8, true, kNoSourcePosition);
2951 param_block->set_scope(param_scope);
2952 descriptor.hoist_scope = scope();
2953 // Pass the appropriate scope in so that PatternRewriter can appropriately
2954 // rewrite inner initializers of the pattern to param_scope
2955 descriptor.scope = param_scope;
2956 // Rewrite the outer initializer to point to param_scope
2957 ReparentParameterExpressionScope(stack_limit(), initial_value,
2958 param_scope);
2959 }
2960
2961 BlockState block_state(&scope_state_, param_scope);
2962 DeclarationParsingResult::Declaration decl(
2963 parameter.pattern, parameter.initializer_end_position, initial_value);
2964 PatternRewriter::DeclareAndInitializeVariables(
2965 this, param_block, &descriptor, &decl, nullptr, CHECK_OK);
2966
2967 if (param_block != init_block) {
2968 param_scope = block_state.FinalizedBlockScope();
2969 if (param_scope != nullptr) {
2970 CheckConflictingVarDeclarations(param_scope, CHECK_OK);
2971 }
2972 init_block->statements()->Add(param_block, zone());
2973 }
2974 }
2975 return init_block;
2976 }
2977
BuildRejectPromiseOnException(Block * inner_block,bool * ok)2978 Block* Parser::BuildRejectPromiseOnException(Block* inner_block, bool* ok) {
2979 // .promise = %AsyncFunctionPromiseCreate();
2980 // try {
2981 // <inner_block>
2982 // } catch (.catch) {
2983 // %RejectPromise(.promise, .catch);
2984 // return .promise;
2985 // } finally {
2986 // %AsyncFunctionPromiseRelease(.promise);
2987 // }
2988 Block* result = factory()->NewBlock(nullptr, 2, true, kNoSourcePosition);
2989
2990 // .promise = %AsyncFunctionPromiseCreate();
2991 Statement* set_promise;
2992 {
2993 Expression* create_promise = factory()->NewCallRuntime(
2994 Context::ASYNC_FUNCTION_PROMISE_CREATE_INDEX,
2995 new (zone()) ZoneList<Expression*>(0, zone()), kNoSourcePosition);
2996 Assignment* assign_promise = factory()->NewAssignment(
2997 Token::INIT, factory()->NewVariableProxy(PromiseVariable()),
2998 create_promise, kNoSourcePosition);
2999 set_promise =
3000 factory()->NewExpressionStatement(assign_promise, kNoSourcePosition);
3001 }
3002 result->statements()->Add(set_promise, zone());
3003
3004 // catch (.catch) { return %RejectPromise(.promise, .catch), .promise }
3005 Scope* catch_scope = NewScope(CATCH_SCOPE);
3006 catch_scope->set_is_hidden();
3007 Variable* catch_variable =
3008 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR,
3009 kCreatedInitialized, NORMAL_VARIABLE);
3010 Block* catch_block = factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
3011
3012 Expression* promise_reject = BuildRejectPromise(
3013 factory()->NewVariableProxy(catch_variable), kNoSourcePosition);
3014 ReturnStatement* return_promise_reject =
3015 factory()->NewReturnStatement(promise_reject, kNoSourcePosition);
3016 catch_block->statements()->Add(return_promise_reject, zone());
3017
3018 TryStatement* try_catch_statement =
3019 factory()->NewTryCatchStatementForAsyncAwait(inner_block, catch_scope,
3020 catch_variable, catch_block,
3021 kNoSourcePosition);
3022
3023 // There is no TryCatchFinally node, so wrap it in an outer try/finally
3024 Block* outer_try_block =
3025 factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
3026 outer_try_block->statements()->Add(try_catch_statement, zone());
3027
3028 // finally { %AsyncFunctionPromiseRelease(.promise) }
3029 Block* finally_block =
3030 factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
3031 {
3032 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
3033 args->Add(factory()->NewVariableProxy(PromiseVariable()), zone());
3034 Expression* call_promise_release = factory()->NewCallRuntime(
3035 Context::ASYNC_FUNCTION_PROMISE_RELEASE_INDEX, args, kNoSourcePosition);
3036 Statement* promise_release = factory()->NewExpressionStatement(
3037 call_promise_release, kNoSourcePosition);
3038 finally_block->statements()->Add(promise_release, zone());
3039 }
3040
3041 Statement* try_finally_statement = factory()->NewTryFinallyStatement(
3042 outer_try_block, finally_block, kNoSourcePosition);
3043
3044 result->statements()->Add(try_finally_statement, zone());
3045 return result;
3046 }
3047
BuildCreateJSGeneratorObject(int pos,FunctionKind kind)3048 Expression* Parser::BuildCreateJSGeneratorObject(int pos, FunctionKind kind) {
3049 DCHECK_NOT_NULL(function_state_->generator_object_variable());
3050 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
3051 args->Add(factory()->NewThisFunction(pos), zone());
3052 args->Add(IsArrowFunction(kind) ? GetLiteralUndefined(pos)
3053 : ThisExpression(kNoSourcePosition),
3054 zone());
3055 return factory()->NewCallRuntime(Runtime::kCreateJSGeneratorObject, args,
3056 pos);
3057 }
3058
BuildResolvePromise(Expression * value,int pos)3059 Expression* Parser::BuildResolvePromise(Expression* value, int pos) {
3060 // %ResolvePromise(.promise, value), .promise
3061 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
3062 args->Add(factory()->NewVariableProxy(PromiseVariable()), zone());
3063 args->Add(value, zone());
3064 Expression* call_runtime =
3065 factory()->NewCallRuntime(Context::PROMISE_RESOLVE_INDEX, args, pos);
3066 return factory()->NewBinaryOperation(
3067 Token::COMMA, call_runtime,
3068 factory()->NewVariableProxy(PromiseVariable()), pos);
3069 }
3070
BuildRejectPromise(Expression * value,int pos)3071 Expression* Parser::BuildRejectPromise(Expression* value, int pos) {
3072 // %RejectPromiseNoDebugEvent(.promise, value, true), .promise
3073 // The NoDebugEvent variant disables the additional debug event for the
3074 // rejection since a debug event already happened for the exception that got
3075 // us here.
3076 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
3077 args->Add(factory()->NewVariableProxy(PromiseVariable()), zone());
3078 args->Add(value, zone());
3079 Expression* call_runtime = factory()->NewCallRuntime(
3080 Context::REJECT_PROMISE_NO_DEBUG_EVENT_INDEX, args, pos);
3081 return factory()->NewBinaryOperation(
3082 Token::COMMA, call_runtime,
3083 factory()->NewVariableProxy(PromiseVariable()), pos);
3084 }
3085
PromiseVariable()3086 Variable* Parser::PromiseVariable() {
3087 // Based on the various compilation paths, there are many different code
3088 // paths which may be the first to access the Promise temporary. Whichever
3089 // comes first should create it and stash it in the FunctionState.
3090 Variable* promise = function_state_->promise_variable();
3091 if (function_state_->promise_variable() == nullptr) {
3092 promise = scope()->NewTemporary(ast_value_factory()->empty_string());
3093 function_state_->set_promise_variable(promise);
3094 }
3095 return promise;
3096 }
3097
BuildInitialYield(int pos,FunctionKind kind)3098 Expression* Parser::BuildInitialYield(int pos, FunctionKind kind) {
3099 Expression* allocation = BuildCreateJSGeneratorObject(pos, kind);
3100 VariableProxy* init_proxy =
3101 factory()->NewVariableProxy(function_state_->generator_object_variable());
3102 Assignment* assignment = factory()->NewAssignment(
3103 Token::INIT, init_proxy, allocation, kNoSourcePosition);
3104 VariableProxy* get_proxy =
3105 factory()->NewVariableProxy(function_state_->generator_object_variable());
3106 // The position of the yield is important for reporting the exception
3107 // caused by calling the .throw method on a generator suspended at the
3108 // initial yield (i.e. right after generator instantiation).
3109 return factory()->NewYield(get_proxy, assignment, scope()->start_position(),
3110 Yield::kOnExceptionThrow);
3111 }
3112
ParseFunction(const AstRawString * function_name,int pos,FunctionKind kind,FunctionLiteral::FunctionType function_type,DeclarationScope * function_scope,int * num_parameters,int * function_length,bool * has_duplicate_parameters,int * materialized_literal_count,int * expected_property_count,bool * ok)3113 ZoneList<Statement*>* Parser::ParseFunction(
3114 const AstRawString* function_name, int pos, FunctionKind kind,
3115 FunctionLiteral::FunctionType function_type,
3116 DeclarationScope* function_scope, int* num_parameters, int* function_length,
3117 bool* has_duplicate_parameters, int* materialized_literal_count,
3118 int* expected_property_count, bool* ok) {
3119 FunctionState function_state(&function_state_, &scope_state_, function_scope);
3120
3121 DuplicateFinder duplicate_finder(scanner()->unicode_cache());
3122 ExpressionClassifier formals_classifier(this, &duplicate_finder);
3123
3124 if (IsGeneratorFunction(kind)) PrepareGeneratorVariables(&function_state);
3125
3126 ParserFormalParameters formals(function_scope);
3127 ParseFormalParameterList(&formals, CHECK_OK);
3128 Expect(Token::RPAREN, CHECK_OK);
3129 int formals_end_position = scanner()->location().end_pos;
3130 *num_parameters = formals.num_parameters();
3131 *function_length = formals.function_length;
3132
3133 CheckArityRestrictions(formals.arity, kind, formals.has_rest,
3134 function_scope->start_position(), formals_end_position,
3135 CHECK_OK);
3136 Expect(Token::LBRACE, CHECK_OK);
3137
3138 ZoneList<Statement*>* body = ParseEagerFunctionBody(
3139 function_name, pos, formals, kind, function_type, ok);
3140
3141 // Validate parameter names. We can do this only after parsing the function,
3142 // since the function can declare itself strict.
3143 const bool allow_duplicate_parameters =
3144 is_sloppy(function_scope->language_mode()) && formals.is_simple &&
3145 !IsConciseMethod(kind);
3146 ValidateFormalParameters(function_scope->language_mode(),
3147 allow_duplicate_parameters, CHECK_OK);
3148
3149 RewriteDestructuringAssignments();
3150
3151 *has_duplicate_parameters =
3152 !classifier()->is_valid_formal_parameter_list_without_duplicates();
3153
3154 *materialized_literal_count = function_state.materialized_literal_count();
3155 *expected_property_count = function_state.expected_property_count();
3156 return body;
3157 }
3158
ParseEagerFunctionBody(const AstRawString * function_name,int pos,const ParserFormalParameters & parameters,FunctionKind kind,FunctionLiteral::FunctionType function_type,bool * ok)3159 ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
3160 const AstRawString* function_name, int pos,
3161 const ParserFormalParameters& parameters, FunctionKind kind,
3162 FunctionLiteral::FunctionType function_type, bool* ok) {
3163 ParsingModeScope mode(this, allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY);
3164 ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone());
3165
3166 static const int kFunctionNameAssignmentIndex = 0;
3167 if (function_type == FunctionLiteral::kNamedExpression) {
3168 DCHECK(function_name != NULL);
3169 // If we have a named function expression, we add a local variable
3170 // declaration to the body of the function with the name of the
3171 // function and let it refer to the function itself (closure).
3172 // Not having parsed the function body, the language mode may still change,
3173 // so we reserve a spot and create the actual const assignment later.
3174 DCHECK_EQ(kFunctionNameAssignmentIndex, result->length());
3175 result->Add(NULL, zone());
3176 }
3177
3178 ZoneList<Statement*>* body = result;
3179 DeclarationScope* function_scope = scope()->AsDeclarationScope();
3180 DeclarationScope* inner_scope = function_scope;
3181 Block* inner_block = nullptr;
3182 if (!parameters.is_simple) {
3183 inner_scope = NewVarblockScope();
3184 inner_scope->set_start_position(scanner()->location().beg_pos);
3185 inner_block = factory()->NewBlock(NULL, 8, true, kNoSourcePosition);
3186 inner_block->set_scope(inner_scope);
3187 body = inner_block->statements();
3188 }
3189
3190 {
3191 BlockState block_state(&scope_state_, inner_scope);
3192
3193 if (IsGeneratorFunction(kind)) {
3194 // We produce:
3195 //
3196 // try { InitialYield; ...body...; return {value: undefined, done: true} }
3197 // finally { %_GeneratorClose(generator) }
3198 //
3199 // - InitialYield yields the actual generator object.
3200 // - Any return statement inside the body will have its argument wrapped
3201 // in a "done" iterator result object.
3202 // - If the generator terminates for whatever reason, we must close it.
3203 // Hence the finally clause.
3204
3205 Block* try_block =
3206 factory()->NewBlock(nullptr, 3, false, kNoSourcePosition);
3207 Expression* initial_yield = BuildInitialYield(pos, kind);
3208 try_block->statements()->Add(
3209 factory()->NewExpressionStatement(initial_yield, kNoSourcePosition),
3210 zone());
3211 ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK);
3212
3213 Statement* final_return = factory()->NewReturnStatement(
3214 BuildIteratorResult(nullptr, true), kNoSourcePosition);
3215 try_block->statements()->Add(final_return, zone());
3216
3217 Block* finally_block =
3218 factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
3219 ZoneList<Expression*>* args =
3220 new (zone()) ZoneList<Expression*>(1, zone());
3221 VariableProxy* call_proxy = factory()->NewVariableProxy(
3222 function_state_->generator_object_variable());
3223 args->Add(call_proxy, zone());
3224 Expression* call = factory()->NewCallRuntime(
3225 Runtime::kInlineGeneratorClose, args, kNoSourcePosition);
3226 finally_block->statements()->Add(
3227 factory()->NewExpressionStatement(call, kNoSourcePosition), zone());
3228
3229 body->Add(factory()->NewTryFinallyStatement(try_block, finally_block,
3230 kNoSourcePosition),
3231 zone());
3232 } else if (IsAsyncFunction(kind)) {
3233 const bool accept_IN = true;
3234 ParseAsyncFunctionBody(inner_scope, body, kind, FunctionBodyType::kNormal,
3235 accept_IN, pos, CHECK_OK);
3236 } else {
3237 ParseStatementList(body, Token::RBRACE, CHECK_OK);
3238 }
3239
3240 if (IsSubclassConstructor(kind)) {
3241 body->Add(factory()->NewReturnStatement(ThisExpression(kNoSourcePosition),
3242 kNoSourcePosition),
3243 zone());
3244 }
3245 }
3246
3247 Expect(Token::RBRACE, CHECK_OK);
3248 scope()->set_end_position(scanner()->location().end_pos);
3249
3250 if (!parameters.is_simple) {
3251 DCHECK_NOT_NULL(inner_scope);
3252 DCHECK_EQ(function_scope, scope());
3253 DCHECK_EQ(function_scope, inner_scope->outer_scope());
3254 DCHECK_EQ(body, inner_block->statements());
3255 SetLanguageMode(function_scope, inner_scope->language_mode());
3256 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK);
3257
3258 if (is_sloppy(inner_scope->language_mode())) {
3259 InsertSloppyBlockFunctionVarBindings(inner_scope);
3260 }
3261
3262 // TODO(littledan): Merge the two rejection blocks into one
3263 if (IsAsyncFunction(kind)) {
3264 init_block = BuildRejectPromiseOnException(init_block, CHECK_OK);
3265 }
3266
3267 DCHECK_NOT_NULL(init_block);
3268
3269 inner_scope->set_end_position(scanner()->location().end_pos);
3270 if (inner_scope->FinalizeBlockScope() != nullptr) {
3271 CheckConflictingVarDeclarations(inner_scope, CHECK_OK);
3272 InsertShadowingVarBindingInitializers(inner_block);
3273 }
3274 inner_scope = nullptr;
3275
3276 result->Add(init_block, zone());
3277 result->Add(inner_block, zone());
3278 } else {
3279 DCHECK_EQ(inner_scope, function_scope);
3280 if (is_sloppy(function_scope->language_mode())) {
3281 InsertSloppyBlockFunctionVarBindings(function_scope);
3282 }
3283 }
3284
3285 if (!IsArrowFunction(kind)) {
3286 // Declare arguments after parsing the function since lexical 'arguments'
3287 // masks the arguments object. Declare arguments before declaring the
3288 // function var since the arguments object masks 'function arguments'.
3289 function_scope->DeclareArguments(ast_value_factory());
3290 }
3291
3292 if (function_type == FunctionLiteral::kNamedExpression) {
3293 Statement* statement;
3294 if (function_scope->LookupLocal(function_name) == nullptr) {
3295 // Now that we know the language mode, we can create the const assignment
3296 // in the previously reserved spot.
3297 DCHECK_EQ(function_scope, scope());
3298 Variable* fvar = function_scope->DeclareFunctionVar(function_name);
3299 VariableProxy* fproxy = factory()->NewVariableProxy(fvar);
3300 statement = factory()->NewExpressionStatement(
3301 factory()->NewAssignment(Token::INIT, fproxy,
3302 factory()->NewThisFunction(pos),
3303 kNoSourcePosition),
3304 kNoSourcePosition);
3305 } else {
3306 statement = factory()->NewEmptyStatement(kNoSourcePosition);
3307 }
3308 result->Set(kFunctionNameAssignmentIndex, statement);
3309 }
3310
3311 MarkCollectedTailCallExpressions();
3312 return result;
3313 }
3314
InstallHomeObject(Expression * function_literal,Expression * home_object)3315 Expression* Parser::InstallHomeObject(Expression* function_literal,
3316 Expression* home_object) {
3317 Block* do_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
3318 Variable* result_var =
3319 scope()->NewTemporary(ast_value_factory()->empty_string());
3320 DoExpression* do_expr =
3321 factory()->NewDoExpression(do_block, result_var, kNoSourcePosition);
3322 Assignment* init = factory()->NewAssignment(
3323 Token::ASSIGN, factory()->NewVariableProxy(result_var), function_literal,
3324 kNoSourcePosition);
3325 do_block->statements()->Add(
3326 factory()->NewExpressionStatement(init, kNoSourcePosition), zone());
3327 Property* home_object_property = factory()->NewProperty(
3328 factory()->NewVariableProxy(result_var),
3329 factory()->NewSymbolLiteral("home_object_symbol", kNoSourcePosition),
3330 kNoSourcePosition);
3331 Assignment* assignment = factory()->NewAssignment(
3332 Token::ASSIGN, home_object_property, home_object, kNoSourcePosition);
3333 do_block->statements()->Add(
3334 factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone());
3335 return do_expr;
3336 }
3337
ClassFieldVariableName(bool is_name,AstValueFactory * ast_value_factory,int index)3338 const AstRawString* ClassFieldVariableName(bool is_name,
3339 AstValueFactory* ast_value_factory,
3340 int index) {
3341 std::string name =
3342 ".class-field-" + std::to_string(index) + (is_name ? "-name" : "-func");
3343 return ast_value_factory->GetOneByteString(name.c_str());
3344 }
3345
SynthesizeClassFieldInitializer(int count)3346 FunctionLiteral* Parser::SynthesizeClassFieldInitializer(int count) {
3347 DCHECK(count > 0);
3348 // Makes a function which reads the names and initializers for each class
3349 // field out of deterministically named local variables and sets each property
3350 // to the result of evaluating its corresponding initializer in turn.
3351
3352 // This produces a function which looks like
3353 // function () {
3354 // this[.class-field-0-name] = .class-field-0-func();
3355 // this[.class-field-1-name] = .class-field-1-func();
3356 // [...]
3357 // this[.class-field-n-name] = .class-field-n-func();
3358 // return this;
3359 // }
3360 // except that it performs defineProperty, so that instead of '=' it has
3361 // %DefineDataPropertyInLiteral(this, .class-field-0-name,
3362 // .class-field-0-func(),
3363 // DONT_ENUM, false)
3364
3365 RaiseLanguageMode(STRICT);
3366 FunctionKind kind = FunctionKind::kConciseMethod;
3367 DeclarationScope* initializer_scope = NewFunctionScope(kind);
3368 SetLanguageMode(initializer_scope, language_mode());
3369 initializer_scope->set_start_position(scanner()->location().end_pos);
3370 initializer_scope->set_end_position(scanner()->location().end_pos);
3371 FunctionState initializer_state(&function_state_, &scope_state_,
3372 initializer_scope);
3373 ZoneList<Statement*>* body = new (zone()) ZoneList<Statement*>(count, zone());
3374 for (int i = 0; i < count; ++i) {
3375 const AstRawString* name =
3376 ClassFieldVariableName(true, ast_value_factory(), i);
3377 VariableProxy* name_proxy = scope()->NewUnresolved(factory(), name);
3378 const AstRawString* function_name =
3379 ClassFieldVariableName(false, ast_value_factory(), i);
3380 VariableProxy* function_proxy =
3381 scope()->NewUnresolved(factory(), function_name);
3382 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
3383 args->Add(function_proxy, zone());
3384 args->Add(ThisExpression(kNoSourcePosition), zone());
3385 Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, args,
3386 kNoSourcePosition);
3387 ZoneList<Expression*>* define_property_args =
3388 new (zone()) ZoneList<Expression*>(5, zone());
3389 define_property_args->Add(ThisExpression(kNoSourcePosition), zone());
3390 define_property_args->Add(name_proxy, zone());
3391 define_property_args->Add(call, zone());
3392 define_property_args->Add(
3393 factory()->NewNumberLiteral(DONT_ENUM, kNoSourcePosition), zone());
3394 define_property_args->Add(
3395 factory()->NewNumberLiteral(
3396 false, // TODO(bakkot) function name inference a la class { x =
3397 // function(){}; static y = function(){}; }
3398 kNoSourcePosition),
3399 zone());
3400 body->Add(factory()->NewExpressionStatement(
3401 factory()->NewCallRuntime(
3402 Runtime::kDefineDataProperty,
3403 define_property_args, // TODO(bakkot) verify that this is
3404 // the same as object_define_property
3405 kNoSourcePosition),
3406 kNoSourcePosition),
3407 zone());
3408 }
3409 body->Add(factory()->NewReturnStatement(ThisExpression(kNoSourcePosition),
3410 kNoSourcePosition),
3411 zone());
3412 FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
3413 ast_value_factory()->empty_string(), initializer_scope, body,
3414 initializer_state.materialized_literal_count(),
3415 initializer_state.expected_property_count(), 0, count,
3416 FunctionLiteral::kNoDuplicateParameters,
3417 FunctionLiteral::kAnonymousExpression,
3418 FunctionLiteral::kShouldLazyCompile, initializer_scope->start_position(),
3419 true);
3420 function_literal->set_is_class_field_initializer(true);
3421 return function_literal;
3422 }
3423
InsertClassFieldInitializer(FunctionLiteral * constructor)3424 FunctionLiteral* Parser::InsertClassFieldInitializer(
3425 FunctionLiteral* constructor) {
3426 Statement* call_initializer = factory()->NewExpressionStatement(
3427 CallClassFieldInitializer(
3428 constructor->scope(),
3429 constructor->scope()->NewUnresolved(
3430 factory(), ast_value_factory()->this_string(), kNoSourcePosition,
3431 THIS_VARIABLE)),
3432 kNoSourcePosition);
3433 constructor->body()->InsertAt(0, call_initializer, zone());
3434 return constructor;
3435 }
3436
3437 // If a class name is specified, this method declares the class variable
3438 // and sets class_info->proxy to point to that name.
DeclareClassVariable(const AstRawString * name,Scope * block_scope,ClassInfo * class_info,int class_token_pos,bool * ok)3439 void Parser::DeclareClassVariable(const AstRawString* name, Scope* block_scope,
3440 ClassInfo* class_info, int class_token_pos,
3441 bool* ok) {
3442 #ifdef DEBUG
3443 scope()->SetScopeName(name);
3444 #endif
3445
3446 if (name != nullptr) {
3447 class_info->proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE);
3448 Declaration* declaration = factory()->NewVariableDeclaration(
3449 class_info->proxy, block_scope, class_token_pos);
3450 Declare(declaration, DeclarationDescriptor::NORMAL, CONST,
3451 Variable::DefaultInitializationFlag(CONST), ok);
3452 }
3453 }
3454
3455 // This method declares a property of the given class. It updates the
3456 // following fields of class_info, as appropriate:
3457 // - constructor
3458 // - static_initializer_var
3459 // - instance_field_initializers
3460 // - properties
DeclareClassProperty(const AstRawString * class_name,ClassLiteralProperty * property,ClassInfo * class_info,bool * ok)3461 void Parser::DeclareClassProperty(const AstRawString* class_name,
3462 ClassLiteralProperty* property,
3463 ClassInfo* class_info, bool* ok) {
3464 if (class_info->has_seen_constructor && class_info->constructor == nullptr) {
3465 class_info->constructor = GetPropertyValue(property)->AsFunctionLiteral();
3466 DCHECK_NOT_NULL(class_info->constructor);
3467 class_info->constructor->set_raw_name(
3468 class_name != nullptr ? class_name
3469 : ast_value_factory()->empty_string());
3470 return;
3471 }
3472
3473 if (property->kind() == ClassLiteralProperty::FIELD) {
3474 DCHECK(allow_harmony_class_fields());
3475 if (property->is_static()) {
3476 if (class_info->static_initializer_var == nullptr) {
3477 class_info->static_initializer_var =
3478 NewTemporary(ast_value_factory()->empty_string());
3479 }
3480 // TODO(bakkot) only do this conditionally
3481 Expression* function = InstallHomeObject(
3482 property->value(),
3483 factory()->NewVariableProxy(class_info->static_initializer_var));
3484 ZoneList<Expression*>* args =
3485 new (zone()) ZoneList<Expression*>(2, zone());
3486 args->Add(function, zone());
3487 args->Add(factory()->NewVariableProxy(class_info->static_initializer_var),
3488 zone());
3489 Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, args,
3490 kNoSourcePosition);
3491 property->set_value(call);
3492 } else {
3493 // if (is_computed_name) { // TODO(bakkot) figure out why this is
3494 // necessary for non-computed names in full-codegen
3495 ZoneList<Expression*>* to_name_args =
3496 new (zone()) ZoneList<Expression*>(1, zone());
3497 to_name_args->Add(property->key(), zone());
3498 property->set_key(factory()->NewCallRuntime(
3499 Runtime::kToName, to_name_args, kNoSourcePosition));
3500 //}
3501 const AstRawString* name = ClassFieldVariableName(
3502 true, ast_value_factory(),
3503 class_info->instance_field_initializers->length());
3504 VariableProxy* name_proxy =
3505 factory()->NewVariableProxy(name, NORMAL_VARIABLE);
3506 Declaration* name_declaration = factory()->NewVariableDeclaration(
3507 name_proxy, scope(), kNoSourcePosition);
3508 Variable* name_var =
3509 Declare(name_declaration, DeclarationDescriptor::NORMAL, CONST,
3510 kNeedsInitialization, ok, scope());
3511 DCHECK(*ok);
3512 if (!*ok) return;
3513 class_info->instance_field_initializers->Add(property->value(), zone());
3514 property->set_value(factory()->NewVariableProxy(name_var));
3515 }
3516 }
3517 class_info->properties->Add(property, zone());
3518 }
3519
3520 // This method rewrites a class literal into a do-expression.
3521 // It uses the following fields of class_info:
3522 // - constructor (if missing, it updates it with a default constructor)
3523 // - proxy
3524 // - extends
3525 // - static_initializer_var
3526 // - instance_field_initializers
3527 // - properties
RewriteClassLiteral(const AstRawString * name,ClassInfo * class_info,int pos,bool * ok)3528 Expression* Parser::RewriteClassLiteral(const AstRawString* name,
3529 ClassInfo* class_info, int pos,
3530 bool* ok) {
3531 int end_pos = scanner()->location().end_pos;
3532 Block* do_block = factory()->NewBlock(nullptr, 1, false, pos);
3533 Variable* result_var = NewTemporary(ast_value_factory()->empty_string());
3534 DoExpression* do_expr = factory()->NewDoExpression(do_block, result_var, pos);
3535
3536 bool has_extends = class_info->extends != nullptr;
3537 bool has_instance_fields =
3538 class_info->instance_field_initializers->length() > 0;
3539 DCHECK(!has_instance_fields || allow_harmony_class_fields());
3540 bool has_default_constructor = class_info->constructor == nullptr;
3541 if (has_default_constructor) {
3542 class_info->constructor =
3543 DefaultConstructor(name, has_extends, has_instance_fields, pos, end_pos,
3544 scope()->language_mode());
3545 }
3546
3547 if (has_instance_fields && !has_extends) {
3548 class_info->constructor =
3549 InsertClassFieldInitializer(class_info->constructor);
3550 class_info->constructor->set_requires_class_field_init(true);
3551 } // The derived case is handled by rewriting super calls.
3552
3553 scope()->set_end_position(end_pos);
3554
3555 if (name != nullptr) {
3556 DCHECK_NOT_NULL(class_info->proxy);
3557 class_info->proxy->var()->set_initializer_position(end_pos);
3558 }
3559
3560 ClassLiteral* class_literal = factory()->NewClassLiteral(
3561 class_info->proxy, class_info->extends, class_info->constructor,
3562 class_info->properties, pos, end_pos);
3563
3564 if (class_info->static_initializer_var != nullptr) {
3565 class_literal->set_static_initializer_proxy(
3566 factory()->NewVariableProxy(class_info->static_initializer_var));
3567 }
3568
3569 do_block->statements()->Add(
3570 factory()->NewExpressionStatement(
3571 factory()->NewAssignment(Token::ASSIGN,
3572 factory()->NewVariableProxy(result_var),
3573 class_literal, kNoSourcePosition),
3574 pos),
3575 zone());
3576 if (allow_harmony_class_fields() &&
3577 (has_instance_fields || (has_extends && !has_default_constructor))) {
3578 // Default constructors for derived classes without fields will not try to
3579 // read this variable, so there's no need to create it.
3580 const AstRawString* init_fn_name =
3581 ast_value_factory()->dot_class_field_init_string();
3582 Variable* init_fn_var = scope()->DeclareLocal(
3583 init_fn_name, CONST, kCreatedInitialized, NORMAL_VARIABLE);
3584 Expression* initializer =
3585 has_instance_fields
3586 ? static_cast<Expression*>(SynthesizeClassFieldInitializer(
3587 class_info->instance_field_initializers->length()))
3588 : factory()->NewBooleanLiteral(false, kNoSourcePosition);
3589 Assignment* assignment = factory()->NewAssignment(
3590 Token::INIT, factory()->NewVariableProxy(init_fn_var), initializer,
3591 kNoSourcePosition);
3592 do_block->statements()->Add(
3593 factory()->NewExpressionStatement(assignment, kNoSourcePosition),
3594 zone());
3595 }
3596 for (int i = 0; i < class_info->instance_field_initializers->length(); ++i) {
3597 const AstRawString* function_name =
3598 ClassFieldVariableName(false, ast_value_factory(), i);
3599 VariableProxy* function_proxy =
3600 factory()->NewVariableProxy(function_name, NORMAL_VARIABLE);
3601 Declaration* function_declaration = factory()->NewVariableDeclaration(
3602 function_proxy, scope(), kNoSourcePosition);
3603 Variable* function_var =
3604 Declare(function_declaration, DeclarationDescriptor::NORMAL, CONST,
3605 kNeedsInitialization, ok, scope());
3606 if (!*ok) return nullptr;
3607 Property* prototype_property = factory()->NewProperty(
3608 factory()->NewVariableProxy(result_var),
3609 factory()->NewStringLiteral(ast_value_factory()->prototype_string(),
3610 kNoSourcePosition),
3611 kNoSourcePosition);
3612 Expression* function_value = InstallHomeObject(
3613 class_info->instance_field_initializers->at(i),
3614 prototype_property); // TODO(bakkot) ideally this would be conditional,
3615 // especially in trivial cases
3616 Assignment* function_assignment = factory()->NewAssignment(
3617 Token::INIT, factory()->NewVariableProxy(function_var), function_value,
3618 kNoSourcePosition);
3619 do_block->statements()->Add(factory()->NewExpressionStatement(
3620 function_assignment, kNoSourcePosition),
3621 zone());
3622 }
3623 do_block->set_scope(scope()->FinalizeBlockScope());
3624 do_expr->set_represented_function(class_info->constructor);
3625 AddFunctionForNameInference(class_info->constructor);
3626
3627 return do_expr;
3628 }
3629
GetLiteralUndefined(int position)3630 Literal* Parser::GetLiteralUndefined(int position) {
3631 return factory()->NewUndefinedLiteral(position);
3632 }
3633
3634
CheckConflictingVarDeclarations(Scope * scope,bool * ok)3635 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
3636 Declaration* decl = scope->CheckConflictingVarDeclarations();
3637 if (decl != NULL) {
3638 // In ES6, conflicting variable bindings are early errors.
3639 const AstRawString* name = decl->proxy()->raw_name();
3640 int position = decl->proxy()->position();
3641 Scanner::Location location =
3642 position == kNoSourcePosition
3643 ? Scanner::Location::invalid()
3644 : Scanner::Location(position, position + 1);
3645 ReportMessageAt(location, MessageTemplate::kVarRedeclaration, name);
3646 *ok = false;
3647 }
3648 }
3649
3650
InsertShadowingVarBindingInitializers(Block * inner_block)3651 void Parser::InsertShadowingVarBindingInitializers(Block* inner_block) {
3652 // For each var-binding that shadows a parameter, insert an assignment
3653 // initializing the variable with the parameter.
3654 Scope* inner_scope = inner_block->scope();
3655 DCHECK(inner_scope->is_declaration_scope());
3656 Scope* function_scope = inner_scope->outer_scope();
3657 DCHECK(function_scope->is_function_scope());
3658 BlockState block_state(&scope_state_, inner_scope);
3659 for (Declaration* decl : *inner_scope->declarations()) {
3660 if (decl->proxy()->var()->mode() != VAR || !decl->IsVariableDeclaration()) {
3661 continue;
3662 }
3663 const AstRawString* name = decl->proxy()->raw_name();
3664 Variable* parameter = function_scope->LookupLocal(name);
3665 if (parameter == nullptr) continue;
3666 VariableProxy* to = NewUnresolved(name);
3667 VariableProxy* from = factory()->NewVariableProxy(parameter);
3668 Expression* assignment =
3669 factory()->NewAssignment(Token::ASSIGN, to, from, kNoSourcePosition);
3670 Statement* statement =
3671 factory()->NewExpressionStatement(assignment, kNoSourcePosition);
3672 inner_block->statements()->InsertAt(0, statement, zone());
3673 }
3674 }
3675
InsertSloppyBlockFunctionVarBindings(DeclarationScope * scope)3676 void Parser::InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope) {
3677 // For the outermost eval scope, we cannot hoist during parsing: let
3678 // declarations in the surrounding scope may prevent hoisting, but the
3679 // information is unaccessible during parsing. In this case, we hoist later in
3680 // DeclarationScope::Analyze.
3681 if (scope->is_eval_scope() && scope->outer_scope() == original_scope_) {
3682 return;
3683 }
3684 scope->HoistSloppyBlockFunctions(factory());
3685 }
3686
3687 // ----------------------------------------------------------------------------
3688 // Parser support
3689
TargetStackContainsLabel(const AstRawString * label)3690 bool Parser::TargetStackContainsLabel(const AstRawString* label) {
3691 for (ParserTarget* t = target_stack_; t != NULL; t = t->previous()) {
3692 if (ContainsLabel(t->statement()->labels(), label)) return true;
3693 }
3694 return false;
3695 }
3696
3697
LookupBreakTarget(const AstRawString * label,bool * ok)3698 BreakableStatement* Parser::LookupBreakTarget(const AstRawString* label,
3699 bool* ok) {
3700 bool anonymous = label == NULL;
3701 for (ParserTarget* t = target_stack_; t != NULL; t = t->previous()) {
3702 BreakableStatement* stat = t->statement();
3703 if ((anonymous && stat->is_target_for_anonymous()) ||
3704 (!anonymous && ContainsLabel(stat->labels(), label))) {
3705 return stat;
3706 }
3707 }
3708 return NULL;
3709 }
3710
3711
LookupContinueTarget(const AstRawString * label,bool * ok)3712 IterationStatement* Parser::LookupContinueTarget(const AstRawString* label,
3713 bool* ok) {
3714 bool anonymous = label == NULL;
3715 for (ParserTarget* t = target_stack_; t != NULL; t = t->previous()) {
3716 IterationStatement* stat = t->statement()->AsIterationStatement();
3717 if (stat == NULL) continue;
3718
3719 DCHECK(stat->is_target_for_anonymous());
3720 if (anonymous || ContainsLabel(stat->labels(), label)) {
3721 return stat;
3722 }
3723 }
3724 return NULL;
3725 }
3726
3727
HandleSourceURLComments(Isolate * isolate,Handle<Script> script)3728 void Parser::HandleSourceURLComments(Isolate* isolate, Handle<Script> script) {
3729 Handle<String> source_url = scanner_.SourceUrl(isolate);
3730 if (!source_url.is_null()) {
3731 script->set_source_url(*source_url);
3732 }
3733 Handle<String> source_mapping_url = scanner_.SourceMappingUrl(isolate);
3734 if (!source_mapping_url.is_null()) {
3735 script->set_source_mapping_url(*source_mapping_url);
3736 }
3737 }
3738
3739
Internalize(Isolate * isolate,Handle<Script> script,bool error)3740 void Parser::Internalize(Isolate* isolate, Handle<Script> script, bool error) {
3741 // Internalize strings and values.
3742 ast_value_factory()->Internalize(isolate);
3743
3744 // Error processing.
3745 if (error) {
3746 if (stack_overflow()) {
3747 isolate->StackOverflow();
3748 } else {
3749 DCHECK(pending_error_handler_.has_pending_error());
3750 pending_error_handler_.ThrowPendingError(isolate, script);
3751 }
3752 }
3753
3754 // Move statistics to Isolate.
3755 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
3756 ++feature) {
3757 if (use_counts_[feature] > 0) {
3758 isolate->CountUsage(v8::Isolate::UseCounterFeature(feature));
3759 }
3760 }
3761 if (scanner_.FoundHtmlComment()) {
3762 isolate->CountUsage(v8::Isolate::kHtmlComment);
3763 if (script->line_offset() == 0 && script->column_offset() == 0) {
3764 isolate->CountUsage(v8::Isolate::kHtmlCommentInExternalScript);
3765 }
3766 }
3767 isolate->counters()->total_preparse_skipped()->Increment(
3768 total_preparse_skipped_);
3769 if (!parsing_on_main_thread_ &&
3770 FLAG_runtime_stats ==
3771 v8::tracing::TracingCategoryObserver::ENABLED_BY_NATIVE) {
3772 // Copy over the counters from the background thread to the main counters on
3773 // the isolate.
3774 // TODO(cbruni,lpy): properly attach the runtime stats to the trace for
3775 // background parsing.
3776 isolate->counters()->runtime_call_stats()->Add(runtime_call_stats_);
3777 }
3778 }
3779
3780
3781 // ----------------------------------------------------------------------------
3782 // The Parser interface.
3783
3784
ParseStatic(ParseInfo * info)3785 bool Parser::ParseStatic(ParseInfo* info) {
3786 Parser parser(info);
3787 if (parser.Parse(info)) {
3788 info->set_language_mode(info->literal()->language_mode());
3789 return true;
3790 }
3791 return false;
3792 }
3793
3794
Parse(ParseInfo * info)3795 bool Parser::Parse(ParseInfo* info) {
3796 DCHECK(info->literal() == NULL);
3797 FunctionLiteral* result = NULL;
3798 // Ok to use Isolate here; this function is only called in the main thread.
3799 DCHECK(parsing_on_main_thread_);
3800 Isolate* isolate = info->isolate();
3801
3802 if (info->is_toplevel()) {
3803 SetCachedData(info);
3804 result = ParseProgram(isolate, info);
3805 } else {
3806 result = ParseFunction(isolate, info);
3807 }
3808 info->set_literal(result);
3809
3810 Internalize(isolate, info->script(), result == NULL);
3811 return (result != NULL);
3812 }
3813
3814
ParseOnBackground(ParseInfo * info)3815 void Parser::ParseOnBackground(ParseInfo* info) {
3816 parsing_on_main_thread_ = false;
3817
3818 DCHECK(info->literal() == NULL);
3819 FunctionLiteral* result = NULL;
3820
3821 ParserLogger logger;
3822 if (produce_cached_parse_data()) log_ = &logger;
3823 if (FLAG_runtime_stats) {
3824 // Create separate runtime stats for background parsing.
3825 runtime_call_stats_ = new (zone()) RuntimeCallStats();
3826 }
3827
3828 std::unique_ptr<Utf16CharacterStream> stream;
3829 Utf16CharacterStream* stream_ptr;
3830 if (info->character_stream()) {
3831 DCHECK(info->source_stream() == nullptr);
3832 stream_ptr = info->character_stream();
3833 } else {
3834 DCHECK(info->character_stream() == nullptr);
3835 stream.reset(ScannerStream::For(info->source_stream(),
3836 info->source_stream_encoding()));
3837 stream_ptr = stream.get();
3838 }
3839 DCHECK(info->maybe_outer_scope_info().is_null());
3840
3841 DCHECK(original_scope_);
3842
3843 // When streaming, we don't know the length of the source until we have parsed
3844 // it. The raw data can be UTF-8, so we wouldn't know the source length until
3845 // we have decoded it anyway even if we knew the raw data length (which we
3846 // don't). We work around this by storing all the scopes which need their end
3847 // position set at the end of the script (the top scope and possible eval
3848 // scopes) and set their end position after we know the script length.
3849 if (info->is_toplevel()) {
3850 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
3851 scanner_.Initialize(stream_ptr);
3852 result = DoParseProgram(info);
3853 } else {
3854 result = DoParseFunction(info, info->function_name(), stream_ptr);
3855 }
3856
3857 info->set_literal(result);
3858
3859 // We cannot internalize on a background thread; a foreground task will take
3860 // care of calling Parser::Internalize just before compilation.
3861
3862 if (produce_cached_parse_data()) {
3863 if (result != NULL) *info->cached_data() = logger.GetScriptData();
3864 log_ = NULL;
3865 }
3866 if (FLAG_runtime_stats) {
3867 // TODO(cbruni,lpy): properly attach the runtime stats to the trace for
3868 // background parsing.
3869 }
3870 }
3871
OpenTemplateLiteral(int pos)3872 Parser::TemplateLiteralState Parser::OpenTemplateLiteral(int pos) {
3873 return new (zone()) TemplateLiteral(zone(), pos);
3874 }
3875
3876
AddTemplateSpan(TemplateLiteralState * state,bool tail)3877 void Parser::AddTemplateSpan(TemplateLiteralState* state, bool tail) {
3878 int pos = scanner()->location().beg_pos;
3879 int end = scanner()->location().end_pos - (tail ? 1 : 2);
3880 const AstRawString* tv = scanner()->CurrentSymbol(ast_value_factory());
3881 const AstRawString* trv = scanner()->CurrentRawSymbol(ast_value_factory());
3882 Literal* cooked = factory()->NewStringLiteral(tv, pos);
3883 Literal* raw = factory()->NewStringLiteral(trv, pos);
3884 (*state)->AddTemplateSpan(cooked, raw, end, zone());
3885 }
3886
3887
AddTemplateExpression(TemplateLiteralState * state,Expression * expression)3888 void Parser::AddTemplateExpression(TemplateLiteralState* state,
3889 Expression* expression) {
3890 (*state)->AddExpression(expression, zone());
3891 }
3892
3893
CloseTemplateLiteral(TemplateLiteralState * state,int start,Expression * tag)3894 Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start,
3895 Expression* tag) {
3896 TemplateLiteral* lit = *state;
3897 int pos = lit->position();
3898 const ZoneList<Expression*>* cooked_strings = lit->cooked();
3899 const ZoneList<Expression*>* raw_strings = lit->raw();
3900 const ZoneList<Expression*>* expressions = lit->expressions();
3901 DCHECK_EQ(cooked_strings->length(), raw_strings->length());
3902 DCHECK_EQ(cooked_strings->length(), expressions->length() + 1);
3903
3904 if (!tag) {
3905 // Build tree of BinaryOps to simplify code-generation
3906 Expression* expr = cooked_strings->at(0);
3907 int i = 0;
3908 while (i < expressions->length()) {
3909 Expression* sub = expressions->at(i++);
3910 Expression* cooked_str = cooked_strings->at(i);
3911
3912 // Let middle be ToString(sub).
3913 ZoneList<Expression*>* args =
3914 new (zone()) ZoneList<Expression*>(1, zone());
3915 args->Add(sub, zone());
3916 Expression* middle = factory()->NewCallRuntime(Runtime::kInlineToString,
3917 args, sub->position());
3918
3919 expr = factory()->NewBinaryOperation(
3920 Token::ADD, factory()->NewBinaryOperation(
3921 Token::ADD, expr, middle, expr->position()),
3922 cooked_str, sub->position());
3923 }
3924 return expr;
3925 } else {
3926 uint32_t hash = ComputeTemplateLiteralHash(lit);
3927
3928 int cooked_idx = function_state_->NextMaterializedLiteralIndex();
3929 int raw_idx = function_state_->NextMaterializedLiteralIndex();
3930
3931 // $getTemplateCallSite
3932 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(4, zone());
3933 args->Add(factory()->NewArrayLiteral(
3934 const_cast<ZoneList<Expression*>*>(cooked_strings),
3935 cooked_idx, pos),
3936 zone());
3937 args->Add(
3938 factory()->NewArrayLiteral(
3939 const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx, pos),
3940 zone());
3941
3942 // Truncate hash to Smi-range.
3943 Smi* hash_obj = Smi::cast(Internals::IntToSmi(static_cast<int>(hash)));
3944 args->Add(factory()->NewNumberLiteral(hash_obj->value(), pos), zone());
3945
3946 Expression* call_site = factory()->NewCallRuntime(
3947 Context::GET_TEMPLATE_CALL_SITE_INDEX, args, start);
3948
3949 // Call TagFn
3950 ZoneList<Expression*>* call_args =
3951 new (zone()) ZoneList<Expression*>(expressions->length() + 1, zone());
3952 call_args->Add(call_site, zone());
3953 call_args->AddAll(*expressions, zone());
3954 return factory()->NewCall(tag, call_args, pos);
3955 }
3956 }
3957
3958
ComputeTemplateLiteralHash(const TemplateLiteral * lit)3959 uint32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) {
3960 const ZoneList<Expression*>* raw_strings = lit->raw();
3961 int total = raw_strings->length();
3962 DCHECK(total);
3963
3964 uint32_t running_hash = 0;
3965
3966 for (int index = 0; index < total; ++index) {
3967 if (index) {
3968 running_hash = StringHasher::ComputeRunningHashOneByte(
3969 running_hash, "${}", 3);
3970 }
3971
3972 const AstRawString* raw_string =
3973 raw_strings->at(index)->AsLiteral()->raw_value()->AsString();
3974 if (raw_string->is_one_byte()) {
3975 const char* data = reinterpret_cast<const char*>(raw_string->raw_data());
3976 running_hash = StringHasher::ComputeRunningHashOneByte(
3977 running_hash, data, raw_string->length());
3978 } else {
3979 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data());
3980 running_hash = StringHasher::ComputeRunningHash(running_hash, data,
3981 raw_string->length());
3982 }
3983 }
3984
3985 return running_hash;
3986 }
3987
PrepareSpreadArguments(ZoneList<Expression * > * list)3988 ZoneList<Expression*>* Parser::PrepareSpreadArguments(
3989 ZoneList<Expression*>* list) {
3990 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
3991 if (list->length() == 1) {
3992 // Spread-call with single spread argument produces an InternalArray
3993 // containing the values from the array.
3994 //
3995 // Function is called or constructed with the produced array of arguments
3996 //
3997 // EG: Apply(Func, Spread(spread0))
3998 ZoneList<Expression*>* spread_list =
3999 new (zone()) ZoneList<Expression*>(0, zone());
4000 spread_list->Add(list->at(0)->AsSpread()->expression(), zone());
4001 args->Add(factory()->NewCallRuntime(Runtime::kSpreadIterablePrepare,
4002 spread_list, kNoSourcePosition),
4003 zone());
4004 return args;
4005 } else {
4006 // Spread-call with multiple arguments produces array literals for each
4007 // sequences of unspread arguments, and converts each spread iterable to
4008 // an Internal array. Finally, all of these produced arrays are flattened
4009 // into a single InternalArray, containing the arguments for the call.
4010 //
4011 // EG: Apply(Func, Flatten([unspread0, unspread1], Spread(spread0),
4012 // Spread(spread1), [unspread2, unspread3]))
4013 int i = 0;
4014 int n = list->length();
4015 while (i < n) {
4016 if (!list->at(i)->IsSpread()) {
4017 ZoneList<Expression*>* unspread =
4018 new (zone()) ZoneList<Expression*>(1, zone());
4019
4020 // Push array of unspread parameters
4021 while (i < n && !list->at(i)->IsSpread()) {
4022 unspread->Add(list->at(i++), zone());
4023 }
4024 int literal_index = function_state_->NextMaterializedLiteralIndex();
4025 args->Add(factory()->NewArrayLiteral(unspread, literal_index,
4026 kNoSourcePosition),
4027 zone());
4028
4029 if (i == n) break;
4030 }
4031
4032 // Push eagerly spread argument
4033 ZoneList<Expression*>* spread_list =
4034 new (zone()) ZoneList<Expression*>(1, zone());
4035 spread_list->Add(list->at(i++)->AsSpread()->expression(), zone());
4036 args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX,
4037 spread_list, kNoSourcePosition),
4038 zone());
4039 }
4040
4041 list = new (zone()) ZoneList<Expression*>(1, zone());
4042 list->Add(factory()->NewCallRuntime(Context::SPREAD_ARGUMENTS_INDEX, args,
4043 kNoSourcePosition),
4044 zone());
4045 return list;
4046 }
4047 UNREACHABLE();
4048 }
4049
SpreadCall(Expression * function,ZoneList<Expression * > * args,int pos)4050 Expression* Parser::SpreadCall(Expression* function,
4051 ZoneList<Expression*>* args, int pos) {
4052 if (function->IsSuperCallReference()) {
4053 // Super calls
4054 // $super_constructor = %_GetSuperConstructor(<this-function>)
4055 // %reflect_construct($super_constructor, args, new.target)
4056 ZoneList<Expression*>* tmp = new (zone()) ZoneList<Expression*>(1, zone());
4057 tmp->Add(function->AsSuperCallReference()->this_function_var(), zone());
4058 Expression* super_constructor = factory()->NewCallRuntime(
4059 Runtime::kInlineGetSuperConstructor, tmp, pos);
4060 args->InsertAt(0, super_constructor, zone());
4061 args->Add(function->AsSuperCallReference()->new_target_var(), zone());
4062 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args,
4063 pos);
4064 } else {
4065 if (function->IsProperty()) {
4066 // Method calls
4067 if (function->AsProperty()->IsSuperAccess()) {
4068 Expression* home = ThisExpression(kNoSourcePosition);
4069 args->InsertAt(0, function, zone());
4070 args->InsertAt(1, home, zone());
4071 } else {
4072 Variable* temp = NewTemporary(ast_value_factory()->empty_string());
4073 VariableProxy* obj = factory()->NewVariableProxy(temp);
4074 Assignment* assign_obj = factory()->NewAssignment(
4075 Token::ASSIGN, obj, function->AsProperty()->obj(),
4076 kNoSourcePosition);
4077 function = factory()->NewProperty(
4078 assign_obj, function->AsProperty()->key(), kNoSourcePosition);
4079 args->InsertAt(0, function, zone());
4080 obj = factory()->NewVariableProxy(temp);
4081 args->InsertAt(1, obj, zone());
4082 }
4083 } else {
4084 // Non-method calls
4085 args->InsertAt(0, function, zone());
4086 args->InsertAt(1, factory()->NewUndefinedLiteral(kNoSourcePosition),
4087 zone());
4088 }
4089 return factory()->NewCallRuntime(Context::REFLECT_APPLY_INDEX, args, pos);
4090 }
4091 }
4092
SpreadCallNew(Expression * function,ZoneList<Expression * > * args,int pos)4093 Expression* Parser::SpreadCallNew(Expression* function,
4094 ZoneList<Expression*>* args, int pos) {
4095 args->InsertAt(0, function, zone());
4096
4097 return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos);
4098 }
4099
4100
SetLanguageMode(Scope * scope,LanguageMode mode)4101 void Parser::SetLanguageMode(Scope* scope, LanguageMode mode) {
4102 v8::Isolate::UseCounterFeature feature;
4103 if (is_sloppy(mode))
4104 feature = v8::Isolate::kSloppyMode;
4105 else if (is_strict(mode))
4106 feature = v8::Isolate::kStrictMode;
4107 else
4108 UNREACHABLE();
4109 ++use_counts_[feature];
4110 scope->SetLanguageMode(mode);
4111 }
4112
SetAsmModule()4113 void Parser::SetAsmModule() {
4114 // Store the usage count; The actual use counter on the isolate is
4115 // incremented after parsing is done.
4116 ++use_counts_[v8::Isolate::kUseAsm];
4117 DCHECK(scope()->is_declaration_scope());
4118 scope()->AsDeclarationScope()->set_asm_module();
4119 }
4120
MarkCollectedTailCallExpressions()4121 void Parser::MarkCollectedTailCallExpressions() {
4122 const ZoneList<Expression*>& tail_call_expressions =
4123 function_state_->tail_call_expressions().expressions();
4124 for (int i = 0; i < tail_call_expressions.length(); ++i) {
4125 MarkTailPosition(tail_call_expressions[i]);
4126 }
4127 }
4128
ExpressionListToExpression(ZoneList<Expression * > * args)4129 Expression* Parser::ExpressionListToExpression(ZoneList<Expression*>* args) {
4130 Expression* expr = args->at(0);
4131 for (int i = 1; i < args->length(); ++i) {
4132 expr = factory()->NewBinaryOperation(Token::COMMA, expr, args->at(i),
4133 expr->position());
4134 }
4135 return expr;
4136 }
4137
4138 // This method intoduces the line initializing the generator object
4139 // when desugaring the body of async_function.
PrepareAsyncFunctionBody(ZoneList<Statement * > * body,FunctionKind kind,int pos)4140 void Parser::PrepareAsyncFunctionBody(ZoneList<Statement*>* body,
4141 FunctionKind kind, int pos) {
4142 // function async_function() {
4143 // .generator_object = %CreateGeneratorObject();
4144 // BuildRejectPromiseOnException({
4145 // ... block ...
4146 // return %ResolvePromise(.promise, expr), .promise;
4147 // })
4148 // }
4149
4150 Variable* temp =
4151 NewTemporary(ast_value_factory()->dot_generator_object_string());
4152 function_state_->set_generator_object_variable(temp);
4153
4154 Expression* init_generator_variable = factory()->NewAssignment(
4155 Token::INIT, factory()->NewVariableProxy(temp),
4156 BuildCreateJSGeneratorObject(pos, kind), kNoSourcePosition);
4157 body->Add(factory()->NewExpressionStatement(init_generator_variable,
4158 kNoSourcePosition),
4159 zone());
4160 }
4161
4162 // This method completes the desugaring of the body of async_function.
RewriteAsyncFunctionBody(ZoneList<Statement * > * body,Block * block,Expression * return_value,bool * ok)4163 void Parser::RewriteAsyncFunctionBody(ZoneList<Statement*>* body, Block* block,
4164 Expression* return_value, bool* ok) {
4165 // function async_function() {
4166 // .generator_object = %CreateGeneratorObject();
4167 // BuildRejectPromiseOnException({
4168 // ... block ...
4169 // return %ResolvePromise(.promise, expr), .promise;
4170 // })
4171 // }
4172
4173 return_value = BuildResolvePromise(return_value, return_value->position());
4174 block->statements()->Add(
4175 factory()->NewReturnStatement(return_value, return_value->position()),
4176 zone());
4177 block = BuildRejectPromiseOnException(block, CHECK_OK_VOID);
4178 body->Add(block, zone());
4179 }
4180
RewriteAwaitExpression(Expression * value,int await_pos)4181 Expression* Parser::RewriteAwaitExpression(Expression* value, int await_pos) {
4182 // yield do {
4183 // tmp = <operand>;
4184 // %AsyncFunctionAwait(.generator_object, tmp, .promise);
4185 // .promise
4186 // }
4187 // The value of the expression is returned to the caller of the async
4188 // function for the first yield statement; for this, .promise is the
4189 // appropriate return value, being a Promise that will be fulfilled or
4190 // rejected with the appropriate value by the desugaring. Subsequent yield
4191 // occurrences will return to the AsyncFunctionNext call within the
4192 // implemementation of the intermediate throwaway Promise's then handler.
4193 // This handler has nothing useful to do with the value, as the Promise is
4194 // ignored. If we yielded the value of the throwawayPromise that
4195 // AsyncFunctionAwait creates as an intermediate, it would create a memory
4196 // leak; we must return .promise instead;
4197 // The operand needs to be evaluated on a separate statement in order to get
4198 // a break location, and the .promise needs to be read earlier so that it
4199 // doesn't insert a false location.
4200 // TODO(littledan): investigate why this ordering is needed in more detail.
4201 Variable* generator_object_variable =
4202 function_state_->generator_object_variable();
4203
4204 // If generator_object_variable is null,
4205 // TODO(littledan): Is this necessary?
4206 if (!generator_object_variable) return value;
4207
4208 const int nopos = kNoSourcePosition;
4209
4210 Block* do_block = factory()->NewBlock(nullptr, 2, false, nopos);
4211
4212 Variable* promise = PromiseVariable();
4213
4214 // Wrap value evaluation to provide a break location.
4215 Variable* temp_var = NewTemporary(ast_value_factory()->empty_string());
4216 Expression* value_assignment = factory()->NewAssignment(
4217 Token::ASSIGN, factory()->NewVariableProxy(temp_var), value, nopos);
4218 do_block->statements()->Add(
4219 factory()->NewExpressionStatement(value_assignment, value->position()),
4220 zone());
4221
4222 ZoneList<Expression*>* async_function_await_args =
4223 new (zone()) ZoneList<Expression*>(3, zone());
4224 Expression* generator_object =
4225 factory()->NewVariableProxy(generator_object_variable);
4226 async_function_await_args->Add(generator_object, zone());
4227 async_function_await_args->Add(factory()->NewVariableProxy(temp_var), zone());
4228 async_function_await_args->Add(factory()->NewVariableProxy(promise), zone());
4229
4230 // The parser emits calls to AsyncFunctionAwaitCaught, but the
4231 // AstNumberingVisitor will rewrite this to AsyncFunctionAwaitUncaught
4232 // if there is no local enclosing try/catch block.
4233 Expression* async_function_await =
4234 factory()->NewCallRuntime(Context::ASYNC_FUNCTION_AWAIT_CAUGHT_INDEX,
4235 async_function_await_args, nopos);
4236 do_block->statements()->Add(
4237 factory()->NewExpressionStatement(async_function_await, await_pos),
4238 zone());
4239
4240 // Wrap await to provide a break location between value evaluation and yield.
4241 Expression* do_expr = factory()->NewDoExpression(do_block, promise, nopos);
4242
4243 generator_object = factory()->NewVariableProxy(generator_object_variable);
4244 return factory()->NewYield(generator_object, do_expr, nopos,
4245 Yield::kOnExceptionRethrow);
4246 }
4247
4248 class NonPatternRewriter : public AstExpressionRewriter {
4249 public:
NonPatternRewriter(uintptr_t stack_limit,Parser * parser)4250 NonPatternRewriter(uintptr_t stack_limit, Parser* parser)
4251 : AstExpressionRewriter(stack_limit), parser_(parser) {}
~NonPatternRewriter()4252 ~NonPatternRewriter() override {}
4253
4254 private:
RewriteExpression(Expression * expr)4255 bool RewriteExpression(Expression* expr) override {
4256 if (expr->IsRewritableExpression()) return true;
4257 // Rewrite only what could have been a pattern but is not.
4258 if (expr->IsArrayLiteral()) {
4259 // Spread rewriting in array literals.
4260 ArrayLiteral* lit = expr->AsArrayLiteral();
4261 VisitExpressions(lit->values());
4262 replacement_ = parser_->RewriteSpreads(lit);
4263 return false;
4264 }
4265 if (expr->IsObjectLiteral()) {
4266 return true;
4267 }
4268 if (expr->IsBinaryOperation() &&
4269 expr->AsBinaryOperation()->op() == Token::COMMA) {
4270 return true;
4271 }
4272 // Everything else does not need rewriting.
4273 return false;
4274 }
4275
VisitLiteralProperty(LiteralProperty * property)4276 void VisitLiteralProperty(LiteralProperty* property) override {
4277 if (property == nullptr) return;
4278 // Do not rewrite (computed) key expressions
4279 AST_REWRITE_PROPERTY(Expression, property, value);
4280 }
4281
4282 Parser* parser_;
4283 };
4284
RewriteNonPattern(bool * ok)4285 void Parser::RewriteNonPattern(bool* ok) {
4286 ValidateExpression(CHECK_OK_VOID);
4287 auto non_patterns_to_rewrite = function_state_->non_patterns_to_rewrite();
4288 int begin = classifier()->GetNonPatternBegin();
4289 int end = non_patterns_to_rewrite->length();
4290 if (begin < end) {
4291 NonPatternRewriter rewriter(stack_limit_, this);
4292 for (int i = begin; i < end; i++) {
4293 DCHECK(non_patterns_to_rewrite->at(i)->IsRewritableExpression());
4294 rewriter.Rewrite(non_patterns_to_rewrite->at(i));
4295 }
4296 non_patterns_to_rewrite->Rewind(begin);
4297 }
4298 }
4299
4300
RewriteDestructuringAssignments()4301 void Parser::RewriteDestructuringAssignments() {
4302 const auto& assignments =
4303 function_state_->destructuring_assignments_to_rewrite();
4304 for (int i = assignments.length() - 1; i >= 0; --i) {
4305 // Rewrite list in reverse, so that nested assignment patterns are rewritten
4306 // correctly.
4307 const DestructuringAssignment& pair = assignments.at(i);
4308 RewritableExpression* to_rewrite =
4309 pair.assignment->AsRewritableExpression();
4310 DCHECK_NOT_NULL(to_rewrite);
4311 if (!to_rewrite->is_rewritten()) {
4312 // Since this function is called at the end of parsing the program,
4313 // pair.scope may already have been removed by FinalizeBlockScope in the
4314 // meantime.
4315 Scope* scope = pair.scope->GetUnremovedScope();
4316 PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite, scope);
4317 }
4318 }
4319 }
4320
RewriteExponentiation(Expression * left,Expression * right,int pos)4321 Expression* Parser::RewriteExponentiation(Expression* left, Expression* right,
4322 int pos) {
4323 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
4324 args->Add(left, zone());
4325 args->Add(right, zone());
4326 return factory()->NewCallRuntime(Context::MATH_POW_INDEX, args, pos);
4327 }
4328
RewriteAssignExponentiation(Expression * left,Expression * right,int pos)4329 Expression* Parser::RewriteAssignExponentiation(Expression* left,
4330 Expression* right, int pos) {
4331 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
4332 if (left->IsVariableProxy()) {
4333 VariableProxy* lhs = left->AsVariableProxy();
4334
4335 Expression* result;
4336 DCHECK_NOT_NULL(lhs->raw_name());
4337 result = ExpressionFromIdentifier(lhs->raw_name(), lhs->position());
4338 args->Add(left, zone());
4339 args->Add(right, zone());
4340 Expression* call =
4341 factory()->NewCallRuntime(Context::MATH_POW_INDEX, args, pos);
4342 return factory()->NewAssignment(Token::ASSIGN, result, call, pos);
4343 } else if (left->IsProperty()) {
4344 Property* prop = left->AsProperty();
4345 auto temp_obj = NewTemporary(ast_value_factory()->empty_string());
4346 auto temp_key = NewTemporary(ast_value_factory()->empty_string());
4347 Expression* assign_obj = factory()->NewAssignment(
4348 Token::ASSIGN, factory()->NewVariableProxy(temp_obj), prop->obj(),
4349 kNoSourcePosition);
4350 Expression* assign_key = factory()->NewAssignment(
4351 Token::ASSIGN, factory()->NewVariableProxy(temp_key), prop->key(),
4352 kNoSourcePosition);
4353 args->Add(factory()->NewProperty(factory()->NewVariableProxy(temp_obj),
4354 factory()->NewVariableProxy(temp_key),
4355 left->position()),
4356 zone());
4357 args->Add(right, zone());
4358 Expression* call =
4359 factory()->NewCallRuntime(Context::MATH_POW_INDEX, args, pos);
4360 Expression* target = factory()->NewProperty(
4361 factory()->NewVariableProxy(temp_obj),
4362 factory()->NewVariableProxy(temp_key), kNoSourcePosition);
4363 Expression* assign =
4364 factory()->NewAssignment(Token::ASSIGN, target, call, pos);
4365 return factory()->NewBinaryOperation(
4366 Token::COMMA, assign_obj,
4367 factory()->NewBinaryOperation(Token::COMMA, assign_key, assign, pos),
4368 pos);
4369 }
4370 UNREACHABLE();
4371 return nullptr;
4372 }
4373
RewriteSpreads(ArrayLiteral * lit)4374 Expression* Parser::RewriteSpreads(ArrayLiteral* lit) {
4375 // Array literals containing spreads are rewritten using do expressions, e.g.
4376 // [1, 2, 3, ...x, 4, ...y, 5]
4377 // is roughly rewritten as:
4378 // do {
4379 // $R = [1, 2, 3];
4380 // for ($i of x) %AppendElement($R, $i);
4381 // %AppendElement($R, 4);
4382 // for ($j of y) %AppendElement($R, $j);
4383 // %AppendElement($R, 5);
4384 // $R
4385 // }
4386 // where $R, $i and $j are fresh temporary variables.
4387 ZoneList<Expression*>::iterator s = lit->FirstSpread();
4388 if (s == lit->EndValue()) return nullptr; // no spread, no rewriting...
4389 Variable* result = NewTemporary(ast_value_factory()->dot_result_string());
4390 // NOTE: The value assigned to R is the whole original array literal,
4391 // spreads included. This will be fixed before the rewritten AST is returned.
4392 // $R = lit
4393 Expression* init_result = factory()->NewAssignment(
4394 Token::INIT, factory()->NewVariableProxy(result), lit, kNoSourcePosition);
4395 Block* do_block = factory()->NewBlock(nullptr, 16, false, kNoSourcePosition);
4396 do_block->statements()->Add(
4397 factory()->NewExpressionStatement(init_result, kNoSourcePosition),
4398 zone());
4399 // Traverse the array literal starting from the first spread.
4400 while (s != lit->EndValue()) {
4401 Expression* value = *s++;
4402 Spread* spread = value->AsSpread();
4403 if (spread == nullptr) {
4404 // If the element is not a spread, we're adding a single:
4405 // %AppendElement($R, value)
4406 // or, in case of a hole,
4407 // ++($R.length)
4408 if (!value->IsLiteral() ||
4409 !value->AsLiteral()->raw_value()->IsTheHole()) {
4410 ZoneList<Expression*>* append_element_args = NewExpressionList(2);
4411 append_element_args->Add(factory()->NewVariableProxy(result), zone());
4412 append_element_args->Add(value, zone());
4413 do_block->statements()->Add(
4414 factory()->NewExpressionStatement(
4415 factory()->NewCallRuntime(Runtime::kAppendElement,
4416 append_element_args,
4417 kNoSourcePosition),
4418 kNoSourcePosition),
4419 zone());
4420 } else {
4421 Property* length_property = factory()->NewProperty(
4422 factory()->NewVariableProxy(result),
4423 factory()->NewStringLiteral(ast_value_factory()->length_string(),
4424 kNoSourcePosition),
4425 kNoSourcePosition);
4426 CountOperation* count_op = factory()->NewCountOperation(
4427 Token::INC, true /* prefix */, length_property, kNoSourcePosition);
4428 do_block->statements()->Add(
4429 factory()->NewExpressionStatement(count_op, kNoSourcePosition),
4430 zone());
4431 }
4432 } else {
4433 // If it's a spread, we're adding a for/of loop iterating through it.
4434 Variable* each = NewTemporary(ast_value_factory()->dot_for_string());
4435 Expression* subject = spread->expression();
4436 // %AppendElement($R, each)
4437 Statement* append_body;
4438 {
4439 ZoneList<Expression*>* append_element_args = NewExpressionList(2);
4440 append_element_args->Add(factory()->NewVariableProxy(result), zone());
4441 append_element_args->Add(factory()->NewVariableProxy(each), zone());
4442 append_body = factory()->NewExpressionStatement(
4443 factory()->NewCallRuntime(Runtime::kAppendElement,
4444 append_element_args, kNoSourcePosition),
4445 kNoSourcePosition);
4446 }
4447 // for (each of spread) %AppendElement($R, each)
4448 ForEachStatement* loop = factory()->NewForEachStatement(
4449 ForEachStatement::ITERATE, nullptr, kNoSourcePosition);
4450 const bool finalize = false;
4451 InitializeForOfStatement(loop->AsForOfStatement(),
4452 factory()->NewVariableProxy(each), subject,
4453 append_body, finalize);
4454 do_block->statements()->Add(loop, zone());
4455 }
4456 }
4457 // Now, rewind the original array literal to truncate everything from the
4458 // first spread (included) until the end. This fixes $R's initialization.
4459 lit->RewindSpreads();
4460 return factory()->NewDoExpression(do_block, result, lit->position());
4461 }
4462
QueueDestructuringAssignmentForRewriting(Expression * expr)4463 void Parser::QueueDestructuringAssignmentForRewriting(Expression* expr) {
4464 DCHECK(expr->IsRewritableExpression());
4465 function_state_->AddDestructuringAssignment(
4466 DestructuringAssignment(expr, scope()));
4467 }
4468
QueueNonPatternForRewriting(Expression * expr,bool * ok)4469 void Parser::QueueNonPatternForRewriting(Expression* expr, bool* ok) {
4470 DCHECK(expr->IsRewritableExpression());
4471 function_state_->AddNonPatternForRewriting(expr, ok);
4472 }
4473
AddAccessorPrefixToFunctionName(bool is_get,FunctionLiteral * function,const AstRawString * name)4474 void Parser::AddAccessorPrefixToFunctionName(bool is_get,
4475 FunctionLiteral* function,
4476 const AstRawString* name) {
4477 DCHECK_NOT_NULL(name);
4478 const AstRawString* prefix = is_get ? ast_value_factory()->get_space_string()
4479 : ast_value_factory()->set_space_string();
4480 function->set_raw_name(ast_value_factory()->NewConsString(prefix, name));
4481 }
4482
SetFunctionNameFromPropertyName(ObjectLiteralProperty * property,const AstRawString * name)4483 void Parser::SetFunctionNameFromPropertyName(ObjectLiteralProperty* property,
4484 const AstRawString* name) {
4485 DCHECK(property->kind() != ObjectLiteralProperty::GETTER);
4486 DCHECK(property->kind() != ObjectLiteralProperty::SETTER);
4487
4488 // Computed name setting must happen at runtime.
4489 DCHECK(!property->is_computed_name());
4490
4491 // Ignore "__proto__" as a name when it's being used to set the [[Prototype]]
4492 // of an object literal.
4493 if (property->kind() == ObjectLiteralProperty::PROTOTYPE) return;
4494
4495 Expression* value = property->value();
4496
4497 DCHECK(!value->IsAnonymousFunctionDefinition() ||
4498 property->kind() == ObjectLiteralProperty::COMPUTED);
4499 SetFunctionName(value, name);
4500 }
4501
SetFunctionNameFromIdentifierRef(Expression * value,Expression * identifier)4502 void Parser::SetFunctionNameFromIdentifierRef(Expression* value,
4503 Expression* identifier) {
4504 if (!identifier->IsVariableProxy()) return;
4505 SetFunctionName(value, identifier->AsVariableProxy()->raw_name());
4506 }
4507
SetFunctionName(Expression * value,const AstRawString * name)4508 void Parser::SetFunctionName(Expression* value, const AstRawString* name) {
4509 DCHECK_NOT_NULL(name);
4510 if (!value->IsAnonymousFunctionDefinition()) return;
4511 auto function = value->AsFunctionLiteral();
4512 if (function != nullptr) {
4513 function->set_raw_name(name);
4514 } else {
4515 DCHECK(value->IsDoExpression());
4516 value->AsDoExpression()->represented_function()->set_raw_name(name);
4517 }
4518 }
4519
4520
4521 // Desugaring of yield*
4522 // ====================
4523 //
4524 // With the help of do-expressions and function.sent, we desugar yield* into a
4525 // loop containing a "raw" yield (a yield that doesn't wrap an iterator result
4526 // object around its argument). Concretely, "yield* iterable" turns into
4527 // roughly the following code:
4528 //
4529 // do {
4530 // const kNext = 0;
4531 // const kReturn = 1;
4532 // const kThrow = 2;
4533 //
4534 // let input = function.sent;
4535 // let mode = kNext;
4536 // let output = undefined;
4537 //
4538 // let iterator = iterable[Symbol.iterator]();
4539 // if (!IS_RECEIVER(iterator)) throw MakeTypeError(kSymbolIteratorInvalid);
4540 //
4541 // while (true) {
4542 // // From the generator to the iterator:
4543 // // Forward input according to resume mode and obtain output.
4544 // switch (mode) {
4545 // case kNext:
4546 // output = iterator.next(input);
4547 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
4548 // break;
4549 // case kReturn:
4550 // IteratorClose(iterator, input, output); // See below.
4551 // break;
4552 // case kThrow:
4553 // let iteratorThrow = iterator.throw;
4554 // if (IS_NULL_OR_UNDEFINED(iteratorThrow)) {
4555 // IteratorClose(iterator); // See below.
4556 // throw MakeTypeError(kThrowMethodMissing);
4557 // }
4558 // output = %_Call(iteratorThrow, iterator, input);
4559 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
4560 // break;
4561 // }
4562 // if (output.done) break;
4563 //
4564 // // From the generator to its user:
4565 // // Forward output, receive new input, and determine resume mode.
4566 // mode = kReturn;
4567 // try {
4568 // try {
4569 // RawYield(output); // See explanation above.
4570 // mode = kNext;
4571 // } catch (error) {
4572 // mode = kThrow;
4573 // }
4574 // } finally {
4575 // input = function.sent;
4576 // continue;
4577 // }
4578 // }
4579 //
4580 // if (mode === kReturn) {
4581 // return {value: output.value, done: true};
4582 // }
4583 // output.value
4584 // }
4585 //
4586 // IteratorClose(iterator) expands to the following:
4587 //
4588 // let iteratorReturn = iterator.return;
4589 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
4590 // let output = %_Call(iteratorReturn, iterator);
4591 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
4592 // }
4593 //
4594 // IteratorClose(iterator, input, output) expands to the following:
4595 //
4596 // let iteratorReturn = iterator.return;
4597 // if (IS_NULL_OR_UNDEFINED(iteratorReturn)) return input;
4598 // output = %_Call(iteratorReturn, iterator, input);
4599 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
4600
RewriteYieldStar(Expression * generator,Expression * iterable,int pos)4601 Expression* Parser::RewriteYieldStar(Expression* generator,
4602 Expression* iterable, int pos) {
4603 const int nopos = kNoSourcePosition;
4604
4605 // Forward definition for break/continue statements.
4606 WhileStatement* loop = factory()->NewWhileStatement(nullptr, nopos);
4607
4608 // let input = undefined;
4609 Variable* var_input = NewTemporary(ast_value_factory()->empty_string());
4610 Statement* initialize_input;
4611 {
4612 Expression* input_proxy = factory()->NewVariableProxy(var_input);
4613 Expression* assignment =
4614 factory()->NewAssignment(Token::ASSIGN, input_proxy,
4615 factory()->NewUndefinedLiteral(nopos), nopos);
4616 initialize_input = factory()->NewExpressionStatement(assignment, nopos);
4617 }
4618
4619 // let mode = kNext;
4620 Variable* var_mode = NewTemporary(ast_value_factory()->empty_string());
4621 Statement* initialize_mode;
4622 {
4623 Expression* mode_proxy = factory()->NewVariableProxy(var_mode);
4624 Expression* knext =
4625 factory()->NewSmiLiteral(JSGeneratorObject::kNext, nopos);
4626 Expression* assignment =
4627 factory()->NewAssignment(Token::ASSIGN, mode_proxy, knext, nopos);
4628 initialize_mode = factory()->NewExpressionStatement(assignment, nopos);
4629 }
4630
4631 // let output = undefined;
4632 Variable* var_output = NewTemporary(ast_value_factory()->empty_string());
4633 Statement* initialize_output;
4634 {
4635 Expression* output_proxy = factory()->NewVariableProxy(var_output);
4636 Expression* assignment =
4637 factory()->NewAssignment(Token::ASSIGN, output_proxy,
4638 factory()->NewUndefinedLiteral(nopos), nopos);
4639 initialize_output = factory()->NewExpressionStatement(assignment, nopos);
4640 }
4641
4642 // let iterator = iterable[Symbol.iterator];
4643 Variable* var_iterator = NewTemporary(ast_value_factory()->empty_string());
4644 Statement* get_iterator;
4645 {
4646 Expression* iterator = GetIterator(iterable, nopos);
4647 Expression* iterator_proxy = factory()->NewVariableProxy(var_iterator);
4648 Expression* assignment = factory()->NewAssignment(
4649 Token::ASSIGN, iterator_proxy, iterator, nopos);
4650 get_iterator = factory()->NewExpressionStatement(assignment, nopos);
4651 }
4652
4653 // if (!IS_RECEIVER(iterator)) throw MakeTypeError(kSymbolIteratorInvalid);
4654 Statement* validate_iterator;
4655 {
4656 Expression* is_receiver_call;
4657 {
4658 auto args = new (zone()) ZoneList<Expression*>(1, zone());
4659 args->Add(factory()->NewVariableProxy(var_iterator), zone());
4660 is_receiver_call =
4661 factory()->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
4662 }
4663
4664 Statement* throw_call;
4665 {
4666 Expression* call =
4667 NewThrowTypeError(MessageTemplate::kSymbolIteratorInvalid,
4668 ast_value_factory()->empty_string(), nopos);
4669 throw_call = factory()->NewExpressionStatement(call, nopos);
4670 }
4671
4672 validate_iterator = factory()->NewIfStatement(
4673 is_receiver_call, factory()->NewEmptyStatement(nopos), throw_call,
4674 nopos);
4675 }
4676
4677 // output = iterator.next(input);
4678 Statement* call_next;
4679 {
4680 Expression* iterator_proxy = factory()->NewVariableProxy(var_iterator);
4681 Expression* literal =
4682 factory()->NewStringLiteral(ast_value_factory()->next_string(), nopos);
4683 Expression* next_property =
4684 factory()->NewProperty(iterator_proxy, literal, nopos);
4685 Expression* input_proxy = factory()->NewVariableProxy(var_input);
4686 auto args = new (zone()) ZoneList<Expression*>(1, zone());
4687 args->Add(input_proxy, zone());
4688 Expression* call = factory()->NewCall(next_property, args, nopos);
4689 Expression* output_proxy = factory()->NewVariableProxy(var_output);
4690 Expression* assignment =
4691 factory()->NewAssignment(Token::ASSIGN, output_proxy, call, nopos);
4692 call_next = factory()->NewExpressionStatement(assignment, nopos);
4693 }
4694
4695 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
4696 Statement* validate_next_output;
4697 {
4698 Expression* is_receiver_call;
4699 {
4700 auto args = new (zone()) ZoneList<Expression*>(1, zone());
4701 args->Add(factory()->NewVariableProxy(var_output), zone());
4702 is_receiver_call =
4703 factory()->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
4704 }
4705
4706 Statement* throw_call;
4707 {
4708 auto args = new (zone()) ZoneList<Expression*>(1, zone());
4709 args->Add(factory()->NewVariableProxy(var_output), zone());
4710 Expression* call = factory()->NewCallRuntime(
4711 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
4712 throw_call = factory()->NewExpressionStatement(call, nopos);
4713 }
4714
4715 validate_next_output = factory()->NewIfStatement(
4716 is_receiver_call, factory()->NewEmptyStatement(nopos), throw_call,
4717 nopos);
4718 }
4719
4720 // let iteratorThrow = iterator.throw;
4721 Variable* var_throw = NewTemporary(ast_value_factory()->empty_string());
4722 Statement* get_throw;
4723 {
4724 Expression* iterator_proxy = factory()->NewVariableProxy(var_iterator);
4725 Expression* literal =
4726 factory()->NewStringLiteral(ast_value_factory()->throw_string(), nopos);
4727 Expression* property =
4728 factory()->NewProperty(iterator_proxy, literal, nopos);
4729 Expression* throw_proxy = factory()->NewVariableProxy(var_throw);
4730 Expression* assignment =
4731 factory()->NewAssignment(Token::ASSIGN, throw_proxy, property, nopos);
4732 get_throw = factory()->NewExpressionStatement(assignment, nopos);
4733 }
4734
4735 // if (IS_NULL_OR_UNDEFINED(iteratorThrow) {
4736 // IteratorClose(iterator);
4737 // throw MakeTypeError(kThrowMethodMissing);
4738 // }
4739 Statement* check_throw;
4740 {
4741 Expression* condition = factory()->NewCompareOperation(
4742 Token::EQ, factory()->NewVariableProxy(var_throw),
4743 factory()->NewNullLiteral(nopos), nopos);
4744 Expression* call =
4745 NewThrowTypeError(MessageTemplate::kThrowMethodMissing,
4746 ast_value_factory()->empty_string(), nopos);
4747 Statement* throw_call = factory()->NewExpressionStatement(call, nopos);
4748
4749 Block* then = factory()->NewBlock(nullptr, 4 + 1, false, nopos);
4750 BuildIteratorCloseForCompletion(
4751 scope(), then->statements(), var_iterator,
4752 factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos));
4753 then->statements()->Add(throw_call, zone());
4754 check_throw = factory()->NewIfStatement(
4755 condition, then, factory()->NewEmptyStatement(nopos), nopos);
4756 }
4757
4758 // output = %_Call(iteratorThrow, iterator, input);
4759 Statement* call_throw;
4760 {
4761 auto args = new (zone()) ZoneList<Expression*>(3, zone());
4762 args->Add(factory()->NewVariableProxy(var_throw), zone());
4763 args->Add(factory()->NewVariableProxy(var_iterator), zone());
4764 args->Add(factory()->NewVariableProxy(var_input), zone());
4765 Expression* call =
4766 factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos);
4767 Expression* assignment = factory()->NewAssignment(
4768 Token::ASSIGN, factory()->NewVariableProxy(var_output), call, nopos);
4769 call_throw = factory()->NewExpressionStatement(assignment, nopos);
4770 }
4771
4772 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
4773 Statement* validate_throw_output;
4774 {
4775 Expression* is_receiver_call;
4776 {
4777 auto args = new (zone()) ZoneList<Expression*>(1, zone());
4778 args->Add(factory()->NewVariableProxy(var_output), zone());
4779 is_receiver_call =
4780 factory()->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
4781 }
4782
4783 Statement* throw_call;
4784 {
4785 auto args = new (zone()) ZoneList<Expression*>(1, zone());
4786 args->Add(factory()->NewVariableProxy(var_output), zone());
4787 Expression* call = factory()->NewCallRuntime(
4788 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
4789 throw_call = factory()->NewExpressionStatement(call, nopos);
4790 }
4791
4792 validate_throw_output = factory()->NewIfStatement(
4793 is_receiver_call, factory()->NewEmptyStatement(nopos), throw_call,
4794 nopos);
4795 }
4796
4797 // if (output.done) break;
4798 Statement* if_done;
4799 {
4800 Expression* output_proxy = factory()->NewVariableProxy(var_output);
4801 Expression* literal =
4802 factory()->NewStringLiteral(ast_value_factory()->done_string(), nopos);
4803 Expression* property = factory()->NewProperty(output_proxy, literal, nopos);
4804 BreakStatement* break_loop = factory()->NewBreakStatement(loop, nopos);
4805 if_done = factory()->NewIfStatement(
4806 property, break_loop, factory()->NewEmptyStatement(nopos), nopos);
4807 }
4808
4809
4810 // mode = kReturn;
4811 Statement* set_mode_return;
4812 {
4813 Expression* mode_proxy = factory()->NewVariableProxy(var_mode);
4814 Expression* kreturn =
4815 factory()->NewSmiLiteral(JSGeneratorObject::kReturn, nopos);
4816 Expression* assignment =
4817 factory()->NewAssignment(Token::ASSIGN, mode_proxy, kreturn, nopos);
4818 set_mode_return = factory()->NewExpressionStatement(assignment, nopos);
4819 }
4820
4821 // Yield(output);
4822 Statement* yield_output;
4823 {
4824 Expression* output_proxy = factory()->NewVariableProxy(var_output);
4825 Yield* yield = factory()->NewYield(generator, output_proxy, nopos,
4826 Yield::kOnExceptionThrow);
4827 yield_output = factory()->NewExpressionStatement(yield, nopos);
4828 }
4829
4830 // mode = kNext;
4831 Statement* set_mode_next;
4832 {
4833 Expression* mode_proxy = factory()->NewVariableProxy(var_mode);
4834 Expression* knext =
4835 factory()->NewSmiLiteral(JSGeneratorObject::kNext, nopos);
4836 Expression* assignment =
4837 factory()->NewAssignment(Token::ASSIGN, mode_proxy, knext, nopos);
4838 set_mode_next = factory()->NewExpressionStatement(assignment, nopos);
4839 }
4840
4841 // mode = kThrow;
4842 Statement* set_mode_throw;
4843 {
4844 Expression* mode_proxy = factory()->NewVariableProxy(var_mode);
4845 Expression* kthrow =
4846 factory()->NewSmiLiteral(JSGeneratorObject::kThrow, nopos);
4847 Expression* assignment =
4848 factory()->NewAssignment(Token::ASSIGN, mode_proxy, kthrow, nopos);
4849 set_mode_throw = factory()->NewExpressionStatement(assignment, nopos);
4850 }
4851
4852 // input = function.sent;
4853 Statement* get_input;
4854 {
4855 Expression* function_sent = FunctionSentExpression(nopos);
4856 Expression* input_proxy = factory()->NewVariableProxy(var_input);
4857 Expression* assignment = factory()->NewAssignment(
4858 Token::ASSIGN, input_proxy, function_sent, nopos);
4859 get_input = factory()->NewExpressionStatement(assignment, nopos);
4860 }
4861
4862 // if (mode === kReturn) {
4863 // return {value: output.value, done: true};
4864 // }
4865 Statement* maybe_return_value;
4866 {
4867 Expression* mode_proxy = factory()->NewVariableProxy(var_mode);
4868 Expression* kreturn =
4869 factory()->NewSmiLiteral(JSGeneratorObject::kReturn, nopos);
4870 Expression* condition = factory()->NewCompareOperation(
4871 Token::EQ_STRICT, mode_proxy, kreturn, nopos);
4872
4873 Expression* output_proxy = factory()->NewVariableProxy(var_output);
4874 Expression* literal =
4875 factory()->NewStringLiteral(ast_value_factory()->value_string(), nopos);
4876 Expression* property = factory()->NewProperty(output_proxy, literal, nopos);
4877 Statement* return_value = factory()->NewReturnStatement(
4878 BuildIteratorResult(property, true), nopos);
4879
4880 maybe_return_value = factory()->NewIfStatement(
4881 condition, return_value, factory()->NewEmptyStatement(nopos), nopos);
4882 }
4883
4884 // output.value
4885 Statement* get_value;
4886 {
4887 Expression* output_proxy = factory()->NewVariableProxy(var_output);
4888 Expression* literal =
4889 factory()->NewStringLiteral(ast_value_factory()->value_string(), nopos);
4890 Expression* property = factory()->NewProperty(output_proxy, literal, nopos);
4891 get_value = factory()->NewExpressionStatement(property, nopos);
4892 }
4893
4894 // Now put things together.
4895
4896 // try { ... } catch(e) { ... }
4897 Statement* try_catch;
4898 {
4899 Block* try_block = factory()->NewBlock(nullptr, 2, false, nopos);
4900 try_block->statements()->Add(yield_output, zone());
4901 try_block->statements()->Add(set_mode_next, zone());
4902
4903 Block* catch_block = factory()->NewBlock(nullptr, 1, false, nopos);
4904 catch_block->statements()->Add(set_mode_throw, zone());
4905
4906 Scope* catch_scope = NewScope(CATCH_SCOPE);
4907 catch_scope->set_is_hidden();
4908 const AstRawString* name = ast_value_factory()->dot_catch_string();
4909 Variable* catch_variable = catch_scope->DeclareLocal(
4910 name, VAR, kCreatedInitialized, NORMAL_VARIABLE);
4911
4912 try_catch = factory()->NewTryCatchStatementForDesugaring(
4913 try_block, catch_scope, catch_variable, catch_block, nopos);
4914 }
4915
4916 // try { ... } finally { ... }
4917 Statement* try_finally;
4918 {
4919 Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos);
4920 try_block->statements()->Add(try_catch, zone());
4921
4922 Block* finally = factory()->NewBlock(nullptr, 2, false, nopos);
4923 finally->statements()->Add(get_input, zone());
4924 finally->statements()->Add(factory()->NewContinueStatement(loop, nopos),
4925 zone());
4926
4927 try_finally = factory()->NewTryFinallyStatement(try_block, finally, nopos);
4928 }
4929
4930 // switch (mode) { ... }
4931 SwitchStatement* switch_mode = factory()->NewSwitchStatement(nullptr, nopos);
4932 {
4933 auto case_next = new (zone()) ZoneList<Statement*>(3, zone());
4934 case_next->Add(call_next, zone());
4935 case_next->Add(validate_next_output, zone());
4936 case_next->Add(factory()->NewBreakStatement(switch_mode, nopos), zone());
4937
4938 auto case_return = new (zone()) ZoneList<Statement*>(5, zone());
4939 BuildIteratorClose(case_return, var_iterator, var_input, var_output);
4940 case_return->Add(factory()->NewBreakStatement(switch_mode, nopos), zone());
4941
4942 auto case_throw = new (zone()) ZoneList<Statement*>(5, zone());
4943 case_throw->Add(get_throw, zone());
4944 case_throw->Add(check_throw, zone());
4945 case_throw->Add(call_throw, zone());
4946 case_throw->Add(validate_throw_output, zone());
4947 case_throw->Add(factory()->NewBreakStatement(switch_mode, nopos), zone());
4948
4949 auto cases = new (zone()) ZoneList<CaseClause*>(3, zone());
4950 Expression* knext =
4951 factory()->NewSmiLiteral(JSGeneratorObject::kNext, nopos);
4952 Expression* kreturn =
4953 factory()->NewSmiLiteral(JSGeneratorObject::kReturn, nopos);
4954 Expression* kthrow =
4955 factory()->NewSmiLiteral(JSGeneratorObject::kThrow, nopos);
4956 cases->Add(factory()->NewCaseClause(knext, case_next, nopos), zone());
4957 cases->Add(factory()->NewCaseClause(kreturn, case_return, nopos), zone());
4958 cases->Add(factory()->NewCaseClause(kthrow, case_throw, nopos), zone());
4959
4960 switch_mode->Initialize(factory()->NewVariableProxy(var_mode), cases);
4961 }
4962
4963 // while (true) { ... }
4964 // Already defined earlier: WhileStatement* loop = ...
4965 {
4966 Block* loop_body = factory()->NewBlock(nullptr, 4, false, nopos);
4967 loop_body->statements()->Add(switch_mode, zone());
4968 loop_body->statements()->Add(if_done, zone());
4969 loop_body->statements()->Add(set_mode_return, zone());
4970 loop_body->statements()->Add(try_finally, zone());
4971
4972 loop->Initialize(factory()->NewBooleanLiteral(true, nopos), loop_body);
4973 }
4974
4975 // do { ... }
4976 DoExpression* yield_star;
4977 {
4978 // The rewriter needs to process the get_value statement only, hence we
4979 // put the preceding statements into an init block.
4980
4981 Block* do_block_ = factory()->NewBlock(nullptr, 7, true, nopos);
4982 do_block_->statements()->Add(initialize_input, zone());
4983 do_block_->statements()->Add(initialize_mode, zone());
4984 do_block_->statements()->Add(initialize_output, zone());
4985 do_block_->statements()->Add(get_iterator, zone());
4986 do_block_->statements()->Add(validate_iterator, zone());
4987 do_block_->statements()->Add(loop, zone());
4988 do_block_->statements()->Add(maybe_return_value, zone());
4989
4990 Block* do_block = factory()->NewBlock(nullptr, 2, false, nopos);
4991 do_block->statements()->Add(do_block_, zone());
4992 do_block->statements()->Add(get_value, zone());
4993
4994 Variable* dot_result =
4995 NewTemporary(ast_value_factory()->dot_result_string());
4996 yield_star = factory()->NewDoExpression(do_block, dot_result, nopos);
4997 Rewriter::Rewrite(this, GetClosureScope(), yield_star, ast_value_factory());
4998 }
4999
5000 return yield_star;
5001 }
5002
CheckCallable(Variable * var,Expression * error,int pos)5003 Statement* Parser::CheckCallable(Variable* var, Expression* error, int pos) {
5004 const int nopos = kNoSourcePosition;
5005 Statement* validate_var;
5006 {
5007 Expression* type_of = factory()->NewUnaryOperation(
5008 Token::TYPEOF, factory()->NewVariableProxy(var), nopos);
5009 Expression* function_literal = factory()->NewStringLiteral(
5010 ast_value_factory()->function_string(), nopos);
5011 Expression* condition = factory()->NewCompareOperation(
5012 Token::EQ_STRICT, type_of, function_literal, nopos);
5013
5014 Statement* throw_call = factory()->NewExpressionStatement(error, pos);
5015
5016 validate_var = factory()->NewIfStatement(
5017 condition, factory()->NewEmptyStatement(nopos), throw_call, nopos);
5018 }
5019 return validate_var;
5020 }
5021
BuildIteratorClose(ZoneList<Statement * > * statements,Variable * iterator,Variable * input,Variable * var_output)5022 void Parser::BuildIteratorClose(ZoneList<Statement*>* statements,
5023 Variable* iterator, Variable* input,
5024 Variable* var_output) {
5025 //
5026 // This function adds four statements to [statements], corresponding to the
5027 // following code:
5028 //
5029 // let iteratorReturn = iterator.return;
5030 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) {
5031 // return {value: input, done: true};
5032 // }
5033 // output = %_Call(iteratorReturn, iterator, input);
5034 // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
5035 //
5036
5037 const int nopos = kNoSourcePosition;
5038
5039 // let iteratorReturn = iterator.return;
5040 Variable* var_return = var_output; // Reusing the output variable.
5041 Statement* get_return;
5042 {
5043 Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
5044 Expression* literal = factory()->NewStringLiteral(
5045 ast_value_factory()->return_string(), nopos);
5046 Expression* property =
5047 factory()->NewProperty(iterator_proxy, literal, nopos);
5048 Expression* return_proxy = factory()->NewVariableProxy(var_return);
5049 Expression* assignment =
5050 factory()->NewAssignment(Token::ASSIGN, return_proxy, property, nopos);
5051 get_return = factory()->NewExpressionStatement(assignment, nopos);
5052 }
5053
5054 // if (IS_NULL_OR_UNDEFINED(iteratorReturn) {
5055 // return {value: input, done: true};
5056 // }
5057 Statement* check_return;
5058 {
5059 Expression* condition = factory()->NewCompareOperation(
5060 Token::EQ, factory()->NewVariableProxy(var_return),
5061 factory()->NewNullLiteral(nopos), nopos);
5062
5063 Expression* value = factory()->NewVariableProxy(input);
5064
5065 Statement* return_input =
5066 factory()->NewReturnStatement(BuildIteratorResult(value, true), nopos);
5067
5068 check_return = factory()->NewIfStatement(
5069 condition, return_input, factory()->NewEmptyStatement(nopos), nopos);
5070 }
5071
5072 // output = %_Call(iteratorReturn, iterator, input);
5073 Statement* call_return;
5074 {
5075 auto args = new (zone()) ZoneList<Expression*>(3, zone());
5076 args->Add(factory()->NewVariableProxy(var_return), zone());
5077 args->Add(factory()->NewVariableProxy(iterator), zone());
5078 args->Add(factory()->NewVariableProxy(input), zone());
5079
5080 Expression* call =
5081 factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos);
5082 Expression* output_proxy = factory()->NewVariableProxy(var_output);
5083 Expression* assignment =
5084 factory()->NewAssignment(Token::ASSIGN, output_proxy, call, nopos);
5085 call_return = factory()->NewExpressionStatement(assignment, nopos);
5086 }
5087
5088 // if (!IS_RECEIVER(output)) %ThrowIteratorResultNotAnObject(output);
5089 Statement* validate_output;
5090 {
5091 Expression* is_receiver_call;
5092 {
5093 auto args = new (zone()) ZoneList<Expression*>(1, zone());
5094 args->Add(factory()->NewVariableProxy(var_output), zone());
5095 is_receiver_call =
5096 factory()->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
5097 }
5098
5099 Statement* throw_call;
5100 {
5101 auto args = new (zone()) ZoneList<Expression*>(1, zone());
5102 args->Add(factory()->NewVariableProxy(var_output), zone());
5103 Expression* call = factory()->NewCallRuntime(
5104 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
5105 throw_call = factory()->NewExpressionStatement(call, nopos);
5106 }
5107
5108 validate_output = factory()->NewIfStatement(
5109 is_receiver_call, factory()->NewEmptyStatement(nopos), throw_call,
5110 nopos);
5111 }
5112
5113 statements->Add(get_return, zone());
5114 statements->Add(check_return, zone());
5115 statements->Add(call_return, zone());
5116 statements->Add(validate_output, zone());
5117 }
5118
FinalizeIteratorUse(Scope * use_scope,Variable * completion,Expression * condition,Variable * iter,Block * iterator_use,Block * target)5119 void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion,
5120 Expression* condition, Variable* iter,
5121 Block* iterator_use, Block* target) {
5122 //
5123 // This function adds two statements to [target], corresponding to the
5124 // following code:
5125 //
5126 // completion = kNormalCompletion;
5127 // try {
5128 // try {
5129 // iterator_use
5130 // } catch(e) {
5131 // if (completion === kAbruptCompletion) completion = kThrowCompletion;
5132 // %ReThrow(e);
5133 // }
5134 // } finally {
5135 // if (condition) {
5136 // #BuildIteratorCloseForCompletion(iter, completion)
5137 // }
5138 // }
5139 //
5140
5141 const int nopos = kNoSourcePosition;
5142
5143 // completion = kNormalCompletion;
5144 Statement* initialize_completion;
5145 {
5146 Expression* proxy = factory()->NewVariableProxy(completion);
5147 Expression* assignment = factory()->NewAssignment(
5148 Token::ASSIGN, proxy,
5149 factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
5150 initialize_completion =
5151 factory()->NewExpressionStatement(assignment, nopos);
5152 }
5153
5154 // if (completion === kAbruptCompletion) completion = kThrowCompletion;
5155 Statement* set_completion_throw;
5156 {
5157 Expression* condition = factory()->NewCompareOperation(
5158 Token::EQ_STRICT, factory()->NewVariableProxy(completion),
5159 factory()->NewSmiLiteral(Parser::kAbruptCompletion, nopos), nopos);
5160
5161 Expression* proxy = factory()->NewVariableProxy(completion);
5162 Expression* assignment = factory()->NewAssignment(
5163 Token::ASSIGN, proxy,
5164 factory()->NewSmiLiteral(Parser::kThrowCompletion, nopos), nopos);
5165 Statement* statement = factory()->NewExpressionStatement(assignment, nopos);
5166 set_completion_throw = factory()->NewIfStatement(
5167 condition, statement, factory()->NewEmptyStatement(nopos), nopos);
5168 }
5169
5170 // if (condition) {
5171 // #BuildIteratorCloseForCompletion(iter, completion)
5172 // }
5173 Block* maybe_close;
5174 {
5175 Block* block = factory()->NewBlock(nullptr, 2, true, nopos);
5176 Expression* proxy = factory()->NewVariableProxy(completion);
5177 BuildIteratorCloseForCompletion(use_scope, block->statements(), iter,
5178 proxy);
5179 DCHECK(block->statements()->length() == 2);
5180
5181 maybe_close = factory()->NewBlock(nullptr, 1, true, nopos);
5182 maybe_close->statements()->Add(
5183 factory()->NewIfStatement(condition, block,
5184 factory()->NewEmptyStatement(nopos), nopos),
5185 zone());
5186 }
5187
5188 // try { #try_block }
5189 // catch(e) {
5190 // #set_completion_throw;
5191 // %ReThrow(e);
5192 // }
5193 Statement* try_catch;
5194 {
5195 Scope* catch_scope = NewScopeWithParent(use_scope, CATCH_SCOPE);
5196 Variable* catch_variable =
5197 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR,
5198 kCreatedInitialized, NORMAL_VARIABLE);
5199 catch_scope->set_is_hidden();
5200
5201 Statement* rethrow;
5202 // We use %ReThrow rather than the ordinary throw because we want to
5203 // preserve the original exception message. This is also why we create a
5204 // TryCatchStatementForReThrow below (which does not clear the pending
5205 // message), rather than a TryCatchStatement.
5206 {
5207 auto args = new (zone()) ZoneList<Expression*>(1, zone());
5208 args->Add(factory()->NewVariableProxy(catch_variable), zone());
5209 rethrow = factory()->NewExpressionStatement(
5210 factory()->NewCallRuntime(Runtime::kReThrow, args, nopos), nopos);
5211 }
5212
5213 Block* catch_block = factory()->NewBlock(nullptr, 2, false, nopos);
5214 catch_block->statements()->Add(set_completion_throw, zone());
5215 catch_block->statements()->Add(rethrow, zone());
5216
5217 try_catch = factory()->NewTryCatchStatementForReThrow(
5218 iterator_use, catch_scope, catch_variable, catch_block, nopos);
5219 }
5220
5221 // try { #try_catch } finally { #maybe_close }
5222 Statement* try_finally;
5223 {
5224 Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos);
5225 try_block->statements()->Add(try_catch, zone());
5226
5227 try_finally =
5228 factory()->NewTryFinallyStatement(try_block, maybe_close, nopos);
5229 }
5230
5231 target->statements()->Add(initialize_completion, zone());
5232 target->statements()->Add(try_finally, zone());
5233 }
5234
BuildIteratorCloseForCompletion(Scope * scope,ZoneList<Statement * > * statements,Variable * iterator,Expression * completion)5235 void Parser::BuildIteratorCloseForCompletion(Scope* scope,
5236 ZoneList<Statement*>* statements,
5237 Variable* iterator,
5238 Expression* completion) {
5239 //
5240 // This function adds two statements to [statements], corresponding to the
5241 // following code:
5242 //
5243 // let iteratorReturn = iterator.return;
5244 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
5245 // if (completion === kThrowCompletion) {
5246 // if (!IS_CALLABLE(iteratorReturn)) {
5247 // throw MakeTypeError(kReturnMethodNotCallable);
5248 // }
5249 // try { %_Call(iteratorReturn, iterator) } catch (_) { }
5250 // } else {
5251 // let output = %_Call(iteratorReturn, iterator);
5252 // if (!IS_RECEIVER(output)) {
5253 // %ThrowIterResultNotAnObject(output);
5254 // }
5255 // }
5256 // }
5257 //
5258
5259 const int nopos = kNoSourcePosition;
5260 // let iteratorReturn = iterator.return;
5261 Variable* var_return = NewTemporary(ast_value_factory()->empty_string());
5262 Statement* get_return;
5263 {
5264 Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
5265 Expression* literal = factory()->NewStringLiteral(
5266 ast_value_factory()->return_string(), nopos);
5267 Expression* property =
5268 factory()->NewProperty(iterator_proxy, literal, nopos);
5269 Expression* return_proxy = factory()->NewVariableProxy(var_return);
5270 Expression* assignment =
5271 factory()->NewAssignment(Token::ASSIGN, return_proxy, property, nopos);
5272 get_return = factory()->NewExpressionStatement(assignment, nopos);
5273 }
5274
5275 // if (!IS_CALLABLE(iteratorReturn)) {
5276 // throw MakeTypeError(kReturnMethodNotCallable);
5277 // }
5278 Statement* check_return_callable;
5279 {
5280 Expression* throw_expr =
5281 NewThrowTypeError(MessageTemplate::kReturnMethodNotCallable,
5282 ast_value_factory()->empty_string(), nopos);
5283 check_return_callable = CheckCallable(var_return, throw_expr, nopos);
5284 }
5285
5286 // try { %_Call(iteratorReturn, iterator) } catch (_) { }
5287 Statement* try_call_return;
5288 {
5289 auto args = new (zone()) ZoneList<Expression*>(2, zone());
5290 args->Add(factory()->NewVariableProxy(var_return), zone());
5291 args->Add(factory()->NewVariableProxy(iterator), zone());
5292
5293 Expression* call =
5294 factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos);
5295
5296 Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos);
5297 try_block->statements()->Add(factory()->NewExpressionStatement(call, nopos),
5298 zone());
5299
5300 Block* catch_block = factory()->NewBlock(nullptr, 0, false, nopos);
5301
5302 Scope* catch_scope = NewScopeWithParent(scope, CATCH_SCOPE);
5303 Variable* catch_variable =
5304 catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR,
5305 kCreatedInitialized, NORMAL_VARIABLE);
5306 catch_scope->set_is_hidden();
5307
5308 try_call_return = factory()->NewTryCatchStatement(
5309 try_block, catch_scope, catch_variable, catch_block, nopos);
5310 }
5311
5312 // let output = %_Call(iteratorReturn, iterator);
5313 // if (!IS_RECEIVER(output)) {
5314 // %ThrowIteratorResultNotAnObject(output);
5315 // }
5316 Block* validate_return;
5317 {
5318 Variable* var_output = NewTemporary(ast_value_factory()->empty_string());
5319 Statement* call_return;
5320 {
5321 auto args = new (zone()) ZoneList<Expression*>(2, zone());
5322 args->Add(factory()->NewVariableProxy(var_return), zone());
5323 args->Add(factory()->NewVariableProxy(iterator), zone());
5324 Expression* call =
5325 factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos);
5326
5327 Expression* output_proxy = factory()->NewVariableProxy(var_output);
5328 Expression* assignment =
5329 factory()->NewAssignment(Token::ASSIGN, output_proxy, call, nopos);
5330 call_return = factory()->NewExpressionStatement(assignment, nopos);
5331 }
5332
5333 Expression* is_receiver_call;
5334 {
5335 auto args = new (zone()) ZoneList<Expression*>(1, zone());
5336 args->Add(factory()->NewVariableProxy(var_output), zone());
5337 is_receiver_call =
5338 factory()->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
5339 }
5340
5341 Statement* throw_call;
5342 {
5343 auto args = new (zone()) ZoneList<Expression*>(1, zone());
5344 args->Add(factory()->NewVariableProxy(var_output), zone());
5345 Expression* call = factory()->NewCallRuntime(
5346 Runtime::kThrowIteratorResultNotAnObject, args, nopos);
5347 throw_call = factory()->NewExpressionStatement(call, nopos);
5348 }
5349
5350 Statement* check_return = factory()->NewIfStatement(
5351 is_receiver_call, factory()->NewEmptyStatement(nopos), throw_call,
5352 nopos);
5353
5354 validate_return = factory()->NewBlock(nullptr, 2, false, nopos);
5355 validate_return->statements()->Add(call_return, zone());
5356 validate_return->statements()->Add(check_return, zone());
5357 }
5358
5359 // if (completion === kThrowCompletion) {
5360 // #check_return_callable;
5361 // #try_call_return;
5362 // } else {
5363 // #validate_return;
5364 // }
5365 Statement* call_return_carefully;
5366 {
5367 Expression* condition = factory()->NewCompareOperation(
5368 Token::EQ_STRICT, completion,
5369 factory()->NewSmiLiteral(Parser::kThrowCompletion, nopos), nopos);
5370
5371 Block* then_block = factory()->NewBlock(nullptr, 2, false, nopos);
5372 then_block->statements()->Add(check_return_callable, zone());
5373 then_block->statements()->Add(try_call_return, zone());
5374
5375 call_return_carefully = factory()->NewIfStatement(condition, then_block,
5376 validate_return, nopos);
5377 }
5378
5379 // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { ... }
5380 Statement* maybe_call_return;
5381 {
5382 Expression* condition = factory()->NewCompareOperation(
5383 Token::EQ, factory()->NewVariableProxy(var_return),
5384 factory()->NewNullLiteral(nopos), nopos);
5385
5386 maybe_call_return = factory()->NewIfStatement(
5387 condition, factory()->NewEmptyStatement(nopos), call_return_carefully,
5388 nopos);
5389 }
5390
5391 statements->Add(get_return, zone());
5392 statements->Add(maybe_call_return, zone());
5393 }
5394
FinalizeForOfStatement(ForOfStatement * loop,Variable * var_completion,int pos)5395 Statement* Parser::FinalizeForOfStatement(ForOfStatement* loop,
5396 Variable* var_completion, int pos) {
5397 //
5398 // This function replaces the loop with the following wrapping:
5399 //
5400 // completion = kNormalCompletion;
5401 // try {
5402 // try {
5403 // #loop;
5404 // } catch(e) {
5405 // if (completion === kAbruptCompletion) completion = kThrowCompletion;
5406 // %ReThrow(e);
5407 // }
5408 // } finally {
5409 // if (!(completion === kNormalCompletion || IS_UNDEFINED(#iterator))) {
5410 // #BuildIteratorCloseForCompletion(#iterator, completion)
5411 // }
5412 // }
5413 //
5414 // Note that the loop's body and its assign_each already contain appropriate
5415 // assignments to completion (see InitializeForOfStatement).
5416 //
5417
5418 const int nopos = kNoSourcePosition;
5419
5420 // !(completion === kNormalCompletion || IS_UNDEFINED(#iterator))
5421 Expression* closing_condition;
5422 {
5423 Expression* lhs = factory()->NewCompareOperation(
5424 Token::EQ_STRICT, factory()->NewVariableProxy(var_completion),
5425 factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
5426 Expression* rhs = factory()->NewCompareOperation(
5427 Token::EQ_STRICT, factory()->NewVariableProxy(loop->iterator()),
5428 factory()->NewUndefinedLiteral(nopos), nopos);
5429 closing_condition = factory()->NewUnaryOperation(
5430 Token::NOT, factory()->NewBinaryOperation(Token::OR, lhs, rhs, nopos),
5431 nopos);
5432 }
5433
5434 Block* final_loop = factory()->NewBlock(nullptr, 2, false, nopos);
5435 {
5436 Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos);
5437 try_block->statements()->Add(loop, zone());
5438
5439 // The scope in which the parser creates this loop.
5440 Scope* loop_scope = scope()->outer_scope();
5441 DCHECK_EQ(loop_scope->scope_type(), BLOCK_SCOPE);
5442 DCHECK_EQ(scope()->scope_type(), BLOCK_SCOPE);
5443
5444 FinalizeIteratorUse(loop_scope, var_completion, closing_condition,
5445 loop->iterator(), try_block, final_loop);
5446 }
5447
5448 return final_loop;
5449 }
5450
5451 #undef CHECK_OK
5452 #undef CHECK_OK_VOID
5453 #undef CHECK_FAILED
5454
5455 } // namespace internal
5456 } // namespace v8
5457