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_PARSING_PARSER_BASE_H | 5 #ifndef V8_PARSING_PARSER_BASE_H |
| 6 #define V8_PARSING_PARSER_BASE_H | 6 #define V8_PARSING_PARSER_BASE_H |
| 7 | 7 |
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/bailout-reason.h" | 9 #include "src/bailout-reason.h" |
| 10 #include "src/hashmap.h" | 10 #include "src/hashmap.h" |
| (...skipping 794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 805 // Checks if the expression is a valid reference expression (e.g., on the | 805 // Checks if the expression is a valid reference expression (e.g., on the |
| 806 // left-hand side of assignments). Although ruled out by ECMA as early errors, | 806 // left-hand side of assignments). Although ruled out by ECMA as early errors, |
| 807 // we allow calls for web compatibility and rewrite them to a runtime throw. | 807 // we allow calls for web compatibility and rewrite them to a runtime throw. |
| 808 ExpressionT CheckAndRewriteReferenceExpression( | 808 ExpressionT CheckAndRewriteReferenceExpression( |
| 809 ExpressionT expression, int beg_pos, int end_pos, | 809 ExpressionT expression, int beg_pos, int end_pos, |
| 810 MessageTemplate::Template message, bool* ok); | 810 MessageTemplate::Template message, bool* ok); |
| 811 ExpressionT ClassifyAndRewriteReferenceExpression( | 811 ExpressionT ClassifyAndRewriteReferenceExpression( |
| 812 ExpressionClassifier* classifier, ExpressionT expression, int beg_pos, | 812 ExpressionClassifier* classifier, ExpressionT expression, int beg_pos, |
| 813 int end_pos, MessageTemplate::Template message, | 813 int end_pos, MessageTemplate::Template message, |
| 814 ParseErrorType type = kSyntaxError); | 814 ParseErrorType type = kSyntaxError); |
| 815 void ClassifyReferenceExpression(ExpressionClassifier* classifier, | |
| 816 ExpressionT expression, int beg_pos, | |
| 817 int end_pos); | |
| 815 ExpressionT CheckAndRewriteReferenceExpression( | 818 ExpressionT CheckAndRewriteReferenceExpression( |
| 816 ExpressionT expression, int beg_pos, int end_pos, | 819 ExpressionT expression, int beg_pos, int end_pos, |
| 817 MessageTemplate::Template message, ParseErrorType type, bool* ok); | 820 MessageTemplate::Template message, ParseErrorType type, bool* ok); |
| 818 | 821 |
| 819 bool IsValidReferenceExpression(ExpressionT expression); | 822 bool IsValidReferenceExpression(ExpressionT expression); |
| 820 | 823 |
| 821 bool IsAssignableIdentifier(ExpressionT expression) { | 824 bool IsAssignableIdentifier(ExpressionT expression) { |
| 822 if (!Traits::IsIdentifier(expression)) return false; | 825 if (!Traits::IsIdentifier(expression)) return false; |
| 823 if (is_strict(language_mode()) && | 826 if (is_strict(language_mode()) && |
| 824 Traits::IsEvalOrArguments(Traits::AsIdentifier(expression))) { | 827 Traits::IsEvalOrArguments(Traits::AsIdentifier(expression))) { |
| (...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1510 MessageTemplate::kStrongEllision); | 1513 MessageTemplate::kStrongEllision); |
| 1511 *ok = false; | 1514 *ok = false; |
| 1512 return this->EmptyExpression(); | 1515 return this->EmptyExpression(); |
| 1513 } | 1516 } |
| 1514 elem = this->GetLiteralTheHole(peek_position(), factory()); | 1517 elem = this->GetLiteralTheHole(peek_position(), factory()); |
| 1515 } else if (peek() == Token::ELLIPSIS) { | 1518 } else if (peek() == Token::ELLIPSIS) { |
| 1516 int start_pos = peek_position(); | 1519 int start_pos = peek_position(); |
| 1517 Consume(Token::ELLIPSIS); | 1520 Consume(Token::ELLIPSIS); |
| 1518 ExpressionT argument = | 1521 ExpressionT argument = |
| 1519 this->ParseAssignmentExpression(true, classifier, CHECK_OK); | 1522 this->ParseAssignmentExpression(true, classifier, CHECK_OK); |
| 1523 ClassifyReferenceExpression(classifier, argument, start_pos, | |
| 1524 scanner()->location().end_pos); | |
| 1520 elem = factory()->NewSpread(argument, start_pos); | 1525 elem = factory()->NewSpread(argument, start_pos); |
| 1521 | 1526 |
| 1522 if (first_spread_index < 0) { | 1527 if (first_spread_index < 0) { |
| 1523 first_spread_index = values->length(); | 1528 first_spread_index = values->length(); |
| 1524 } | 1529 } |
| 1525 | 1530 |
| 1526 CheckDestructuringElement(argument, classifier, start_pos, | 1531 CheckDestructuringElement(argument, classifier, start_pos, |
|
adamk
2015/12/12 01:03:35
I think CheckDestructuringElement is doing the wor
caitp (gmail)
2015/12/12 01:08:14
Yes, there is some redundant stuff here --- as men
adamk
2015/12/12 01:10:44
Would much prefer less duplication to message clar
| |
| 1527 scanner()->location().end_pos); | 1532 scanner()->location().end_pos); |
| 1528 | 1533 |
| 1529 if (peek() == Token::COMMA) { | 1534 if (peek() == Token::COMMA) { |
| 1530 classifier->RecordPatternError( | 1535 classifier->RecordPatternError( |
| 1531 Scanner::Location(start_pos, scanner()->location().end_pos), | 1536 Scanner::Location(start_pos, scanner()->location().end_pos), |
| 1532 MessageTemplate::kElementAfterRest); | 1537 MessageTemplate::kElementAfterRest); |
| 1533 } | 1538 } |
| 1534 } else { | 1539 } else { |
| 1535 elem = this->ParseAssignmentExpression(true, kIsPatternElement, | 1540 elem = this->ParseAssignmentExpression(true, kIsPatternElement, |
| 1536 classifier, CHECK_OK); | 1541 classifier, CHECK_OK); |
| 1542 ClassifyReferenceExpression(classifier, elem, pos, | |
| 1543 scanner()->location().end_pos); | |
| 1537 if (!this->IsValidReferenceExpression(elem) && | 1544 if (!this->IsValidReferenceExpression(elem) && |
| 1538 !classifier->is_valid_assignment_pattern()) { | 1545 !classifier->is_valid_assignment_pattern()) { |
| 1539 classifier->RecordPatternError( | 1546 classifier->RecordPatternError( |
| 1540 Scanner::Location(pos, scanner()->location().end_pos), | 1547 Scanner::Location(pos, scanner()->location().end_pos), |
| 1541 MessageTemplate::kInvalidDestructuringTarget); | 1548 MessageTemplate::kInvalidDestructuringTarget); |
| 1542 } | 1549 } |
| 1543 } | 1550 } |
| 1544 values->Add(elem, zone_); | 1551 values->Add(elem, zone_); |
| 1545 if (peek() != Token::RBRACK) { | 1552 if (peek() != Token::RBRACK) { |
| 1546 Expect(Token::COMMA, CHECK_OK); | 1553 Expect(Token::COMMA, CHECK_OK); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1663 // PropertyName ':' AssignmentExpression | 1670 // PropertyName ':' AssignmentExpression |
| 1664 if (!*is_computed_name) { | 1671 if (!*is_computed_name) { |
| 1665 checker->CheckProperty(name_token, kValueProperty, false, false, | 1672 checker->CheckProperty(name_token, kValueProperty, false, false, |
| 1666 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 1673 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| 1667 } | 1674 } |
| 1668 Consume(Token::COLON); | 1675 Consume(Token::COLON); |
| 1669 int pos = peek_position(); | 1676 int pos = peek_position(); |
| 1670 value = this->ParseAssignmentExpression( | 1677 value = this->ParseAssignmentExpression( |
| 1671 true, kIsPatternElement, classifier, | 1678 true, kIsPatternElement, classifier, |
| 1672 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 1679 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| 1673 | 1680 ClassifyReferenceExpression(classifier, value, pos, |
| 1681 scanner()->location().end_pos); | |
| 1674 if (!this->IsValidReferenceExpression(value) && | 1682 if (!this->IsValidReferenceExpression(value) && |
| 1675 !classifier->is_valid_assignment_pattern()) { | 1683 !classifier->is_valid_assignment_pattern()) { |
| 1676 classifier->RecordPatternError( | 1684 classifier->RecordPatternError( |
| 1677 Scanner::Location(pos, scanner()->location().end_pos), | 1685 Scanner::Location(pos, scanner()->location().end_pos), |
| 1678 MessageTemplate::kInvalidDestructuringTarget); | 1686 MessageTemplate::kInvalidDestructuringTarget); |
| 1679 } | 1687 } |
| 1680 | 1688 |
| 1681 return factory()->NewObjectLiteralProperty(name_expression, value, false, | 1689 return factory()->NewObjectLiteralProperty(name_expression, value, false, |
| 1682 *is_computed_name); | 1690 *is_computed_name); |
| 1683 } | 1691 } |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1704 classifier->RecordDuplicateFormalParameterError(scanner()->location()); | 1712 classifier->RecordDuplicateFormalParameterError(scanner()->location()); |
| 1705 } | 1713 } |
| 1706 if (name_token == Token::LET) { | 1714 if (name_token == Token::LET) { |
| 1707 classifier->RecordLetPatternError( | 1715 classifier->RecordLetPatternError( |
| 1708 scanner()->location(), MessageTemplate::kLetInLexicalBinding); | 1716 scanner()->location(), MessageTemplate::kLetInLexicalBinding); |
| 1709 } | 1717 } |
| 1710 | 1718 |
| 1711 ExpressionT lhs = this->ExpressionFromIdentifier( | 1719 ExpressionT lhs = this->ExpressionFromIdentifier( |
| 1712 name, next_beg_pos, next_end_pos, scope_, factory()); | 1720 name, next_beg_pos, next_end_pos, scope_, factory()); |
| 1713 | 1721 |
| 1722 ClassifyReferenceExpression(classifier, lhs, next_beg_pos, next_end_pos); | |
| 1723 | |
| 1714 if (peek() == Token::ASSIGN) { | 1724 if (peek() == Token::ASSIGN) { |
| 1715 Consume(Token::ASSIGN); | 1725 Consume(Token::ASSIGN); |
| 1716 ExpressionClassifier rhs_classifier; | 1726 ExpressionClassifier rhs_classifier; |
| 1717 ExpressionT rhs = this->ParseAssignmentExpression( | 1727 ExpressionT rhs = this->ParseAssignmentExpression( |
| 1718 true, &rhs_classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | 1728 true, &rhs_classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); |
| 1719 classifier->Accumulate(rhs_classifier, | 1729 classifier->Accumulate(rhs_classifier, |
| 1720 ExpressionClassifier::ExpressionProductions); | 1730 ExpressionClassifier::ExpressionProductions); |
| 1721 value = factory()->NewAssignment(Token::ASSIGN, lhs, rhs, | 1731 value = factory()->NewAssignment(Token::ASSIGN, lhs, rhs, |
| 1722 RelocInfo::kNoPosition); | 1732 RelocInfo::kNoPosition); |
| 1723 classifier->RecordCoverInitializedNameError( | 1733 classifier->RecordCoverInitializedNameError( |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2043 ExpressionClassifier::FormalParametersProductions | | 2053 ExpressionClassifier::FormalParametersProductions | |
| 2044 ExpressionClassifier::CoverInitializedNameProduction); | 2054 ExpressionClassifier::CoverInitializedNameProduction); |
| 2045 | 2055 |
| 2046 bool maybe_pattern = | 2056 bool maybe_pattern = |
| 2047 expression->IsObjectLiteral() || expression->IsArrayLiteral(); | 2057 expression->IsObjectLiteral() || expression->IsArrayLiteral(); |
| 2048 // bool binding_pattern = | 2058 // bool binding_pattern = |
| 2049 // allow_harmony_destructuring_bind() && maybe_pattern && !is_rhs; | 2059 // allow_harmony_destructuring_bind() && maybe_pattern && !is_rhs; |
| 2050 | 2060 |
| 2051 if (!Token::IsAssignmentOp(peek())) { | 2061 if (!Token::IsAssignmentOp(peek())) { |
| 2052 // Parsed conditional expression only (no assignment). | 2062 // Parsed conditional expression only (no assignment). |
| 2063 if (is_pattern_element && !maybe_pattern) { | |
| 2064 ClassifyReferenceExpression(classifier, expression, lhs_beg_pos, | |
| 2065 scanner()->location().end_pos); | |
| 2066 } | |
| 2053 if (is_pattern_element && !this->IsValidReferenceExpression(expression) && | 2067 if (is_pattern_element && !this->IsValidReferenceExpression(expression) && |
| 2054 !maybe_pattern) { | 2068 !maybe_pattern) { |
| 2055 classifier->RecordPatternError( | 2069 classifier->RecordPatternError( |
| 2056 Scanner::Location(lhs_beg_pos, scanner()->location().end_pos), | 2070 Scanner::Location(lhs_beg_pos, scanner()->location().end_pos), |
| 2057 MessageTemplate::kInvalidDestructuringTarget); | 2071 MessageTemplate::kInvalidDestructuringTarget); |
| 2058 } else if (is_rhs && maybe_pattern) { | 2072 } else if (is_rhs && maybe_pattern) { |
| 2059 ValidateExpression(classifier, CHECK_OK); | 2073 ValidateExpression(classifier, CHECK_OK); |
| 2060 } | 2074 } |
| 2061 | 2075 |
| 2062 return expression; | 2076 return expression; |
| (...skipping 1168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3231 ExpressionClassifier classifier; | 3245 ExpressionClassifier classifier; |
| 3232 ExpressionT result = ClassifyAndRewriteReferenceExpression( | 3246 ExpressionT result = ClassifyAndRewriteReferenceExpression( |
| 3233 &classifier, expression, beg_pos, end_pos, message, type); | 3247 &classifier, expression, beg_pos, end_pos, message, type); |
| 3234 ValidateExpression(&classifier, ok); | 3248 ValidateExpression(&classifier, ok); |
| 3235 if (!*ok) return this->EmptyExpression(); | 3249 if (!*ok) return this->EmptyExpression(); |
| 3236 return result; | 3250 return result; |
| 3237 } | 3251 } |
| 3238 | 3252 |
| 3239 | 3253 |
| 3240 template <typename Traits> | 3254 template <typename Traits> |
| 3255 void ParserBase<Traits>::ClassifyReferenceExpression( | |
|
adamk
2015/12/12 01:03:35
Indeed, this code is very close to the existing Ch
| |
| 3256 ExpressionClassifier* classifier, ExpressionT expression, int beg_pos, | |
| 3257 int end_pos) { | |
| 3258 if (!this->IsIdentifier(expression)) return; | |
| 3259 IdentifierT ref = this->AsIdentifier(expression); | |
| 3260 if (is_strict(language_mode()) && this->IsEvalOrArguments(ref)) { | |
| 3261 classifier->RecordAssignmentPatternError( | |
| 3262 Scanner::Location(beg_pos, end_pos), | |
| 3263 MessageTemplate::kStrictEvalArguments); | |
| 3264 } else if (is_strong(language_mode()) && this->IsUndefined(ref)) { | |
| 3265 classifier->RecordAssignmentPatternError( | |
| 3266 Scanner::Location(beg_pos, end_pos), MessageTemplate::kStrongUndefined); | |
| 3267 } | |
| 3268 } | |
| 3269 | |
| 3270 | |
| 3271 template <typename Traits> | |
| 3241 typename ParserBase<Traits>::ExpressionT | 3272 typename ParserBase<Traits>::ExpressionT |
| 3242 ParserBase<Traits>::ClassifyAndRewriteReferenceExpression( | 3273 ParserBase<Traits>::ClassifyAndRewriteReferenceExpression( |
| 3243 ExpressionClassifier* classifier, ExpressionT expression, int beg_pos, | 3274 ExpressionClassifier* classifier, ExpressionT expression, int beg_pos, |
| 3244 int end_pos, MessageTemplate::Template message, ParseErrorType type) { | 3275 int end_pos, MessageTemplate::Template message, ParseErrorType type) { |
| 3245 Scanner::Location location(beg_pos, end_pos); | 3276 Scanner::Location location(beg_pos, end_pos); |
| 3246 if (this->IsIdentifier(expression)) { | 3277 if (this->IsIdentifier(expression)) { |
| 3247 if (is_strict(language_mode()) && | 3278 if (is_strict(language_mode()) && |
| 3248 this->IsEvalOrArguments(this->AsIdentifier(expression))) { | 3279 this->IsEvalOrArguments(this->AsIdentifier(expression))) { |
| 3249 classifier->RecordExpressionError( | 3280 classifier->RecordExpressionError( |
| 3250 location, MessageTemplate::kStrictEvalArguments, kSyntaxError); | 3281 location, MessageTemplate::kStrictEvalArguments, kSyntaxError); |
| 3282 classifier->RecordAssignmentPatternError( | |
| 3283 location, MessageTemplate::kStrictEvalArguments); | |
| 3251 return expression; | 3284 return expression; |
| 3252 } | 3285 } |
| 3253 if (is_strong(language_mode()) && | 3286 if (is_strong(language_mode()) && |
| 3254 this->IsUndefined(this->AsIdentifier(expression))) { | 3287 this->IsUndefined(this->AsIdentifier(expression))) { |
| 3255 classifier->RecordExpressionError( | 3288 classifier->RecordExpressionError( |
| 3256 location, MessageTemplate::kStrongUndefined, kSyntaxError); | 3289 location, MessageTemplate::kStrongUndefined, kSyntaxError); |
| 3290 classifier->RecordAssignmentPatternError( | |
| 3291 location, MessageTemplate::kStrongUndefined); | |
| 3257 return expression; | 3292 return expression; |
| 3258 } | 3293 } |
| 3259 } | 3294 } |
| 3260 if (expression->IsValidReferenceExpression()) { | 3295 if (expression->IsValidReferenceExpression()) { |
| 3261 return expression; | 3296 return expression; |
| 3262 } else if (expression->IsCall()) { | 3297 } else if (expression->IsCall()) { |
| 3263 // If it is a call, make it a runtime error for legacy web compatibility. | 3298 // If it is a call, make it a runtime error for legacy web compatibility. |
| 3264 // Rewrite `expr' to `expr[throw ReferenceError]'. | 3299 // Rewrite `expr' to `expr[throw ReferenceError]'. |
| 3265 int pos = location.beg_pos; | 3300 int pos = location.beg_pos; |
| 3266 ExpressionT error = this->NewThrowReferenceError(message, pos); | 3301 ExpressionT error = this->NewThrowReferenceError(message, pos); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3349 return; | 3384 return; |
| 3350 } | 3385 } |
| 3351 has_seen_constructor_ = true; | 3386 has_seen_constructor_ = true; |
| 3352 return; | 3387 return; |
| 3353 } | 3388 } |
| 3354 } | 3389 } |
| 3355 } // namespace internal | 3390 } // namespace internal |
| 3356 } // namespace v8 | 3391 } // namespace v8 |
| 3357 | 3392 |
| 3358 #endif // V8_PARSING_PARSER_BASE_H | 3393 #endif // V8_PARSING_PARSER_BASE_H |
| OLD | NEW |