v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
parser.cc
Go to the documentation of this file.
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
6
7#include <algorithm>
8#include <memory>
9#include <optional>
10
13#include "src/ast/ast.h"
15#include "src/base/ieee754.h"
19#include "src/common/globals.h"
24#include "src/logging/log.h"
27#include "src/numbers/ieee754.h"
31#include "src/runtime/runtime.h"
37
38namespace v8::internal {
39
41 bool call_super, int pos) {
42 int expected_property_count = 0;
43 const int parameter_count = 0;
44
47 DeclarationScope* function_scope = NewFunctionScope(kind);
49 // Set start and end position to the same value
50 function_scope->set_start_position(pos);
51 function_scope->set_end_position(pos);
52 ScopedPtrList<Statement> body(pointer_buffer());
53
54 {
55 FunctionState function_state(&function_state_, &scope_, function_scope);
56
57 // ES#sec-runtime-semantics-classdefinitionevaluation
58 //
59 // 14.a
60 // ...
61 // iv. If F.[[ConstructorKind]] is DERIVED, then
62 // 1. NOTE: This branch behaves similarly to constructor(...args) {
63 // super(...args); }. The most notable distinction is that while the
64 // aforementioned ECMAScript source text observably calls the
65 // @@iterator method on %Array.prototype%, this function does not.
66 // 2. Let func be ! F.[[GetPrototypeOf]]().
67 // 3. If IsConstructor(func) is false, throw a TypeError exception.
68 // 4. Let result be ? Construct(func, args, NewTarget).
69 // ...
70 if (call_super) {
72 Expression* call =
73 factory()->NewSuperCallForwardArgs(super_call_ref, pos);
74 body.Add(factory()->NewReturnStatement(call, pos));
75 }
76
77 expected_property_count = function_state.expected_property_count();
78 }
79
80 FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
81 name, function_scope, body, expected_property_count, parameter_count,
83 FunctionSyntaxKind::kAnonymousExpression, default_eager_compile_hint(),
84 pos, true, GetNextInfoId());
85 return function_literal;
86}
87
89 const AstRawString* name,
90 bool is_static, int pos) {
91 ScopedPtrList<Statement> body(pointer_buffer());
92 DeclarationScope* function_scope =
93 NewFunctionScope(is_static ? FunctionKind::kGetterFunction
96 function_scope->set_start_position(pos);
97 function_scope->set_end_position(pos);
98 {
99 FunctionState function_state(&function_state_, &scope_, function_scope);
100 body.Add(factory()->NewAutoAccessorGetterBody(name_proxy, pos));
101 }
102 // TODO(42202709): Enable lazy compilation by adding custom handling in
103 // `Parser::DoParseFunction`.
104 FunctionLiteral* getter = factory()->NewFunctionLiteral(
105 nullptr, function_scope, body, 0, 0, 0,
108 FunctionLiteral::kShouldEagerCompile, pos, true, GetNextInfoId());
109 const AstRawString* prefix =
110 name ? ast_value_factory()->get_space_string() : nullptr;
111 SetFunctionName(getter, name, prefix);
112 return getter;
113}
114
116 const AstRawString* name,
117 bool is_static, int pos) {
118 ScopedPtrList<Statement> body(pointer_buffer());
119 DeclarationScope* function_scope =
120 NewFunctionScope(is_static ? FunctionKind::kSetterFunction
122 SetLanguageMode(function_scope, LanguageMode::kStrict);
123 function_scope->set_start_position(pos);
124 function_scope->set_end_position(pos);
125 function_scope->DeclareParameter(ast_value_factory()->empty_string(),
126 VariableMode::kTemporary, false, false,
127 ast_value_factory(), kNoSourcePosition);
128 {
129 FunctionState function_state(&function_state_, &scope_, function_scope);
130 body.Add(factory()->NewAutoAccessorSetterBody(name_proxy, pos));
131 }
132 // TODO(42202709): Enable lazy compilation by adding custom handling in
133 // `Parser::DoParseFunction`.
134 FunctionLiteral* setter = factory()->NewFunctionLiteral(
135 nullptr, function_scope, body, 0, 1, 0,
138 FunctionLiteral::kShouldEagerCompile, pos, true, GetNextInfoId());
139 const AstRawString* prefix =
140 name ? ast_value_factory()->set_space_string() : nullptr;
141 SetFunctionName(setter, name, prefix);
142 return setter;
143}
144
146 ClassInfo* class_info,
147 const AstRawString* name,
148 bool is_static, int pos) {
149 VariableProxy* accessor_storage_name_proxy =
151 scope, class_info,
152 AutoAccessorVariableName(ast_value_factory(),
153 class_info->autoaccessor_count++),
154 is_static);
155 // The property value position will match the beginning of the "accessor"
156 // keyword, which can be the same as the start of the parent class scope, use
157 // the position of the next two characters to distinguish them.
158 FunctionLiteral* getter = MakeAutoAccessorGetter(accessor_storage_name_proxy,
159 name, is_static, pos + 1);
160 FunctionLiteral* setter = MakeAutoAccessorSetter(accessor_storage_name_proxy,
161 name, is_static, pos + 2);
162 return factory()->NewAutoAccessorInfo(getter, setter,
163 accessor_storage_name_proxy);
164}
165
167 ClassScope* scope, ClassInfo* class_info, const AstRawString* name,
168 Expression* key, Expression* value, bool is_static, bool is_computed_name,
169 bool is_private, int pos) {
170 AutoAccessorInfo* accessor_info =
171 NewAutoAccessorInfo(scope, class_info, name, is_static, pos);
172 return factory()->NewClassLiteralProperty(
173 key, value, accessor_info, is_static, is_computed_name, is_private);
174}
175
177 Token::Value token,
178 MessageTemplate message) {
179 const char* arg = nullptr;
180 switch (token) {
181 case Token::kEos:
182 message = MessageTemplate::kUnexpectedEOS;
183 break;
184 case Token::kSmi:
185 case Token::kNumber:
186 case Token::kBigInt:
187 message = MessageTemplate::kUnexpectedTokenNumber;
188 break;
189 case Token::kString:
190 message = MessageTemplate::kUnexpectedTokenString;
191 break;
192 case Token::kPrivateName:
193 case Token::kIdentifier:
194 message = MessageTemplate::kUnexpectedTokenIdentifier;
195 // Use ReportMessageAt with the AstRawString parameter; skip the
196 // ReportMessageAt below.
197 ReportMessageAt(location, message, GetIdentifier());
198 return;
199 case Token::kAwait:
200 case Token::kEnum:
201 message = MessageTemplate::kUnexpectedReserved;
202 break;
203 case Token::kLet:
204 case Token::kStatic:
205 case Token::kYield:
206 case Token::kFutureStrictReservedWord:
207 message = is_strict(language_mode())
208 ? MessageTemplate::kUnexpectedStrictReserved
209 : MessageTemplate::kUnexpectedTokenIdentifier;
210 arg = Token::String(token);
211 break;
212 case Token::kTemplateSpan:
213 case Token::kTemplateTail:
214 message = MessageTemplate::kUnexpectedTemplateString;
215 break;
216 case Token::kEscapedStrictReservedWord:
217 case Token::kEscapedKeyword:
218 message = MessageTemplate::kInvalidEscapedReservedWord;
219 break;
220 case Token::kIllegal:
221 if (scanner()->has_error()) {
222 message = scanner()->error();
223 location = scanner()->error_location();
224 } else {
225 message = MessageTemplate::kInvalidOrUnexpectedToken;
226 }
227 break;
228 case Token::kRegExpLiteral:
229 message = MessageTemplate::kUnexpectedTokenRegExp;
230 break;
231 default:
232 const char* name = Token::String(token);
233 DCHECK_NOT_NULL(name);
234 arg = name;
235 break;
236 }
237 ReportMessageAt(location, message, arg);
238}
239
240// ----------------------------------------------------------------------------
241// Implementation of Parser
242
244 Token::Value op, int pos) {
245 // Constant fold numeric operations.
246 if ((*x)->IsNumberLiteral() && y->IsNumberLiteral()) {
247 double x_val = (*x)->AsLiteral()->AsNumber();
248 double y_val = y->AsLiteral()->AsNumber();
249 switch (op) {
250 case Token::kAdd:
251 *x = factory()->NewNumberLiteral(x_val + y_val, pos);
252 return true;
253 case Token::kSub:
254 *x = factory()->NewNumberLiteral(x_val - y_val, pos);
255 return true;
256 case Token::kMul:
257 *x = factory()->NewNumberLiteral(x_val * y_val, pos);
258 return true;
259 case Token::kDiv:
260 *x = factory()->NewNumberLiteral(base::Divide(x_val, y_val), pos);
261 return true;
262 case Token::kMod:
263 *x = factory()->NewNumberLiteral(Modulo(x_val, y_val), pos);
264 return true;
265 case Token::kBitOr: {
266 int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
267 *x = factory()->NewNumberLiteral(value, pos);
268 return true;
269 }
270 case Token::kBitAnd: {
271 int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
272 *x = factory()->NewNumberLiteral(value, pos);
273 return true;
274 }
275 case Token::kBitXor: {
276 int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
277 *x = factory()->NewNumberLiteral(value, pos);
278 return true;
279 }
280 case Token::kShl: {
281 int value =
283 *x = factory()->NewNumberLiteral(value, pos);
284 return true;
285 }
286 case Token::kShr: {
287 uint32_t shift = DoubleToInt32(y_val) & 0x1F;
288 uint32_t value = DoubleToUint32(x_val) >> shift;
289 *x = factory()->NewNumberLiteral(value, pos);
290 return true;
291 }
292 case Token::kSar: {
293 uint32_t shift = DoubleToInt32(y_val) & 0x1F;
294 int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
295 *x = factory()->NewNumberLiteral(value, pos);
296 return true;
297 }
298 case Token::kExp:
299 *x = factory()->NewNumberLiteral(math::pow(x_val, y_val), pos);
300 return true;
301 default:
302 break;
303 }
304 }
305
306 // Constant fold string concatenation.
307 if (op == Token::kAdd) {
308 // Only consider string concatenation of two strings.
309 // TODO(leszeks): We could also eagerly convert other literals to string if
310 // one side of the addition is a string.
311 if (y->IsStringLiteral()) {
312 if ((*x)->IsStringLiteral()) {
313 const AstRawString* x_val = (*x)->AsLiteral()->AsRawString();
314 const AstRawString* y_val = y->AsLiteral()->AsRawString();
315 AstConsString* cons = ast_value_factory()->NewConsString(x_val, y_val);
316 *x = factory()->NewConsStringLiteral(cons, (*x)->position());
317 return true;
318 }
319 if ((*x)->IsConsStringLiteral()) {
320 const AstRawString* y_val = y->AsLiteral()->AsRawString();
321 (*x)->AsLiteral()->AsConsString()->AddString(zone(), y_val);
322 return true;
323 }
324 }
325 }
326 return false;
327}
328
330 Expression* then_expression,
331 Expression* else_expression, int pos,
332 const SourceRange& then_range) {
333 if (*x && (*x)->IsConditionalChain()) {
334 ConditionalChain* conditional_chain = (*x)->AsConditionalChain();
335 if (then_expression != nullptr) {
336 conditional_chain->AddChainEntry(cond, then_expression, pos);
337 AppendConditionalChainSourceRange(conditional_chain, then_range);
338 }
339 if (else_expression != nullptr) {
340 conditional_chain->set_else_expression(else_expression);
341 DCHECK_GT(conditional_chain->conditional_chain_length(), 1);
342 }
343 return true;
344 }
345 return false;
346}
347
349 const SourceRange& else_range) {
350 if (*x && (*x)->IsConditionalChain()) {
351 ConditionalChain* conditional_chain = (*x)->AsConditionalChain();
352 AppendConditionalChainElseSourceRange(conditional_chain, else_range);
353 }
354}
355
357 Token::Value op, int pos,
358 const SourceRange& range) {
359 // Filter out unsupported ops.
360 if (!Token::IsBinaryOp(op) || op == Token::kExp) return false;
361
362 // Convert *x into an nary operation with the given op, returning false if
363 // this is not possible.
364 NaryOperation* nary = nullptr;
365 if ((*x)->IsBinaryOperation()) {
366 BinaryOperation* binop = (*x)->AsBinaryOperation();
367 if (binop->op() != op) return false;
368
369 nary = factory()->NewNaryOperation(op, binop->left(), 2);
370 nary->AddSubsequent(binop->right(), binop->position());
372 *x = nary;
373 } else if ((*x)->IsNaryOperation()) {
374 nary = (*x)->AsNaryOperation();
375 if (nary->op() != op) return false;
376 } else {
377 return false;
378 }
379
380 // Append our current expression to the nary operation.
381 // TODO(leszeks): Do some literal collapsing here if we're appending Smi or
382 // String literals.
383 nary->AddSubsequent(y, pos);
384 nary->clear_parenthesized();
386
387 return true;
388}
389
391 base::Vector<const uint8_t> literal = scanner()->BigIntLiteral();
392 if (literal[0] != '0' || literal.length() == 1) {
393 return ast_value_factory()->GetOneByteString(literal);
394 }
395 std::unique_ptr<char[]> decimal =
397 return ast_value_factory()->GetOneByteString(decimal.get());
398}
399
401 Token::Value op, int pos) {
402 DCHECK_NOT_NULL(expression);
403 const Literal* literal = expression->AsLiteral();
404 if (literal != nullptr) {
405 if (op == Token::kNot) {
406 // Convert the literal to a boolean condition and negate it.
407 return factory()->NewBooleanLiteral(literal->ToBooleanIsFalse(), pos);
408 } else if (literal->IsNumberLiteral()) {
409 // Compute some expressions involving only number literals.
410 double value = literal->AsNumber();
411 switch (op) {
412 case Token::kAdd:
413 return expression;
414 case Token::kSub:
415 return factory()->NewNumberLiteral(-value, pos);
416 case Token::kBitNot:
417 return factory()->NewNumberLiteral(~DoubleToInt32(value), pos);
418 default:
419 break;
420 }
421 }
422 }
423 return factory()->NewUnaryOperation(op, expression, pos);
424}
425
427 MessageTemplate message,
428 const AstRawString* arg, int pos) {
429 ScopedPtrList<Expression> args(pointer_buffer());
430 args.Add(factory()->NewSmiLiteral(static_cast<int>(message), pos));
431 args.Add(factory()->NewStringLiteral(arg, pos));
432 CallRuntime* call_constructor = factory()->NewCallRuntime(id, args, pos);
433 return factory()->NewThrow(call_constructor, pos);
434}
435
437 const AstRawString* home_object_name;
438 if (IsStatic(scope()->GetReceiverScope()->function_kind())) {
439 home_object_name = ast_value_factory_->dot_static_home_object_string();
440 } else {
441 home_object_name = ast_value_factory_->dot_home_object_string();
442 }
443
444 VariableProxy* proxy = NewUnresolved(home_object_name, pos);
445 proxy->set_is_home_object();
446 return factory()->NewSuperPropertyReference(proxy, pos);
447}
448
450 VariableProxy* new_target_proxy =
451 NewUnresolved(ast_value_factory()->new_target_string(), pos);
452 VariableProxy* this_function_proxy =
453 NewUnresolved(ast_value_factory()->this_function_string(), pos);
454 return factory()->NewSuperCallReference(new_target_proxy, this_function_proxy,
455 pos);
456}
457
459 auto proxy = NewUnresolved(ast_value_factory()->new_target_string(), pos);
460 proxy->set_is_new_target();
461 return proxy;
462}
463
465 ScopedPtrList<Expression> args(pointer_buffer());
466 if (!has_module_in_scope_chain()) {
467 DCHECK(IsParsingWhileDebugging());
468 // When debugging, we permit import.meta invocations -- however, they will
469 // never produce a non-undefined result outside of a module.
470 return factory()->NewUndefinedLiteral(pos);
471 }
472 return factory()->NewCallRuntime(Runtime::kInlineGetImportMetaObject, args,
473 pos);
474}
475
477 switch (token) {
478 case Token::kNullLiteral:
479 return factory()->NewNullLiteral(pos);
480 case Token::kTrueLiteral:
481 return factory()->NewBooleanLiteral(true, pos);
482 case Token::kFalseLiteral:
483 return factory()->NewBooleanLiteral(false, pos);
484 case Token::kSmi: {
485 uint32_t value = scanner()->smi_value();
486 return factory()->NewSmiLiteral(value, pos);
487 }
488 case Token::kNumber: {
489 double value = scanner()->DoubleValue();
490 return factory()->NewNumberLiteral(value, pos);
491 }
492 case Token::kBigInt:
493 return factory()->NewBigIntLiteral(
494 AstBigInt(scanner()->CurrentLiteralAsCString(zone())), pos);
495 case Token::kString: {
496 return factory()->NewStringLiteral(GetSymbol(), pos);
497 }
498 default:
499 DCHECK(false);
500 }
501 return FailureExpression();
502}
503
506 int pos) {
507 if (ParsingExtension()) {
508 // The extension structures are only accessible while parsing the
509 // very first time, not when reparsing because of lazy compilation.
510 GetClosureScope()->ForceEagerCompilation();
511 }
512
513 if (!name->is_one_byte()) {
514 // There are no two-byte named intrinsics.
515 ReportMessage(MessageTemplate::kNotDefined, name);
516 return FailureExpression();
517 }
518
519 const Runtime::Function* function =
520 Runtime::FunctionForName(name->raw_data(), name->length());
521
522 // Be more permissive when fuzzing. Intrinsics are not supported.
523 if (v8_flags.fuzzing) {
524 return NewV8RuntimeFunctionForFuzzing(function, args, pos);
525 }
526
527 if (function == nullptr) {
528 ReportMessage(MessageTemplate::kNotDefined, name);
529 return FailureExpression();
530 }
531
532 // Check that the expected number of arguments are being passed.
533 if (function->nargs != -1 && function->nargs != args.length()) {
534 ReportMessage(MessageTemplate::kRuntimeWrongNumArgs);
535 return FailureExpression();
536 }
537
538 return factory()->NewCallRuntime(function, args, pos);
539}
540
541// More permissive runtime-function creation on fuzzers.
543 const Runtime::Function* function, const ScopedPtrList<Expression>& args,
544 int pos) {
545 CHECK(v8_flags.fuzzing);
546
547 // Intrinsics are not supported for fuzzing. Only allow runtime functions
548 // marked as fuzzing-safe. Also prevent later errors due to too few arguments
549 // and just ignore this call.
550 if (function == nullptr ||
551 !Runtime::IsEnabledForFuzzing(function->function_id) ||
552 function->nargs > args.length()) {
553 return factory()->NewUndefinedLiteral(kNoSourcePosition);
554 }
555
556 // Flexible number of arguments permitted.
557 if (function->nargs == -1) {
558 return factory()->NewCallRuntime(function, args, pos);
559 }
560
561 // Otherwise ignore superfluous arguments.
562 ScopedPtrList<Expression> permissive_args(pointer_buffer());
563 for (int i = 0; i < function->nargs; i++) {
564 permissive_args.Add(args.at(i));
565 }
566 return factory()->NewCallRuntime(function, permissive_args, pos);
567}
568
571 info->zone(), &scanner_, info->stack_limit(),
572 info->ast_value_factory(), info->pending_error_handler(),
573 info->runtime_call_stats(), info->v8_file_logger(), info->flags(),
574 true, info->flags().compile_hints_magic_enabled(),
575 info->flags().compile_hints_per_function_magic_enabled()),
576 local_isolate_(local_isolate),
577 info_(info),
578 scanner_(info->character_stream(), flags()),
579 preparser_zone_(info->zone()->allocator(), "pre-parser-zone"),
580 reusable_preparser_(nullptr),
581 mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
582 source_range_map_(info->source_range_map()),
583 total_preparse_skipped_(0),
584 consumed_preparse_data_(info->consumed_preparse_data()),
585 preparse_data_buffer_(),
586 parameters_end_pos_(info->parameters_end_pos()) {
587 // Even though we were passed ParseInfo, we should not store it in
588 // Parser - this makes sure that Isolate is not accidentally accessed via
589 // ParseInfo during background parsing.
590 DCHECK_NOT_NULL(info->character_stream());
591 // Determine if functions can be lazily compiled. This is necessary to
592 // allow some of our builtin JS files to be lazily compiled. These
593 // builtins cannot be handled lazily by the parser, since we have to know
594 // if a function uses the special natives syntax, which is something the
595 // parser records.
596 // If the debugger requests compilation for break points, we cannot be
597 // aggressive about lazy compilation, because it might trigger compilation
598 // of functions without an outer context when setting a breakpoint through
599 // Debug::FindSharedFunctionInfoInScript
600 // We also compile eagerly for kProduceExhaustiveCodeCache.
601 bool can_compile_lazily = flags().allow_lazy_compile() && !flags().is_eager();
602
603 set_default_eager_compile_hint(can_compile_lazily
606 allow_lazy_ = flags().allow_lazy_compile() && flags().allow_lazy_parsing() &&
607 info->extension() == nullptr && can_compile_lazily;
608 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
609 ++feature) {
610 use_counts_[feature] = 0;
611 }
612}
613
615 DCHECK_NULL(original_scope_);
616 DCHECK_NULL(info->script_scope());
617 DeclarationScope* script_scope =
618 NewScriptScope(flags().is_repl_mode() ? REPLMode::kYes : REPLMode::kNo);
619 info->set_script_scope(script_scope);
620 original_scope_ = script_scope;
621}
622
623template <typename IsolateT>
625 IsolateT* isolate, ParseInfo* info,
626 MaybeDirectHandle<ScopeInfo> maybe_outer_scope_info,
629 DirectHandle<ScopeInfo> outer_scope_info;
630 if (maybe_outer_scope_info.ToHandle(&outer_scope_info)) {
631 DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
632 original_scope_ = Scope::DeserializeScopeChain(
633 isolate, zone(), *outer_scope_info, info->script_scope(),
634 ast_value_factory(), mode, info);
635
636 DeclarationScope* receiver_scope = original_scope_->GetReceiverScope();
637 if (receiver_scope->HasReceiverToDeserialize()) {
638 receiver_scope->DeserializeReceiver(ast_value_factory());
639 }
640 if (info->has_module_in_scope_chain()) {
641 set_has_module_in_scope_chain();
642 }
643 }
644}
645
647 Isolate* isolate, ParseInfo* info,
648 MaybeDirectHandle<ScopeInfo> maybe_outer_scope_info,
651 LocalIsolate* isolate, ParseInfo* info,
652 MaybeDirectHandle<ScopeInfo> maybe_outer_scope_info,
654
655namespace {
656
657void MaybeProcessSourceRanges(ParseInfo* parse_info, Expression* root,
658 uintptr_t stack_limit_) {
659 if (parse_info->source_range_map() != nullptr) {
661 parse_info->source_range_map());
662 visitor.Run();
663 }
664}
665
666} // namespace
667
669 ParseInfo* info,
670 MaybeDirectHandle<ScopeInfo> maybe_outer_scope_info) {
671 DCHECK_EQ(script->id(), flags().script_id());
672
673 // It's OK to use the Isolate & counters here, since this function is only
674 // called in the main thread.
675 DCHECK(parsing_on_main_thread_);
676 RCS_SCOPE(runtime_call_stats_, flags().is_eval()
677 ? RuntimeCallCounterId::kParseEval
678 : RuntimeCallCounterId::kParseProgram);
679 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseProgram");
680 base::ElapsedTimer timer;
681 if (V8_UNLIKELY(v8_flags.log_function_events)) timer.Start();
682
683 // Initialize parser state.
684 DeserializeScopeChain(isolate, info, maybe_outer_scope_info,
686
687 DCHECK_EQ(script->is_wrapped(), info->is_wrapped_as_function());
688 if (script->is_wrapped()) {
689 maybe_wrapped_arguments_ = handle(script->wrapped_arguments(), isolate);
690 }
691
693 FunctionLiteral* result = DoParseProgram(isolate, info);
694 HandleSourceURLComments(isolate, script);
695 if (result == nullptr) return;
696 MaybeProcessSourceRanges(info, result, stack_limit_);
697 PostProcessParseResult(isolate, info, result);
698
699 if (V8_UNLIKELY(v8_flags.log_function_events)) {
700 double ms = timer.Elapsed().InMillisecondsF();
701 const char* event_name = "parse-eval";
702 int start = -1;
703 int end = -1;
704 if (!flags().is_eval()) {
705 event_name = "parse-script";
706 start = 0;
707 end = Cast<String>(script->source())->length();
708 }
709 LOG(isolate,
710 FunctionEvent(event_name, flags().script_id(), ms, start, end, "", 0));
711 }
712}
713
715 // Note that this function can be called from the main thread or from a
716 // background thread. We should not access anything Isolate / heap dependent
717 // via ParseInfo, and also not pass it forward. If not on the main thread
718 // isolate will be nullptr.
719 DCHECK_EQ(parsing_on_main_thread_, isolate != nullptr);
721
723 ResetInfoId();
724
725 FunctionLiteral* result = nullptr;
726 {
727 Scope* outer = original_scope_;
728 DCHECK_NOT_NULL(outer);
729 if (flags().is_eval()) {
730 outer = NewEvalScope(outer);
731 } else if (flags().is_module()) {
732 DCHECK_EQ(outer, info->script_scope());
733 outer = NewModuleScope(info->script_scope());
734 }
735
736 DeclarationScope* scope = outer->AsDeclarationScope();
737 scope->set_start_position(0);
738
739 FunctionState function_state(&function_state_, &scope_, scope);
740 ScopedPtrList<Statement> body(pointer_buffer());
741 int beg_pos = scanner()->location().beg_pos;
742 if (flags().is_module()) {
743 DCHECK(flags().is_module());
744
746 Expression* initial_yield = BuildInitialYield(
748 body.Add(
749 factory()->NewExpressionStatement(initial_yield, kNoSourcePosition));
750 ParseModuleItemList(&body);
751 // Modules will always have an initial yield. If there are any
752 // additional suspends, they are awaits, and we treat the module as a
753 // ModuleWithTopLevelAwait.
754 if (function_state.suspend_count() > 1) {
756 }
757 if (!has_error() &&
758 !module()->Validate(this->scope()->AsModuleScope(),
759 pending_error_handler(), zone())) {
760 scanner()->set_parser_error();
761 }
762 } else if (info->is_wrapped_as_function()) {
763 DCHECK(parsing_on_main_thread_);
764 ParseWrapped(isolate, info, &body, scope, zone());
765 } else if (flags().is_repl_mode()) {
766 ParseREPLProgram(info, &body, scope);
767 } else {
768 // Don't count the mode in the use counters--give the program a chance
769 // to enable script-wide strict mode below.
770 this->scope()->SetLanguageMode(info->language_mode());
771 ParseStatementList(&body, Token::kEos);
772 }
773
774 // The parser will peek but not consume kEos. Our scope logically goes all
775 // the way to the kEos, though.
776 scope->set_end_position(peek_position());
777
778 if (is_strict(language_mode())) {
779 CheckStrictOctalLiteral(beg_pos, end_position());
780 }
781 if (is_sloppy(language_mode())) {
782 // TODO(littledan): Function bindings on the global object that modify
783 // pre-existing bindings should be made writable, enumerable and
784 // nonconfigurable if possible, whereas this code will leave attributes
785 // unchanged if the property already exists.
787 }
788 // Internalize the ast strings in the case of eval so we can check for
789 // conflicting var declarations with outer scope-info-backed scopes.
790 if (flags().is_eval()) {
791 DCHECK(parsing_on_main_thread_);
792 DCHECK(!isolate->main_thread_local_heap()->IsParked());
793 info->ast_value_factory()->Internalize(isolate);
794 }
795 CheckConflictingVarDeclarations(scope);
796
797 if (flags().parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) {
798 if (body.length() != 1 || !body.at(0)->IsExpressionStatement() ||
799 !body.at(0)
800 ->AsExpressionStatement()
801 ->expression()
802 ->IsFunctionLiteral()) {
803 ReportMessage(MessageTemplate::kSingleFunctionLiteral);
804 }
805 }
806
807 int parameter_count = 0;
808 result = factory()->NewScriptOrEvalFunctionLiteral(
809 scope, body, function_state.expected_property_count(), parameter_count);
810 result->set_suspend_count(function_state.suspend_count());
811 }
812
813 info->set_max_info_id(GetLastInfoId());
814
815 if (has_error()) return nullptr;
816
818
819 return result;
820}
821
822template <typename IsolateT>
823void Parser::PostProcessParseResult(IsolateT* isolate, ParseInfo* info,
826
827 info->set_literal(literal);
828 info->set_language_mode(literal->language_mode());
829 if (info->flags().is_eval()) {
830 info->set_allow_eval_cache(allow_eval_cache());
831 }
832
833 info->ast_value_factory()->Internalize(isolate);
834
835 {
836 RCS_SCOPE(info->runtime_call_stats(), RuntimeCallCounterId::kCompileAnalyse,
837 RuntimeCallStats::kThreadSpecific);
838 bool has_stack_overflow = false;
839 if (!Rewriter::Rewrite(info, &has_stack_overflow) ||
841 // Null out the literal to indicate that something failed.
842 info->set_literal(nullptr);
843 if (has_stack_overflow) {
844 // Propagate stack overflow state from Rewriter to parser.
845 set_stack_overflow();
846 }
847 return;
848 }
849 }
850}
851
852template void Parser::PostProcessParseResult(Isolate* isolate, ParseInfo* info,
854template void Parser::PostProcessParseResult(LocalIsolate* isolate,
855 ParseInfo* info,
857
859 Isolate* isolate, ParseInfo* info, Zone* zone) {
860 DCHECK(parsing_on_main_thread_);
861 DCHECK_NOT_NULL(isolate);
862 DirectHandle<FixedArray> arguments =
863 maybe_wrapped_arguments_.ToHandleChecked();
864 int arguments_length = arguments->length();
865 ZonePtrList<const AstRawString>* arguments_for_wrapped_function =
866 zone->New<ZonePtrList<const AstRawString>>(arguments_length, zone);
867 for (int i = 0; i < arguments_length; i++) {
868 const AstRawString* argument_string = ast_value_factory()->GetString(
869 Cast<String>(arguments->get(i)),
871 arguments_for_wrapped_function->Add(argument_string, zone);
872 }
873 return arguments_for_wrapped_function;
874}
875
878 DeclarationScope* outer_scope, Zone* zone) {
879 DCHECK(parsing_on_main_thread_);
880 DCHECK(info->is_wrapped_as_function());
881 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
882
883 // Set function and block state for the outer eval scope.
884 DCHECK(outer_scope->is_eval_scope());
885 FunctionState function_state(&function_state_, &scope_, outer_scope);
886
887 const AstRawString* function_name = nullptr;
888 Scanner::Location location(0, 0);
889
890 ZonePtrList<const AstRawString>* arguments_for_wrapped_function =
891 PrepareWrappedArguments(isolate, info, zone);
892
893 FunctionLiteral* function_literal =
894 ParseFunctionLiteral(function_name, location, kSkipFunctionNameCheck,
897 arguments_for_wrapped_function);
898
899 Statement* return_statement =
900 factory()->NewReturnStatement(function_literal, kNoSourcePosition);
901 body->Add(return_statement);
902}
903
905 DeclarationScope* scope) {
906 // REPL scripts are handled nearly the same way as the body of an async
907 // function. The difference is the value used to resolve the async
908 // promise.
909 // For a REPL script this is the completion value of the
910 // script instead of the expression of some "return" statement. The
911 // completion value of the script is obtained by manually invoking
912 // the {Rewriter} which will return a VariableProxy referencing the
913 // result.
914 DCHECK(flags().is_repl_mode());
915 this->scope()->SetLanguageMode(info->language_mode());
917
918 BlockT block = impl()->NullBlock();
919 {
920 StatementListT statements(pointer_buffer());
921 ParseStatementList(&statements, Token::kEos);
922 block = factory()->NewBlock(true, statements);
923 }
924
925 if (has_error()) return;
926
927 bool has_stack_overflow = false;
928 std::optional<VariableProxy*> maybe_result = Rewriter::RewriteBody(
929 info, scope, block->statements(), &has_stack_overflow);
930 if (!maybe_result) {
931 if (has_stack_overflow) {
932 // Propagate stack overflow state from Rewriter to parser.
933 set_stack_overflow();
934 }
935 return;
936 }
937 Expression* result_value =
938 *maybe_result ? static_cast<Expression*>(*maybe_result)
939 : factory()->NewUndefinedLiteral(kNoSourcePosition);
940 Expression* wrapped_result_value = WrapREPLResult(result_value);
941 block->statements()->Add(factory()->NewAsyncReturnStatement(
942 wrapped_result_value, kNoSourcePosition),
943 zone());
944 DCHECK(!info->pending_error_handler()->stack_overflow());
945 body->Add(block);
946}
947
949 // REPL scripts additionally wrap the ".result" variable in an
950 // object literal:
951 //
952 // return %_AsyncFunctionResolve(
953 // .generator_object, {__proto__: null, .repl_result: .result});
954 //
955 // Should ".result" be a resolved promise itself, the async return
956 // would chain the promises and return the resolve value instead of
957 // the promise.
958
959 Literal* property_name = factory()->NewStringLiteral(
960 ast_value_factory()->dot_repl_result_string(), kNoSourcePosition);
961 ObjectLiteralProperty* property =
962 factory()->NewObjectLiteralProperty(property_name, value, true);
963
964 Literal* proto_name = factory()->NewStringLiteral(
965 ast_value_factory()->proto_string(), kNoSourcePosition);
966 ObjectLiteralProperty* prototype = factory()->NewObjectLiteralProperty(
967 proto_name, factory()->NewNullLiteral(kNoSourcePosition), false);
968
969 ScopedPtrList<ObjectLiteralProperty> properties(pointer_buffer());
970 properties.Add(property);
971 properties.Add(prototype);
972 return factory()->NewObjectLiteral(properties, false, kNoSourcePosition,
973 false);
974}
975
978 // It's OK to use the Isolate & counters here, since this function is only
979 // called in the main thread.
980 DCHECK(parsing_on_main_thread_);
981 RCS_SCOPE(runtime_call_stats_, RuntimeCallCounterId::kParseFunction);
982 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseFunction");
983 base::ElapsedTimer timer;
984 if (V8_UNLIKELY(v8_flags.log_function_events)) timer.Start();
985
986 MaybeDirectHandle<ScopeInfo> maybe_outer_scope_info;
987 if (shared_info->HasOuterScopeInfo()) {
988 maybe_outer_scope_info =
989 direct_handle(shared_info->GetOuterScopeInfo(), isolate);
990 }
991 int start_position = shared_info->StartPosition();
992 int end_position = shared_info->EndPosition();
993
994 DeserializeScopeChain(isolate, info, maybe_outer_scope_info,
996 DCHECK_EQ(factory()->zone(), info->zone());
997
998 DirectHandle<Script> script(Cast<Script>(shared_info->script()), isolate);
999 if (shared_info->is_wrapped()) {
1000 maybe_wrapped_arguments_ = handle(script->wrapped_arguments(), isolate);
1001 }
1002
1003 int function_literal_id = shared_info->function_literal_id();
1004
1005 // Initialize parser state.
1006 info->set_function_name(ast_value_factory()->GetString(
1007 shared_info->Name(), SharedStringAccessGuardIfNeeded(isolate)));
1009
1010 FunctionKind function_kind = flags().function_kind();
1012 if (V8_UNLIKELY(IsClassMembersInitializerFunction(function_kind))) {
1013 // Reparsing of class member initializer functions has to be handled
1014 // specially because they require reparsing of the whole class body,
1015 // function start/end positions correspond to the class literal body
1016 // positions.
1018 function_kind, start_position, function_literal_id, end_position,
1019 info->function_name());
1020 info->set_max_info_id(GetLastInfoId());
1021 } else if (V8_UNLIKELY(shared_info->private_name_lookup_skips_outer_class() &&
1022 original_scope_->is_class_scope())) {
1023 // If the function skips the outer class and the outer scope is a class, the
1024 // function is in heritage position. Otherwise the function scope's skip bit
1025 // will be correctly inherited from the outer scope.
1026 ClassScope::HeritageParsingScope heritage(original_scope_->AsClassScope());
1027 result = DoParseFunction(isolate, info, start_position, end_position,
1028 function_literal_id, info->function_name());
1029 } else {
1030 result = DoParseFunction(isolate, info, start_position, end_position,
1031 function_literal_id, info->function_name());
1032 }
1033 if (result == nullptr) return;
1034 MaybeProcessSourceRanges(info, result, stack_limit_);
1035 PostProcessParseResult(isolate, info, result);
1036 if (V8_UNLIKELY(v8_flags.log_function_events)) {
1037 double ms = timer.Elapsed().InMillisecondsF();
1038 // We should already be internalized by now, so the debug name will be
1039 // available.
1040 DeclarationScope* function_scope = result->scope();
1041 std::unique_ptr<char[]> function_name = shared_info->DebugNameCStr();
1042 LOG(isolate,
1043 FunctionEvent("parse-function", flags().script_id(), ms,
1044 function_scope->start_position(),
1045 function_scope->end_position(), function_name.get(),
1046 strlen(function_name.get())));
1047 }
1048}
1049
1051 int start_position, int end_position,
1052 int function_literal_id,
1053 const AstRawString* raw_name) {
1054 DCHECK_EQ(parsing_on_main_thread_, isolate != nullptr);
1055 DCHECK_NOT_NULL(raw_name);
1057
1058 DCHECK(ast_value_factory());
1059 fni_.PushEnclosingName(raw_name);
1060
1061 ResetInfoId();
1062 DCHECK_LT(0, function_literal_id);
1063 SkipInfos(function_literal_id - 1);
1064
1065 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
1066
1067 // Place holder for the result.
1068 FunctionLiteral* result = nullptr;
1069
1070 {
1071 // Parse the function literal.
1072 Scope* outer = original_scope_;
1073 DeclarationScope* outer_function = outer->GetClosureScope();
1074 DCHECK(outer);
1075 FunctionState function_state(&function_state_, &scope_, outer_function);
1076 BlockState block_state(&scope_, outer);
1077 DCHECK(is_sloppy(outer->language_mode()) ||
1078 is_strict(info->language_mode()));
1079 FunctionKind kind = flags().function_kind();
1081 flags().function_syntax_kind() ==
1083
1084 if (IsArrowFunction(kind)) {
1085 if (IsAsyncFunction(kind)) {
1086 DCHECK(!scanner()->HasLineTerminatorAfterNext());
1087 if (!Check(Token::kAsync)) {
1088 CHECK(stack_overflow());
1089 return nullptr;
1090 }
1091 if (!(peek_any_identifier() || peek() == Token::kLeftParen)) {
1092 CHECK(stack_overflow());
1093 return nullptr;
1094 }
1095 }
1096
1097 CHECK_EQ(function_literal_id, GetNextInfoId());
1098
1099 // TODO(adamk): We should construct this scope from the ScopeInfo.
1100 DeclarationScope* scope = NewFunctionScope(kind);
1101 scope->set_has_checked_syntax(true);
1102
1103 // This bit only needs to be explicitly set because we're
1104 // not passing the ScopeInfo to the Scope constructor.
1105 SetLanguageMode(scope, info->language_mode());
1106
1107 scope->set_start_position(start_position);
1108 ParserFormalParameters formals(scope);
1109 {
1110 ParameterDeclarationParsingScope formals_scope(this);
1111 // Parsing patterns as variable reference expression creates
1112 // NewUnresolved references in current scope. Enter arrow function
1113 // scope for formal parameter parsing.
1114 BlockState inner_block_state(&scope_, scope);
1115 if (Check(Token::kLeftParen)) {
1116 // '(' StrictFormalParameters ')'
1117 ParseFormalParameterList(&formals);
1118 Expect(Token::kRightParen);
1119 } else {
1120 // BindingIdentifier
1121 ParameterParsingScope parameter_parsing_scope(impl(), &formals);
1122 ParseFormalParameter(&formals);
1123 DeclareFormalParameters(&formals);
1124 }
1125 formals.duplicate_loc = formals_scope.duplicate_location();
1126 }
1127
1128 // It doesn't really matter what value we pass here for
1129 // could_be_immediately_invoked since we already introduced an eager
1130 // compilation scope above.
1131 bool could_be_immediately_invoked = false;
1132 Expression* expression = ParseArrowFunctionLiteral(
1133 formals, function_literal_id, could_be_immediately_invoked);
1134 // Scanning must end at the same position that was recorded
1135 // previously. If not, parsing has been interrupted due to a stack
1136 // overflow, at which point the partially parsed arrow function
1137 // concise body happens to be a valid expression. This is a problem
1138 // only for arrow functions with single expression bodies, since there
1139 // is no end token such as "}" for normal functions.
1140 if (scanner()->location().end_pos == end_position) {
1141 // The pre-parser saw an arrow function here, so the full parser
1142 // must produce a FunctionLiteral.
1143 DCHECK(expression->IsFunctionLiteral());
1144 result = expression->AsFunctionLiteral();
1145 }
1146 } else if (IsDefaultConstructor(kind)) {
1147 DCHECK_EQ(scope(), outer);
1149 start_position);
1150 } else {
1151 ZonePtrList<const AstRawString>* arguments_for_wrapped_function =
1152 info->is_wrapped_as_function()
1153 ? PrepareWrappedArguments(isolate, info, zone())
1154 : nullptr;
1157 kNoSourcePosition, flags().function_syntax_kind(),
1158 info->language_mode(), arguments_for_wrapped_function);
1159 }
1160
1161 if (has_error()) return nullptr;
1162 result->set_requires_instance_members_initializer(
1164 result->set_class_scope_has_private_brand(
1165 flags().class_scope_has_private_brand());
1166 result->set_has_static_private_methods_or_accessors(
1168 }
1169
1170 info->set_max_info_id(GetLastInfoId());
1171
1172 DCHECK_IMPLIES(result, function_literal_id == result->function_literal_id());
1173 return result;
1174}
1175
1177 FunctionKind initializer_kind, int initializer_pos, int initializer_id,
1178 int initializer_end_pos, const AstRawString* class_name) {
1179 // When the function is a class members initializer function, we record the
1180 // source range of the entire class body as its positions in its SFI, so at
1181 // this point the scanner should be rewound to the position of the class
1182 // token.
1183 DCHECK_EQ(peek_position(), initializer_pos);
1184 // Insert a FunctionState with the closest outer Declaration scope
1185 DeclarationScope* nearest_decl_scope = original_scope_->GetDeclarationScope();
1186 DCHECK_NOT_NULL(nearest_decl_scope);
1187 FunctionState function_state(&function_state_, &scope_, nearest_decl_scope);
1188
1189 // We will reindex the function literals later.
1190 ResetInfoId();
1191 SkipInfos(initializer_id - 1);
1192
1193 // We preparse the class members that are not fields with initializers
1194 // in order to collect the function literal ids.
1196
1197 ExpressionParsingScope no_expression_scope(impl());
1198
1199 // Reparse the whole class body to build member initializer functions.
1200 FunctionLiteral* initializer;
1201 {
1202 bool is_anonymous = IsEmptyIdentifier(class_name);
1203 BlockState block_state(&scope_, original_scope_);
1204 RaiseLanguageMode(LanguageMode::kStrict);
1205
1206 BlockState object_literal_scope_state(&object_literal_scope_, nullptr);
1207
1208 ClassInfo class_info(this);
1209 class_info.is_anonymous = is_anonymous;
1210
1211 // Create an arbitrary non-Null expression to indicate that the class
1212 // extends something. Doing so unconditionally is fine because:
1213 // - the fact whether the class extends something affects parsing of
1214 // 'super' expressions which cause parse-time SyntaxError if the class
1215 // is not a derived one. However, all such errors must have been
1216 // reported during initial parse of the class declaration.
1217 // - "extends" clause affects class constructor's FunctionKind, but here
1218 // we are interested only in the member initializer functions and thus
1219 // we can ignore the constructor function details.
1220 //
1221 // Given all the above we can simplify things and for the purpose of class
1222 // member initializers reparsing don't bother propagating the existence of
1223 // the "extends" clause through scope serialization/deserialization.
1224 class_info.extends = factory()->NewNullLiteral(kNoSourcePosition);
1225
1226 // Note that we don't recheck class_name for strict-reserved words or eval
1227 // because all such checks have already been done during initial paring and
1228 // respective SyntaxErrors must have been thrown if necessary.
1229
1230 // Class initializers don't care about position of the class token.
1231 int class_token_pos = kNoSourcePosition;
1232
1233#ifdef DEBUG
1234 scope()->MarkReparsingForClassInitializer();
1235#endif
1236
1237 ParseClassLiteralBody(class_info, class_name, class_token_pos, Token::kEos);
1238
1239 if (initializer_kind == FunctionKind::kClassMembersInitializerFunction) {
1240 DCHECK_EQ(class_info.instance_members_function_id, initializer_id);
1241 initializer = CreateInstanceMembersInitializer(class_name, &class_info);
1242 } else {
1243 DCHECK_EQ(class_info.static_elements_function_id, initializer_id);
1244 initializer = CreateStaticElementsInitializer(class_name, &class_info);
1245 }
1246 initializer->scope()->TakeUnresolvedReferencesFromParent();
1247 }
1248
1249 if (has_error()) return nullptr;
1250
1251 DCHECK(IsClassMembersInitializerFunction(initializer_kind));
1252
1253 no_expression_scope.ValidateExpression();
1254
1255 DCHECK_EQ(initializer->kind(), initializer_kind);
1256 DCHECK_EQ(initializer->function_literal_id(), initializer_id);
1257 DCHECK_EQ(initializer->end_position(), initializer_end_pos);
1258
1259 return initializer;
1260}
1261
1263 // ecma262/#prod-ModuleItem
1264 // ModuleItem :
1265 // ImportDeclaration
1266 // ExportDeclaration
1267 // StatementListItem
1268
1269 Token::Value next = peek();
1270
1271 if (next == Token::kExport) {
1272 return ParseExportDeclaration();
1273 }
1274
1275 if (next == Token::kImport) {
1276 // We must be careful not to parse a dynamic import expression as an import
1277 // declaration. Same for import.meta expressions.
1278 Token::Value peek_ahead = PeekAhead();
1279 if (peek_ahead != Token::kLeftParen && peek_ahead != Token::kPeriod) {
1281 return factory()->EmptyStatement();
1282 }
1283 }
1284
1285 return ParseStatementListItem();
1286}
1287
1289 // ecma262/#prod-Module
1290 // Module :
1291 // ModuleBody?
1292 //
1293 // ecma262/#prod-ModuleItemList
1294 // ModuleBody :
1295 // ModuleItem*
1296
1297 DCHECK(scope()->is_module_scope());
1298 while (peek() != Token::kEos) {
1299 Statement* stat = ParseModuleItem();
1300 if (stat == nullptr) return;
1301 if (stat->IsEmptyStatement()) continue;
1302 body->Add(stat);
1303 }
1304}
1305
1307 // ModuleSpecifier :
1308 // StringLiteral
1309
1310 Expect(Token::kString);
1311 return GetSymbol();
1312}
1313
1315 Scanner::Location* reserved_loc,
1316 Scanner::Location* string_literal_local_name_loc) {
1317 // ExportClause :
1318 // '{' '}'
1319 // '{' ExportsList '}'
1320 // '{' ExportsList ',' '}'
1321 //
1322 // ExportsList :
1323 // ExportSpecifier
1324 // ExportsList ',' ExportSpecifier
1325 //
1326 // ExportSpecifier :
1327 // IdentifierName
1328 // IdentifierName 'as' IdentifierName
1329 // IdentifierName 'as' ModuleExportName
1330 // ModuleExportName
1331 // ModuleExportName 'as' ModuleExportName
1332 //
1333 // ModuleExportName :
1334 // StringLiteral
1335 ZoneChunkList<ExportClauseData>* export_data =
1336 zone()->New<ZoneChunkList<ExportClauseData>>(zone());
1337
1338 Expect(Token::kLeftBrace);
1339
1340 Token::Value name_tok;
1341 while ((name_tok = peek()) != Token::kRightBrace) {
1342 const AstRawString* local_name = ParseExportSpecifierName();
1343 if (!string_literal_local_name_loc->IsValid() &&
1344 name_tok == Token::kString) {
1345 // Keep track of the first string literal local name exported for error
1346 // reporting. These must be followed by a 'from' clause.
1347 *string_literal_local_name_loc = scanner()->location();
1348 } else if (!reserved_loc->IsValid() &&
1350 flags().is_module())) {
1351 // Keep track of the first reserved word encountered in case our
1352 // caller needs to report an error.
1353 *reserved_loc = scanner()->location();
1354 }
1355 const AstRawString* export_name;
1356 Scanner::Location location = scanner()->location();
1357 if (CheckContextualKeyword(ast_value_factory()->as_string())) {
1358 export_name = ParseExportSpecifierName();
1359 // Set the location to the whole "a as b" string, so that it makes sense
1360 // both for errors due to "a" and for errors due to "b".
1361 location.end_pos = scanner()->location().end_pos;
1362 } else {
1363 export_name = local_name;
1364 }
1365 export_data->push_back({export_name, local_name, location});
1366 if (peek() == Token::kRightBrace) break;
1367 if (V8_UNLIKELY(!Check(Token::kComma))) {
1368 ReportUnexpectedToken(Next());
1369 break;
1370 }
1371 }
1372
1373 Expect(Token::kRightBrace);
1374 return export_data;
1375}
1376
1378 Token::Value next = Next();
1379
1380 // IdentifierName
1381 if (V8_LIKELY(Token::IsPropertyName(next))) {
1382 return GetSymbol();
1383 }
1384
1385 // ModuleExportName
1386 if (next == Token::kString) {
1387 const AstRawString* export_name = GetSymbol();
1388 if (V8_LIKELY(export_name->is_one_byte())) return export_name;
1390 reinterpret_cast<const uint16_t*>(export_name->raw_data()),
1391 export_name->length())) {
1392 return export_name;
1393 }
1394 ReportMessage(MessageTemplate::kInvalidModuleExportName);
1395 return EmptyIdentifierString();
1396 }
1397
1398 ReportUnexpectedToken(next);
1399 return EmptyIdentifierString();
1400}
1401
1403 // NamedImports :
1404 // '{' '}'
1405 // '{' ImportsList '}'
1406 // '{' ImportsList ',' '}'
1407 //
1408 // ImportsList :
1409 // ImportSpecifier
1410 // ImportsList ',' ImportSpecifier
1411 //
1412 // ImportSpecifier :
1413 // BindingIdentifier
1414 // IdentifierName 'as' BindingIdentifier
1415 // ModuleExportName 'as' BindingIdentifier
1416
1417 Expect(Token::kLeftBrace);
1418
1419 auto result = zone()->New<ZonePtrList<const NamedImport>>(1, zone());
1420 while (peek() != Token::kRightBrace) {
1421 const AstRawString* import_name = ParseExportSpecifierName();
1422 const AstRawString* local_name = import_name;
1423 Scanner::Location location = scanner()->location();
1424 // In the presence of 'as', the left-side of the 'as' can
1425 // be any IdentifierName. But without 'as', it must be a valid
1426 // BindingIdentifier.
1427 if (CheckContextualKeyword(ast_value_factory()->as_string())) {
1428 local_name = ParsePropertyName();
1429 }
1430 if (!Token::IsValidIdentifier(scanner()->current_token(),
1431 LanguageMode::kStrict, false,
1432 flags().is_module())) {
1433 ReportMessage(MessageTemplate::kUnexpectedReserved);
1434 return nullptr;
1435 } else if (IsEvalOrArguments(local_name)) {
1436 ReportMessage(MessageTemplate::kStrictEvalArguments);
1437 return nullptr;
1438 }
1439
1442
1443 NamedImport* import =
1444 zone()->New<NamedImport>(import_name, local_name, location);
1445 result->Add(import, zone());
1446
1447 if (peek() == Token::kRightBrace) break;
1448 Expect(Token::kComma);
1449 }
1450
1451 Expect(Token::kRightBrace);
1452 return result;
1453}
1454
1456 // WithClause :
1457 // with '{' '}'
1458 // with '{' WithEntries ','? '}'
1459
1460 // WithEntries :
1461 // LiteralPropertyName
1462 // LiteralPropertyName ':' StringLiteral , WithEntries
1463
1464 auto import_attributes = zone()->New<ImportAttributes>(zone());
1465
1466 if (v8_flags.harmony_import_attributes && Check(Token::kWith)) {
1467 // 'with' keyword consumed
1468 } else {
1469 return import_attributes;
1470 }
1471
1472 Expect(Token::kLeftBrace);
1473
1474 while (peek() != Token::kRightBrace) {
1475 const AstRawString* attribute_key =
1476 Check(Token::kString) ? GetSymbol() : ParsePropertyName();
1477
1478 Scanner::Location location = scanner()->location();
1479
1480 Expect(Token::kColon);
1481 Expect(Token::kString);
1482
1483 const AstRawString* attribute_value = GetSymbol();
1484
1485 // Set the location to the whole "key: 'value'"" string, so that it makes
1486 // sense both for errors due to the key and errors due to the value.
1487 location.end_pos = scanner()->location().end_pos;
1488
1489 auto result = import_attributes->insert(std::make_pair(
1490 attribute_key, std::make_pair(attribute_value, location)));
1491 if (!result.second) {
1492 // It is a syntax error if two WithEntries have the same key.
1493 ReportMessageAt(location, MessageTemplate::kImportAttributesDuplicateKey,
1494 attribute_key);
1495 break;
1496 }
1497
1498 if (peek() == Token::kRightBrace) break;
1499 if (V8_UNLIKELY(!Check(Token::kComma))) {
1500 ReportUnexpectedToken(Next());
1501 break;
1502 }
1503 }
1504
1505 Expect(Token::kRightBrace);
1506
1507 return import_attributes;
1508}
1509
1511 // ImportDeclaration :
1512 // 'import' ImportClause 'from' ModuleSpecifier ';'
1513 // 'import' ModuleSpecifier ';'
1514 // 'import' ImportClause 'from' ModuleSpecifier [no LineTerminator here]
1515 // AssertClause ';'
1516 // 'import' ModuleSpecifier [no LineTerminator here] AssertClause';'
1517 // 'import' 'source' ImportedBinding 'from' ModuleSpecifier ';'
1518 //
1519 // ImportClause :
1520 // ImportedDefaultBinding
1521 // NameSpaceImport
1522 // NamedImports
1523 // ImportedDefaultBinding ',' NameSpaceImport
1524 // ImportedDefaultBinding ',' NamedImports
1525 //
1526 // NameSpaceImport :
1527 // '*' 'as' ImportedBinding
1528
1529 int pos = peek_position();
1530 Expect(Token::kImport);
1531
1532 Token::Value tok = peek();
1533
1534 // 'import' ModuleSpecifier ';'
1535 if (tok == Token::kString) {
1536 Scanner::Location specifier_loc = scanner()->peek_location();
1537 const AstRawString* module_specifier = ParseModuleSpecifier();
1538 const ImportAttributes* import_attributes = ParseImportWithOrAssertClause();
1539 ExpectSemicolon();
1540 module()->AddEmptyImport(module_specifier, import_attributes, specifier_loc,
1541 zone());
1542 return;
1543 }
1544
1545 // Parse ImportedDefaultBinding or 'source' ImportedBinding if present.
1546 const AstRawString* import_default_binding = nullptr;
1547 Scanner::Location import_default_binding_loc;
1549 if (tok != Token::kMul && tok != Token::kLeftBrace) {
1550 if (v8_flags.js_source_phase_imports &&
1551 PeekContextualKeyword(ast_value_factory()->source_string()) &&
1552 PeekAhead() == Token::kIdentifier &&
1553 PeekAheadAhead() == Token::kIdentifier) {
1554 Consume(Token::kIdentifier);
1555 import_phase = ModuleImportPhase::kSource;
1556 }
1557 import_default_binding = ParseNonRestrictedIdentifier();
1558 import_default_binding_loc = scanner()->location();
1559 DeclareUnboundVariable(import_default_binding, VariableMode::kConst,
1561 }
1562
1563 // Parse NameSpaceImport or NamedImports if present.
1564 const AstRawString* module_namespace_binding = nullptr;
1565 Scanner::Location module_namespace_binding_loc;
1566 const ZonePtrList<const NamedImport>* named_imports = nullptr;
1567 if (import_phase == ModuleImportPhase::kEvaluation &&
1568 (import_default_binding == nullptr || Check(Token::kComma))) {
1569 switch (peek()) {
1570 case Token::kMul: {
1571 Consume(Token::kMul);
1572 ExpectContextualKeyword(ast_value_factory()->as_string());
1573 module_namespace_binding = ParseNonRestrictedIdentifier();
1574 module_namespace_binding_loc = scanner()->location();
1575 DeclareUnboundVariable(module_namespace_binding, VariableMode::kConst,
1577 break;
1578 }
1579
1580 case Token::kLeftBrace:
1581 named_imports = ParseNamedImports(pos);
1582 break;
1583
1584 default:
1585 ReportUnexpectedToken(scanner()->current_token());
1586 return;
1587 }
1588 }
1589
1590 ExpectContextualKeyword(ast_value_factory()->from_string());
1591 Scanner::Location specifier_loc = scanner()->peek_location();
1592 const AstRawString* module_specifier = ParseModuleSpecifier();
1593 // TODO(42204365): Enable import attributes with source phase import once
1594 // specified.
1595 const ImportAttributes* import_attributes =
1596 import_phase == ModuleImportPhase::kEvaluation
1598 : zone()->New<ImportAttributes>(zone());
1599 ExpectSemicolon();
1600
1601 // Now that we have all the information, we can make the appropriate
1602 // declarations.
1603
1604 // TODO(neis): Would prefer to call DeclareVariable for each case below rather
1605 // than above and in ParseNamedImports, but then a possible error message
1606 // would point to the wrong location. Maybe have a DeclareAt version of
1607 // Declare that takes a location?
1608
1609 if (module_namespace_binding != nullptr) {
1611 module()->AddStarImport(module_namespace_binding, module_specifier,
1612 import_attributes, module_namespace_binding_loc,
1613 specifier_loc, zone());
1614 }
1615
1616 if (import_default_binding != nullptr) {
1618 v8_flags.js_source_phase_imports);
1619 module()->AddImport(ast_value_factory()->default_string(),
1620 import_default_binding, module_specifier, import_phase,
1621 import_attributes, import_default_binding_loc,
1622 specifier_loc, zone());
1623 }
1624
1625 if (named_imports != nullptr) {
1627 if (named_imports->length() == 0) {
1628 module()->AddEmptyImport(module_specifier, import_attributes,
1629 specifier_loc, zone());
1630 } else {
1631 for (const NamedImport* import : *named_imports) {
1632 module()->AddImport(import->import_name, import->local_name,
1633 module_specifier, import_phase, import_attributes,
1634 import->location, specifier_loc, zone());
1635 }
1636 }
1637 }
1638}
1639
1641 // Supports the following productions, starting after the 'default' token:
1642 // 'export' 'default' HoistableDeclaration
1643 // 'export' 'default' ClassDeclaration
1644 // 'export' 'default' AssignmentExpression[In] ';'
1645
1646 Expect(Token::kDefault);
1647 Scanner::Location default_loc = scanner()->location();
1648
1649 ZonePtrList<const AstRawString> local_names(1, zone());
1650 Statement* result = nullptr;
1651 switch (peek()) {
1652 case Token::kFunction:
1653 result = ParseHoistableDeclaration(&local_names, true);
1654 break;
1655
1656 case Token::kClass:
1657 Consume(Token::kClass);
1658 result = ParseClassDeclaration(&local_names, true);
1659 break;
1660
1661 case Token::kAsync:
1662 if (PeekAhead() == Token::kFunction &&
1663 !scanner()->HasLineTerminatorAfterNext()) {
1664 Consume(Token::kAsync);
1665 result = ParseAsyncFunctionDeclaration(&local_names, true);
1666 break;
1667 }
1668 [[fallthrough]];
1669
1670 default: {
1671 int pos = position();
1672 AcceptINScope scope(this, true);
1673 Expression* value = ParseAssignmentExpression();
1674 SetFunctionName(value, ast_value_factory()->default_string());
1675
1676 const AstRawString* local_name =
1677 ast_value_factory()->dot_default_string();
1678 local_names.Add(local_name, zone());
1679
1680 // It's fine to declare this as VariableMode::kConst because the user has
1681 // no way of writing to it.
1682 VariableProxy* proxy =
1685
1686 Assignment* assignment = factory()->NewAssignment(
1687 Token::kInit, proxy, value, kNoSourcePosition);
1689 factory()->NewExpressionStatement(assignment, kNoSourcePosition));
1690
1691 ExpectSemicolon();
1692 break;
1693 }
1694 }
1695
1696 if (result != nullptr) {
1697 DCHECK_EQ(local_names.length(), 1);
1698 module()->AddExport(local_names.first(),
1699 ast_value_factory()->default_string(), default_loc,
1700 zone());
1701 }
1702
1703 return result;
1704}
1705
1707 const char* prefix = ".ns-export";
1708 std::string s(prefix);
1709 s.append(std::to_string(number_of_named_namespace_exports_++));
1710 return ast_value_factory()->GetOneByteString(s.c_str());
1711}
1712
1714 int pos = position();
1715 Consume(Token::kMul);
1716
1717 if (!PeekContextualKeyword(ast_value_factory()->as_string())) {
1718 // 'export' '*' 'from' ModuleSpecifier ';'
1719 Scanner::Location loc = scanner()->location();
1720 ExpectContextualKeyword(ast_value_factory()->from_string());
1721 Scanner::Location specifier_loc = scanner()->peek_location();
1722 const AstRawString* module_specifier = ParseModuleSpecifier();
1723 const ImportAttributes* import_attributes = ParseImportWithOrAssertClause();
1724 ExpectSemicolon();
1725 module()->AddStarExport(module_specifier, import_attributes, loc,
1726 specifier_loc, zone());
1727 return;
1728 }
1729
1730 // 'export' '*' 'as' IdentifierName 'from' ModuleSpecifier ';'
1731 //
1732 // Desugaring:
1733 // export * as x from "...";
1734 // ~>
1735 // import * as .x from "..."; export {.x as x};
1736 //
1737 // Note that the desugared internal namespace export name (.x above) will
1738 // never conflict with a string literal export name, as literal string export
1739 // names in local name positions (i.e. left of 'as' or in a clause without
1740 // 'as') are disallowed without a following 'from' clause.
1741
1742 ExpectContextualKeyword(ast_value_factory()->as_string());
1743 const AstRawString* export_name = ParseExportSpecifierName();
1744 Scanner::Location export_name_loc = scanner()->location();
1745 const AstRawString* local_name = NextInternalNamespaceExportName();
1748 pos);
1749
1750 ExpectContextualKeyword(ast_value_factory()->from_string());
1751 Scanner::Location specifier_loc = scanner()->peek_location();
1752 const AstRawString* module_specifier = ParseModuleSpecifier();
1753 const ImportAttributes* import_attributes = ParseImportWithOrAssertClause();
1754 ExpectSemicolon();
1755
1756 module()->AddStarImport(local_name, module_specifier, import_attributes,
1757 local_name_loc, specifier_loc, zone());
1758 module()->AddExport(local_name, export_name, export_name_loc, zone());
1759}
1760
1762 // ExportDeclaration:
1763 // 'export' '*' 'from' ModuleSpecifier ';'
1764 // 'export' '*' 'from' ModuleSpecifier [no LineTerminator here]
1765 // AssertClause ';'
1766 // 'export' '*' 'as' IdentifierName 'from' ModuleSpecifier ';'
1767 // 'export' '*' 'as' IdentifierName 'from' ModuleSpecifier
1768 // [no LineTerminator here] AssertClause ';'
1769 // 'export' '*' 'as' ModuleExportName 'from' ModuleSpecifier ';'
1770 // 'export' '*' 'as' ModuleExportName 'from' ModuleSpecifier ';'
1771 // [no LineTerminator here] AssertClause ';'
1772 // 'export' ExportClause ('from' ModuleSpecifier)? ';'
1773 // 'export' ExportClause ('from' ModuleSpecifier [no LineTerminator here]
1774 // AssertClause)? ';'
1775 // 'export' VariableStatement
1776 // 'export' Declaration
1777 // 'export' 'default' ... (handled in ParseExportDefault)
1778 //
1779 // ModuleExportName :
1780 // StringLiteral
1781
1782 Expect(Token::kExport);
1783 Statement* result = nullptr;
1784 ZonePtrList<const AstRawString> names(1, zone());
1785 Scanner::Location loc = scanner()->peek_location();
1786 switch (peek()) {
1787 case Token::kDefault:
1788 return ParseExportDefault();
1789
1790 case Token::kMul:
1792 return factory()->EmptyStatement();
1793
1794 case Token::kLeftBrace: {
1795 // There are two cases here:
1796 //
1797 // 'export' ExportClause ';'
1798 // and
1799 // 'export' ExportClause FromClause ';'
1800 //
1801 // In the first case, the exported identifiers in ExportClause must
1802 // not be reserved words, while in the latter they may be. We
1803 // pass in a location that gets filled with the first reserved word
1804 // encountered, and then throw a SyntaxError if we are in the
1805 // non-FromClause case.
1807 Scanner::Location string_literal_local_name_loc =
1809 ZoneChunkList<ExportClauseData>* export_data =
1810 ParseExportClause(&reserved_loc, &string_literal_local_name_loc);
1811 if (CheckContextualKeyword(ast_value_factory()->from_string())) {
1812 Scanner::Location specifier_loc = scanner()->peek_location();
1813 const AstRawString* module_specifier = ParseModuleSpecifier();
1814 const ImportAttributes* import_attributes =
1816 ExpectSemicolon();
1817
1818 if (export_data->empty()) {
1819 module()->AddEmptyImport(module_specifier, import_attributes,
1820 specifier_loc, zone());
1821 } else {
1822 for (const ExportClauseData& data : *export_data) {
1823 module()->AddExport(data.local_name, data.export_name,
1824 module_specifier, import_attributes,
1825 data.location, specifier_loc, zone());
1826 }
1827 }
1828 } else {
1829 if (reserved_loc.IsValid()) {
1830 // No FromClause, so reserved words are invalid in ExportClause.
1831 ReportMessageAt(reserved_loc, MessageTemplate::kUnexpectedReserved);
1832 return nullptr;
1833 } else if (string_literal_local_name_loc.IsValid()) {
1834 ReportMessageAt(string_literal_local_name_loc,
1835 MessageTemplate::kModuleExportNameWithoutFromClause);
1836 return nullptr;
1837 }
1838
1839 ExpectSemicolon();
1840
1841 for (const ExportClauseData& data : *export_data) {
1842 module()->AddExport(data.local_name, data.export_name, data.location,
1843 zone());
1844 }
1845 }
1846 return factory()->EmptyStatement();
1847 }
1848
1849 case Token::kFunction:
1850 result = ParseHoistableDeclaration(&names, false);
1851 break;
1852
1853 case Token::kClass:
1854 Consume(Token::kClass);
1855 result = ParseClassDeclaration(&names, false);
1856 break;
1857
1858 case Token::kVar:
1859 case Token::kLet:
1860 case Token::kConst:
1861 result = ParseVariableStatement(kStatementListItem, &names);
1862 break;
1863
1864 case Token::kAsync:
1865 Consume(Token::kAsync);
1866 if (peek() == Token::kFunction &&
1867 !scanner()->HasLineTerminatorBeforeNext()) {
1868 result = ParseAsyncFunctionDeclaration(&names, false);
1869 break;
1870 }
1871 [[fallthrough]];
1872
1873 default:
1874 ReportUnexpectedToken(scanner()->current_token());
1875 return nullptr;
1876 }
1877 loc.end_pos = scanner()->location().end_pos;
1878
1879 SourceTextModuleDescriptor* descriptor = module();
1880 for (const AstRawString* name : names) {
1881 descriptor->AddExport(name, name, loc, zone());
1882 }
1883
1884 return result;
1885}
1886
1888 InitializationFlag init, int pos) {
1889 bool was_added;
1890 Variable* var = DeclareVariable(name, NORMAL_VARIABLE, mode, init, scope(),
1891 &was_added, pos, end_position());
1892 // The variable will be added to the declarations list, but since we are not
1893 // binding it to anything, we can simply ignore it here.
1894 USE(var);
1895}
1896
1898 VariableMode mode, int pos) {
1899 DCHECK_NOT_NULL(name);
1900 VariableProxy* proxy =
1901 factory()->NewVariableProxy(name, NORMAL_VARIABLE, position());
1902 bool was_added;
1903 Variable* var = DeclareVariable(name, NORMAL_VARIABLE, mode,
1904 Variable::DefaultInitializationFlag(mode),
1905 scope(), &was_added, pos, end_position());
1906 proxy->BindTo(var);
1907 return proxy;
1908}
1909
1911 VariableMode mode, Scope* scope,
1912 bool* was_added, int initializer_position) {
1914 proxy->raw_name(), kind, mode, Variable::DefaultInitializationFlag(mode),
1915 scope, was_added, proxy->position(), kNoSourcePosition);
1916 var->set_initializer_position(initializer_position);
1917 proxy->BindTo(var);
1918}
1919
1922 Scope* scope, bool* was_added, int begin,
1923 int end) {
1925 if (mode == VariableMode::kVar && !scope->is_declaration_scope()) {
1926 DCHECK(scope->is_block_scope() || scope->is_with_scope());
1927 declaration = factory()->NewNestedVariableDeclaration(scope, begin);
1928 } else {
1929 declaration = factory()->NewVariableDeclaration(begin);
1930 }
1931 Declare(declaration, name, kind, mode, init, scope, was_added, begin, end);
1932 return declaration->var();
1933}
1934
1936 VariableKind variable_kind, VariableMode mode,
1937 InitializationFlag init, Scope* scope, bool* was_added,
1938 int var_begin_pos, int var_end_pos) {
1939 bool local_ok = true;
1940 bool sloppy_mode_block_scope_function_redefinition = false;
1941 scope->DeclareVariable(
1942 declaration, name, var_begin_pos, mode, variable_kind, init, was_added,
1943 &sloppy_mode_block_scope_function_redefinition, &local_ok);
1944 if (!local_ok) {
1945 // If we only have the start position of a proxy, we can't highlight the
1946 // whole variable name. Pretend its length is 1 so that we highlight at
1947 // least the first character.
1948 Scanner::Location loc(var_begin_pos, var_end_pos != kNoSourcePosition
1949 ? var_end_pos
1950 : var_begin_pos + 1);
1951 if (variable_kind == PARAMETER_VARIABLE) {
1952 ReportMessageAt(loc, MessageTemplate::kParamDupe);
1953 } else {
1954 ReportMessageAt(loc, MessageTemplate::kVarRedeclaration,
1955 declaration->var()->raw_name());
1956 }
1957 } else if (sloppy_mode_block_scope_function_redefinition) {
1959 }
1960}
1961
1963 DeclarationParsingResult* parsing_result) {
1964 ScopedPtrList<Statement> statements(pointer_buffer());
1965 for (const auto& declaration : parsing_result->declarations) {
1966 if (!declaration.initializer) continue;
1967 InitializeVariables(&statements, parsing_result->descriptor.kind,
1968 &declaration);
1969 }
1970 return factory()->NewBlock(true, statements);
1971}
1972
1974 FunctionLiteral* function, VariableMode mode,
1975 VariableKind kind, int beg_pos, int end_pos,
1978 factory()->NewFunctionDeclaration(function, beg_pos);
1979 bool was_added;
1980 Declare(declaration, variable_name, kind, mode, kCreatedInitialized, scope(),
1981 &was_added, beg_pos);
1982 if (info()->flags().coverage_enabled()) {
1983 // Force the function to be allocated when collecting source coverage, so
1984 // that even dead functions get source coverage data.
1985 declaration->var()->set_is_used();
1986 }
1987 if (names) names->Add(variable_name, zone());
1989 Token::Value init =
1990 loop_nesting_depth() > 0 ? Token::kAssign : Token::kInit;
1992 factory()->NewSloppyBlockFunctionStatement(end_pos, declaration->var(),
1993 init);
1994 GetDeclarationScope()->DeclareSloppyBlockFunction(statement);
1995 return statement;
1996 }
1997 return factory()->EmptyStatement();
1998}
1999
2001 Expression* value,
2003 int class_token_pos, int end_pos) {
2004 VariableProxy* proxy =
2005 DeclareBoundVariable(variable_name, VariableMode::kLet, class_token_pos);
2006 proxy->var()->set_initializer_position(end_pos);
2007 if (names) names->Add(variable_name, zone());
2008
2009 Assignment* assignment =
2010 factory()->NewAssignment(Token::kInit, proxy, value, class_token_pos);
2011 return IgnoreCompletion(
2012 factory()->NewExpressionStatement(assignment, kNoSourcePosition));
2013}
2014
2016 // Make sure that the function containing the native declaration
2017 // isn't lazily compiled. The extension structures are only
2018 // accessible while parsing the first time not when reparsing
2019 // because of lazy compilation.
2020 GetClosureScope()->ForceEagerCompilation();
2021
2022 // TODO(1240846): It's weird that native function declarations are
2023 // introduced dynamically when we meet their declarations, whereas
2024 // other functions are set up when entering the surrounding scope.
2027 factory()->NewNativeFunctionLiteral(name, extension(), kNoSourcePosition);
2028 return factory()->NewExpressionStatement(
2029 factory()->NewAssignment(Token::kInit, proxy, lit, kNoSourcePosition),
2030 pos);
2031}
2032
2034 Block* block = factory()->NewBlock(1, true);
2035 block->statements()->Add(statement, zone());
2036 return block;
2037}
2038
2040 Scope* scope) {
2041 // In order to get the CaseClauses to execute in their own lexical scope,
2042 // but without requiring downstream code to have special scope handling
2043 // code for switch statements, desugar into blocks as follows:
2044 // { // To group the statements--harmless to evaluate Expression in scope
2045 // .tag_variable = Expression;
2046 // { // To give CaseClauses a scope
2047 // switch (.tag_variable) { CaseClause* }
2048 // }
2049 // }
2050 DCHECK_NOT_NULL(scope);
2051 DCHECK(scope->is_block_scope());
2052 DCHECK_GE(switch_statement->position(), scope->start_position());
2053 DCHECK_LT(switch_statement->position(), scope->end_position());
2054
2055 Block* switch_block = factory()->NewBlock(2, false);
2056
2057 Expression* tag = switch_statement->tag();
2058 Variable* tag_variable =
2059 NewTemporary(ast_value_factory()->dot_switch_tag_string());
2060 Assignment* tag_assign = factory()->NewAssignment(
2061 Token::kAssign, factory()->NewVariableProxy(tag_variable), tag,
2062 tag->position());
2063 // Wrap with IgnoreCompletion so the tag isn't returned as the completion
2064 // value, in case the switch statements don't have a value.
2065 Statement* tag_statement = IgnoreCompletion(
2066 factory()->NewExpressionStatement(tag_assign, kNoSourcePosition));
2067 switch_block->statements()->Add(tag_statement, zone());
2068
2069 switch_statement->set_tag(factory()->NewVariableProxy(tag_variable));
2070 Block* cases_block = factory()->NewBlock(1, false);
2071 cases_block->statements()->Add(switch_statement, zone());
2072 cases_block->set_scope(scope);
2073 switch_block->statements()->Add(cases_block, zone());
2074 return switch_block;
2075}
2076
2079 const DeclarationParsingResult::Declaration* declaration) {
2080 if (has_error()) return;
2081
2082 DCHECK_NOT_NULL(declaration->initializer);
2083
2084 int pos = declaration->value_beg_pos;
2085 if (pos == kNoSourcePosition) {
2086 pos = declaration->initializer->position();
2087 }
2088 Assignment* assignment = factory()->NewAssignment(
2089 Token::kInit, declaration->pattern, declaration->initializer, pos);
2090 statements->Add(factory()->NewExpressionStatement(assignment, pos));
2091}
2092
2093Block* Parser::RewriteCatchPattern(CatchInfo* catch_info) {
2094 DCHECK_NOT_NULL(catch_info->pattern);
2095
2096 DeclarationParsingResult::Declaration decl(
2097 catch_info->pattern, factory()->NewVariableProxy(catch_info->variable));
2098
2099 ScopedPtrList<Statement> init_statements(pointer_buffer());
2100 InitializeVariables(&init_statements, NORMAL_VARIABLE, &decl);
2101 return factory()->NewBlock(true, init_statements);
2102}
2103
2105 for (Declaration* decl : *scope->declarations()) {
2106 if (decl->var()->raw_name() == name) {
2107 int position = decl->position();
2108 Scanner::Location location =
2111 : Scanner::Location(position, position + name->length());
2112 ReportMessageAt(location, MessageTemplate::kVarRedeclaration, name);
2113 return;
2114 }
2115 }
2116 UNREACHABLE();
2117}
2118
2120 const SourceRange& catch_range,
2121 Block* finally_block,
2122 const SourceRange& finally_range,
2123 const CatchInfo& catch_info, int pos) {
2124 // Simplify the AST nodes by converting:
2125 // 'try B0 catch B1 finally B2'
2126 // to:
2127 // 'try { try B0 catch B1 } finally B2'
2128
2129 if (catch_block != nullptr && finally_block != nullptr) {
2130 // If we have both, create an inner try/catch.
2132 statement = factory()->NewTryCatchStatement(try_block, catch_info.scope,
2133 catch_block, kNoSourcePosition);
2135
2136 try_block = factory()->NewBlock(1, false);
2137 try_block->statements()->Add(statement, zone());
2138 catch_block = nullptr; // Clear to indicate it's been handled.
2139 }
2140
2141 if (catch_block != nullptr) {
2142 DCHECK_NULL(finally_block);
2143 TryCatchStatement* stmt = factory()->NewTryCatchStatement(
2144 try_block, catch_info.scope, catch_block, pos);
2145 RecordTryCatchStatementSourceRange(stmt, catch_range);
2146 return stmt;
2147 } else {
2148 DCHECK_NOT_NULL(finally_block);
2149 TryFinallyStatement* stmt =
2150 factory()->NewTryFinallyStatement(try_block, finally_block, pos);
2151 RecordTryFinallyStatementSourceRange(stmt, finally_range);
2152 return stmt;
2153 }
2154}
2155
2158 // For ES6 Generators, we just prepend the initial yield.
2159 Expression* initial_yield = BuildInitialYield(pos, kind);
2160 body->Add(
2161 factory()->NewExpressionStatement(initial_yield, kNoSourcePosition));
2162 ParseStatementList(body, Token::kRightBrace);
2163}
2164
2168
2169 Expression* initial_yield = BuildInitialYield(pos, kind);
2170 body->Add(
2171 factory()->NewExpressionStatement(initial_yield, kNoSourcePosition));
2172 ParseStatementList(body, Token::kRightBrace);
2173}
2174
2176 FunctionSyntaxKind function_syntax_kind,
2177 DeclarationScope* function_scope) {
2178 if (function_syntax_kind == FunctionSyntaxKind::kNamedExpression &&
2179 function_scope->LookupLocal(function_name) == nullptr) {
2180 DCHECK_EQ(function_scope, scope());
2181 function_scope->DeclareFunctionVar(function_name);
2182 }
2183}
2184
2185// Special case for legacy for
2186//
2187// for (var x = initializer in enumerable) body
2188//
2189// An initialization block of the form
2190//
2191// {
2192// x = initializer;
2193// }
2194//
2195// is returned in this case. It has reserved space for two statements,
2196// so that (later on during parsing), the equivalent of
2197//
2198// for (x in enumerable) body
2199//
2200// is added as a second statement to it.
2201Block* Parser::RewriteForVarInLegacy(const ForInfo& for_info) {
2202 const DeclarationParsingResult::Declaration& decl =
2203 for_info.parsing_result.declarations[0];
2204 if (!IsLexicalVariableMode(for_info.parsing_result.descriptor.mode) &&
2205 decl.initializer != nullptr && decl.pattern->IsVariableProxy()) {
2207 const AstRawString* name = decl.pattern->AsVariableProxy()->raw_name();
2208 VariableProxy* single_var = NewUnresolved(name);
2209 Block* init_block = factory()->NewBlock(2, true);
2210 init_block->statements()->Add(
2211 factory()->NewExpressionStatement(
2212 factory()->NewAssignment(Token::kAssign, single_var,
2213 decl.initializer, decl.value_beg_pos),
2215 zone());
2216 return init_block;
2217 }
2218 return nullptr;
2219}
2220
2221// Rewrite a for-in/of statement of the form
2222//
2223// for (let/const/var x in/of e) b
2224//
2225// into
2226//
2227// {
2228// var temp;
2229// for (temp in/of e) {
2230// let/const/var x = temp;
2231// b;
2232// }
2233// let x; // for TDZ
2234// }
2236 Block** body_block,
2237 Expression** each_variable) {
2238 DCHECK_EQ(1, for_info->parsing_result.declarations.size());
2239 DeclarationParsingResult::Declaration& decl =
2240 for_info->parsing_result.declarations[0];
2241 Variable* temp = NewTemporary(ast_value_factory()->dot_for_string());
2242 ScopedPtrList<Statement> each_initialization_statements(pointer_buffer());
2243 DCHECK_IMPLIES(!has_error(), decl.pattern != nullptr);
2244 decl.initializer = factory()->NewVariableProxy(temp, for_info->position);
2245 InitializeVariables(&each_initialization_statements, NORMAL_VARIABLE, &decl);
2246
2247 *body_block = factory()->NewBlock(3, false);
2248 (*body_block)
2249 ->statements()
2250 ->Add(factory()->NewBlock(true, each_initialization_statements), zone());
2251 *each_variable = factory()->NewVariableProxy(temp, for_info->position);
2252}
2253
2254// Create a TDZ for any lexically-bound names in for in/of statements.
2256 const ForInfo& for_info) {
2257 if (IsLexicalVariableMode(for_info.parsing_result.descriptor.mode)) {
2258 DCHECK_NULL(init_block);
2259
2260 init_block = factory()->NewBlock(1, false);
2261
2262 for (const AstRawString* bound_name : for_info.bound_names) {
2263 // TODO(adamk): This needs to be some sort of special
2264 // INTERNAL variable that's invisible to the debugger
2265 // but visible to everything else.
2268 tdz_proxy->var()->set_initializer_position(position());
2269 }
2270 }
2271 return init_block;
2272}
2273
2275 ForStatement* loop, Statement* init, Expression* cond, Statement* next,
2276 Statement* body, Scope* inner_scope, const ForInfo& for_info) {
2277 // ES6 13.7.4.8 specifies that on each loop iteration the let variables are
2278 // copied into a new environment. Moreover, the "next" statement must be
2279 // evaluated not in the environment of the just completed iteration but in
2280 // that of the upcoming one. We achieve this with the following desugaring.
2281 // Extra care is needed to preserve the completion value of the original loop.
2282 //
2283 // We are given a for statement of the form
2284 //
2285 // labels: for (let/const x = i; cond; next) body
2286 //
2287 // and rewrite it as follows. Here we write {{ ... }} for init-blocks, ie.,
2288 // blocks whose ignore_completion_value_ flag is set.
2289 //
2290 // {
2291 // let/const x = i;
2292 // temp_x = x;
2293 // first = 1;
2294 // undefined;
2295 // outer: for (;;) {
2296 // let/const x = temp_x;
2297 // {{ if (first == 1) {
2298 // first = 0;
2299 // } else {
2300 // next;
2301 // }
2302 // flag = 1;
2303 // if (!cond) break;
2304 // }}
2305 // labels: for (; flag == 1; flag = 0, temp_x = x) {
2306 // body
2307 // }
2308 // {{ if (flag == 1) // Body used break.
2309 // break;
2310 // }}
2311 // }
2312 // }
2313
2314 DCHECK_GT(for_info.bound_names.length(), 0);
2315 ScopedPtrList<Variable> temps(pointer_buffer());
2316
2317 Block* outer_block =
2318 factory()->NewBlock(for_info.bound_names.length() + 4, false);
2319
2320 // Add statement: let/const x = i.
2321 outer_block->statements()->Add(init, zone());
2322
2323 const AstRawString* temp_name = ast_value_factory()->dot_for_string();
2324
2325 // For each lexical variable x:
2326 // make statement: temp_x = x.
2327 for (const AstRawString* bound_name : for_info.bound_names) {
2328 VariableProxy* proxy = NewUnresolved(bound_name);
2329 Variable* temp = NewTemporary(temp_name);
2330 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
2331 Assignment* assignment = factory()->NewAssignment(
2332 Token::kAssign, temp_proxy, proxy, kNoSourcePosition);
2333 Statement* assignment_statement =
2334 factory()->NewExpressionStatement(assignment, kNoSourcePosition);
2335 outer_block->statements()->Add(assignment_statement, zone());
2336 temps.Add(temp);
2337 }
2338
2339 Variable* first = nullptr;
2340 // Make statement: first = 1.
2341 if (next) {
2342 first = NewTemporary(temp_name);
2343 VariableProxy* first_proxy = factory()->NewVariableProxy(first);
2344 Expression* const1 = factory()->NewSmiLiteral(1, kNoSourcePosition);
2345 Assignment* assignment = factory()->NewAssignment(
2346 Token::kAssign, first_proxy, const1, kNoSourcePosition);
2347 Statement* assignment_statement =
2348 factory()->NewExpressionStatement(assignment, kNoSourcePosition);
2349 outer_block->statements()->Add(assignment_statement, zone());
2350 }
2351
2352 // make statement: undefined;
2353 outer_block->statements()->Add(
2354 factory()->NewExpressionStatement(
2355 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition),
2356 zone());
2357
2358 // Make statement: outer: for (;;)
2359 // Note that we don't actually create the label, or set this loop up as an
2360 // explicit break target, instead handing it directly to those nodes that
2361 // need to know about it. This should be safe because we don't run any code
2362 // in this function that looks up break targets.
2363 ForStatement* outer_loop = factory()->NewForStatement(kNoSourcePosition);
2364 outer_block->statements()->Add(outer_loop, zone());
2365 outer_block->set_scope(scope());
2366
2367 Block* inner_block = factory()->NewBlock(3, false);
2368 {
2369 BlockState block_state(&scope_, inner_scope);
2370
2371 Block* ignore_completion_block =
2372 factory()->NewBlock(for_info.bound_names.length() + 3, true);
2373 ScopedPtrList<Variable> inner_vars(pointer_buffer());
2374 // For each let variable x:
2375 // make statement: let/const x = temp_x.
2376 for (int i = 0; i < for_info.bound_names.length(); i++) {
2378 for_info.bound_names[i], for_info.parsing_result.descriptor.mode,
2380 inner_vars.Add(proxy->var());
2381 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
2382 Assignment* assignment = factory()->NewAssignment(
2383 Token::kInit, proxy, temp_proxy, kNoSourcePosition);
2384 Statement* assignment_statement =
2385 factory()->NewExpressionStatement(assignment, kNoSourcePosition);
2386 int declaration_pos = for_info.parsing_result.descriptor.declaration_pos;
2387 DCHECK_NE(declaration_pos, kNoSourcePosition);
2388 proxy->var()->set_initializer_position(declaration_pos);
2389 ignore_completion_block->statements()->Add(assignment_statement, zone());
2390 }
2391
2392 // Make statement: if (first == 1) { first = 0; } else { next; }
2393 if (next) {
2394 DCHECK(first);
2395 Expression* compare = nullptr;
2396 // Make compare expression: first == 1.
2397 {
2398 Expression* const1 = factory()->NewSmiLiteral(1, kNoSourcePosition);
2399 VariableProxy* first_proxy = factory()->NewVariableProxy(first);
2400 compare = factory()->NewCompareOperation(Token::kEq, first_proxy,
2401 const1, kNoSourcePosition);
2402 }
2403 Statement* clear_first = nullptr;
2404 // Make statement: first = 0.
2405 {
2406 VariableProxy* first_proxy = factory()->NewVariableProxy(first);
2407 Expression* const0 = factory()->NewSmiLiteral(0, kNoSourcePosition);
2408 Assignment* assignment = factory()->NewAssignment(
2409 Token::kAssign, first_proxy, const0, kNoSourcePosition);
2410 clear_first =
2411 factory()->NewExpressionStatement(assignment, kNoSourcePosition);
2412 }
2413 Statement* clear_first_or_next = factory()->NewIfStatement(
2414 compare, clear_first, next, kNoSourcePosition);
2415 ignore_completion_block->statements()->Add(clear_first_or_next, zone());
2416 }
2417
2418 Variable* flag = NewTemporary(temp_name);
2419 // Make statement: flag = 1.
2420 {
2421 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
2422 Expression* const1 = factory()->NewSmiLiteral(1, kNoSourcePosition);
2423 Assignment* assignment = factory()->NewAssignment(
2424 Token::kAssign, flag_proxy, const1, kNoSourcePosition);
2425 Statement* assignment_statement =
2426 factory()->NewExpressionStatement(assignment, kNoSourcePosition);
2427 ignore_completion_block->statements()->Add(assignment_statement, zone());
2428 }
2429
2430 // Make statement: if (!cond) break.
2431 if (cond) {
2432 Statement* stop =
2433 factory()->NewBreakStatement(outer_loop, kNoSourcePosition);
2434 Statement* noop = factory()->EmptyStatement();
2435 ignore_completion_block->statements()->Add(
2436 factory()->NewIfStatement(cond, noop, stop, cond->position()),
2437 zone());
2438 }
2439
2440 inner_block->statements()->Add(ignore_completion_block, zone());
2441 // Make cond expression for main loop: flag == 1.
2442 Expression* flag_cond = nullptr;
2443 {
2444 Expression* const1 = factory()->NewSmiLiteral(1, kNoSourcePosition);
2445 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
2446 flag_cond = factory()->NewCompareOperation(Token::kEq, flag_proxy, const1,
2448 }
2449
2450 // Create chain of expressions "flag = 0, temp_x = x, ..."
2451 Statement* compound_next_statement = nullptr;
2452 {
2453 Expression* compound_next = nullptr;
2454 // Make expression: flag = 0.
2455 {
2456 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
2457 Expression* const0 = factory()->NewSmiLiteral(0, kNoSourcePosition);
2458 compound_next = factory()->NewAssignment(Token::kAssign, flag_proxy,
2459 const0, kNoSourcePosition);
2460 }
2461
2462 // Make the comma-separated list of temp_x = x assignments.
2463 int inner_var_proxy_pos = scanner()->location().beg_pos;
2464 for (int i = 0; i < for_info.bound_names.length(); i++) {
2465 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
2466 VariableProxy* proxy =
2467 factory()->NewVariableProxy(inner_vars.at(i), inner_var_proxy_pos);
2468 Assignment* assignment = factory()->NewAssignment(
2469 Token::kAssign, temp_proxy, proxy, kNoSourcePosition);
2470 compound_next = factory()->NewBinaryOperation(
2471 Token::kComma, compound_next, assignment, kNoSourcePosition);
2472 }
2473
2474 compound_next_statement =
2475 factory()->NewExpressionStatement(compound_next, kNoSourcePosition);
2476 }
2477
2478 // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x)
2479 // Note that we reuse the original loop node, which retains its labels
2480 // and ensures that any break or continue statements in body point to
2481 // the right place.
2482 loop->Initialize(nullptr, flag_cond, compound_next_statement, body);
2483 inner_block->statements()->Add(loop, zone());
2484
2485 // Make statement: {{if (flag == 1) break;}}
2486 {
2487 Expression* compare = nullptr;
2488 // Make compare expression: flag == 1.
2489 {
2490 Expression* const1 = factory()->NewSmiLiteral(1, kNoSourcePosition);
2491 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
2492 compare = factory()->NewCompareOperation(Token::kEq, flag_proxy, const1,
2494 }
2495 Statement* stop =
2496 factory()->NewBreakStatement(outer_loop, kNoSourcePosition);
2497 Statement* empty = factory()->EmptyStatement();
2498 Statement* if_flag_break =
2499 factory()->NewIfStatement(compare, stop, empty, kNoSourcePosition);
2500 inner_block->statements()->Add(IgnoreCompletion(if_flag_break), zone());
2501 }
2502
2503 inner_block->set_scope(inner_scope);
2504 }
2505
2506 outer_loop->Initialize(nullptr, nullptr, nullptr, inner_block);
2507
2508 return outer_block;
2509}
2510
2512 if (has_duplicate()) {
2513 parser->ReportMessageAt(duplicate_loc, MessageTemplate::kParamDupe);
2514 }
2515}
2517 if (strict_error_loc.IsValid()) {
2518 parser->ReportMessageAt(strict_error_loc, strict_error_message);
2519 }
2520}
2521
2523 ParserFormalParameters* parameters, Expression* expr, int end_pos) {
2524 // ArrowFunctionFormals ::
2525 // Nary(Token::kComma, VariableProxy*, Tail)
2526 // Binary(Token::kComma, NonTailArrowFunctionFormals, Tail)
2527 // Tail
2528 // NonTailArrowFunctionFormals ::
2529 // Binary(Token::kComma, NonTailArrowFunctionFormals, VariableProxy)
2530 // VariableProxy
2531 // Tail ::
2532 // VariableProxy
2533 // Spread(VariableProxy)
2534 //
2535 // We need to visit the parameters in left-to-right order
2536 //
2537
2538 // For the Nary case, we simply visit the parameters in a loop.
2539 if (expr->IsNaryOperation()) {
2540 NaryOperation* nary = expr->AsNaryOperation();
2541 // The classifier has already run, so we know that the expression is a valid
2542 // arrow function formals production.
2543 DCHECK_EQ(nary->op(), Token::kComma);
2544 // Each op position is the end position of the *previous* expr, with the
2545 // second (i.e. first "subsequent") op position being the end position of
2546 // the first child expression.
2547 Expression* next = nary->first();
2548 for (size_t i = 0; i < nary->subsequent_length(); ++i) {
2549 AddArrowFunctionFormalParameters(parameters, next,
2550 nary->subsequent_op_position(i));
2551 next = nary->subsequent(i);
2552 }
2553 AddArrowFunctionFormalParameters(parameters, next, end_pos);
2554 return;
2555 }
2556
2557 // For the binary case, we recurse on the left-hand side of binary comma
2558 // expressions.
2559 if (expr->IsBinaryOperation()) {
2560 BinaryOperation* binop = expr->AsBinaryOperation();
2561 // The classifier has already run, so we know that the expression is a valid
2562 // arrow function formals production.
2563 DCHECK_EQ(binop->op(), Token::kComma);
2564 Expression* left = binop->left();
2565 Expression* right = binop->right();
2566 int comma_pos = binop->position();
2567 AddArrowFunctionFormalParameters(parameters, left, comma_pos);
2568 // LHS of comma expression should be unparenthesized.
2569 expr = right;
2570 }
2571
2572 // Only the right-most expression may be a rest parameter.
2573 DCHECK(!parameters->has_rest);
2574
2575 bool is_rest = expr->IsSpread();
2576 if (is_rest) {
2577 expr = expr->AsSpread()->expression();
2578 parameters->has_rest = true;
2579 }
2580 DCHECK_IMPLIES(parameters->is_simple, !is_rest);
2581 DCHECK_IMPLIES(parameters->is_simple, expr->IsVariableProxy());
2582
2583 Expression* initializer = nullptr;
2584 if (expr->IsAssignment()) {
2585 Assignment* assignment = expr->AsAssignment();
2586 DCHECK(!assignment->IsCompoundAssignment());
2587 initializer = assignment->value();
2588 expr = assignment->target();
2589 }
2590
2591 AddFormalParameter(parameters, expr, initializer, end_pos, is_rest);
2592}
2593
2595 ParserFormalParameters* parameters, Expression* expr,
2596 const Scanner::Location& params_loc) {
2597 if (expr->IsEmptyParentheses() || has_error()) return;
2598
2599 AddArrowFunctionFormalParameters(parameters, expr, params_loc.end_pos);
2600
2601 if (parameters->arity + 1 /* receiver */ > Code::kMaxArguments) {
2602 ReportMessageAt(params_loc, MessageTemplate::kMalformedArrowFunParamList);
2603 return;
2604 }
2605
2606 DeclareFormalParameters(parameters);
2607 DCHECK_IMPLIES(parameters->is_simple,
2608 parameters->scope->has_simple_parameters());
2609}
2610
2612 ParserFormalParameters* parameters) {
2613 // Make space for the arrow function above the formal parameters.
2615 for (auto p : parameters->params) {
2616 if (p->pattern != nullptr) reindexer.Reindex(p->pattern);
2617 if (p->initializer() != nullptr) {
2618 reindexer.Reindex(p->initializer());
2619 }
2620 if (reindexer.HasStackOverflow()) {
2621 set_stack_overflow();
2622 return;
2623 }
2624 }
2625}
2626
2628 // Make space for the member initializer function above the computed property
2629 // name.
2631 reindexer.Reindex(computed_name);
2632}
2633
2635 // Calling a generator returns a generator object. That object is stored
2636 // in a temporary variable, a definition that is used by "yield"
2637 // expressions.
2638 function_state_->scope()->DeclareGeneratorObjectVar(
2639 ast_value_factory()->dot_generator_object_string());
2640}
2641
2643 const AstRawString* function_name, Scanner::Location function_name_location,
2644 FunctionNameValidity function_name_validity, FunctionKind kind,
2645 int function_token_pos, FunctionSyntaxKind function_syntax_kind,
2646 LanguageMode language_mode,
2647 ZonePtrList<const AstRawString>* arguments_for_wrapped_function) {
2648 // Function ::
2649 // '(' FormalParameterList? ')' '{' FunctionBody '}'
2650 //
2651 // Getter ::
2652 // '(' ')' '{' FunctionBody '}'
2653 //
2654 // Setter ::
2655 // '(' PropertySetParameterList ')' '{' FunctionBody '}'
2656
2657 bool is_wrapped = function_syntax_kind == FunctionSyntaxKind::kWrapped;
2658 DCHECK_EQ(is_wrapped, arguments_for_wrapped_function != nullptr);
2659
2660 int pos = function_token_pos == kNoSourcePosition ? peek_position()
2661 : function_token_pos;
2663
2664 // Anonymous functions were passed either the empty symbol or a null
2665 // handle as the function name. Remember if we were passed a non-empty
2666 // handle to decide whether to invoke function name inference.
2667 bool should_infer_name = function_name == nullptr;
2668
2669 // We want a non-null handle as the function name by default. We will handle
2670 // the "function does not have a shared name" case later.
2671 if (should_infer_name) {
2672 function_name = ast_value_factory()->empty_string();
2673 }
2674
2675 // This is true if we get here through CreateDynamicFunction.
2676 bool params_need_validation = parameters_end_pos_ != kNoSourcePosition;
2677 int compile_hint_position = peek_position();
2678
2679 FunctionLiteral::EagerCompileHint eager_compile_hint =
2680 function_state_->next_function_is_likely_called() || is_wrapped ||
2681 params_need_validation ||
2682 (info()->flags().compile_hints_magic_enabled() &&
2683 scanner()->SawMagicCommentCompileHintsAll()) ||
2684 (info()->flags().compile_hints_per_function_magic_enabled() &&
2685 scanner()->HasPerFunctionCompileHint(compile_hint_position))
2687 : default_eager_compile_hint();
2688
2689 // Determine if the function can be parsed lazily. Lazy parsing is
2690 // different from lazy compilation; we need to parse more eagerly than we
2691 // compile.
2692
2693 // We can only parse lazily if we also compile lazily. The heuristics for lazy
2694 // compilation are:
2695 // - It must not have been prohibited by the caller to Parse (some callers
2696 // need a full AST).
2697 // - The outer scope must allow lazy compilation of inner functions.
2698 // - The function mustn't be a function expression with an open parenthesis
2699 // before; we consider that a hint that the function will be called
2700 // immediately, and it would be a waste of time to make it lazily
2701 // compiled.
2702 // These are all things we can know at this point, without looking at the
2703 // function itself.
2704
2705 // We separate between lazy parsing top level functions and lazy parsing inner
2706 // functions, because the latter needs to do more work. In particular, we need
2707 // to track unresolved variables to distinguish between these cases:
2708 // (function foo() {
2709 // bar = function() { return 1; }
2710 // })();
2711 // and
2712 // (function foo() {
2713 // var a = 1;
2714 // bar = function() { return a; }
2715 // })();
2716
2717 // Now foo will be parsed eagerly and compiled eagerly (optimization: assume
2718 // parenthesis before the function means that it will be called
2719 // immediately). bar can be parsed lazily, but we need to parse it in a mode
2720 // that tracks unresolved variables.
2721 DCHECK_IMPLIES(parse_lazily(), info()->flags().allow_lazy_compile());
2722 DCHECK_IMPLIES(parse_lazily(), has_error() || allow_lazy_);
2723 DCHECK_IMPLIES(parse_lazily(), extension() == nullptr);
2724
2725 eager_compile_hint =
2726 GetEmbedderCompileHint(eager_compile_hint, compile_hint_position);
2727
2728 const bool is_lazy =
2729 eager_compile_hint == FunctionLiteral::kShouldLazyCompile;
2730 const bool is_top_level = AllowsLazyParsingWithoutUnresolvedVariables();
2731 const bool is_eager_top_level_function = !is_lazy && is_top_level;
2732
2733 RCS_SCOPE(runtime_call_stats_, RuntimeCallCounterId::kParseFunctionLiteral,
2734 RuntimeCallStats::kThreadSpecific);
2735 base::ElapsedTimer timer;
2736 if (V8_UNLIKELY(v8_flags.log_function_events)) timer.Start();
2737
2738 // Determine whether we can lazy parse the inner function. Lazy compilation
2739 // has to be enabled, which is either forced by overall parse flags or via a
2740 // ParsingModeScope.
2741 const bool can_preparse = parse_lazily();
2742
2743 // Determine whether we can post any parallel compile tasks. Preparsing must
2744 // be possible, there has to be a dispatcher, and the character stream must be
2745 // cloneable.
2746 const bool can_post_parallel_task =
2747 can_preparse && info()->dispatcher() &&
2748 scanner()->stream()->can_be_cloned_for_parallel_access();
2749
2750 // If parallel compile tasks are enabled, and this isn't a re-parse, enable
2751 // parallel compile for the subset of functions as defined by flags.
2752 bool should_post_parallel_task =
2753 can_post_parallel_task && !flags().is_reparse() &&
2754 ((is_eager_top_level_function &&
2755 flags().post_parallel_compile_tasks_for_eager_toplevel()) ||
2756 (is_lazy && flags().post_parallel_compile_tasks_for_lazy()));
2757
2758 // Determine whether we should lazy parse the inner function. This will be
2759 // when either the function is lazy by inspection, or when we force it to be
2760 // preparsed now so that we can then post a parallel full parse & compile task
2761 // for it.
2762 const bool should_preparse =
2763 can_preparse && (is_lazy || should_post_parallel_task);
2764
2765 ScopedPtrList<Statement> body(pointer_buffer());
2766 int expected_property_count = 0;
2767 int suspend_count = -1;
2768 int num_parameters = -1;
2769 int function_length = -1;
2770 bool has_duplicate_parameters = false;
2771 int function_literal_id = GetNextInfoId();
2772 ProducedPreparseData* produced_preparse_data = nullptr;
2773
2774 // Inner functions will be parsed using a temporary Zone. After parsing, we
2775 // will migrate unresolved variable into a Scope in the main Zone.
2776 Zone* parse_zone = should_preparse ? &preparser_zone_ : zone();
2777 // This Scope lives in the main zone. We'll migrate data into that zone later.
2778 DeclarationScope* scope = NewFunctionScope(kind, parse_zone);
2779 SetLanguageMode(scope, language_mode);
2780 if (is_wrapped) {
2781 scope->set_is_wrapped_function();
2782 }
2783#ifdef DEBUG
2784 scope->SetScopeName(function_name);
2785#endif
2786
2787 if (!is_wrapped && V8_UNLIKELY(!Check(Token::kLeftParen))) {
2788 ReportUnexpectedToken(Next());
2789 return nullptr;
2790 }
2791 scope->set_start_position(position());
2792
2793 // Eager or lazy parse? If is_lazy_top_level_function, we'll parse
2794 // lazily. We'll call SkipFunction, which may decide to
2795 // abort lazy parsing if it suspects that wasn't a good idea. If so (in
2796 // which case the parser is expected to have backtracked), or if we didn't
2797 // try to lazy parse in the first place, we'll have to parse eagerly.
2798 bool did_preparse_successfully =
2799 should_preparse &&
2800 SkipFunction(function_name, kind, function_syntax_kind, scope,
2801 &num_parameters, &function_length, &produced_preparse_data);
2802
2803 if (!did_preparse_successfully) {
2804 // If skipping aborted, it rewound the scanner until before the lparen.
2805 // Consume it in that case.
2806 if (should_preparse) Consume(Token::kLeftParen);
2807 should_post_parallel_task = false;
2808 ParseFunction(&body, function_name, pos, kind, function_syntax_kind, scope,
2809 &num_parameters, &function_length, &has_duplicate_parameters,
2810 &expected_property_count, &suspend_count,
2811 arguments_for_wrapped_function);
2812 }
2813
2814 if (V8_UNLIKELY(v8_flags.log_function_events)) {
2815 double ms = timer.Elapsed().InMillisecondsF();
2816 const char* event_name =
2817 should_preparse
2818 ? (is_top_level ? "preparse-no-resolution" : "preparse-resolution")
2819 : "full-parse";
2820 v8_file_logger_->FunctionEvent(
2821 event_name, flags().script_id(), ms, scope->start_position(),
2822 scope->end_position(),
2823 reinterpret_cast<const char*>(function_name->raw_data()),
2824 function_name->byte_length(), function_name->is_one_byte());
2825 }
2826#ifdef V8_RUNTIME_CALL_STATS
2827 if (did_preparse_successfully && runtime_call_stats_ &&
2828 V8_UNLIKELY(TracingFlags::is_runtime_stats_enabled())) {
2829 runtime_call_stats_->CorrectCurrentCounterId(
2830 RuntimeCallCounterId::kPreParseWithVariableResolution,
2831 RuntimeCallStats::kThreadSpecific);
2832 }
2833#endif // V8_RUNTIME_CALL_STATS
2834
2835 // Validate function name. We can do this only after parsing the function,
2836 // since the function can declare itself strict.
2837 language_mode = scope->language_mode();
2838 CheckFunctionName(language_mode, function_name, function_name_validity,
2839 function_name_location);
2840
2841 if (is_strict(language_mode)) {
2842 CheckStrictOctalLiteral(scope->start_position(), scope->end_position());
2843 }
2844
2845 FunctionLiteral::ParameterFlag duplicate_parameters =
2848
2849 // Note that the FunctionLiteral needs to be created in the main Zone again.
2850 FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
2851 function_name, scope, body, expected_property_count, num_parameters,
2852 function_length, duplicate_parameters, function_syntax_kind,
2853 eager_compile_hint, pos, true, function_literal_id,
2854 produced_preparse_data);
2855 function_literal->set_function_token_position(function_token_pos);
2856 function_literal->set_suspend_count(suspend_count);
2857
2858 RecordFunctionLiteralSourceRange(function_literal);
2859
2860 if (should_post_parallel_task && !has_error()) {
2861 function_literal->set_should_parallel_compile();
2862 }
2863
2864 if (should_infer_name) {
2865 fni_.AddFunction(function_literal);
2866 }
2867 return function_literal;
2868}
2869
2871 FunctionSyntaxKind function_syntax_kind,
2872 DeclarationScope* function_scope, int* num_parameters,
2873 int* function_length,
2874 ProducedPreparseData** produced_preparse_data) {
2875 FunctionState function_state(&function_state_, &scope_, function_scope);
2876 function_scope->set_zone(&preparser_zone_);
2877
2878 DCHECK_NE(kNoSourcePosition, function_scope->start_position());
2880
2882 scanner()->current_token() == Token::kArrow);
2883
2884 // FIXME(marja): There are 2 ways to skip functions now. Unify them.
2886 int end_position;
2887 LanguageMode language_mode;
2888 int num_inner_infos;
2889 bool uses_super_property;
2890 if (stack_overflow()) return true;
2891 {
2893 *produced_preparse_data =
2895 main_zone(), function_scope->start_position(), &end_position,
2896 num_parameters, function_length, &num_inner_infos,
2897 &uses_super_property, &language_mode);
2898 }
2899
2900 function_scope->outer_scope()->SetMustUsePreparseData();
2901 function_scope->set_is_skipped_function(true);
2902 function_scope->set_end_position(end_position);
2903 scanner()->SeekForward(end_position - 1);
2904 Expect(Token::kRightBrace);
2905 SetLanguageMode(function_scope, language_mode);
2906 if (uses_super_property) {
2907 function_scope->RecordSuperPropertyUsage();
2908 }
2909 SkipInfos(num_inner_infos);
2910 function_scope->ResetAfterPreparsing(ast_value_factory_, false);
2911 return true;
2912 }
2913
2914 Scanner::BookmarkScope bookmark(scanner());
2915 bookmark.Set(function_scope->start_position());
2916
2917 UnresolvedList::Iterator unresolved_private_tail;
2918 PrivateNameScopeIterator private_name_scope_iter(function_scope);
2919 if (!private_name_scope_iter.Done()) {
2920 unresolved_private_tail =
2921 private_name_scope_iter.GetScope()->GetUnresolvedPrivateNameTail();
2922 }
2923
2924 // With no cached data, we partially parse the function, without building an
2925 // AST. This gathers the data needed to build a lazy function.
2926 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse");
2927
2929 function_name, kind, function_syntax_kind, function_scope, use_counts_,
2930 produced_preparse_data);
2931
2933 // Propagate stack overflow.
2934 set_stack_overflow();
2935 } else if (pending_error_handler()->has_error_unidentifiable_by_preparser()) {
2936 // Make sure we don't re-preparse inner functions of the aborted function.
2937 // The error might be in an inner function.
2938 allow_lazy_ = false;
2940 DCHECK(!pending_error_handler()->stack_overflow());
2941 // If we encounter an error that the preparser can not identify we reset to
2942 // the state before preparsing. The caller may then fully parse the function
2943 // to identify the actual error.
2944 bookmark.Apply();
2945 if (!private_name_scope_iter.Done()) {
2946 private_name_scope_iter.GetScope()->ResetUnresolvedPrivateNameTail(
2947 unresolved_private_tail);
2948 }
2949 function_scope->ResetAfterPreparsing(ast_value_factory_, true);
2950 pending_error_handler()->clear_unidentifiable_error();
2951 return false;
2952 } else if (pending_error_handler()->has_pending_error()) {
2953 DCHECK(!pending_error_handler()->stack_overflow());
2954 DCHECK(has_error());
2955 } else {
2956 DCHECK(!pending_error_handler()->stack_overflow());
2957 set_allow_eval_cache(reusable_preparser()->allow_eval_cache());
2958
2960 function_scope->set_end_position(logger->end());
2961 Expect(Token::kRightBrace);
2963 function_scope->end_position() - function_scope->start_position();
2964 *num_parameters = logger->num_parameters();
2965 *function_length = logger->function_length();
2966 SkipInfos(logger->num_inner_infos());
2967 if (!private_name_scope_iter.Done()) {
2968 private_name_scope_iter.GetScope()->MigrateUnresolvedPrivateNameTail(
2969 factory(), unresolved_private_tail);
2970 }
2971 function_scope->AnalyzePartially(this, factory(), MaybeParsingArrowhead());
2972 }
2973
2974 return true;
2975}
2976
2978 const ParserFormalParameters& parameters) {
2979 DCHECK(!parameters.is_simple);
2980 DCHECK(scope()->is_function_scope());
2981 DCHECK_EQ(scope(), parameters.scope);
2982 ScopedPtrList<Statement> init_statements(pointer_buffer());
2983 int index = 0;
2984 for (auto parameter : parameters.params) {
2985 Expression* initial_value =
2986 factory()->NewVariableProxy(parameters.scope->parameter(index));
2987 if (parameter->initializer() != nullptr) {
2988 // IS_UNDEFINED($param) ? initializer : $param
2989
2990 auto condition = factory()->NewCompareOperation(
2991 Token::kEqStrict,
2992 factory()->NewVariableProxy(parameters.scope->parameter(index)),
2993 factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
2994 initial_value =
2995 factory()->NewConditional(condition, parameter->initializer(),
2996 initial_value, kNoSourcePosition);
2997 }
2998
2999 BlockState block_state(&scope_, scope()->AsDeclarationScope());
3000 DeclarationParsingResult::Declaration decl(parameter->pattern,
3001 initial_value);
3002 InitializeVariables(&init_statements, PARAMETER_VARIABLE, &decl);
3003
3004 ++index;
3005 }
3006 return factory()->NewParameterInitializationBlock(init_statements);
3007}
3008
3010 Expression* yield_result = factory()->NewVariableProxy(
3011 function_state_->scope()->generator_object_var());
3012 // The position of the yield is important for reporting the exception
3013 // caused by calling the .throw method on a generator suspended at the
3014 // initial yield (i.e. right after generator instantiation).
3015 function_state_->AddSuspend();
3016 return factory()->NewYield(yield_result, scope()->start_position(),
3018}
3019
3021 ScopedPtrList<Statement>* body, const AstRawString* function_name, int pos,
3022 FunctionKind kind, FunctionSyntaxKind function_syntax_kind,
3023 DeclarationScope* function_scope, int* num_parameters, int* function_length,
3024 bool* has_duplicate_parameters, int* expected_property_count,
3025 int* suspend_count,
3026 ZonePtrList<const AstRawString>* arguments_for_wrapped_function) {
3027 FunctionParsingScope function_parsing_scope(this);
3029
3030 FunctionState function_state(&function_state_, &scope_, function_scope);
3031
3032 bool is_wrapped = function_syntax_kind == FunctionSyntaxKind::kWrapped;
3033
3034 int expected_parameters_end_pos = parameters_end_pos_;
3035 if (expected_parameters_end_pos != kNoSourcePosition) {
3036 // This is the first function encountered in a CreateDynamicFunction eval.
3038 // The function name should have been ignored, giving us the empty string
3039 // here.
3040 DCHECK_EQ(function_name, ast_value_factory()->empty_string());
3041 }
3042
3043 ParserFormalParameters formals(function_scope);
3044
3045 {
3046 ParameterDeclarationParsingScope formals_scope(this);
3047 if (is_wrapped) {
3048 // For a function implicitly wrapped in function header and footer, the
3049 // function arguments are provided separately to the source, and are
3050 // declared directly here.
3051 for (const AstRawString* arg : *arguments_for_wrapped_function) {
3052 const bool is_rest = false;
3054 AddFormalParameter(&formals, argument, NullExpression(),
3055 kNoSourcePosition, is_rest);
3056 }
3057 DCHECK_EQ(arguments_for_wrapped_function->length(),
3058 formals.num_parameters());
3059 DeclareFormalParameters(&formals);
3060 } else {
3061 // For a regular function, the function arguments are parsed from source.
3062 DCHECK_NULL(arguments_for_wrapped_function);
3063 ParseFormalParameterList(&formals);
3064 if (expected_parameters_end_pos != kNoSourcePosition) {
3065 // Check for '(' or ')' shenanigans in the parameter string for dynamic
3066 // functions.
3067 int position = peek_position();
3068 if (position < expected_parameters_end_pos) {
3069 ReportMessageAt(Scanner::Location(position, position + 1),
3070 MessageTemplate::kArgStringTerminatesParametersEarly);
3071 return;
3072 } else if (position > expected_parameters_end_pos) {
3073 ReportMessageAt(Scanner::Location(expected_parameters_end_pos - 2,
3074 expected_parameters_end_pos),
3075 MessageTemplate::kUnexpectedEndOfArgString);
3076 return;
3077 }
3078 }
3079 Expect(Token::kRightParen);
3080 int formals_end_position = end_position();
3081
3082 CheckArityRestrictions(formals.arity, kind, formals.has_rest,
3083 function_scope->start_position(),
3084 formals_end_position);
3085 Expect(Token::kLeftBrace);
3086 }
3087 formals.duplicate_loc = formals_scope.duplicate_location();
3088 }
3089
3090 *num_parameters = formals.num_parameters();
3091 *function_length = formals.function_length;
3092
3093 AcceptINScope scope(this, true);
3094 ParseFunctionBody(body, function_name, pos, formals, kind,
3095 function_syntax_kind, FunctionBodyType::kBlock);
3096
3098
3099 *expected_property_count = function_state.expected_property_count();
3100 *suspend_count = function_state.suspend_count();
3101}
3102
3104 ClassInfo* class_info, int class_token_pos) {
3105#ifdef DEBUG
3106 scope->SetScopeName(name);
3107#endif
3108
3109 DCHECK_IMPLIES(IsEmptyIdentifier(name), class_info->is_anonymous);
3110 // Declare a special class variable for anonymous classes with the dot
3111 // if we need to save it for static private method access.
3112 Variable* class_variable =
3113 scope->DeclareClassVariable(ast_value_factory(), name, class_token_pos);
3114 Declaration* declaration = factory()->NewVariableDeclaration(class_token_pos);
3115 scope->declarations()->Add(declaration);
3116 declaration->set_var(class_variable);
3117}
3118
3120 ClassScope* scope, ClassInfo* class_info, const AstRawString* name,
3121 bool is_static) {
3122 if (scope->is_reparsed()) {
3123 DeclarationScope* declaration_scope =
3124 is_static ? class_info->static_elements_scope
3125 : class_info->instance_members_scope;
3126 return declaration_scope->NewUnresolved(factory()->ast_node_factory(), name,
3127 position());
3128 }
3129 VariableProxy* proxy =
3131 proxy->var()->ForceContextAllocation();
3132 return proxy;
3133}
3134
3136 VariableMode mode,
3137 IsStaticFlag is_static_flag,
3138 const AstRawString* name) {
3139 DCHECK_NOT_NULL(name);
3140 int begin = position();
3141 int end = end_position();
3142 bool was_added = false;
3144 Variable* var =
3145 scope->DeclarePrivateName(name, mode, is_static_flag, &was_added);
3146 if (!was_added) {
3147 Scanner::Location loc(begin, end);
3148 ReportMessageAt(loc, MessageTemplate::kVarRedeclaration, var->raw_name());
3149 }
3150 return factory()->NewVariableProxy(var, begin);
3151}
3152
3154 ClassInfo* class_info,
3155 bool is_static) {
3156 if (is_static) {
3157 class_info->static_elements->Add(
3158 factory()->NewClassLiteralStaticElement(property), zone());
3159 return;
3160 }
3161 class_info->instance_fields->Add(property, zone());
3162}
3163
3165 ClassLiteralProperty* property,
3166 bool is_static, bool is_computed_name,
3167 ClassInfo* class_info) {
3168 AddInstanceFieldOrStaticElement(property, class_info, is_static);
3169
3170 if (is_computed_name) {
3171 // We create a synthetic variable name here so that scope
3172 // analysis doesn't dedupe the vars.
3173 const AstRawString* name = ClassFieldVariableName(
3174 ast_value_factory(), class_info->computed_field_count);
3175 VariableProxy* proxy =
3176 CreateSyntheticContextVariableProxy(scope, class_info, name, is_static);
3177 property->set_computed_name_proxy(proxy);
3178 class_info->public_members->Add(property, zone());
3179 }
3180}
3181
3183 const AstRawString* property_name,
3184 ClassLiteralProperty* property,
3186 bool is_static, ClassInfo* class_info) {
3189 AddInstanceFieldOrStaticElement(property, class_info, is_static);
3190 }
3191 class_info->private_members->Add(property, zone());
3192
3193 VariableProxy* proxy;
3194 if (scope->is_reparsed()) {
3195 PrivateNameScopeIterator private_name_scope_iter(scope);
3196 proxy = ExpressionFromPrivateName(&private_name_scope_iter, property_name,
3197 position());
3198 } else {
3200 scope, GetVariableMode(kind),
3202 property_name);
3203 int pos = property->value()->position();
3204 if (pos == kNoSourcePosition) {
3205 pos = property->key()->position();
3206 }
3207 proxy->var()->set_initializer_position(pos);
3208 }
3209 property->SetPrivateNameProxy(proxy);
3210}
3211
3212// This method declares a property of the given class. It updates the
3213// following fields of class_info, as appropriate:
3214// - constructor
3215// - properties
3217 ClassLiteralProperty* property,
3218 bool is_constructor,
3219 ClassInfo* class_info) {
3220 if (is_constructor) {
3221 DCHECK(!class_info->constructor);
3222 class_info->constructor = property->value()->AsFunctionLiteral();
3223 DCHECK_NOT_NULL(class_info->constructor);
3224 class_info->constructor->set_raw_name(
3225 class_name != nullptr ? ast_value_factory()->NewConsString(class_name)
3226 : nullptr);
3227 return;
3228 }
3229
3230 class_info->public_members->Add(property, zone());
3231}
3232
3233void Parser::AddClassStaticBlock(Block* block, ClassInfo* class_info) {
3234 DCHECK(class_info->has_static_elements());
3235 class_info->static_elements->Add(
3236 factory()->NewClassLiteralStaticElement(block), zone());
3237}
3238
3240 const AstRawString* class_name, DeclarationScope* scope,
3241 int function_literal_id, Statement* initializer_stmt) {
3243 // function() { .. class fields initializer .. }
3244 ScopedPtrList<Statement> statements(pointer_buffer());
3245 statements.Add(initializer_stmt);
3246 FunctionLiteral* result = factory()->NewFunctionLiteral(
3247 class_name, scope, statements, 0, 0, 0,
3251 function_literal_id);
3252#ifdef DEBUG
3253 scope->SetScopeName(class_name);
3254#endif
3256
3257 return result;
3258}
3259
3261 const AstRawString* name, ClassInfo* class_info) {
3263 name, class_info->static_elements_scope,
3264 class_info->static_elements_function_id,
3265 factory()->NewInitializeClassStaticElementsStatement(
3266 class_info->static_elements, kNoSourcePosition));
3267}
3268
3270 const AstRawString* name, ClassInfo* class_info) {
3272 name, class_info->instance_members_scope,
3273 class_info->instance_members_function_id,
3274 factory()->NewInitializeClassMembersStatement(class_info->instance_fields,
3276}
3277
3278// This method generates a ClassLiteral AST node.
3279// It uses the following fields of class_info:
3280// - constructor (if missing, it updates it with a default constructor)
3281// - proxy
3282// - extends
3283// - properties
3284// - has_static_computed_names
3286 const AstRawString* name,
3287 ClassInfo* class_info, int pos) {
3288 DCHECK_NOT_NULL(block_scope);
3289 DCHECK_EQ(block_scope->scope_type(), CLASS_SCOPE);
3291
3292 bool has_extends = class_info->extends != nullptr;
3293 bool has_default_constructor = class_info->constructor == nullptr;
3294 int end_pos = block_scope->end_position();
3295 if (has_default_constructor) {
3296 class_info->constructor = DefaultConstructor(name, has_extends, pos);
3297 }
3298
3299 if (!IsEmptyIdentifier(name)) {
3300 DCHECK_NOT_NULL(block_scope->class_variable());
3301 block_scope->class_variable()->set_initializer_position(end_pos);
3302 }
3303
3304 FunctionLiteral* static_initializer = nullptr;
3305 if (class_info->has_static_elements()) {
3306 static_initializer = CreateStaticElementsInitializer(name, class_info);
3307 }
3308
3309 FunctionLiteral* instance_members_initializer_function = nullptr;
3310 if (class_info->has_instance_members()) {
3311 instance_members_initializer_function =
3312 CreateInstanceMembersInitializer(name, class_info);
3313 class_info->constructor->set_requires_instance_members_initializer(true);
3314 class_info->constructor->add_expected_properties(
3315 class_info->instance_fields->length());
3316 }
3317
3318 if (class_info->requires_brand) {
3319 class_info->constructor->set_class_scope_has_private_brand(true);
3320 }
3321 if (class_info->has_static_private_methods_or_accessors) {
3322 class_info->constructor->set_has_static_private_methods_or_accessors(true);
3323 }
3324 ClassLiteral* class_literal = factory()->NewClassLiteral(
3325 block_scope, class_info->extends, class_info->constructor,
3326 class_info->public_members, class_info->private_members,
3327 static_initializer, instance_members_initializer_function, pos, end_pos,
3328 class_info->has_static_computed_names, class_info->is_anonymous,
3329 class_info->home_object_variable,
3330 class_info->static_home_object_variable);
3331
3332 AddFunctionForNameInference(class_info->constructor);
3333 return class_literal;
3334}
3335
3337 // For each var-binding that shadows a parameter, insert an assignment
3338 // initializing the variable with the parameter.
3339 Scope* inner_scope = inner_block->scope();
3340 DCHECK(inner_scope->is_declaration_scope());
3341 Scope* function_scope = inner_scope->outer_scope();
3342 DCHECK(function_scope->is_function_scope());
3343 BlockState block_state(&scope_, inner_scope);
3344 // According to https://tc39.es/ecma262/#sec-functiondeclarationinstantiation
3345 // If a variable's name conflicts with the names of both parameters and
3346 // functions, no bindings should be created for it. A set is used here
3347 // to record such variables.
3348 std::set<Variable*> hoisted_func_vars;
3349 std::vector<std::pair<Variable*, Variable*>> var_param_bindings;
3350 for (Declaration* decl : *inner_scope->declarations()) {
3351 if (!decl->IsVariableDeclaration()) {
3352 hoisted_func_vars.insert(decl->var());
3353 continue;
3354 } else if (decl->var()->mode() != VariableMode::kVar) {
3355 continue;
3356 }
3357 const AstRawString* name = decl->var()->raw_name();
3358 Variable* parameter = function_scope->LookupLocal(name);
3359 if (parameter == nullptr) continue;
3360 var_param_bindings.push_back(std::pair(decl->var(), parameter));
3361 }
3362
3363 for (auto decl : var_param_bindings) {
3364 if (hoisted_func_vars.find(decl.first) != hoisted_func_vars.end()) {
3365 continue;
3366 }
3367 const AstRawString* name = decl.first->raw_name();
3368 VariableProxy* to = NewUnresolved(name);
3369 VariableProxy* from = factory()->NewVariableProxy(decl.second);
3370 Expression* assignment =
3371 factory()->NewAssignment(Token::kAssign, to, from, kNoSourcePosition);
3373 factory()->NewExpressionStatement(assignment, kNoSourcePosition);
3374 inner_block->statements()->InsertAt(0, statement, zone());
3375 }
3376}
3377
3379 // For the outermost eval scope, we cannot hoist during parsing: let
3380 // declarations in the surrounding scope may prevent hoisting, but the
3381 // information is unaccessible during parsing. In this case, we hoist later in
3382 // DeclarationScope::Analyze.
3383 if (scope->is_eval_scope() && scope->outer_scope() == original_scope_) {
3384 return;
3385 }
3386 scope->HoistSloppyBlockFunctions(factory());
3387}
3388
3389// ----------------------------------------------------------------------------
3390// Parser support
3391
3392template <typename IsolateT>
3393void Parser::HandleSourceURLComments(IsolateT* isolate,
3394 DirectHandle<Script> script) {
3395 DirectHandle<String> source_url = scanner_.SourceUrl(isolate);
3396 if (!source_url.is_null()) {
3397 script->set_source_url(*source_url);
3398 }
3399 DirectHandle<String> source_mapping_url = scanner_.SourceMappingUrl(isolate);
3400 // The API can provide a source map URL and the API should take precedence.
3401 // Let's make sure we do not override the API with the magic comment.
3402 if (!source_mapping_url.is_null() &&
3403 IsUndefined(script->source_mapping_url(isolate), isolate)) {
3404 script->set_source_mapping_url(*source_mapping_url);
3405 }
3406}
3407
3408template void Parser::HandleSourceURLComments(Isolate* isolate,
3409 DirectHandle<Script> script);
3410template void Parser::HandleSourceURLComments(LocalIsolate* isolate,
3411 DirectHandle<Script> script);
3412
3414 CHECK_NOT_NULL(isolate);
3415
3416 // Move statistics to Isolate.
3417 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
3418 ++feature) {
3419 if (use_counts_[feature] > 0) {
3420 isolate->CountUsage(v8::Isolate::UseCounterFeature(feature));
3421 }
3422 }
3423 if (scanner_.FoundHtmlComment()) {
3424 isolate->CountUsage(v8::Isolate::kHtmlComment);
3425 if (script->line_offset() == 0 && script->column_offset() == 0) {
3426 isolate->CountUsage(v8::Isolate::kHtmlCommentInExternalScript);
3427 }
3428 }
3430 isolate->CountUsage(v8::Isolate::kCompileHintsMagicAll);
3431 }
3434 }
3435}
3436
3438 DirectHandle<Script> script,
3440 int* preparse_skipped) {
3441 // Move statistics to Isolate.
3442 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
3443 ++feature) {
3444 if (use_counts_[feature] > 0) {
3445 use_counts->emplace_back(v8::Isolate::UseCounterFeature(feature));
3446 }
3447 }
3448 if (scanner_.FoundHtmlComment()) {
3450 if (script->line_offset() == 0 && script->column_offset() == 0) {
3452 }
3453 }
3456 }
3459 }
3460
3461 *preparse_skipped = total_preparse_skipped_;
3462}
3463
3465 DirectHandle<Script> script, int start_position,
3466 int end_position, int function_literal_id) {
3467 RCS_SCOPE(isolate, RuntimeCallCounterId::kParseProgram,
3468 RuntimeCallStats::CounterMode::kThreadSpecific);
3469 parsing_on_main_thread_ = false;
3470
3471 DCHECK_NULL(info->literal());
3472 FunctionLiteral* result = nullptr;
3473
3474 // We can park the isolate while parsing, it doesn't need to allocate or
3475 // access the main thread.
3476 isolate->ParkIfOnBackgroundAndExecute([this, start_position, end_position,
3477 function_literal_id, info, &result]() {
3479
3480 DCHECK(original_scope_);
3481
3482 // When streaming, we don't know the length of the source until we have
3483 // parsed it. The raw data can be UTF-8, so we wouldn't know the source
3484 // length until we have decoded it anyway even if we knew the raw data
3485 // length (which we don't). We work around this by storing all the scopes
3486 // which need their end position set at the end of the script (the top scope
3487 // and possible eval scopes) and set their end position after we know the
3488 // script length.
3489 if (flags().is_toplevel()) {
3490 DCHECK_EQ(start_position, 0);
3491 DCHECK_EQ(end_position, 0);
3492 DCHECK_EQ(function_literal_id, kFunctionLiteralIdTopLevel);
3493 result = DoParseProgram(/* isolate = */ nullptr, info);
3494 } else {
3495 std::optional<ClassScope::HeritageParsingScope> heritage;
3496 if (V8_UNLIKELY(flags().private_name_lookup_skips_outer_class() &&
3497 original_scope_->is_class_scope())) {
3498 // If the function skips the outer class and the outer scope is a class,
3499 // the function is in heritage position. Otherwise the function scope's
3500 // skip bit will be correctly inherited from the outer scope.
3501 heritage.emplace(original_scope_->AsClassScope());
3502 }
3503 result = DoParseFunction(/* isolate = */ nullptr, info, start_position,
3504 end_position, function_literal_id,
3505 info->function_name());
3506 }
3507 if (result == nullptr) return;
3508 MaybeProcessSourceRanges(info, result, stack_limit_);
3509 });
3510 // We need to unpark by now though, to be able to internalize.
3511 if (flags().is_toplevel()) {
3512 HandleSourceURLComments(isolate, script);
3513 }
3514 if (result == nullptr) return;
3515 PostProcessParseResult(isolate, info, result);
3516}
3517
3521
3522void Parser::AddTemplateSpan(TemplateLiteralState* state, bool should_cook,
3523 bool tail) {
3524 int end = scanner()->location().end_pos - (tail ? 1 : 2);
3525 const AstRawString* raw = scanner()->CurrentRawSymbol(ast_value_factory());
3526 if (should_cook) {
3527 const AstRawString* cooked = scanner()->CurrentSymbol(ast_value_factory());
3528 (*state)->AddTemplateSpan(cooked, raw, end, zone());
3529 } else {
3530 (*state)->AddTemplateSpan(nullptr, raw, end, zone());
3531 }
3532}
3533
3535 Expression* expression) {
3536 (*state)->AddExpression(expression, zone());
3537}
3538
3540 Expression* tag) {
3541 TemplateLiteral* lit = *state;
3542 int pos = lit->position();
3543 const ZonePtrList<const AstRawString>* cooked_strings = lit->cooked();
3544 const ZonePtrList<const AstRawString>* raw_strings = lit->raw();
3545 const ZonePtrList<Expression>* expressions = lit->expressions();
3546 DCHECK_EQ(cooked_strings->length(), raw_strings->length());
3547 DCHECK_EQ(cooked_strings->length(), expressions->length() + 1);
3548
3549 if (!tag) {
3550 if (cooked_strings->length() == 1) {
3551 return factory()->NewStringLiteral(cooked_strings->first(), pos);
3552 }
3553 return factory()->NewTemplateLiteral(cooked_strings, expressions, pos);
3554 } else {
3555 // GetTemplateObject
3556 Expression* template_object =
3557 factory()->NewGetTemplateObject(cooked_strings, raw_strings, pos);
3558
3559 // Call TagFn
3560 ScopedPtrList<Expression> call_args(pointer_buffer());
3561 call_args.Add(template_object);
3562 call_args.AddAll(expressions->ToConstVector());
3563 return factory()->NewTaggedTemplate(tag, call_args, pos);
3564 }
3565}
3566
3569 if (is_sloppy(mode))
3570 feature = v8::Isolate::kSloppyMode;
3571 else if (is_strict(mode))
3572 feature = v8::Isolate::kStrictMode;
3573 else
3574 UNREACHABLE();
3575 ++use_counts_[feature];
3576 scope->SetLanguageMode(mode);
3577}
3578
3579#if V8_ENABLE_WEBASSEMBLY
3580void Parser::SetAsmModule() {
3581 // Store the usage count; The actual use counter on the isolate is
3582 // incremented after parsing is done.
3584 DCHECK(scope()->is_declaration_scope());
3585 scope()->AsDeclarationScope()->set_is_asm_module();
3586 info_->set_contains_asm_module(true);
3587}
3588#endif // V8_ENABLE_WEBASSEMBLY
3589
3592 Expression* expr = args.at(0);
3593 if (args.length() == 1) return expr;
3594 if (args.length() == 2) {
3595 return factory()->NewBinaryOperation(Token::kComma, expr, args.at(1),
3596 args.at(1)->position());
3597 }
3599 factory()->NewNaryOperation(Token::kComma, expr, args.length() - 1);
3600 for (int i = 1; i < args.length(); i++) {
3601 result->AddSubsequent(args.at(i), args.at(i)->position());
3602 }
3603 return result;
3604}
3605
3607 const AstRawString* name,
3608 const AstRawString* prefix) {
3609 if (has_error()) return;
3610 // Ensure that the function we are going to create has shared name iff
3611 // we are not going to set it later.
3612 if (property->NeedsSetFunctionName()) {
3613 name = nullptr;
3614 prefix = nullptr;
3615 } else {
3616 // If the property value is an anonymous function or an anonymous class or
3617 // a concise method or an accessor function which doesn't require the name
3618 // to be set then the shared name must be provided.
3619 DCHECK_IMPLIES(property->value()->IsAnonymousFunctionDefinition() ||
3620 property->value()->IsConciseMethodDefinition() ||
3621 property->value()->IsAccessorFunctionDefinition(),
3622 name != nullptr);
3623 }
3624
3625 Expression* value = property->value();
3626 SetFunctionName(value, name, prefix);
3627}
3628
3630 const AstRawString* name,
3631 const AstRawString* prefix) {
3632 // Ignore "__proto__" as a name when it's being used to set the [[Prototype]]
3633 // of an object literal.
3634 // See ES #sec-__proto__-property-names-in-object-initializers.
3635 if (property->IsPrototype() || has_error()) return;
3636
3637 DCHECK(!property->value()->IsAnonymousFunctionDefinition() ||
3638 property->kind() == ObjectLiteralProperty::COMPUTED);
3639
3640 SetFunctionNameFromPropertyName(static_cast<LiteralProperty*>(property), name,
3641 prefix);
3642}
3643
3646 if (!identifier->IsVariableProxy()) return;
3647 // IsIdentifierRef of parenthesized expressions is false.
3648 if (identifier->is_parenthesized()) return;
3649 SetFunctionName(value, identifier->AsVariableProxy()->raw_name());
3650}
3651
3653 const AstRawString* prefix) {
3654 if (!value->IsAnonymousFunctionDefinition() &&
3655 !value->IsConciseMethodDefinition() &&
3656 !value->IsAccessorFunctionDefinition()) {
3657 return;
3658 }
3659 auto function = value->AsFunctionLiteral();
3660 if (value->IsClassLiteral()) {
3661 function = value->AsClassLiteral()->constructor();
3662 }
3663 if (function != nullptr) {
3664 AstConsString* cons_name = nullptr;
3665 if (name != nullptr) {
3666 if (prefix != nullptr) {
3667 cons_name = ast_value_factory()->NewConsString(prefix, name);
3668 } else {
3669 cons_name = ast_value_factory()->NewConsString(name);
3670 }
3671 } else {
3672 DCHECK_NULL(prefix);
3673 }
3674 function->set_raw_name(cons_name);
3675 }
3676}
3677
3678} // namespace v8::internal
int16_t parameter_count
Definition builtins.cc:67
Builtins::Kind kind
Definition builtins.cc:40
PropertyT * getter
SourcePosition pos
static bool HasUnpairedSurrogate(const uint16_t *code_units, size_t length)
Definition unicode-inl.h:64
@ kHtmlCommentInExternalScript
Definition v8-isolate.h:489
@ kSourceMappingUrlMagicCommentAtSign
Definition v8-isolate.h:598
@ kUseCounterFeatureCount
Definition v8-isolate.h:641
@ kSloppyModeBlockScopedFunctionRedefinition
Definition v8-isolate.h:491
@ kCompileHintsMagicAll
Definition v8-isolate.h:592
void emplace_back(Args &&... args)
Expression * target() const
Definition ast.h:2170
Expression * value() const
Definition ast.h:2171
int position() const
Definition ast.h:155
const unsigned char * raw_data() const
Token::Value op() const
Definition ast.h:1916
Expression * right() const
Definition ast.h:1918
Expression * left() const
Definition ast.h:1917
void set_scope(Scope *scope)
Definition ast.h:333
Scope * scope() const
Definition ast.h:332
ZonePtrList< Statement > * statements()
Definition ast.h:323
void ResetUnresolvedPrivateNameTail(UnresolvedList::Iterator tail)
Definition scopes.cc:2994
Variable * DeclareClassVariable(AstValueFactory *ast_value_factory, const AstRawString *name, int class_token_pos)
Definition scopes.cc:3193
void MigrateUnresolvedPrivateNameTail(AstNodeFactory *ast_node_factory, UnresolvedList::Iterator tail)
Definition scopes.cc:3010
Variable * class_variable()
Definition scopes.h:1453
Variable * DeclarePrivateName(const AstRawString *name, VariableMode mode, IsStaticFlag is_static_flag, bool *was_added)
Definition scopes.cc:2956
UnresolvedList::Iterator GetUnresolvedPrivateNameTail()
Definition scopes.cc:2986
static const int kMaxArguments
Definition code.h:463
size_t conditional_chain_length() const
Definition ast.h:2085
void set_else_expression(Expression *s)
Definition ast.h:2089
void AddChainEntry(Expression *cond, Expression *then, int pos)
Definition ast.h:2091
virtual ProducedPreparseData * GetDataForSkippableFunction(Zone *zone, int start_position, int *end_position, int *num_parameters, int *function_length, int *num_inner_functions, bool *uses_super_property, LanguageMode *language_mode)=0
void ResetAfterPreparsing(AstValueFactory *ast_value_factory, bool aborted)
Definition scopes.cc:1640
static V8_WARN_UNUSED_RESULT bool Analyze(ParseInfo *info)
Definition scopes.cc:687
void set_is_skipped_function(bool is_skipped_function)
Definition scopes.h:1187
FunctionKind function_kind() const
Definition scopes.h:863
void DeserializeReceiver(AstValueFactory *ast_value_factory)
Definition scopes.cc:1343
void HoistSloppyBlockFunctions(AstNodeFactory *factory)
Definition scopes.cc:581
void set_zone(Zone *zone)
Definition scopes.h:948
void AnalyzePartially(Parser *parser, AstNodeFactory *ast_node_factory, bool maybe_in_arrowhead)
Definition scopes.cc:1711
Variable * parameter(int index) const
Definition scopes.h:1058
void set_has_checked_syntax(bool has_checked_syntax)
Definition scopes.h:965
Variable * DeclareParameter(const AstRawString *name, VariableMode mode, bool is_optional, bool is_rest, AstValueFactory *ast_value_factory, int position)
Definition scopes.cc:1012
Variable * DeclareFunctionVar(const AstRawString *name, Scope *cache=nullptr)
Definition scopes.cc:813
bool has_simple_parameters() const
Definition scopes.h:1076
V8_INLINE bool is_null() const
Definition handles.h:693
void clear_parenthesized()
Definition ast.h:280
void Initialize(Statement *init, Expression *cond, Statement *next, Statement *body)
Definition ast.h:506
FunctionKind kind() const
Definition ast.cc:231
int function_literal_id() const
Definition ast.h:2408
void set_suspend_count(int suspend_count)
Definition ast.h:2400
DeclarationScope * scope() const
Definition ast.h:2315
void set_function_token_position(int pos)
Definition ast.h:2317
V8_WARN_UNUSED_RESULT V8_INLINE bool ToHandle(DirectHandle< S > *out) const
Expression * subsequent(size_t index) const
Definition ast.h:1944
int subsequent_op_position(size_t index) const
Definition ast.h:1949
void AddSubsequent(Expression *expr, int pos)
Definition ast.h:1953
Token::Value op() const
Definition ast.h:1942
size_t subsequent_length() const
Definition ast.h:1948
Expression * first() const
Definition ast.h:1943
const Scanner::Location & duplicate_location() const
LazyCompileDispatcher * dispatcher() const
Definition parse-info.h:262
const UnoptimizedCompileFlags & flags() const
Definition parse-info.h:249
SourceRangeMap * source_range_map() const
Definition parse-info.h:337
const ZonePtrList< Expression > * expressions() const
Definition parser.h:494
const ZonePtrList< const AstRawString > * raw() const
Definition parser.h:493
const ZonePtrList< const AstRawString > * cooked() const
Definition parser.h:492
void SetLanguageMode(Scope *scope, LanguageMode mode)
Definition parser.cc:3567
void Declare(Declaration *declaration, const AstRawString *name, VariableKind kind, VariableMode mode, InitializationFlag init, Scope *declaration_scope, bool *was_added, int var_begin_pos, int var_end_pos=kNoSourcePosition)
Definition parser.cc:1935
bool CollapseNaryExpression(Expression **x, Expression *y, Token::Value op, int pos, const SourceRange &range)
Definition parser.cc:356
Parser(LocalIsolate *local_isolate, ParseInfo *info)
Definition parser.cc:569
bool AllowsLazyParsingWithoutUnresolvedVariables() const
Definition parser.h:190
V8_INLINE void AddFunctionForNameInference(FunctionLiteral *func_to_infer)
Definition parser.h:670
void DeclarePublicClassField(ClassScope *scope, ClassLiteralProperty *property, bool is_static, bool is_computed_name, ClassInfo *class_info)
Definition parser.cc:3164
void ParseGeneratorFunctionBody(int pos, FunctionKind kind, ScopedPtrList< Statement > *body)
Definition parser.cc:2156
Statement * RewriteSwitchStatement(SwitchStatement *switch_statement, Scope *scope)
Definition parser.cc:2039
Statement * DeclareNative(const AstRawString *name, int pos)
Definition parser.cc:2015
void UpdateStatistics(Isolate *isolate, DirectHandle< Script > script)
Definition parser.cc:3413
void InsertSloppyBlockFunctionVarBindings(DeclarationScope *scope)
Definition parser.cc:3378
Expression * NewV8Intrinsic(const AstRawString *name, const ScopedPtrList< Expression > &args, int pos)
Definition parser.cc:504
ParseInfo * info() const
Definition parser.h:1102
int use_counts_[v8::Isolate::kUseCounterFeatureCount]
Definition parser.h:1132
Block * RewriteForVarInLegacy(const ForInfo &for_info)
Definition parser.cc:2201
void ParseModuleItemList(ScopedPtrList< Statement > *body)
Definition parser.cc:1288
const AstRawString * GetBigIntAsSymbol()
Definition parser.cc:390
void DeclareFunctionNameVar(const AstRawString *function_name, FunctionSyntaxKind function_syntax_kind, DeclarationScope *function_scope)
Definition parser.cc:2175
Statement * ParseExportDeclaration()
Definition parser.cc:1761
ZonePtrList< const NamedImport > * ParseNamedImports(int pos)
Definition parser.cc:1402
void DeserializeScopeChain(IsolateT *isolate, ParseInfo *info, MaybeDirectHandle< ScopeInfo > maybe_outer_scope_info, Scope::DeserializationMode mode=Scope::DeserializationMode::kScopesOnly)
Definition parser.cc:624
bool SkipFunction(const AstRawString *function_name, FunctionKind kind, FunctionSyntaxKind function_syntax_kind, DeclarationScope *function_scope, int *num_parameters, int *function_length, ProducedPreparseData **produced_preparsed_scope_data)
Definition parser.cc:2870
FunctionLiteral * DefaultConstructor(const AstRawString *name, bool call_super, int pos)
Definition parser.cc:40
void InitializeEmptyScopeChain(ParseInfo *info)
Definition parser.cc:614
void ParseImportDeclaration()
Definition parser.cc:1510
void AppendConditionalChainElse(Expression **x, const SourceRange &else_range)
Definition parser.cc:348
void AddTemplateSpan(TemplateLiteralState *state, bool should_cook, bool tail)
Definition parser.cc:3522
Expression * NewTargetExpression(int pos)
Definition parser.cc:458
void ParseAsyncGeneratorFunctionBody(int pos, FunctionKind kind, ScopedPtrList< Statement > *body)
Definition parser.cc:2165
V8_INLINE void RecordTryFinallyStatementSourceRange(TryFinallyStatement *node, const SourceRange &body_range)
Definition parser.h:1079
AutoAccessorInfo * NewAutoAccessorInfo(ClassScope *scope, ClassInfo *class_info, const AstRawString *name, bool is_static, int pos)
Definition parser.cc:145
V8_WARN_UNUSED_RESULT Variable * DeclareVariable(const AstRawString *name, VariableKind kind, VariableMode mode, InitializationFlag init, Scope *declaration_scope, bool *was_added, int begin, int end=kNoSourcePosition)
Definition parser.cc:1920
Statement * ParseExportDefault()
Definition parser.cc:1640
Expression * RewriteClassLiteral(ClassScope *block_scope, const AstRawString *name, ClassInfo *class_info, int pos)
Definition parser.cc:3285
Expression * WrapREPLResult(Expression *value)
Definition parser.cc:948
V8_INLINE VariableProxy * ExpressionFromPrivateName(PrivateNameScopeIterator *private_name_scope, const AstRawString *name, int start_position)
Definition parser.h:817
void InsertShadowingVarBindingInitializers(Block *block)
Definition parser.cc:3336
V8_INLINE bool IsEmptyIdentifier(const AstRawString *subject) const
Definition parser.h:771
void AddClassStaticBlock(Block *block, ClassInfo *class_info)
Definition parser.cc:3233
Expression * NewThrowError(Runtime::FunctionId function_id, MessageTemplate message, const AstRawString *arg, int pos)
Definition parser.cc:426
V8_INLINE const AstRawString * GetSymbol() const
Definition parser.h:777
Statement * RewriteTryStatement(Block *try_block, Block *catch_block, const SourceRange &catch_range, Block *finally_block, const SourceRange &finally_range, const CatchInfo &catch_info, int pos)
Definition parser.cc:2119
TemplateLiteralState OpenTemplateLiteral(int pos)
Definition parser.cc:3518
void DeclarePublicClassMethod(const AstRawString *class_name, ClassLiteralProperty *property, bool is_constructor, ClassInfo *class_info)
Definition parser.cc:3216
void InitializeVariables(ScopedPtrList< Statement > *statements, VariableKind kind, const DeclarationParsingResult::Declaration *declaration)
Definition parser.cc:2077
ImportAttributes * ParseImportWithOrAssertClause()
Definition parser.cc:1455
V8_WARN_UNUSED_RESULT VariableProxy * DeclareBoundVariable(const AstRawString *name, VariableMode mode, int pos)
Definition parser.cc:1897
void DesugarBindingInForEachStatement(ForInfo *for_info, Block **body_block, Expression **each_variable)
Definition parser.cc:2235
FunctionLiteral * DoParseFunction(Isolate *isolate, ParseInfo *info, int start_position, int end_position, int function_literal_id, const AstRawString *raw_name)
Definition parser.cc:1050
Expression * CloseTemplateLiteral(TemplateLiteralState *state, int start, Expression *tag)
Definition parser.cc:3539
FunctionLiteral * MakeAutoAccessorGetter(VariableProxy *name_proxy, const AstRawString *name, bool is_static, int pos)
Definition parser.cc:88
LocalIsolate * local_isolate_
Definition parser.h:1112
V8_INLINE v8::Extension * extension() const
Definition parser.h:614
Variable * NewTemporary(const AstRawString *name)
Definition parser.h:219
Statement * DeclareClass(const AstRawString *variable_name, Expression *value, ZonePtrList< const AstRawString > *names, int class_token_pos, int end_pos)
Definition parser.cc:2000
void HandleSourceURLComments(IsolateT *isolate, DirectHandle< Script > script)
Definition parser.cc:3393
MaybeHandle< FixedArray > maybe_wrapped_arguments_
Definition parser.h:1119
Statement * BuildInitializationBlock(DeclarationParsingResult *parsing_result)
Definition parser.cc:1962
VariableProxy * CreatePrivateNameVariable(ClassScope *scope, VariableMode mode, IsStaticFlag is_static_flag, const AstRawString *name)
Definition parser.cc:3135
friend bool v8::internal::parsing::ParseFunction(ParseInfo *, DirectHandle< SharedFunctionInfo > shared_info, Isolate *, parsing::ReportStatisticsMode stats_mode)
void ReindexComputedMemberName(Expression *computed_name)
Definition parser.cc:2627
ConsumedPreparseData * consumed_preparse_data_
Definition parser.h:1136
void DeclareClassVariable(ClassScope *scope, const AstRawString *name, ClassInfo *class_info, int class_token_pos)
Definition parser.cc:3103
Block * RewriteCatchPattern(CatchInfo *catch_info)
Definition parser.cc:2093
FunctionLiteral * CreateInitializerFunction(const AstRawString *class_name, DeclarationScope *scope, int function_literal_id, Statement *initializer_stmt)
Definition parser.cc:3239
const AstRawString * NextInternalNamespaceExportName()
Definition parser.cc:1706
ZonePtrList< const AstRawString > * PrepareWrappedArguments(Isolate *isolate, ParseInfo *info, Zone *zone)
Definition parser.cc:858
VariableProxy * CreateSyntheticContextVariableProxy(ClassScope *scope, ClassInfo *class_info, const AstRawString *name, bool is_static)
Definition parser.cc:3119
V8_INLINE void AppendConditionalChainElseSourceRange(ConditionalChain *node, const SourceRange &range)
Definition parser.h:983
V8_INLINE void AppendNaryOperationSourceRange(NaryOperation *node, const SourceRange &range)
Definition parser.h:941
void DeclareUnboundVariable(const AstRawString *name, VariableMode mode, InitializationFlag init, int pos)
Definition parser.cc:1887
void AddInstanceFieldOrStaticElement(ClassLiteralProperty *property, ClassInfo *class_info, bool is_static)
Definition parser.cc:3153
friend bool v8::internal::parsing::ParseProgram(ParseInfo *, DirectHandle< Script >, MaybeDirectHandle< ScopeInfo > maybe_outer_scope_info, Isolate *, parsing::ReportStatisticsMode stats_mode)
ClassLiteralProperty * NewClassLiteralPropertyWithAccessorInfo(ClassScope *scope, ClassInfo *class_info, const AstRawString *name, Expression *key, Expression *value, bool is_static, bool is_computed_name, bool is_private, int pos)
Definition parser.cc:166
const AstRawString * ParseExportSpecifierName()
Definition parser.cc:1377
Statement * DesugarLexicalBindingsInForStatement(ForStatement *loop, Statement *init, Expression *cond, Statement *next, Statement *body, Scope *inner_scope, const ForInfo &for_info)
Definition parser.cc:2274
const AstRawString * ParseModuleSpecifier()
Definition parser.cc:1306
V8_INLINE void DeclareFormalParameters(ParserFormalParameters *parameters)
Definition parser.h:880
Expression * FailureExpression()
Definition parser.h:756
V8_INLINE bool ParsingExtension() const
Definition parser.h:616
Block * BuildParameterInitializationBlock(const ParserFormalParameters &parameters)
Definition parser.cc:2977
V8_INLINE VariableProxy * ExpressionFromIdentifier(const AstRawString *name, int start_position, InferName infer=InferName::kYes)
Definition parser.h:826
V8_INLINE const AstRawString * GetIdentifier() const
Definition parser.h:783
Expression * NewV8RuntimeFunctionForFuzzing(const Runtime::Function *function, const ScopedPtrList< Expression > &args, int pos)
Definition parser.cc:542
FunctionLiteral * MakeAutoAccessorSetter(VariableProxy *name_proxy, const AstRawString *name, bool is_static, int pos)
Definition parser.cc:115
void ParseWrapped(Isolate *isolate, ParseInfo *info, ScopedPtrList< Statement > *body, DeclarationScope *scope, Zone *zone)
Definition parser.cc:876
Expression * ExpressionListToExpression(const ScopedPtrList< Expression > &args)
Definition parser.cc:3590
V8_INLINE void AppendConditionalChainSourceRange(ConditionalChain *node, const SourceRange &range)
Definition parser.h:966
V8_INLINE void AddFormalParameter(ParserFormalParameters *parameters, Expression *pattern, Expression *initializer, int initializer_end_position, bool is_rest)
Definition parser.h:866
FunctionLiteral * ParseClassForMemberInitialization(FunctionKind initializer_kind, int initializer_pos, int initializer_id, int initializer_end_pos, const AstRawString *class_name)
Definition parser.cc:1176
void ReportUnexpectedTokenAt(Scanner::Location location, Token::Value token, MessageTemplate message=MessageTemplate::kUnexpectedToken)
Definition parser.cc:176
void ReindexArrowFunctionFormalParameters(ParserFormalParameters *parameters)
Definition parser.cc:2611
void PrepareGeneratorVariables()
Definition parser.cc:2634
Expression * ImportMetaExpression(int pos)
Definition parser.cc:464
static V8_INLINE std::nullptr_t NullExpression()
Definition parser.h:746
void SetFunctionNameFromPropertyName(LiteralProperty *property, const AstRawString *name, const AstRawString *prefix=nullptr)
Definition parser.cc:3606
ZoneChunkList< ExportClauseData > * ParseExportClause(Scanner::Location *reserved_loc, Scanner::Location *string_literal_local_name_loc)
Definition parser.cc:1314
Expression * BuildInitialYield(int pos, FunctionKind kind)
Definition parser.cc:3009
FunctionLiteral * DoParseProgram(Isolate *isolate, ParseInfo *info)
Definition parser.cc:714
V8_INLINE const AstRawString * EmptyIdentifierString() const
Definition parser.h:768
bool ShortcutLiteralBinaryExpression(Expression **x, Expression *y, Token::Value op, int pos)
Definition parser.cc:243
void DeclarePrivateClassMember(ClassScope *scope, const AstRawString *property_name, ClassLiteralProperty *property, ClassLiteralProperty::Kind kind, bool is_static, ClassInfo *class_info)
Definition parser.cc:3182
void SetFunctionNameFromIdentifierRef(Expression *value, Expression *identifier)
Definition parser.cc:3644
void ParseOnBackground(LocalIsolate *isolate, ParseInfo *info, DirectHandle< Script > script, int start_position, int end_position, int function_literal_id)
Definition parser.cc:3464
Statement * DeclareFunction(const AstRawString *variable_name, FunctionLiteral *function, VariableMode mode, VariableKind kind, int beg_pos, int end_pos, ZonePtrList< const AstRawString > *names)
Definition parser.cc:1973
void ParseREPLProgram(ParseInfo *info, ScopedPtrList< Statement > *body, DeclarationScope *scope)
Definition parser.cc:904
FunctionLiteral * ParseFunctionLiteral(const AstRawString *name, Scanner::Location function_name_location, FunctionNameValidity function_name_validity, FunctionKind kind, int function_token_position, FunctionSyntaxKind type, LanguageMode language_mode, ZonePtrList< const AstRawString > *arguments_for_wrapped_function)
Definition parser.cc:2642
V8_INLINE void RecordFunctionLiteralSourceRange(FunctionLiteral *node)
Definition parser.h:1002
SuperCallReference * NewSuperCallReference(int pos)
Definition parser.cc:449
V8_INLINE bool IsEvalOrArguments(const AstRawString *identifier) const
Definition parser.h:566
bool CollapseConditionalChain(Expression **x, Expression *cond, Expression *then_expression, Expression *else_expression, int pos, const SourceRange &then_range)
Definition parser.cc:329
Block * CreateForEachStatementTDZ(Block *init_block, const ForInfo &for_info)
Definition parser.cc:2255
void AddArrowFunctionFormalParameters(ParserFormalParameters *parameters, Expression *params, int end_pos)
Definition parser.cc:2522
Expression * BuildUnaryExpression(Expression *expression, Token::Value op, int pos)
Definition parser.cc:400
void AddTemplateExpression(TemplateLiteralState *state, Expression *expression)
Definition parser.cc:3534
bool parse_lazily() const
Definition parser.h:196
FunctionLiteral * CreateStaticElementsInitializer(const AstRawString *name, ClassInfo *class_info)
Definition parser.cc:3260
V8_INLINE void RecordTryCatchStatementSourceRange(TryCatchStatement *node, const SourceRange &body_range)
Definition parser.h:1072
Statement * ParseModuleItem()
Definition parser.cc:1262
void DeclareArrowFunctionFormalParameters(ParserFormalParameters *parameters, Expression *params, const Scanner::Location &params_loc)
Definition parser.cc:2594
V8_INLINE FunctionLiteral::EagerCompileHint GetEmbedderCompileHint(FunctionLiteral::EagerCompileHint current_compile_hint, int position)
Definition parser.h:1086
Block * IgnoreCompletion(Statement *statement)
Definition parser.cc:2033
Expression * ExpressionFromLiteral(Token::Value token, int pos)
Definition parser.cc:476
int number_of_named_namespace_exports_
Definition parser.h:1128
PreParser * reusable_preparser()
Definition parser.h:265
void DeclareAndBindVariable(VariableProxy *proxy, VariableKind kind, VariableMode mode, Scope *declaration_scope, bool *was_added, int initializer_position)
Definition parser.cc:1910
FunctionLiteral * CreateInstanceMembersInitializer(const AstRawString *name, ClassInfo *class_info)
Definition parser.cc:3269
Expression * NewSuperPropertyReference(int pos)
Definition parser.cc:436
void PostProcessParseResult(IsolateT *isolate, ParseInfo *info, FunctionLiteral *literal)
Definition parser.cc:823
ParseInfo * info_
Definition parser.h:1113
void SetFunctionName(Expression *value, const AstRawString *name, const AstRawString *prefix=nullptr)
Definition parser.cc:3652
void ReportVarRedeclarationIn(const AstRawString *name, Scope *scope)
Definition parser.cc:2104
V8_INLINE void ConvertBinaryToNaryOperationSourceRange(BinaryOperation *binary_op, NaryOperation *nary_op)
Definition parser.h:926
PreParserLogger * logger()
Definition preparser.h:891
PreParseResult PreParseFunction(const AstRawString *function_name, FunctionKind kind, FunctionSyntaxKind function_syntax_kind, DeclarationScope *function_scope, int *use_counts, ProducedPreparseData **produced_preparser_scope_data)
Definition preparser.cc:101
static V8_EXPORT_PRIVATE bool Rewrite(ParseInfo *info, bool *out_has_stack_overflow)
Definition rewriter.cc:386
static std::optional< VariableProxy * > RewriteBody(ParseInfo *info, Scope *scope, ZonePtrList< Statement > *body, bool *out_has_stack_overflow)
Definition rewriter.cc:406
static bool IsEnabledForFuzzing(FunctionId id)
Definition runtime.cc:197
static const Function * FunctionForName(const unsigned char *name, int length)
Definition runtime.cc:326
void Set(size_t bookmark)
Definition scanner.cc:69
bool FoundHtmlComment() const
Definition scanner.h:443
bool SawMagicCommentCompileHintsAll() const
Definition scanner.h:437
bool SawSourceMappingUrlMagicCommentAtSign() const
Definition scanner.h:433
DirectHandle< String > SourceMappingUrl(IsolateT *isolate) const
Definition scanner.cc:701
DirectHandle< String > SourceUrl(IsolateT *isolate) const
Definition scanner.cc:689
void SetLanguageMode(LanguageMode language_mode)
Definition scopes.h:288
void set_end_position(int statement_pos)
Definition scopes.h:343
base::ThreadedList< Declaration > * declarations()
Definition scopes.h:229
bool is_reparsed() const
Definition scopes.h:116
Scope * outer_scope() const
Definition scopes.h:488
DeclarationScope * AsDeclarationScope()
static Scope * DeserializeScopeChain(IsolateT *isolate, Zone *zone, Tagged< ScopeInfo > scope_info, DeclarationScope *script_scope, AstValueFactory *ast_value_factory, DeserializationMode deserialization_mode, ParseInfo *info=nullptr)
Definition scopes.cc:416
VariableProxy * NewUnresolved(AstNodeFactory *factory, const AstRawString *name, int start_pos, VariableKind kind=NORMAL_VARIABLE)
Definition scopes.h:234
DeclarationScope * GetReceiverScope()
Definition scopes.cc:1501
bool is_eval_scope() const
Definition scopes.h:361
bool is_function_scope() const
Definition scopes.h:362
void SetMustUsePreparseData()
Definition scopes.h:181
ScopeType scope_type() const
Definition scopes.h:474
DeclarationScope * GetClosureScope()
Definition scopes.cc:1480
void set_is_wrapped_function()
Definition scopes.h:401
bool is_with_scope() const
Definition scopes.h:371
void set_start_position(int statement_pos)
Definition scopes.h:339
Variable * DeclareVariable(Declaration *declaration, const AstRawString *name, int pos, VariableMode mode, VariableKind kind, InitializationFlag init, bool *was_added, bool *sloppy_mode_block_scope_function_redefinition, bool *ok)
Definition scopes.cc:1091
bool is_block_scope() const
Definition scopes.h:368
int end_position() const
Definition scopes.h:342
DeclarationScope * GetDeclarationScope()
Definition scopes.cc:1456
LanguageMode language_mode() const
Definition scopes.h:477
bool HasReceiverToDeserialize() const
Definition scopes.cc:1381
int start_position() const
Definition scopes.h:338
bool is_declaration_scope() const
Definition scopes.h:372
Variable * LookupLocal(const AstRawString *name)
Definition scopes.h:200
void AddAll(base::Vector< const T > list)
Definition scoped-list.h:84
void Add(const T &value)
Definition scoped-list.h:78
const T & at(int i) const
Definition scoped-list.h:59
void AddExport(const AstRawString *local_name, const AstRawString *export_name, const Scanner::Location loc, Zone *zone)
Definition modules.cc:90
void set_tag(Expression *t)
Definition ast.h:736
Expression * tag() const
Definition ast.h:735
static ThreadId Current()
Definition thread-id.h:32
static V8_INLINE bool IsValidIdentifier(Value token, LanguageMode language_mode, bool is_generator, bool disallow_await)
Definition token.h:237
static bool IsBinaryOp(Value op)
Definition token.h:295
static const char * String(Value token)
Definition token.h:328
static bool IsPropertyName(Value token)
Definition token.h:233
void BindTo(Variable *var)
Definition ast.cc:173
Variable * var() const
Definition ast.h:1517
const AstRawString * raw_name() const
Definition ast.h:1513
void set_initializer_position(int pos)
Definition variables.h:122
const AstRawString * raw_name() const
Definition variables.h:65
void ForceContextAllocation()
Definition variables.h:81
void push_back(const T &item)
V8_INLINE int length() const
Definition zone-list.h:101
base::Vector< const T > ToConstVector() const
Definition zone-list.h:110
void Add(const T &element, Zone *zone)
T * New(Args &&... args)
Definition zone.h:114
RecordWriteMode const mode_
int start
int end
DeclarationScope * scope_
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
RpoNumber block
ZoneVector< RpoNumber > & result
LiftoffAssembler::CacheState state
int x
FunctionLiteral * literal
Definition liveedit.cc:294
int position
Definition liveedit.cc:290
#define LOG(isolate, Call)
Definition log.h:78
LocalIsolate * local_isolate_
int s
Definition mul-fft.cc:297
signed_type ShlWithWraparound(signed_type a, signed_type b)
T Divide(T x, T y)
double pow(double x, double y)
Definition ieee754.cc:14
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
uint32_t DoubleToUint32(double x)
@ kNeedsInitialization
Definition globals.h:2225
@ kCreatedInitialized
Definition globals.h:2225
bool IsArrowFunction(FunctionKind kind)
bool is_sloppy(LanguageMode language_mode)
Definition globals.h:773
constexpr int kNoSourcePosition
Definition globals.h:850
bool IsLexicalVariableMode(VariableMode mode)
Definition globals.h:2155
double Modulo(double x, double y)
Definition utils.h:105
bool IsDerivedConstructor(FunctionKind kind)
bool IsConciseMethod(FunctionKind kind)
bool IsAsyncFunction(FunctionKind kind)
bool IsAccessorFunction(FunctionKind kind)
bool IsStatic(FunctionKind kind)
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in name
Definition flags.cc:2086
Flag flags[]
Definition flags.cc:3797
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in allocation gc speed threshold for starting incremental marking via a task in percent of available threshold for starting incremental marking immediately in percent of available Use a single schedule for determining a marking schedule between JS and C objects schedules the minor GC task with kUserVisible priority max worker number of concurrent for NumberOfWorkerThreads start background threads that allocate memory concurrent_array_buffer_sweeping use parallel threads to clear weak refs in the atomic pause trace progress of the incremental marking trace object counts and memory usage report a tick only when allocated zone memory changes by this amount TracingFlags::gc_stats TracingFlags::gc_stats track native contexts that are expected to be garbage collected verify heap pointers before and after GC memory reducer runs GC with ReduceMemoryFootprint flag Maximum number of memory reducer GCs scheduled Old gen GC speed is computed directly from gc tracer counters Perform compaction on full GCs based on V8 s default heuristics Perform compaction on every full GC Perform code space compaction when finalizing a full GC with stack Stress GC compaction to flush out bugs with moving objects flush of baseline code when it has not been executed recently Use time base code flushing instead of age Use a progress bar to scan large objects in increments when incremental marking is active force incremental marking for small heaps and run it more often force marking at random points between and force scavenge at random points between and reclaim otherwise unreachable unmodified wrapper objects when possible less compaction in non memory reducing mode use high priority threads for concurrent Marking Test mode only flag It allows an unit test to select evacuation candidates use incremental marking for CppHeap cppheap_concurrent_marking c value for membalancer A special constant to balance between memory and space tradeoff The smaller the more memory it uses enable use of SSE4 instructions if available enable use of AVX VNNI instructions if available enable use of POPCNT instruction if available force all emitted branches to be in long mode(MIPS/PPC only)") DEFINE_BOOL(partial_constant_pool
@ SLOPPY_BLOCK_FUNCTION_VARIABLE
Definition globals.h:2112
@ PARAMETER_VARIABLE
Definition globals.h:2110
@ ONLY_SINGLE_FUNCTION_LITERAL
Definition globals.h:1655
bool IsAsyncGeneratorFunction(FunctionKind kind)
SharedFunctionInfo::HasStaticPrivateMethodsOrAccessorsBit SharedFunctionInfo::MaglevCompilationFailedBit SharedFunctionInfo::FunctionSyntaxKindBits has_duplicate_parameters
constexpr int kFunctionLiteralIdTopLevel
Definition globals.h:2767
static T ArithmeticShiftRight(T x, int shift)
Definition utils.h:60
int32_t DoubleToInt32(double x)
bool is_strict(LanguageMode language_mode)
Definition globals.h:777
V8_EXPORT_PRIVATE FlagValues v8_flags
bool IsClassMembersInitializerFunction(FunctionKind kind)
@ kSkipFunctionNameCheck
Definition parser-base.h:40
SharedFunctionInfo::HasStaticPrivateMethodsOrAccessorsBit SharedFunctionInfo::MaglevCompilationFailedBit SharedFunctionInfo::FunctionSyntaxKindBits SharedFunctionInfo::HasDuplicateParametersBit requires_instance_members_initializer
bool IsImmutableLexicalOrPrivateVariableMode(VariableMode mode)
Definition globals.h:2150
bool IsDefaultConstructor(FunctionKind kind)
std::unique_ptr< char[]> BigIntLiteralToDecimal(LocalIsolate *isolate, base::Vector< const uint8_t > literal)
kInterpreterTrampolineOffset script
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
ModuleImportPhase
OptimizedCompilationInfo * info_
Definition pipeline.cc:305
uint32_t compare
const uintptr_t stack_limit_
#define RCS_SCOPE(...)
#define DCHECK_NULL(val)
Definition logging.h:491
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define CHECK_NOT_NULL(val)
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define DCHECK_GT(v1, v2)
Definition logging.h:487
#define USE(...)
Definition macros.h:293
void ValidateStrictMode(Parser *parser) const
Definition parser.cc:2516
base::ThreadedList< Parameter > params
Definition parser.h:92
MessageTemplate strict_error_message
Definition parser.h:95
Scanner::Location strict_error_loc
Definition parser.h:94
Scanner::Location duplicate_loc
Definition parser.h:93
void ValidateDuplicate(Parser *parser) const
Definition parser.cc:2511
static Location invalid()
Definition scanner.h:270
Symbol identifier
Symbol declaration
Symbol * expression
Symbol statement
#define TRACE_EVENT0(category_group, name)
#define TRACE_DISABLED_BY_DEFAULT(name)
#define V8_LIKELY(condition)
Definition v8config.h:661
#define V8_UNLIKELY(condition)
Definition v8config.h:660