Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_PREPARSER_H | 5 #ifndef V8_PREPARSER_H |
| 6 #define V8_PREPARSER_H | 6 #define V8_PREPARSER_H |
| 7 | 7 |
| 8 #include "src/v8.h" | 8 #include "src/v8.h" |
| 9 | 9 |
| 10 #include "src/bailout-reason.h" | 10 #include "src/bailout-reason.h" |
| (...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 574 | 574 |
| 575 void ReportMessageAt(Scanner::Location location, const char* message, | 575 void ReportMessageAt(Scanner::Location location, const char* message, |
| 576 ParseErrorType error_type = kSyntaxError) { | 576 ParseErrorType error_type = kSyntaxError) { |
| 577 Traits::ReportMessageAt(location, message, reinterpret_cast<const char*>(0), | 577 Traits::ReportMessageAt(location, message, reinterpret_cast<const char*>(0), |
| 578 error_type); | 578 error_type); |
| 579 } | 579 } |
| 580 | 580 |
| 581 void ReportUnexpectedToken(Token::Value token); | 581 void ReportUnexpectedToken(Token::Value token); |
| 582 void ReportUnexpectedTokenAt(Scanner::Location location, Token::Value token); | 582 void ReportUnexpectedTokenAt(Scanner::Location location, Token::Value token); |
| 583 | 583 |
| 584 class ExpressionClassifier { | |
| 585 public: | |
| 586 struct Error { | |
| 587 Error() | |
| 588 : location(Scanner::Location::invalid()), | |
| 589 message(nullptr), | |
| 590 arg(nullptr) {} | |
| 591 | |
| 592 Scanner::Location location; | |
| 593 const char* message; | |
| 594 const char* arg; | |
| 595 | |
| 596 bool HasError() const { return location.IsValid(); } | |
| 597 }; | |
| 598 | |
| 599 ExpressionClassifier() {} | |
| 600 | |
| 601 bool is_valid_expression() const { return !expression_error_.HasError(); } | |
| 602 | |
| 603 bool is_valid_binding_pattern() const { | |
| 604 return !binding_pattern_error_.HasError(); | |
| 605 } | |
| 606 | |
| 607 bool is_valid_assignment_pattern() const { | |
| 608 return !assignment_pattern_error_.HasError(); | |
| 609 } | |
| 610 | |
| 611 const Error& expression_error() const { return expression_error_; } | |
| 612 | |
| 613 const Error& binding_pattern_error() const { | |
| 614 return binding_pattern_error_; | |
| 615 } | |
| 616 | |
| 617 const Error& assignment_pattern_error() const { | |
| 618 return assignment_pattern_error_; | |
| 619 } | |
| 620 | |
| 621 | |
|
arv (Not doing code reviews)
2015/04/27 13:59:24
nit: -1 newline
Dmitry Lomov (no reviews)
2015/04/27 14:09:16
Done.
| |
| 622 void RecordExpressionError(const Scanner::Location& loc, | |
| 623 const char* message, const char* arg = nullptr) { | |
| 624 if (!is_valid_expression()) return; | |
| 625 expression_error_.location = loc; | |
| 626 expression_error_.message = message; | |
| 627 expression_error_.arg = arg; | |
| 628 } | |
| 629 | |
| 630 void RecordBindingPatternError(const Scanner::Location& loc, | |
| 631 const char* message, | |
| 632 const char* arg = nullptr) { | |
| 633 if (!is_valid_binding_pattern()) return; | |
| 634 binding_pattern_error_.location = loc; | |
| 635 binding_pattern_error_.message = message; | |
| 636 binding_pattern_error_.arg = arg; | |
| 637 } | |
| 638 | |
| 639 void RecordAssignmentPatternError(const Scanner::Location& loc, | |
| 640 const char* message, | |
| 641 const char* arg = nullptr) { | |
| 642 if (!is_valid_assignment_pattern()) return; | |
| 643 assignment_pattern_error_.location = loc; | |
| 644 assignment_pattern_error_.message = message; | |
| 645 assignment_pattern_error_.arg = arg; | |
| 646 } | |
| 647 | |
| 648 private: | |
| 649 Error expression_error_; | |
| 650 Error binding_pattern_error_; | |
| 651 Error assignment_pattern_error_; | |
| 652 }; | |
| 653 | |
| 654 void ReportClassifierError( | |
| 655 const typename ExpressionClassifier::Error& error) { | |
| 656 Traits::ReportMessageAt(error.location, error.message, error.arg, | |
| 657 kSyntaxError); | |
| 658 } | |
| 659 | |
| 660 void ValidateExpression(const ExpressionClassifier* classifier, bool* ok) { | |
| 661 if (!classifier->is_valid_expression()) { | |
| 662 ReportClassifierError(classifier->expression_error()); | |
| 663 *ok = false; | |
| 664 } | |
| 665 } | |
| 666 | |
| 667 void ValidateBindingPattern(const ExpressionClassifier* classifier, | |
| 668 bool* ok) { | |
| 669 if (!classifier->is_valid_binding_pattern()) { | |
| 670 ReportClassifierError(classifier->binding_pattern_error()); | |
| 671 *ok = false; | |
| 672 } | |
| 673 } | |
| 674 | |
| 675 | |
|
arv (Not doing code reviews)
2015/04/27 13:59:24
inconsistent newlines
Dmitry Lomov (no reviews)
2015/04/27 14:09:16
Done.
| |
| 676 void ValidateAssignmentPattern(const ExpressionClassifier* classifier, | |
| 677 bool* ok) { | |
| 678 if (!classifier->is_valid_assignment_pattern()) { | |
| 679 ReportClassifierError(classifier->assignment_pattern_error()); | |
| 680 *ok = false; | |
| 681 } | |
| 682 } | |
| 683 | |
| 684 | |
| 584 // Recursive descent functions: | 685 // Recursive descent functions: |
| 585 | 686 |
| 586 // Parses an identifier that is valid for the current scope, in particular it | 687 // Parses an identifier that is valid for the current scope, in particular it |
| 587 // fails on strict mode future reserved keywords in a strict scope. If | 688 // fails on strict mode future reserved keywords in a strict scope. If |
| 588 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or | 689 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or |
| 589 // "arguments" as identifier even in strict mode (this is needed in cases like | 690 // "arguments" as identifier even in strict mode (this is needed in cases like |
| 590 // "var foo = eval;"). | 691 // "var foo = eval;"). |
| 591 IdentifierT ParseIdentifier(AllowRestrictedIdentifiers, bool* ok); | 692 IdentifierT ParseIdentifier(AllowRestrictedIdentifiers, bool* ok); |
| 693 IdentifierT ParseAndClassifyIdentifier(ExpressionClassifier* classifier, | |
| 694 bool* ok); | |
| 592 // Parses an identifier or a strict mode future reserved word, and indicate | 695 // Parses an identifier or a strict mode future reserved word, and indicate |
| 593 // whether it is strict mode future reserved. | 696 // whether it is strict mode future reserved. |
| 594 IdentifierT ParseIdentifierOrStrictReservedWord( | 697 IdentifierT ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, |
| 595 bool* is_strict_reserved, | 698 bool* ok); |
| 596 bool* ok); | |
| 597 IdentifierT ParseIdentifierName(bool* ok); | 699 IdentifierT ParseIdentifierName(bool* ok); |
| 598 // Parses an identifier and determines whether or not it is 'get' or 'set'. | 700 // Parses an identifier and determines whether or not it is 'get' or 'set'. |
| 599 IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get, | 701 IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get, bool* is_set, |
| 600 bool* is_set, | |
| 601 bool* ok); | 702 bool* ok); |
| 602 | 703 |
| 603 | 704 |
| 604 class ExpressionClassifier { | |
| 605 public: | |
| 606 ExpressionClassifier() | |
| 607 : expression_error_(Scanner::Location::invalid()), | |
| 608 binding_pattern_error_(Scanner::Location::invalid()), | |
| 609 assignment_pattern_error_(Scanner::Location::invalid()) {} | |
| 610 | |
| 611 bool is_valid_expression() const { | |
| 612 return expression_error_ == Scanner::Location::invalid(); | |
| 613 } | |
| 614 | |
| 615 bool is_valid_binding_pattern() const { | |
| 616 return binding_pattern_error_ == Scanner::Location::invalid(); | |
| 617 } | |
| 618 | |
| 619 bool is_valid_assignmnent_pattern() const { | |
| 620 return assignment_pattern_error_ == Scanner::Location::invalid(); | |
| 621 } | |
| 622 | |
| 623 void RecordExpressionError(const Scanner::Location& loc) { | |
| 624 if (!is_valid_expression()) return; | |
| 625 expression_error_ = loc; | |
| 626 } | |
| 627 | |
| 628 void RecordBindingPatternError(const Scanner::Location& loc) { | |
| 629 if (!is_valid_binding_pattern()) return; | |
| 630 binding_pattern_error_ = loc; | |
| 631 } | |
| 632 | |
| 633 void RecordAssignmentPatternError(const Scanner::Location& loc) { | |
| 634 if (!is_valid_assignmnent_pattern()) return; | |
| 635 assignment_pattern_error_ = loc; | |
| 636 } | |
| 637 | |
| 638 private: | |
| 639 Scanner::Location expression_error_; | |
| 640 Scanner::Location binding_pattern_error_; | |
| 641 Scanner::Location assignment_pattern_error_; | |
| 642 }; | |
| 643 | |
| 644 ExpressionT ParseRegExpLiteral(bool seen_equal, | 705 ExpressionT ParseRegExpLiteral(bool seen_equal, |
| 645 ExpressionClassifier* classifier, bool* ok); | 706 ExpressionClassifier* classifier, bool* ok); |
| 646 | 707 |
| 647 ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier, | 708 ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier, |
| 648 bool* ok); | 709 bool* ok); |
| 649 ExpressionT ParseExpression(bool accept_IN, bool* ok); | 710 ExpressionT ParseExpression(bool accept_IN, bool* ok); |
| 650 ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier, | 711 ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier, |
| 651 bool* ok); | 712 bool* ok); |
| 652 ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok); | 713 ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok); |
| 653 ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set, | 714 ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set, |
| (...skipping 1299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1953 const char* name = Token::String(token); | 2014 const char* name = Token::String(token); |
| 1954 DCHECK(name != NULL); | 2015 DCHECK(name != NULL); |
| 1955 Traits::ReportMessageAt(source_location, "unexpected_token", name); | 2016 Traits::ReportMessageAt(source_location, "unexpected_token", name); |
| 1956 } | 2017 } |
| 1957 } | 2018 } |
| 1958 | 2019 |
| 1959 | 2020 |
| 1960 template <class Traits> | 2021 template <class Traits> |
| 1961 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier( | 2022 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier( |
| 1962 AllowRestrictedIdentifiers allow_restricted_identifiers, bool* ok) { | 2023 AllowRestrictedIdentifiers allow_restricted_identifiers, bool* ok) { |
| 2024 ExpressionClassifier classifier; | |
| 2025 auto result = ParseAndClassifyIdentifier(&classifier, ok); | |
| 2026 if (!*ok) return Traits::EmptyIdentifier(); | |
| 2027 | |
| 2028 if (allow_restricted_identifiers == kDontAllowRestrictedIdentifiers) { | |
| 2029 ValidateAssignmentPattern(&classifier, ok); | |
| 2030 if (!*ok) return Traits::EmptyIdentifier(); | |
| 2031 ValidateBindingPattern(&classifier, ok); | |
| 2032 if (!*ok) return Traits::EmptyIdentifier(); | |
| 2033 } else { | |
| 2034 ValidateExpression(&classifier, ok); | |
| 2035 if (!*ok) return Traits::EmptyIdentifier(); | |
| 2036 } | |
| 2037 | |
| 2038 return result; | |
| 2039 } | |
| 2040 | |
| 2041 | |
| 2042 template <class Traits> | |
| 2043 typename ParserBase<Traits>::IdentifierT | |
| 2044 ParserBase<Traits>::ParseAndClassifyIdentifier(ExpressionClassifier* classifier, | |
| 2045 bool* ok) { | |
| 1963 Token::Value next = Next(); | 2046 Token::Value next = Next(); |
| 1964 if (next == Token::IDENTIFIER) { | 2047 if (next == Token::IDENTIFIER) { |
| 1965 IdentifierT name = this->GetSymbol(scanner()); | 2048 IdentifierT name = this->GetSymbol(scanner()); |
| 1966 if (allow_restricted_identifiers == kDontAllowRestrictedIdentifiers) { | 2049 if (is_strict(language_mode()) && this->IsEvalOrArguments(name)) { |
| 1967 if (is_strict(language_mode()) && this->IsEvalOrArguments(name)) { | 2050 classifier->RecordBindingPatternError(scanner()->location(), |
| 1968 ReportMessage("strict_eval_arguments"); | 2051 "strict_eval_arguments"); |
| 1969 *ok = false; | 2052 } |
| 1970 } | 2053 if (is_strong(language_mode()) && this->IsUndefined(name)) { |
| 1971 if (is_strong(language_mode()) && this->IsUndefined(name)) { | 2054 // TODO(dslomov): allow 'undefined' in nested patterns. |
| 1972 ReportMessage("strong_undefined"); | 2055 classifier->RecordBindingPatternError(scanner()->location(), |
| 1973 *ok = false; | 2056 "strong_undefined"); |
| 1974 } | 2057 classifier->RecordAssignmentPatternError(scanner()->location(), |
| 1975 } else { | 2058 "strong_undefined"); |
| 1976 if (is_strong(language_mode()) && this->IsArguments(name)) { | 2059 } |
| 1977 ReportMessage("strong_arguments"); | 2060 if (is_strong(language_mode()) && this->IsArguments(name)) { |
| 1978 *ok = false; | 2061 classifier->RecordExpressionError(scanner()->location(), |
| 1979 } | 2062 "strong_arguments"); |
| 1980 } | 2063 } |
| 1981 if (this->IsArguments(name)) scope_->RecordArgumentsUsage(); | 2064 if (this->IsArguments(name)) scope_->RecordArgumentsUsage(); |
| 1982 return name; | 2065 return name; |
| 1983 } else if (is_sloppy(language_mode()) && | 2066 } else if (is_sloppy(language_mode()) && |
| 1984 (next == Token::FUTURE_STRICT_RESERVED_WORD || | 2067 (next == Token::FUTURE_STRICT_RESERVED_WORD || |
| 1985 next == Token::LET || next == Token::STATIC || | 2068 next == Token::LET || next == Token::STATIC || |
| 1986 (next == Token::YIELD && !is_generator()))) { | 2069 (next == Token::YIELD && !is_generator()))) { |
| 1987 return this->GetSymbol(scanner()); | 2070 return this->GetSymbol(scanner()); |
| 1988 } else { | 2071 } else { |
| 1989 this->ReportUnexpectedToken(next); | 2072 this->ReportUnexpectedToken(next); |
| 1990 *ok = false; | 2073 *ok = false; |
| 1991 return Traits::EmptyIdentifier(); | 2074 return Traits::EmptyIdentifier(); |
| 1992 } | 2075 } |
| 1993 } | 2076 } |
| 1994 | 2077 |
| 2078 | |
| 1995 template <class Traits> | 2079 template <class Traits> |
| 1996 typename ParserBase<Traits>::IdentifierT ParserBase< | 2080 typename ParserBase<Traits>::IdentifierT ParserBase< |
| 1997 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, | 2081 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, |
| 1998 bool* ok) { | 2082 bool* ok) { |
| 1999 Token::Value next = Next(); | 2083 Token::Value next = Next(); |
| 2000 if (next == Token::IDENTIFIER) { | 2084 if (next == Token::IDENTIFIER) { |
| 2001 *is_strict_reserved = false; | 2085 *is_strict_reserved = false; |
| 2002 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET || | 2086 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET || |
| 2003 next == Token::STATIC || | 2087 next == Token::STATIC || |
| 2004 (next == Token::YIELD && !this->is_generator())) { | 2088 (next == Token::YIELD && !this->is_generator())) { |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2134 result = | 2218 result = |
| 2135 this->ExpressionFromLiteral(token, beg_pos, scanner(), factory()); | 2219 this->ExpressionFromLiteral(token, beg_pos, scanner(), factory()); |
| 2136 break; | 2220 break; |
| 2137 | 2221 |
| 2138 case Token::IDENTIFIER: | 2222 case Token::IDENTIFIER: |
| 2139 case Token::LET: | 2223 case Token::LET: |
| 2140 case Token::STATIC: | 2224 case Token::STATIC: |
| 2141 case Token::YIELD: | 2225 case Token::YIELD: |
| 2142 case Token::FUTURE_STRICT_RESERVED_WORD: { | 2226 case Token::FUTURE_STRICT_RESERVED_WORD: { |
| 2143 // Using eval or arguments in this context is OK even in strict mode. | 2227 // Using eval or arguments in this context is OK even in strict mode. |
| 2144 IdentifierT name = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | 2228 IdentifierT name = ParseAndClassifyIdentifier(classifier, CHECK_OK); |
| 2145 result = this->ExpressionFromIdentifier(name, beg_pos, end_pos, scope_, | 2229 result = this->ExpressionFromIdentifier(name, beg_pos, end_pos, scope_, |
| 2146 factory()); | 2230 factory()); |
| 2147 break; | 2231 break; |
| 2148 } | 2232 } |
| 2149 | 2233 |
| 2150 case Token::STRING: { | 2234 case Token::STRING: { |
| 2151 Consume(Token::STRING); | 2235 Consume(Token::STRING); |
| 2152 result = this->ExpressionFromString(beg_pos, scanner(), factory()); | 2236 result = this->ExpressionFromString(beg_pos, scanner(), factory()); |
| 2153 break; | 2237 break; |
| 2154 } | 2238 } |
| 2155 | 2239 |
| 2156 case Token::ASSIGN_DIV: | 2240 case Token::ASSIGN_DIV: |
| 2157 result = this->ParseRegExpLiteral(true, classifier, CHECK_OK); | 2241 result = this->ParseRegExpLiteral(true, classifier, CHECK_OK); |
| 2158 break; | 2242 break; |
| 2159 | 2243 |
| 2160 case Token::DIV: | 2244 case Token::DIV: |
| 2161 result = this->ParseRegExpLiteral(false, classifier, CHECK_OK); | 2245 result = this->ParseRegExpLiteral(false, classifier, CHECK_OK); |
| 2162 break; | 2246 break; |
| 2163 | 2247 |
| 2164 case Token::LBRACK: | 2248 case Token::LBRACK: |
| 2165 result = this->ParseArrayLiteral(classifier, CHECK_OK); | 2249 result = this->ParseArrayLiteral(classifier, CHECK_OK); |
| 2166 break; | 2250 break; |
| 2167 | 2251 |
| 2168 case Token::LBRACE: | 2252 case Token::LBRACE: |
| 2169 result = this->ParseObjectLiteral(classifier, CHECK_OK); | 2253 result = this->ParseObjectLiteral(classifier, CHECK_OK); |
| 2170 break; | 2254 break; |
| 2171 | 2255 |
| 2172 case Token::LPAREN: | 2256 case Token::LPAREN: |
| 2173 Consume(Token::LPAREN); | 2257 Consume(Token::LPAREN); |
| 2258 classifier->RecordBindingPatternError(scanner()->location(), | |
| 2259 "unexpected_token", "("); | |
| 2260 classifier->RecordAssignmentPatternError(scanner()->location(), | |
| 2261 "unexpected_token", "("); | |
| 2174 if (allow_harmony_arrow_functions() && Check(Token::RPAREN)) { | 2262 if (allow_harmony_arrow_functions() && Check(Token::RPAREN)) { |
| 2175 // As a primary expression, the only thing that can follow "()" is "=>". | 2263 // As a primary expression, the only thing that can follow "()" is "=>". |
| 2176 Scope* scope = this->NewScope(scope_, ARROW_SCOPE); | 2264 Scope* scope = this->NewScope(scope_, ARROW_SCOPE); |
| 2177 scope->set_start_position(beg_pos); | 2265 scope->set_start_position(beg_pos); |
| 2178 FormalParameterErrorLocations error_locs; | 2266 FormalParameterErrorLocations error_locs; |
| 2179 bool has_rest = false; | 2267 bool has_rest = false; |
| 2180 result = this->ParseArrowFunctionLiteral(scope, error_locs, has_rest, | 2268 result = this->ParseArrowFunctionLiteral(scope, error_locs, has_rest, |
| 2181 classifier, CHECK_OK); | 2269 classifier, CHECK_OK); |
| 2182 } else { | 2270 } else { |
| 2183 // Heuristically try to detect immediately called functions before | 2271 // Heuristically try to detect immediately called functions before |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2234 | 2322 |
| 2235 return result; | 2323 return result; |
| 2236 } | 2324 } |
| 2237 | 2325 |
| 2238 | 2326 |
| 2239 template <class Traits> | 2327 template <class Traits> |
| 2240 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( | 2328 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( |
| 2241 bool accept_IN, bool* ok) { | 2329 bool accept_IN, bool* ok) { |
| 2242 ExpressionClassifier classifier; | 2330 ExpressionClassifier classifier; |
| 2243 ExpressionT result = ParseExpression(accept_IN, &classifier, CHECK_OK); | 2331 ExpressionT result = ParseExpression(accept_IN, &classifier, CHECK_OK); |
| 2244 // TODO(dslomov): report error if not a valid expression. | 2332 ValidateExpression(&classifier, CHECK_OK); |
| 2245 return result; | 2333 return result; |
| 2246 } | 2334 } |
| 2247 | 2335 |
| 2248 | 2336 |
| 2249 // Precedence = 1 | 2337 // Precedence = 1 |
| 2250 template <class Traits> | 2338 template <class Traits> |
| 2251 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( | 2339 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( |
| 2252 bool accept_IN, ExpressionClassifier* classifier, bool* ok) { | 2340 bool accept_IN, ExpressionClassifier* classifier, bool* ok) { |
| 2253 // Expression :: | 2341 // Expression :: |
| 2254 // AssignmentExpression | 2342 // AssignmentExpression |
| (...skipping 1458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3713 *ok = false; | 3801 *ok = false; |
| 3714 return; | 3802 return; |
| 3715 } | 3803 } |
| 3716 has_seen_constructor_ = true; | 3804 has_seen_constructor_ = true; |
| 3717 return; | 3805 return; |
| 3718 } | 3806 } |
| 3719 } | 3807 } |
| 3720 } } // v8::internal | 3808 } } // v8::internal |
| 3721 | 3809 |
| 3722 #endif // V8_PREPARSER_H | 3810 #endif // V8_PREPARSER_H |
| OLD | NEW |