Bug Summary

File:out/../deps/v8/src/parsing/parser.cc
Warning:line 1056, column 5
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

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