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/message-template.h"
10 : #include "src/parsing/scanner.h"
11 : #include "src/zone/zone.h" // For ScopedPtrList.
12 :
13 : namespace v8 {
14 : namespace internal {
15 :
16 : template <typename Types>
17 : class ExpressionParsingScope;
18 : template <typename Types>
19 : class AccumulationScope;
20 : template <typename Types>
21 : class ArrowHeadParsingScope;
22 : class VariableProxy;
23 :
24 : // ExpressionScope is used in a stack fashion, and is used to specialize
25 : // expression parsing for the task at hand. It allows the parser to reuse the
26 : // same code to parse destructuring declarations, assignment patterns,
27 : // expressions, and (async) arrow function heads.
28 : //
29 : // One of the specific subclasses needs to be instantiated to tell the parser
30 : // the meaning of the expression it will parse next. The parser then calls
31 : // Record* on the expression_scope() to indicate errors. The expression_scope
32 : // will either discard those errors, immediately report those errors, or
33 : // classify the errors for later validation.
34 : // TODO(verwaest): Record is a slightly odd name since it will directly throw
35 : // for unambiguous scopes.
36 : template <typename Types>
37 : class ExpressionScope {
38 : public:
39 : typedef typename Types::Impl ParserT;
40 : typedef typename Types::Expression ExpressionT;
41 :
42 71499954 : VariableProxy* NewVariable(const AstRawString* name,
43 71505143 : int pos = kNoSourcePosition) {
44 84802991 : VariableProxy* result = parser_->NewRawVariable(name, pos);
45 71505143 : if (CanBeExpression()) {
46 48183523 : AsExpressionParsingScope()->TrackVariable(result);
47 36624657 : } else if (type_ == kVarDeclaration && parser_->loop_nesting_depth() > 0) {
48 : // Due to hoisting, the value of a 'var'-declared variable may actually
49 : // change even if the code contains only the "initial" assignment, namely
50 : // when that assignment occurs inside a loop. For example:
51 : //
52 : // let i = 10;
53 : // do { var x = i } while (i--):
54 : //
55 : // Note that non-lexical variables include temporaries, which may also get
56 : // assigned inside a loop due to the various rewritings that the parser
57 : // performs.
58 : //
59 : // Pessimistically mark all vars in loops as assigned. This
60 : // overapproximates the actual assigned vars due to unassigned var without
61 : // initializer, but that's unlikely anyway.
62 : //
63 : // This also handles marking of loop variables in for-in and for-of loops,
64 : // as determined by loop-nesting-depth.
65 : result->set_is_assigned();
66 : }
67 71503006 : return result;
68 : }
69 :
70 4206288 : void MarkIdentifierAsAssigned() {
71 4970447 : if (!CanBeExpression()) return;
72 4150343 : AsExpressionParsingScope()->MarkIdentifierAsAssigned();
73 : }
74 :
75 183867 : void ValidateAsPattern(ExpressionT expression, int begin, int end) {
76 183867 : if (!CanBeExpression()) return;
77 182599 : AsExpressionParsingScope()->ValidatePattern(expression, begin, end);
78 : AsExpressionParsingScope()->ClearExpressionError();
79 : }
80 :
81 : // Record async arrow parameters errors in all ambiguous async arrow scopes in
82 : // the chain up to the first unambiguous scope.
83 22337 : void RecordAsyncArrowParametersError(const Scanner::Location& loc,
84 22906 : MessageTemplate message) {
85 : // Only ambiguous scopes (ExpressionParsingScope, *ArrowHeadParsingScope)
86 : // need to propagate errors to a possible kAsyncArrowHeadParsingScope, so
87 : // immediately return if the current scope is not ambiguous.
88 45243 : if (!CanBeExpression()) return;
89 : AsExpressionParsingScope()->RecordAsyncArrowParametersError(loc, message);
90 : }
91 :
92 : // Record initializer errors in all scopes that can turn into parameter scopes
93 : // (ArrowHeadParsingScopes) up to the first known unambiguous parameter scope.
94 96645 : void RecordParameterInitializerError(const Scanner::Location& loc,
95 7740 : MessageTemplate message) {
96 306969 : ExpressionScope* scope = this;
97 283304 : while (!scope->IsCertainlyParameterDeclaration()) {
98 178919 : if (!has_possible_parameter_in_scope_chain_) return;
99 120310 : if (scope->CanBeParameterDeclaration()) {
100 : scope->AsArrowHeadParsingScope()->RecordDeclarationError(loc, message);
101 : }
102 : scope = scope->parent();
103 120310 : if (scope == nullptr) return;
104 : }
105 : Report(loc, message);
106 : }
107 :
108 10690276 : void RecordPatternError(const Scanner::Location& loc,
109 42468 : MessageTemplate message) {
110 : // TODO(verwaest): Non-assigning expression?
111 10690276 : if (IsCertainlyPattern()) {
112 : Report(loc, message);
113 : } else {
114 : AsExpressionParsingScope()->RecordPatternError(loc, message);
115 : }
116 10690276 : }
117 :
118 59315 : void RecordStrictModeParameterError(const Scanner::Location& loc,
119 59315 : MessageTemplate message) {
120 : DCHECK_IMPLIES(!has_error(), loc.IsValid());
121 118630 : if (!CanBeParameterDeclaration()) return;
122 20469 : if (IsCertainlyParameterDeclaration()) {
123 17006 : if (is_strict(parser_->language_mode())) {
124 : Report(loc, message);
125 : } else {
126 8503 : parser_->parameters_->set_strict_parameter_error(loc, message);
127 : }
128 : } else {
129 11966 : parser_->next_arrow_function_info_.strict_parameter_error_location = loc;
130 11966 : parser_->next_arrow_function_info_.strict_parameter_error_message =
131 : message;
132 : }
133 : }
134 :
135 31522892 : void RecordDeclarationError(const Scanner::Location& loc,
136 31526745 : MessageTemplate message) {
137 63045784 : if (!CanBeDeclaration()) return;
138 2813903 : if (IsCertainlyDeclaration()) {
139 : Report(loc, message);
140 : } else {
141 : AsArrowHeadParsingScope()->RecordDeclarationError(loc, message);
142 : }
143 : }
144 :
145 : void RecordExpressionError(const Scanner::Location& loc,
146 33387 : MessageTemplate message) {
147 33387 : if (!CanBeExpression()) return;
148 : // TODO(verwaest): Non-assigning expression?
149 : // if (IsCertainlyExpression()) Report(loc, message);
150 : AsExpressionParsingScope()->RecordExpressionError(loc, message);
151 : }
152 :
153 : void RecordLexicalDeclarationError(const Scanner::Location& loc,
154 2812 : MessageTemplate message) {
155 1612 : if (IsLexicalDeclaration()) Report(loc, message);
156 : }
157 :
158 11349323 : void RecordNonSimpleParameter() {
159 11349323 : if (!IsArrowHeadParsingScope()) return;
160 : AsArrowHeadParsingScope()->RecordNonSimpleParameter();
161 : }
162 :
163 : protected:
164 : enum ScopeType : uint8_t {
165 : // Expression or assignment target.
166 : kExpression,
167 :
168 : // Declaration or expression or assignment target.
169 : kMaybeArrowParameterDeclaration,
170 : kMaybeAsyncArrowParameterDeclaration,
171 :
172 : // Declarations.
173 : kParameterDeclaration,
174 : kVarDeclaration,
175 : kLexicalDeclaration,
176 : };
177 :
178 : ParserT* parser() const { return parser_; }
179 : ExpressionScope* parent() const { return parent_; }
180 :
181 : void Report(const Scanner::Location& loc, MessageTemplate message) const {
182 98741 : parser_->ReportMessageAt(loc, message);
183 : }
184 :
185 : ExpressionScope(ParserT* parser, ScopeType type)
186 : : parser_(parser),
187 : parent_(parser->expression_scope_),
188 : type_(type),
189 : has_possible_parameter_in_scope_chain_(
190 : CanBeParameterDeclaration() ||
191 149010951 : (parent_ && parent_->has_possible_parameter_in_scope_chain_)) {
192 76661330 : parser->expression_scope_ = this;
193 : }
194 :
195 : ~ExpressionScope() {
196 : DCHECK(parser_->expression_scope_ == this ||
197 : parser_->expression_scope_ == parent_);
198 76664957 : parser_->expression_scope_ = parent_;
199 : }
200 :
201 : ExpressionParsingScope<Types>* AsExpressionParsingScope() {
202 : DCHECK(CanBeExpression());
203 : return static_cast<ExpressionParsingScope<Types>*>(this);
204 : }
205 :
206 : #ifdef DEBUG
207 : bool has_error() const { return parser_->has_error(); }
208 : #endif
209 :
210 : bool CanBeExpression() const {
211 : return IsInRange(type_, kExpression, kMaybeAsyncArrowParameterDeclaration);
212 : }
213 : bool CanBeDeclaration() const {
214 : return IsInRange(type_, kMaybeArrowParameterDeclaration,
215 : kLexicalDeclaration);
216 : }
217 : bool IsCertainlyDeclaration() const {
218 : return IsInRange(type_, kParameterDeclaration, kLexicalDeclaration);
219 : }
220 : bool IsVariableDeclaration() const {
221 : return IsInRange(type_, kVarDeclaration, kLexicalDeclaration);
222 : }
223 : bool IsAsyncArrowHeadParsingScope() const {
224 : return type_ == kMaybeAsyncArrowParameterDeclaration;
225 : }
226 :
227 : private:
228 : friend class AccumulationScope<Types>;
229 : friend class ExpressionParsingScope<Types>;
230 :
231 : ArrowHeadParsingScope<Types>* AsArrowHeadParsingScope() {
232 : DCHECK(IsArrowHeadParsingScope());
233 : return static_cast<ArrowHeadParsingScope<Types>*>(this);
234 : }
235 :
236 : bool IsArrowHeadParsingScope() const {
237 : return IsInRange(type_, kMaybeArrowParameterDeclaration,
238 : kMaybeAsyncArrowParameterDeclaration);
239 : }
240 10690276 : bool IsCertainlyPattern() const { return IsCertainlyDeclaration(); }
241 : bool CanBeParameterDeclaration() const {
242 : return IsInRange(type_, kMaybeArrowParameterDeclaration,
243 : kParameterDeclaration);
244 : }
245 : bool IsCertainlyParameterDeclaration() const {
246 : return type_ == kParameterDeclaration;
247 : }
248 : bool IsLexicalDeclaration() const { return type_ == kLexicalDeclaration; }
249 :
250 : ParserT* parser_;
251 : ExpressionScope<Types>* parent_;
252 : ScopeType type_;
253 : bool has_possible_parameter_in_scope_chain_;
254 :
255 : DISALLOW_COPY_AND_ASSIGN(ExpressionScope);
256 : };
257 :
258 : // Used to unambiguously parse var, let, const declarations.
259 : template <typename Types>
260 18190 : class VariableDeclarationParsingScope : public ExpressionScope<Types> {
261 : public:
262 : typedef typename Types::Impl ParserT;
263 : typedef class ExpressionScope<Types> ExpressionScopeT;
264 : typedef typename ExpressionScopeT::ScopeType ScopeType;
265 :
266 9095 : VariableDeclarationParsingScope(ParserT* parser, VariableMode mode)
267 : : ExpressionScopeT(parser, IsLexicalVariableMode(mode)
268 : ? ExpressionScopeT::kLexicalDeclaration
269 : : ExpressionScopeT::kVarDeclaration),
270 28703916 : mode_(mode) {}
271 :
272 : private:
273 : VariableMode mode_;
274 :
275 : DISALLOW_COPY_AND_ASSIGN(VariableDeclarationParsingScope);
276 : };
277 :
278 : template <typename Types>
279 : class ParameterDeclarationParsingScope : public ExpressionScope<Types> {
280 : public:
281 : typedef typename Types::Impl ParserT;
282 : typedef class ExpressionScope<Types> ExpressionScopeT;
283 : typedef typename ExpressionScopeT::ScopeType ScopeType;
284 :
285 : explicit ParameterDeclarationParsingScope(ParserT* parser)
286 : : ExpressionScopeT(parser, ExpressionScopeT::kParameterDeclaration) {}
287 :
288 : private:
289 : DISALLOW_COPY_AND_ASSIGN(ParameterDeclarationParsingScope);
290 : };
291 :
292 : // Parsing expressions is always ambiguous between at least left-hand-side and
293 : // right-hand-side of assignments. This class is used to keep track of errors
294 : // relevant for either side until it is clear what was being parsed.
295 : // The class also keeps track of all variable proxies that are created while the
296 : // scope was active. If the scope is an expression, the variable proxies will be
297 : // added to the unresolved list. Otherwise they are declarations and aren't
298 : // added. The list is also used to mark the variables as assigned in case we are
299 : // parsing an assignment expression.
300 : template <typename Types>
301 : class ExpressionParsingScope : public ExpressionScope<Types> {
302 : public:
303 : typedef typename Types::Impl ParserT;
304 : typedef typename Types::Expression ExpressionT;
305 : typedef class ExpressionScope<Types> ExpressionScopeT;
306 : typedef typename ExpressionScopeT::ScopeType ScopeType;
307 :
308 57997663 : ExpressionParsingScope(ParserT* parser,
309 : ScopeType type = ExpressionScopeT::kExpression)
310 : : ExpressionScopeT(parser, type),
311 : variable_list_(parser->variable_buffer()),
312 : has_async_arrow_in_scope_chain_(
313 : type == ExpressionScopeT::kMaybeAsyncArrowParameterDeclaration ||
314 22124156 : (this->parent() && this->parent()->CanBeExpression() &&
315 : this->parent()
316 : ->AsExpressionParsingScope()
317 312112603 : ->has_async_arrow_in_scope_chain_)) {
318 : DCHECK(this->CanBeExpression());
319 : clear(kExpressionIndex);
320 : clear(kPatternIndex);
321 57997663 : }
322 :
323 : void RecordAsyncArrowParametersError(const Scanner::Location& loc,
324 : MessageTemplate message) {
325 18858 : for (ExpressionScopeT* scope = this; scope != nullptr;
326 : scope = scope->parent()) {
327 16049 : if (!has_async_arrow_in_scope_chain_) break;
328 8098 : if (scope->type_ ==
329 : ExpressionScopeT::kMaybeAsyncArrowParameterDeclaration) {
330 : scope->AsArrowHeadParsingScope()->RecordDeclarationError(loc, message);
331 : }
332 : }
333 : }
334 :
335 108323501 : ~ExpressionParsingScope() { DCHECK(this->has_error() || verified_); }
336 :
337 104463 : ExpressionT ValidateAndRewriteReference(ExpressionT expression, int beg_pos,
338 : int end_pos) {
339 113476 : if (V8_LIKELY(this->parser()->IsAssignableIdentifier(expression))) {
340 93128 : MarkIdentifierAsAssigned();
341 : this->mark_verified();
342 93128 : return expression;
343 11335 : } else if (V8_LIKELY(expression->IsProperty())) {
344 : ValidateExpression();
345 2322 : return expression;
346 : }
347 : this->mark_verified();
348 : return this->parser()->RewriteInvalidReferenceExpression(
349 : expression, beg_pos, end_pos, MessageTemplate::kInvalidLhsInFor,
350 9013 : kSyntaxError);
351 : }
352 :
353 : void RecordExpressionError(const Scanner::Location& loc,
354 : MessageTemplate message) {
355 : Record(kExpressionIndex, loc, message);
356 : }
357 :
358 : void RecordPatternError(const Scanner::Location& loc,
359 : MessageTemplate message) {
360 : Record(kPatternIndex, loc, message);
361 : }
362 :
363 57721986 : void ValidateExpression() { Validate(kExpressionIndex); }
364 :
365 350119 : void ValidatePattern(ExpressionT expression, int begin, int end) {
366 234868 : Validate(kPatternIndex);
367 354485 : if (expression->is_parenthesized()) {
368 : ExpressionScopeT::Report(Scanner::Location(begin, end),
369 3414 : MessageTemplate::kInvalidDestructuringTarget);
370 : }
371 770096 : for (int i = 0; i < variable_list_.length(); i++) {
372 770096 : variable_list_.at(i)->set_is_assigned();
373 : }
374 234868 : }
375 :
376 : void ClearExpressionError() {
377 : DCHECK(verified_);
378 : #ifdef DEBUG
379 : verified_ = false;
380 : #endif
381 : clear(kExpressionIndex);
382 : }
383 :
384 48183263 : void TrackVariable(VariableProxy* variable) {
385 96366526 : if (!this->CanBeDeclaration()) {
386 44648971 : this->parser()->scope()->AddUnresolved(variable);
387 : }
388 48182835 : variable_list_.Add(variable);
389 48181570 : }
390 :
391 4243369 : void MarkIdentifierAsAssigned() {
392 : // It's possible we're parsing a syntax error. In that case it's not
393 : // guaranteed that there's a variable in the list.
394 16971131 : if (variable_list_.length() == 0) return;
395 4241024 : variable_list_.at(variable_list_.length() - 1)->set_is_assigned();
396 : }
397 :
398 : protected:
399 : bool is_verified() const {
400 : #ifdef DEBUG
401 : return verified_;
402 : #else
403 : return false;
404 : #endif
405 : }
406 :
407 420056 : void ValidatePattern() { Validate(kPatternIndex); }
408 :
409 : ScopedPtrList<VariableProxy>* variable_list() { return &variable_list_; }
410 :
411 : private:
412 : friend class AccumulationScope<Types>;
413 :
414 : enum ErrorNumber : uint8_t {
415 : kExpressionIndex = 0,
416 : kPatternIndex = 1,
417 : kNumberOfErrors = 2,
418 : };
419 : void clear(int index) {
420 318145179 : messages_[index] = MessageTemplate::kNone;
421 318145179 : locations_[index] = Scanner::Location::invalid();
422 : }
423 163710260 : bool is_valid(int index) const { return !locations_[index].IsValid(); }
424 : void Record(int index, const Scanner::Location& loc,
425 : MessageTemplate message) {
426 : DCHECK_IMPLIES(!this->has_error(), loc.IsValid());
427 10666011 : if (!is_valid(index)) return;
428 7907685 : messages_[index] = message;
429 7907685 : locations_[index] = loc;
430 : }
431 58374544 : void Validate(int index) {
432 : DCHECK(!this->is_verified());
433 58374544 : if (!is_valid(index)) Report(index);
434 : this->mark_verified();
435 58374544 : }
436 : void Report(int index) const {
437 26341 : ExpressionScopeT::Report(locations_[index], messages_[index]);
438 : }
439 :
440 : // Debug verification to make sure every scope is validated exactly once.
441 : void mark_verified() {
442 : #ifdef DEBUG
443 : verified_ = true;
444 : #endif
445 : }
446 : void clear_verified() {
447 : #ifdef DEBUG
448 : verified_ = false;
449 : #endif
450 : }
451 : #ifdef DEBUG
452 : bool verified_ = false;
453 : #endif
454 :
455 : ScopedPtrList<VariableProxy> variable_list_;
456 : MessageTemplate messages_[kNumberOfErrors];
457 : Scanner::Location locations_[kNumberOfErrors];
458 : bool has_async_arrow_in_scope_chain_;
459 :
460 : DISALLOW_COPY_AND_ASSIGN(ExpressionParsingScope);
461 : };
462 :
463 : // This class is used to parse multiple ambiguous expressions and declarations
464 : // in the same scope. E.g., in async(X,Y,Z) or [X,Y,Z], X and Y and Z will all
465 : // be parsed in the respective outer ArrowHeadParsingScope and
466 : // ExpressionParsingScope. It provides a clean error state in the underlying
467 : // scope to parse the individual expressions, while keeping track of the
468 : // expression and pattern errors since the start. The AccumulationScope is only
469 : // used to keep track of the errors so far, and the underlying ExpressionScope
470 : // keeps being used as the expression_scope(). If the expression_scope() isn't
471 : // ambiguous, this class does not do anything.
472 : template <typename Types>
473 : class AccumulationScope {
474 : public:
475 : typedef typename Types::Impl ParserT;
476 :
477 : static const int kNumberOfErrors =
478 : ExpressionParsingScope<Types>::kNumberOfErrors;
479 158732700 : explicit AccumulationScope(ExpressionScope<Types>* scope) : scope_(nullptr) {
480 105824860 : if (!scope->CanBeExpression()) return;
481 52670529 : scope_ = scope->AsExpressionParsingScope();
482 157936492 : for (int i = 0; i < kNumberOfErrors; i++) {
483 : // If the underlying scope is already invalid at the start, stop
484 : // accumulating. That means an error was found outside of an
485 : // accumulating path.
486 105335716 : if (!scope_->is_valid(i)) {
487 69753 : scope_ = nullptr;
488 69753 : break;
489 : }
490 : copy(i);
491 : }
492 : }
493 :
494 : // Merge errors from the underlying ExpressionParsingScope into this scope.
495 : // Only keeps the first error across all accumulate calls, and removes the
496 : // error from the underlying scope.
497 105112527 : void Accumulate() {
498 210225054 : if (scope_ == nullptr) return;
499 : DCHECK(!scope_->is_verified());
500 201671954 : for (int i = 0; i < kNumberOfErrors; i++) {
501 403343908 : if (!locations_[i].IsValid()) copy(i);
502 201671954 : scope_->clear(i);
503 : }
504 : }
505 :
506 : // This is called instead of Accumulate in case the parsed member is already
507 : // known to be an expression. In that case we don't need to accumulate the
508 : // expression but rather validate it immediately. We also ignore the pattern
509 : // error since the parsed member is known to not be a pattern. This is
510 : // necessary for "{x:1}.y" parsed as part of an assignment pattern. {x:1} will
511 : // record a pattern error, but "{x:1}.y" is actually a valid as part of an
512 : // assignment pattern since it's a property access.
513 295890 : void ValidateExpression() {
514 591777 : if (scope_ == nullptr) return;
515 : DCHECK(!scope_->is_verified());
516 : scope_->ValidateExpression();
517 : DCHECK(scope_->is_verified());
518 295300 : scope_->clear(ExpressionParsingScope<Types>::kPatternIndex);
519 : #ifdef DEBUG
520 : scope_->clear_verified();
521 : #endif
522 : }
523 :
524 52911729 : ~AccumulationScope() {
525 52911729 : if (scope_ == nullptr) return;
526 52597704 : Accumulate();
527 157787247 : for (int i = 0; i < kNumberOfErrors; i++) copy_back(i);
528 52912272 : }
529 :
530 : private:
531 : void copy(int entry) {
532 299207123 : messages_[entry] = scope_->messages_[entry];
533 299207123 : locations_[entry] = scope_->locations_[entry];
534 : }
535 :
536 : void copy_back(int entry) {
537 210378000 : if (!locations_[entry].IsValid()) return;
538 1988880 : scope_->messages_[entry] = messages_[entry];
539 1988880 : scope_->locations_[entry] = locations_[entry];
540 : }
541 :
542 : ExpressionParsingScope<Types>* scope_;
543 : MessageTemplate messages_[2];
544 : Scanner::Location locations_[2];
545 :
546 : DISALLOW_COPY_AND_ASSIGN(AccumulationScope);
547 : };
548 :
549 : // The head of an arrow function is ambiguous between expression, assignment
550 : // pattern and declaration. This keeps track of the additional declaration
551 : // error and allows the scope to be validated as a declaration rather than an
552 : // expression or a pattern.
553 : template <typename Types>
554 : class ArrowHeadParsingScope : public ExpressionParsingScope<Types> {
555 : public:
556 : typedef typename Types::Impl ParserT;
557 : typedef typename ExpressionScope<Types>::ScopeType ScopeType;
558 :
559 : ArrowHeadParsingScope(ParserT* parser, FunctionKind kind)
560 : : ExpressionParsingScope<Types>(
561 : parser,
562 : kind == FunctionKind::kArrowFunction
563 : ? ExpressionScope<Types>::kMaybeArrowParameterDeclaration
564 : : ExpressionScope<
565 3362005 : Types>::kMaybeAsyncArrowParameterDeclaration) {
566 : DCHECK(kind == FunctionKind::kAsyncArrowFunction ||
567 : kind == FunctionKind::kArrowFunction);
568 : DCHECK(this->CanBeDeclaration());
569 : DCHECK(!this->IsCertainlyDeclaration());
570 : }
571 :
572 2941905 : void ValidateExpression() {
573 : // Turns out this is not an arrow head. Clear any possible tracked strict
574 : // parameter errors, and reinterpret tracked variables as unresolved
575 : // references.
576 5999831 : this->parser()->next_arrow_function_info_.ClearStrictParameterError();
577 2941905 : ExpressionParsingScope<Types>::ValidateExpression();
578 11999728 : for (int i = 0; i < this->variable_list()->length(); i++) {
579 6115852 : this->parser()->scope()->AddUnresolved(this->variable_list()->at(i));
580 : }
581 2941938 : }
582 :
583 420056 : DeclarationScope* ValidateAndCreateScope() {
584 : DCHECK(!this->is_verified());
585 420056 : if (declaration_error_location.IsValid()) {
586 : ExpressionScope<Types>::Report(declaration_error_location,
587 435493 : declaration_error_message);
588 : }
589 420056 : this->ValidatePattern();
590 :
591 840122 : DeclarationScope* result = this->parser()->NewFunctionScope(kind());
592 420082 : if (!has_simple_parameter_list_) result->SetHasNonSimpleParameters();
593 : // TODO(verwaest): Add declarations.
594 420082 : return result;
595 : }
596 :
597 : void RecordDeclarationError(const Scanner::Location& loc,
598 : MessageTemplate message) {
599 : DCHECK_IMPLIES(!this->has_error(), loc.IsValid());
600 2856598 : declaration_error_location = loc;
601 2856598 : declaration_error_message = message;
602 : }
603 :
604 196970 : void RecordNonSimpleParameter() { has_simple_parameter_list_ = false; }
605 :
606 : private:
607 : FunctionKind kind() const {
608 : return this->IsAsyncArrowHeadParsingScope()
609 420061 : ? FunctionKind::kAsyncArrowFunction
610 420061 : : FunctionKind::kArrowFunction;
611 : }
612 :
613 : Scanner::Location declaration_error_location = Scanner::Location::invalid();
614 : MessageTemplate declaration_error_message = MessageTemplate::kNone;
615 : bool has_simple_parameter_list_ = true;
616 :
617 : DISALLOW_COPY_AND_ASSIGN(ArrowHeadParsingScope);
618 : };
619 :
620 : } // namespace internal
621 : } // namespace v8
622 :
623 : #endif // V8_PARSING_EXPRESSION_SCOPE_H_
|