Line data Source code
1 : // Copyright 2018 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 : #ifndef V8_PARSING_EXPRESSION_SCOPE_H_
6 : #define V8_PARSING_EXPRESSION_SCOPE_H_
7 :
8 : #include "src/ast/scopes.h"
9 : #include "src/function-kind.h"
10 : #include "src/message-template.h"
11 : #include "src/parsing/scanner.h"
12 : #include "src/zone/zone.h" // For ScopedPtrList.
13 :
14 : namespace v8 {
15 : namespace internal {
16 :
17 : template <typename Types>
18 : class ExpressionParsingScope;
19 : template <typename Types>
20 : class AccumulationScope;
21 : template <typename Types>
22 : class ArrowHeadParsingScope;
23 : template <typename Types>
24 : class ParameterDeclarationParsingScope;
25 : template <typename Types>
26 : class VariableDeclarationParsingScope;
27 : class VariableProxy;
28 :
29 : // ExpressionScope is used in a stack fashion, and is used to specialize
30 : // expression parsing for the task at hand. It allows the parser to reuse the
31 : // same code to parse destructuring declarations, assignment patterns,
32 : // expressions, and (async) arrow function heads.
33 : //
34 : // One of the specific subclasses needs to be instantiated to tell the parser
35 : // the meaning of the expression it will parse next. The parser then calls
36 : // Record* on the expression_scope() to indicate errors. The expression_scope
37 : // will either discard those errors, immediately report those errors, or
38 : // classify the errors for later validation.
39 : // TODO(verwaest): Record is a slightly odd name since it will directly throw
40 : // for unambiguous scopes.
41 : template <typename Types>
42 : class ExpressionScope {
43 : public:
44 : using ParserT = typename Types::Impl;
45 : using ExpressionT = typename Types::Expression;
46 :
47 71779987 : VariableProxy* NewVariable(const AstRawString* name,
48 : int pos = kNoSourcePosition) {
49 71779987 : VariableProxy* result = parser_->NewRawVariable(name, pos);
50 71783960 : if (CanBeExpression()) {
51 50435311 : AsExpressionParsingScope()->TrackVariable(result);
52 : } else {
53 21348649 : Variable* var = Declare(name, pos);
54 32268621 : if (IsVarDeclaration() && !parser()->scope()->is_declaration_scope()) {
55 : // Make sure we'll properly resolve the variable since we might be in a
56 : // with or catch scope. In those cases the proxy isn't guaranteed to
57 : // refer to the declared variable, so consider it unresolved.
58 938739 : parser()->scope()->AddUnresolved(result);
59 : } else {
60 : DCHECK_NOT_NULL(var);
61 20409955 : result->BindTo(var);
62 : }
63 : }
64 71783034 : return result;
65 : }
66 :
67 23589873 : Variable* Declare(const AstRawString* name, int pos = kNoSourcePosition) {
68 23589873 : if (type_ == kParameterDeclaration) {
69 7918261 : return AsParameterDeclarationParsingScope()->Declare(name, pos);
70 : }
71 15671612 : return AsVariableDeclarationParsingScope()->Declare(name, pos);
72 : }
73 :
74 : void MarkIdentifierAsAssigned() {
75 4298288 : if (!CanBeExpression()) return;
76 4242850 : AsExpressionParsingScope()->MarkIdentifierAsAssigned();
77 : }
78 :
79 : void ValidateAsPattern(ExpressionT expression, int begin, int end) {
80 189862 : if (!CanBeExpression()) return;
81 188594 : AsExpressionParsingScope()->ValidatePattern(expression, begin, end);
82 : AsExpressionParsingScope()->ClearExpressionError();
83 : }
84 :
85 : // Record async arrow parameters errors in all ambiguous async arrow scopes in
86 : // the chain up to the first unambiguous scope.
87 : void RecordAsyncArrowParametersError(const Scanner::Location& loc,
88 : MessageTemplate message) {
89 : // Only ambiguous scopes (ExpressionParsingScope, *ArrowHeadParsingScope)
90 : // need to propagate errors to a possible kAsyncArrowHeadParsingScope, so
91 : // immediately return if the current scope is not ambiguous.
92 22968 : if (!CanBeExpression()) return;
93 : AsExpressionParsingScope()->RecordAsyncArrowParametersError(loc, message);
94 : }
95 :
96 : // Record initializer errors in all scopes that can turn into parameter scopes
97 : // (ArrowHeadParsingScopes) up to the first known unambiguous parameter scope.
98 97560 : void RecordParameterInitializerError(const Scanner::Location& loc,
99 : MessageTemplate message) {
100 : ExpressionScope* scope = this;
101 140580 : while (!scope->IsCertainlyParameterDeclaration()) {
102 132828 : if (!has_possible_parameter_in_scope_chain_) return;
103 56677 : if (scope->CanBeParameterDeclaration()) {
104 : scope->AsArrowHeadParsingScope()->RecordDeclarationError(loc, message);
105 : }
106 : scope = scope->parent();
107 56677 : if (scope == nullptr) return;
108 : }
109 : Report(loc, message);
110 : }
111 :
112 2462019 : void RecordThisUse() {
113 : ExpressionScope* scope = this;
114 5793782 : do {
115 5793782 : if (scope->IsArrowHeadParsingScope()) {
116 : scope->AsArrowHeadParsingScope()->RecordThisUse();
117 : }
118 : scope = scope->parent();
119 : } while (scope != nullptr);
120 2462019 : }
121 :
122 9825727 : void RecordPatternError(const Scanner::Location& loc,
123 : MessageTemplate message) {
124 : // TODO(verwaest): Non-assigning expression?
125 9825727 : if (IsCertainlyPattern()) {
126 : Report(loc, message);
127 : } else {
128 : AsExpressionParsingScope()->RecordPatternError(loc, message);
129 : }
130 9825727 : }
131 :
132 59570 : void RecordStrictModeParameterError(const Scanner::Location& loc,
133 : MessageTemplate message) {
134 : DCHECK_IMPLIES(!has_error(), loc.IsValid());
135 59570 : if (!CanBeParameterDeclaration()) return;
136 20565 : if (IsCertainlyParameterDeclaration()) {
137 17112 : if (is_strict(parser_->language_mode())) {
138 : Report(loc, message);
139 : } else {
140 8556 : parser_->parameters_->set_strict_parameter_error(loc, message);
141 : }
142 : } else {
143 12009 : parser_->next_arrow_function_info_.strict_parameter_error_location = loc;
144 12009 : parser_->next_arrow_function_info_.strict_parameter_error_message =
145 : message;
146 : }
147 : }
148 :
149 38324691 : void RecordDeclarationError(const Scanner::Location& loc,
150 : MessageTemplate message) {
151 38324691 : if (!CanBeDeclaration()) return;
152 2850400 : if (IsCertainlyDeclaration()) {
153 : Report(loc, message);
154 : } else {
155 : AsArrowHeadParsingScope()->RecordDeclarationError(loc, message);
156 : }
157 : }
158 :
159 : void RecordExpressionError(const Scanner::Location& loc,
160 : MessageTemplate message) {
161 33123 : if (!CanBeExpression()) return;
162 : // TODO(verwaest): Non-assigning expression?
163 : // if (IsCertainlyExpression()) Report(loc, message);
164 : AsExpressionParsingScope()->RecordExpressionError(loc, message);
165 : }
166 :
167 : void RecordNonSimpleParameter() {
168 11460588 : if (!IsArrowHeadParsingScope()) return;
169 : AsArrowHeadParsingScope()->RecordNonSimpleParameter();
170 : }
171 :
172 : bool IsCertainlyDeclaration() const {
173 : return IsInRange(type_, kParameterDeclaration, kLexicalDeclaration);
174 : }
175 :
176 : protected:
177 : enum ScopeType : uint8_t {
178 : // Expression or assignment target.
179 : kExpression,
180 :
181 : // Declaration or expression or assignment target.
182 : kMaybeArrowParameterDeclaration,
183 : kMaybeAsyncArrowParameterDeclaration,
184 :
185 : // Declarations.
186 : kParameterDeclaration,
187 : kVarDeclaration,
188 : kLexicalDeclaration,
189 : };
190 :
191 : ParserT* parser() const { return parser_; }
192 : ExpressionScope* parent() const { return parent_; }
193 :
194 : void Report(const Scanner::Location& loc, MessageTemplate message) const {
195 97069 : parser_->ReportMessageAt(loc, message);
196 : }
197 :
198 : ExpressionScope(ParserT* parser, ScopeType type)
199 : : parser_(parser),
200 : parent_(parser->expression_scope_),
201 : type_(type),
202 : has_possible_parameter_in_scope_chain_(
203 : CanBeParameterDeclaration() ||
204 150160808 : (parent_ && parent_->has_possible_parameter_in_scope_chain_)) {
205 77307320 : parser->expression_scope_ = this;
206 : }
207 :
208 : ~ExpressionScope() {
209 : DCHECK(parser_->expression_scope_ == this ||
210 : parser_->expression_scope_ == parent_);
211 77311407 : parser_->expression_scope_ = parent_;
212 77311407 : }
213 :
214 : ExpressionParsingScope<Types>* AsExpressionParsingScope() {
215 : DCHECK(CanBeExpression());
216 : return static_cast<ExpressionParsingScope<Types>*>(this);
217 : }
218 :
219 : #ifdef DEBUG
220 : bool has_error() const { return parser_->has_error(); }
221 : #endif
222 :
223 : bool CanBeExpression() const {
224 : return IsInRange(type_, kExpression, kMaybeAsyncArrowParameterDeclaration);
225 : }
226 : bool CanBeDeclaration() const {
227 : return IsInRange(type_, kMaybeArrowParameterDeclaration,
228 : kLexicalDeclaration);
229 : }
230 : bool IsVariableDeclaration() const {
231 : return IsInRange(type_, kVarDeclaration, kLexicalDeclaration);
232 : }
233 : bool IsLexicalDeclaration() const { return type_ == kLexicalDeclaration; }
234 : bool IsAsyncArrowHeadParsingScope() const {
235 : return type_ == kMaybeAsyncArrowParameterDeclaration;
236 : }
237 : bool IsVarDeclaration() const { return type_ == kVarDeclaration; }
238 :
239 : private:
240 : friend class AccumulationScope<Types>;
241 : friend class ExpressionParsingScope<Types>;
242 :
243 : ArrowHeadParsingScope<Types>* AsArrowHeadParsingScope() {
244 : DCHECK(IsArrowHeadParsingScope());
245 : return static_cast<ArrowHeadParsingScope<Types>*>(this);
246 : }
247 :
248 : ParameterDeclarationParsingScope<Types>*
249 : AsParameterDeclarationParsingScope() {
250 : DCHECK(IsCertainlyParameterDeclaration());
251 : return static_cast<ParameterDeclarationParsingScope<Types>*>(this);
252 : }
253 :
254 : VariableDeclarationParsingScope<Types>* AsVariableDeclarationParsingScope() {
255 : DCHECK(IsVariableDeclaration());
256 : return static_cast<VariableDeclarationParsingScope<Types>*>(this);
257 : }
258 :
259 : bool IsArrowHeadParsingScope() const {
260 : return IsInRange(type_, kMaybeArrowParameterDeclaration,
261 : kMaybeAsyncArrowParameterDeclaration);
262 : }
263 : bool IsCertainlyPattern() const { return IsCertainlyDeclaration(); }
264 : bool CanBeParameterDeclaration() const {
265 : return IsInRange(type_, kMaybeArrowParameterDeclaration,
266 : kParameterDeclaration);
267 : }
268 : bool IsCertainlyParameterDeclaration() const {
269 : return type_ == kParameterDeclaration;
270 : }
271 :
272 : ParserT* parser_;
273 : ExpressionScope<Types>* parent_;
274 : ScopeType type_;
275 : bool has_possible_parameter_in_scope_chain_;
276 :
277 : DISALLOW_COPY_AND_ASSIGN(ExpressionScope);
278 : };
279 :
280 : // Used to unambiguously parse var, let, const declarations.
281 : template <typename Types>
282 13809260 : class VariableDeclarationParsingScope : public ExpressionScope<Types> {
283 : public:
284 : using ParserT = typename Types::Impl;
285 : using ExpressionScopeT = ExpressionScope<Types>;
286 : using ScopeType = typename ExpressionScopeT::ScopeType;
287 :
288 : VariableDeclarationParsingScope(ParserT* parser, VariableMode mode,
289 : ZonePtrList<const AstRawString>* names)
290 : : ExpressionScopeT(parser, IsLexicalVariableMode(mode)
291 : ? ExpressionScopeT::kLexicalDeclaration
292 : : ExpressionScopeT::kVarDeclaration),
293 : mode_(mode),
294 27609375 : names_(names) {}
295 :
296 15671597 : Variable* Declare(const AstRawString* name, int pos) {
297 : VariableKind kind = NORMAL_VARIABLE;
298 : bool was_added;
299 : Variable* var = this->parser()->DeclareVariable(
300 15671597 : name, kind, mode_, Variable::DefaultInitializationFlag(mode_),
301 15671597 : this->parser()->scope(), &was_added, pos);
302 29482695 : if (was_added &&
303 : this->parser()->scope()->num_var() > kMaxNumFunctionLocals) {
304 0 : this->parser()->ReportMessage(MessageTemplate::kTooManyVariables);
305 : }
306 15671666 : if (names_) names_->Add(name, this->parser()->zone());
307 15671662 : if (this->IsLexicalDeclaration()) {
308 2515554 : if (this->parser()->IsLet(name)) {
309 6836 : this->parser()->ReportMessageAt(
310 : Scanner::Location(pos, pos + name->length()),
311 : MessageTemplate::kLetInLexicalBinding);
312 : }
313 : } else {
314 13156108 : if (this->parser()->loop_nesting_depth() > 0) {
315 : // Due to hoisting, the value of a 'var'-declared variable may actually
316 : // change even if the code contains only the "initial" assignment,
317 : // namely when that assignment occurs inside a loop. For example:
318 : //
319 : // let i = 10;
320 : // do { var x = i } while (i--):
321 : //
322 : // Note that non-lexical variables include temporaries, which may also
323 : // get assigned inside a loop due to the various rewritings that the
324 : // parser performs.
325 : //
326 : // Pessimistically mark all vars in loops as assigned. This
327 : // overapproximates the actual assigned vars due to unassigned var
328 : // without initializer, but that's unlikely anyway.
329 : //
330 : // This also handles marking of loop variables in for-in and for-of
331 : // loops, as determined by loop-nesting-depth.
332 : DCHECK_NOT_NULL(var);
333 : var->set_maybe_assigned();
334 : }
335 : }
336 15671662 : return var;
337 : }
338 :
339 : private:
340 : // Limit the allowed number of local variables in a function. The hard limit
341 : // in Ignition is 2^31-1 due to the size of register operands. We limit it to
342 : // a more reasonable lower up-limit.
343 : static const int kMaxNumFunctionLocals = (1 << 23) - 1;
344 :
345 : VariableMode mode_;
346 : ZonePtrList<const AstRawString>* names_;
347 :
348 : DISALLOW_COPY_AND_ASSIGN(VariableDeclarationParsingScope);
349 : };
350 :
351 : template <typename Types>
352 4444852 : class ParameterDeclarationParsingScope : public ExpressionScope<Types> {
353 : public:
354 : using ParserT = typename Types::Impl;
355 : using ExpressionScopeT = ExpressionScope<Types>;
356 : using ScopeType = typename ExpressionScopeT::ScopeType;
357 :
358 : explicit ParameterDeclarationParsingScope(ParserT* parser)
359 4444857 : : ExpressionScopeT(parser, ExpressionScopeT::kParameterDeclaration) {}
360 :
361 7918257 : Variable* Declare(const AstRawString* name, int pos) {
362 : VariableKind kind = PARAMETER_VARIABLE;
363 : VariableMode mode = VariableMode::kVar;
364 : bool was_added;
365 : Variable* var = this->parser()->DeclareVariable(
366 : name, kind, mode, Variable::DefaultInitializationFlag(mode),
367 3919121 : this->parser()->scope(), &was_added, pos);
368 7918279 : if (!has_duplicate() && !was_added) {
369 7202 : duplicate_loc_ = Scanner::Location(pos, pos + name->length());
370 : }
371 7918279 : return var;
372 : }
373 :
374 : bool has_duplicate() const { return duplicate_loc_.IsValid(); }
375 :
376 : const Scanner::Location& duplicate_location() const { return duplicate_loc_; }
377 :
378 : private:
379 : Scanner::Location duplicate_loc_ = Scanner::Location::invalid();
380 : DISALLOW_COPY_AND_ASSIGN(ParameterDeclarationParsingScope);
381 : };
382 :
383 : // Parsing expressions is always ambiguous between at least left-hand-side and
384 : // right-hand-side of assignments. This class is used to keep track of errors
385 : // relevant for either side until it is clear what was being parsed.
386 : // The class also keeps track of all variable proxies that are created while the
387 : // scope was active. If the scope is an expression, the variable proxies will be
388 : // added to the unresolved list. Otherwise they are declarations and aren't
389 : // added. The list is also used to mark the variables as assigned in case we are
390 : // parsing an assignment expression.
391 : template <typename Types>
392 : class ExpressionParsingScope : public ExpressionScope<Types> {
393 : public:
394 : using ParserT = typename Types::Impl;
395 : using ExpressionT = typename Types::Expression;
396 : using ExpressionScopeT = ExpressionScope<Types>;
397 : using ScopeType = typename ExpressionScopeT::ScopeType;
398 :
399 59053288 : ExpressionParsingScope(ParserT* parser,
400 : ScopeType type = ExpressionScopeT::kExpression)
401 : : ExpressionScopeT(parser, type),
402 : variable_list_(parser->variable_buffer()),
403 : has_async_arrow_in_scope_chain_(
404 : type == ExpressionScopeT::kMaybeAsyncArrowParameterDeclaration ||
405 15831592 : (this->parent() && this->parent()->CanBeExpression() &&
406 : this->parent()
407 : ->AsExpressionParsingScope()
408 252045988 : ->has_async_arrow_in_scope_chain_)) {
409 : DCHECK(this->CanBeExpression());
410 : clear(kExpressionIndex);
411 : clear(kPatternIndex);
412 59053288 : }
413 :
414 : void RecordAsyncArrowParametersError(const Scanner::Location& loc,
415 : MessageTemplate message) {
416 10806 : for (ExpressionScopeT* scope = this; scope != nullptr;
417 : scope = scope->parent()) {
418 18205 : if (!has_async_arrow_in_scope_chain_) break;
419 10226 : if (scope->type_ ==
420 : ExpressionScopeT::kMaybeAsyncArrowParameterDeclaration) {
421 : scope->AsArrowHeadParsingScope()->RecordDeclarationError(loc, message);
422 : }
423 : }
424 : }
425 :
426 60082614 : ~ExpressionParsingScope() { DCHECK(this->has_error() || verified_); }
427 :
428 104455 : ExpressionT ValidateAndRewriteReference(ExpressionT expression, int beg_pos,
429 : int end_pos) {
430 104455 : if (V8_LIKELY(this->parser()->IsAssignableIdentifier(expression))) {
431 93096 : MarkIdentifierAsAssigned();
432 : this->mark_verified();
433 93096 : return expression;
434 11359 : } else if (V8_LIKELY(expression->IsProperty())) {
435 2322 : ValidateExpression();
436 2322 : return expression;
437 : }
438 : this->mark_verified();
439 : return this->parser()->RewriteInvalidReferenceExpression(
440 : expression, beg_pos, end_pos, MessageTemplate::kInvalidLhsInFor,
441 9037 : kSyntaxError);
442 : }
443 :
444 : void RecordExpressionError(const Scanner::Location& loc,
445 : MessageTemplate message) {
446 : Record(kExpressionIndex, loc, message);
447 : }
448 :
449 : void RecordPatternError(const Scanner::Location& loc,
450 : MessageTemplate message) {
451 : Record(kPatternIndex, loc, message);
452 : }
453 :
454 117399176 : void ValidateExpression() { Validate(kExpressionIndex); }
455 :
456 240880 : void ValidatePattern(ExpressionT expression, int begin, int end) {
457 : Validate(kPatternIndex);
458 240880 : if (expression->is_parenthesized()) {
459 1716 : ExpressionScopeT::Report(Scanner::Location(begin, end),
460 : MessageTemplate::kInvalidDestructuringTarget);
461 : }
462 788126 : for (VariableProxy* proxy : variable_list_) {
463 : proxy->set_is_assigned();
464 : }
465 240880 : }
466 :
467 : void ClearExpressionError() {
468 : DCHECK(verified_);
469 : #ifdef DEBUG
470 : verified_ = false;
471 : #endif
472 : clear(kExpressionIndex);
473 : }
474 :
475 50435181 : void TrackVariable(VariableProxy* variable) {
476 50435181 : if (!this->CanBeDeclaration()) {
477 46748748 : this->parser()->scope()->AddUnresolved(variable);
478 : }
479 : variable_list_.Add(variable);
480 50434361 : }
481 :
482 4335915 : void MarkIdentifierAsAssigned() {
483 : // It's possible we're parsing a syntax error. In that case it's not
484 : // guaranteed that there's a variable in the list.
485 4335915 : if (variable_list_.length() == 0) return;
486 4333538 : variable_list_.at(variable_list_.length() - 1)->set_is_assigned();
487 : }
488 :
489 : protected:
490 : bool is_verified() const {
491 : #ifdef DEBUG
492 : return verified_;
493 : #else
494 : return false;
495 : #endif
496 : }
497 :
498 1034860 : void ValidatePattern() { Validate(kPatternIndex); }
499 :
500 : ScopedPtrList<VariableProxy>* variable_list() { return &variable_list_; }
501 :
502 : private:
503 : friend class AccumulationScope<Types>;
504 :
505 : enum ErrorNumber : uint8_t {
506 : kExpressionIndex = 0,
507 : kPatternIndex = 1,
508 : kNumberOfErrors = 2,
509 : };
510 : void clear(int index) {
511 336733333 : messages_[index] = MessageTemplate::kNone;
512 336733333 : locations_[index] = Scanner::Location::invalid();
513 : }
514 : bool is_valid(int index) const { return !locations_[index].IsValid(); }
515 : void Record(int index, const Scanner::Location& loc,
516 : MessageTemplate message) {
517 : DCHECK_IMPLIES(!this->has_error(), loc.IsValid());
518 9801586 : if (!is_valid(index)) return;
519 7938781 : messages_[index] = message;
520 7938781 : locations_[index] = loc;
521 : }
522 : void Validate(int index) {
523 : DCHECK(!this->is_verified());
524 59457898 : if (!is_valid(index)) Report(index);
525 : this->mark_verified();
526 : }
527 : void Report(int index) const {
528 24649 : ExpressionScopeT::Report(locations_[index], messages_[index]);
529 : }
530 :
531 : // Debug verification to make sure every scope is validated exactly once.
532 : void mark_verified() {
533 : #ifdef DEBUG
534 : verified_ = true;
535 : #endif
536 : }
537 : void clear_verified() {
538 : #ifdef DEBUG
539 : verified_ = false;
540 : #endif
541 : }
542 : #ifdef DEBUG
543 : bool verified_ = false;
544 : #endif
545 :
546 : ScopedPtrList<VariableProxy> variable_list_;
547 : MessageTemplate messages_[kNumberOfErrors];
548 : Scanner::Location locations_[kNumberOfErrors];
549 : bool has_async_arrow_in_scope_chain_;
550 :
551 : DISALLOW_COPY_AND_ASSIGN(ExpressionParsingScope);
552 : };
553 :
554 : // This class is used to parse multiple ambiguous expressions and declarations
555 : // in the same scope. E.g., in async(X,Y,Z) or [X,Y,Z], X and Y and Z will all
556 : // be parsed in the respective outer ArrowHeadParsingScope and
557 : // ExpressionParsingScope. It provides a clean error state in the underlying
558 : // scope to parse the individual expressions, while keeping track of the
559 : // expression and pattern errors since the start. The AccumulationScope is only
560 : // used to keep track of the errors so far, and the underlying ExpressionScope
561 : // keeps being used as the expression_scope(). If the expression_scope() isn't
562 : // ambiguous, this class does not do anything.
563 : template <typename Types>
564 : class AccumulationScope {
565 : public:
566 : using ParserT = typename Types::Impl;
567 :
568 : static const int kNumberOfErrors =
569 : ExpressionParsingScope<Types>::kNumberOfErrors;
570 162713162 : explicit AccumulationScope(ExpressionScope<Types>* scope) : scope_(nullptr) {
571 54239332 : if (!scope->CanBeExpression()) return;
572 53995678 : scope_ = scope->AsExpressionParsingScope();
573 269828146 : for (int i = 0; i < kNumberOfErrors; i++) {
574 : // If the underlying scope is already invalid at the start, stop
575 : // accumulating. That means an error was found outside of an
576 : // accumulating path.
577 107989980 : if (!scope_->is_valid(i)) {
578 73746 : scope_ = nullptr;
579 73746 : break;
580 : }
581 : copy(i);
582 : }
583 : }
584 :
585 : // Merge errors from the underlying ExpressionParsingScope into this scope.
586 : // Only keeps the first error across all accumulate calls, and removes the
587 : // error from the underlying scope.
588 : void Accumulate() {
589 112443577 : if (scope_ == nullptr) return;
590 : DCHECK(!scope_->is_verified());
591 545300891 : for (int i = 0; i < kNumberOfErrors; i++) {
592 218119936 : if (!locations_[i].IsValid()) copy(i);
593 218119936 : scope_->clear(i);
594 : }
595 : }
596 :
597 : // This is called instead of Accumulate in case the parsed member is already
598 : // known to be an expression. In that case we don't need to accumulate the
599 : // expression but rather validate it immediately. We also ignore the pattern
600 : // error since the parsed member is known to not be a pattern. This is
601 : // necessary for "{x:1}.y" parsed as part of an assignment pattern. {x:1} will
602 : // record a pattern error, but "{x:1}.y" is actually a valid as part of an
603 : // assignment pattern since it's a property access.
604 : void ValidateExpression() {
605 318820 : if (scope_ == nullptr) return;
606 : DCHECK(!scope_->is_verified());
607 318227 : scope_->ValidateExpression();
608 : DCHECK(scope_->is_verified());
609 318227 : scope_->clear(ExpressionParsingScope<Types>::kPatternIndex);
610 : #ifdef DEBUG
611 : scope_->clear_verified();
612 : #endif
613 : }
614 :
615 54239754 : ~AccumulationScope() {
616 54239754 : if (scope_ == nullptr) return;
617 : Accumulate();
618 269610052 : for (int i = 0; i < kNumberOfErrors; i++) copy_back(i);
619 53922178 : }
620 :
621 : private:
622 : void copy(int entry) {
623 318278875 : messages_[entry] = scope_->messages_[entry];
624 318278875 : locations_[entry] = scope_->locations_[entry];
625 : }
626 :
627 : void copy_back(int entry) {
628 107843937 : if (!locations_[entry].IsValid()) return;
629 2059959 : scope_->messages_[entry] = messages_[entry];
630 2059959 : scope_->locations_[entry] = locations_[entry];
631 : }
632 :
633 : ExpressionParsingScope<Types>* scope_;
634 : MessageTemplate messages_[2];
635 : Scanner::Location locations_[2];
636 :
637 : DISALLOW_COPY_AND_ASSIGN(AccumulationScope);
638 : };
639 :
640 : // The head of an arrow function is ambiguous between expression, assignment
641 : // pattern and declaration. This keeps track of the additional declaration
642 : // error and allows the scope to be validated as a declaration rather than an
643 : // expression or a pattern.
644 : template <typename Types>
645 3501882 : class ArrowHeadParsingScope : public ExpressionParsingScope<Types> {
646 : public:
647 : using ParserT = typename Types::Impl;
648 : using ScopeType = typename ExpressionScope<Types>::ScopeType;
649 :
650 : ArrowHeadParsingScope(ParserT* parser, FunctionKind kind)
651 : : ExpressionParsingScope<Types>(
652 : parser,
653 : kind == FunctionKind::kArrowFunction
654 : ? ExpressionScope<Types>::kMaybeArrowParameterDeclaration
655 : : ExpressionScope<
656 3501866 : Types>::kMaybeAsyncArrowParameterDeclaration) {
657 : DCHECK(kind == FunctionKind::kAsyncArrowFunction ||
658 : kind == FunctionKind::kArrowFunction);
659 : DCHECK(this->CanBeDeclaration());
660 : DCHECK(!this->IsCertainlyDeclaration());
661 : }
662 :
663 2984456 : void ValidateExpression() {
664 : // Turns out this is not an arrow head. Clear any possible tracked strict
665 : // parameter errors, and reinterpret tracked variables as unresolved
666 : // references.
667 : this->parser()->next_arrow_function_info_.ClearStrictParameterError();
668 2984456 : ExpressionParsingScope<Types>::ValidateExpression();
669 9205617 : for (VariableProxy* proxy : *this->variable_list()) {
670 3110580 : this->parser()->scope()->AddUnresolved(proxy);
671 : }
672 2984458 : }
673 :
674 517430 : DeclarationScope* ValidateAndCreateScope() {
675 : DCHECK(!this->is_verified());
676 517430 : if (declaration_error_location.IsValid()) {
677 15462 : ExpressionScope<Types>::Report(declaration_error_location,
678 : declaration_error_message);
679 : }
680 517430 : this->ValidatePattern();
681 :
682 517429 : DeclarationScope* result = this->parser()->NewFunctionScope(kind());
683 517425 : if (!has_simple_parameter_list_) result->SetHasNonSimpleParameters();
684 : VariableKind kind = PARAMETER_VARIABLE;
685 : VariableMode mode =
686 517425 : has_simple_parameter_list_ ? VariableMode::kVar : VariableMode::kLet;
687 1671825 : for (VariableProxy* proxy : *this->variable_list()) {
688 : bool was_added;
689 144186 : this->parser()->DeclareAndBindVariable(
690 : proxy, kind, mode, Variable::DefaultInitializationFlag(mode), result,
691 : &was_added, proxy->position());
692 577200 : if (!was_added) {
693 2562 : ExpressionScope<Types>::Report(proxy->location(),
694 : MessageTemplate::kParamDupe);
695 : }
696 : }
697 :
698 : int initializer_position = this->parser()->end_position();
699 661613 : for (auto declaration : *result->declarations()) {
700 : declaration->var()->set_initializer_position(initializer_position);
701 : }
702 517428 : if (uses_this_) result->UsesThis();
703 517428 : return result;
704 : }
705 :
706 : void RecordDeclarationError(const Scanner::Location& loc,
707 : MessageTemplate message) {
708 : DCHECK_IMPLIES(!this->has_error(), loc.IsValid());
709 2869921 : declaration_error_location = loc;
710 2869921 : declaration_error_message = message;
711 : }
712 :
713 204440 : void RecordNonSimpleParameter() { has_simple_parameter_list_ = false; }
714 2564 : void RecordThisUse() { uses_this_ = true; }
715 :
716 : private:
717 : FunctionKind kind() const {
718 : return this->IsAsyncArrowHeadParsingScope()
719 : ? FunctionKind::kAsyncArrowFunction
720 517429 : : FunctionKind::kArrowFunction;
721 : }
722 :
723 : Scanner::Location declaration_error_location = Scanner::Location::invalid();
724 : MessageTemplate declaration_error_message = MessageTemplate::kNone;
725 : bool has_simple_parameter_list_ = true;
726 : bool uses_this_ = false;
727 :
728 : DISALLOW_COPY_AND_ASSIGN(ArrowHeadParsingScope);
729 : };
730 :
731 : } // namespace internal
732 : } // namespace v8
733 :
734 : #endif // V8_PARSING_EXPRESSION_SCOPE_H_
|