Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: src/parsing/parser-base.h

Issue 2133543003: [parser] report errors for invalid binding patterns in async formal parameters (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/base/hashmap.h" 10 #include "src/base/hashmap.h"
(...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 } 890 }
891 891
892 bool IsValidArrowFormalParametersStart(Token::Value token) { 892 bool IsValidArrowFormalParametersStart(Token::Value token) {
893 return is_any_identifier(token) || token == Token::LPAREN; 893 return is_any_identifier(token) || token == Token::LPAREN;
894 } 894 }
895 895
896 void ValidateArrowFormalParameters(const ExpressionClassifier* classifier, 896 void ValidateArrowFormalParameters(const ExpressionClassifier* classifier,
897 ExpressionT expr, 897 ExpressionT expr,
898 bool parenthesized_formals, bool is_async, 898 bool parenthesized_formals, bool is_async,
899 bool* ok) { 899 bool* ok) {
900 if (classifier->is_valid_binding_pattern()) { 900 if (!is_async && classifier->is_valid_binding_pattern()) {
901 // A simple arrow formal parameter: IDENTIFIER => BODY. 901 // A simple arrow formal parameter: IDENTIFIER => BODY.
902 if (!this->IsIdentifier(expr)) { 902 if (!this->IsIdentifier(expr)) {
903 Traits::ReportMessageAt(scanner()->location(), 903 Traits::ReportMessageAt(scanner()->location(),
904 MessageTemplate::kUnexpectedToken, 904 MessageTemplate::kUnexpectedToken,
905 Token::String(scanner()->current_token())); 905 Token::String(scanner()->current_token()));
906 *ok = false; 906 *ok = false;
907 } 907 }
908 } else if (!classifier->is_valid_arrow_formal_parameters()) { 908 } else if (!classifier->is_valid_arrow_formal_parameters()) {
909 // If after parsing the expr, we see an error but the expression is 909 // If after parsing the expr, we see an error but the expression is
910 // neither a valid binding pattern nor a valid parenthesized formal 910 // neither a valid binding pattern nor a valid parenthesized formal
911 // parameter list, show the "arrow formal parameters" error if the formals 911 // parameter list, show the "arrow formal parameters" error if the formals
912 // started with a parenthesis, and the binding pattern error otherwise. 912 // started with a parenthesis, and the binding pattern error otherwise.
913 const typename ExpressionClassifier::Error& error = 913 const typename ExpressionClassifier::Error& error =
914 parenthesized_formals ? classifier->arrow_formal_parameters_error() 914 parenthesized_formals ? classifier->arrow_formal_parameters_error()
915 : classifier->binding_pattern_error(); 915 : classifier->binding_pattern_error();
916 ReportClassifierError(error); 916 ReportClassifierError(error);
917 *ok = false; 917 *ok = false;
918 } 918 }
919 if (is_async && !classifier->is_valid_async_arrow_formal_parameters()) { 919 if (is_async) {
920 const typename ExpressionClassifier::Error& error = 920 if (!classifier->is_valid_async_arrow_formal_parameters()) {
921 classifier->async_arrow_formal_parameters_error(); 921 const typename ExpressionClassifier::Error& error =
922 ReportClassifierError(error); 922 classifier->async_arrow_formal_parameters_error();
923 *ok = false; 923 ReportClassifierError(error);
924 *ok = false;
925 }
926 if (!classifier->is_valid_binding_pattern()) {
nickie 2016/07/11 13:19:50 Is it possible that we have both !is_valid_async_a
caitp 2016/07/11 13:24:42 Yeah, this is true --- the WebKit style is to just
nickie 2016/07/11 13:32:18 Yes, I think that adding return statements is a be
927 ReportClassifierError(classifier->binding_pattern_error());
928 *ok = false;
929 }
924 } 930 }
925 } 931 }
926 932
927 void ValidateLetPattern(const ExpressionClassifier* classifier, bool* ok) { 933 void ValidateLetPattern(const ExpressionClassifier* classifier, bool* ok) {
928 if (!classifier->is_valid_let_pattern()) { 934 if (!classifier->is_valid_let_pattern()) {
929 ReportClassifierError(classifier->let_pattern_error()); 935 ReportClassifierError(classifier->let_pattern_error());
930 *ok = false; 936 *ok = false;
931 } 937 }
932 } 938 }
933 939
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1017 Scanner::Location* first_spread_pos, bool maybe_arrow, 1023 Scanner::Location* first_spread_pos, bool maybe_arrow,
1018 ExpressionClassifier* classifier, bool* ok); 1024 ExpressionClassifier* classifier, bool* ok);
1019 typename Traits::Type::ExpressionList ParseArguments( 1025 typename Traits::Type::ExpressionList ParseArguments(
1020 Scanner::Location* first_spread_pos, ExpressionClassifier* classifier, 1026 Scanner::Location* first_spread_pos, ExpressionClassifier* classifier,
1021 bool* ok) { 1027 bool* ok) {
1022 return ParseArguments(first_spread_pos, false, classifier, ok); 1028 return ParseArguments(first_spread_pos, false, classifier, ok);
1023 } 1029 }
1024 1030
1025 ExpressionT ParseAssignmentExpression(bool accept_IN, 1031 ExpressionT ParseAssignmentExpression(bool accept_IN,
1026 ExpressionClassifier* classifier, 1032 ExpressionClassifier* classifier,
1027 bool* ok); 1033 bool marge_partterns, bool* ok);
nickie 2016/07/11 13:19:50 Unless I'm missing the pun, "merge_patterns" :-)
caitp 2016/07/11 13:24:42 just a typo, will fix
1034 ExpressionT ParseAssignmentExpression(bool accept_IN,
1035 ExpressionClassifier* classifier,
1036 bool* ok) {
1037 return ParseAssignmentExpression(accept_IN, classifier, false, ok);
1038 }
1028 ExpressionT ParseYieldExpression(bool accept_IN, 1039 ExpressionT ParseYieldExpression(bool accept_IN,
1029 ExpressionClassifier* classifier, bool* ok); 1040 ExpressionClassifier* classifier, bool* ok);
1030 ExpressionT ParseTailCallExpression(ExpressionClassifier* classifier, 1041 ExpressionT ParseTailCallExpression(ExpressionClassifier* classifier,
1031 bool* ok); 1042 bool* ok);
1032 ExpressionT ParseConditionalExpression(bool accept_IN, 1043 ExpressionT ParseConditionalExpression(bool accept_IN,
1033 ExpressionClassifier* classifier, 1044 ExpressionClassifier* classifier,
1034 bool* ok); 1045 bool* ok);
1035 ExpressionT ParseBinaryExpression(int prec, bool accept_IN, 1046 ExpressionT ParseBinaryExpression(int prec, bool accept_IN,
1036 ExpressionClassifier* classifier, bool* ok); 1047 ExpressionClassifier* classifier, bool* ok);
1037 ExpressionT ParseUnaryExpression(ExpressionClassifier* classifier, bool* ok); 1048 ExpressionT ParseUnaryExpression(ExpressionClassifier* classifier, bool* ok);
(...skipping 1127 matching lines...) Expand 10 before | Expand all | Expand 10 after
2165 Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList)); 2176 Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList));
2166 bool done = (peek() == Token::RPAREN); 2177 bool done = (peek() == Token::RPAREN);
2167 bool was_unspread = false; 2178 bool was_unspread = false;
2168 int unspread_sequences_count = 0; 2179 int unspread_sequences_count = 0;
2169 while (!done) { 2180 while (!done) {
2170 int start_pos = peek_position(); 2181 int start_pos = peek_position();
2171 bool is_spread = Check(Token::ELLIPSIS); 2182 bool is_spread = Check(Token::ELLIPSIS);
2172 int expr_pos = peek_position(); 2183 int expr_pos = peek_position();
2173 2184
2174 ExpressionT argument = this->ParseAssignmentExpression( 2185 ExpressionT argument = this->ParseAssignmentExpression(
2175 true, classifier, CHECK_OK_CUSTOM(NullExpressionList)); 2186 true, classifier, maybe_arrow, CHECK_OK_CUSTOM(NullExpressionList));
2176 CheckNoTailCallExpressions(classifier, CHECK_OK_CUSTOM(NullExpressionList)); 2187 CheckNoTailCallExpressions(classifier, CHECK_OK_CUSTOM(NullExpressionList));
2177 if (!maybe_arrow) { 2188 if (!maybe_arrow) {
2178 Traits::RewriteNonPattern(classifier, 2189 Traits::RewriteNonPattern(classifier,
2179 CHECK_OK_CUSTOM(NullExpressionList)); 2190 CHECK_OK_CUSTOM(NullExpressionList));
2180 } 2191 }
2181 if (is_spread) { 2192 if (is_spread) {
2182 if (!spread_arg.IsValid()) { 2193 if (!spread_arg.IsValid()) {
2183 spread_arg.beg_pos = start_pos; 2194 spread_arg.beg_pos = start_pos;
2184 spread_arg.end_pos = peek_position(); 2195 spread_arg.end_pos = peek_position();
2185 } 2196 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
2232 } 2243 }
2233 2244
2234 return result; 2245 return result;
2235 } 2246 }
2236 2247
2237 // Precedence = 2 2248 // Precedence = 2
2238 template <class Traits> 2249 template <class Traits>
2239 typename ParserBase<Traits>::ExpressionT 2250 typename ParserBase<Traits>::ExpressionT
2240 ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, 2251 ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
2241 ExpressionClassifier* classifier, 2252 ExpressionClassifier* classifier,
2242 bool* ok) { 2253 bool merge_patterns, bool* ok) {
2243 // AssignmentExpression :: 2254 // AssignmentExpression ::
2244 // ConditionalExpression 2255 // ConditionalExpression
2245 // ArrowFunction 2256 // ArrowFunction
2246 // YieldExpression 2257 // YieldExpression
2247 // LeftHandSideExpression AssignmentOperator AssignmentExpression 2258 // LeftHandSideExpression AssignmentOperator AssignmentExpression
2248 bool is_destructuring_assignment = false; 2259 bool is_destructuring_assignment = false;
2249 int lhs_beg_pos = peek_position(); 2260 int lhs_beg_pos = peek_position();
2250 2261
2251 if (peek() == Token::YIELD && is_generator()) { 2262 if (peek() == Token::YIELD && is_generator()) {
2252 return this->ParseYieldExpression(accept_IN, classifier, ok); 2263 return this->ParseYieldExpression(accept_IN, classifier, ok);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
2324 return expression; 2335 return expression;
2325 } 2336 }
2326 2337
2327 if (this->IsValidReferenceExpression(expression)) { 2338 if (this->IsValidReferenceExpression(expression)) {
2328 arrow_formals_classifier.ForgiveAssignmentPatternError(); 2339 arrow_formals_classifier.ForgiveAssignmentPatternError();
2329 } 2340 }
2330 2341
2331 // "expression" was not itself an arrow function parameter list, but it might 2342 // "expression" was not itself an arrow function parameter list, but it might
2332 // form part of one. Propagate speculative formal parameter error locations. 2343 // form part of one. Propagate speculative formal parameter error locations.
2333 // Do not merge pending non-pattern expressions yet! 2344 // Do not merge pending non-pattern expressions yet!
2334 classifier->Accumulate( 2345 int productions_to_propagate =
2335 &arrow_formals_classifier,
2336 ExpressionClassifier::StandardProductions | 2346 ExpressionClassifier::StandardProductions |
2337 ExpressionClassifier::FormalParametersProductions | 2347 ExpressionClassifier::FormalParametersProductions |
2338 ExpressionClassifier::CoverInitializedNameProduction | 2348 ExpressionClassifier::CoverInitializedNameProduction |
2339 ExpressionClassifier::AsyncArrowFormalParametersProduction | 2349 ExpressionClassifier::AsyncArrowFormalParametersProduction |
2340 ExpressionClassifier::AsyncBindingPatternProduction, 2350 ExpressionClassifier::AsyncBindingPatternProduction;
2341 false); 2351 if (merge_patterns) {
Dan Ehrenberg 2016/07/11 23:22:47 I find this logic of when to merge_patterns to be
caitp 2016/07/11 23:32:24 That doesn't really work, because then we could fa
Dan Ehrenberg 2016/07/11 23:37:57 I don't understand the issue. The binding pattern
nickie 2016/07/12 13:11:53 I tried the following with Dan's patch and they se
caitp 2016/07/12 14:38:30 What are either of you even talking about? Using p
2352 productions_to_propagate |= ExpressionClassifier::BindingPatternProduction;
2353 }
2354
2355 classifier->Accumulate(&arrow_formals_classifier, productions_to_propagate,
2356 false);
2342 2357
2343 if (!Token::IsAssignmentOp(peek())) { 2358 if (!Token::IsAssignmentOp(peek())) {
2344 // Parsed conditional expression only (no assignment). 2359 // Parsed conditional expression only (no assignment).
2345 // Now pending non-pattern expressions must be merged. 2360 // Now pending non-pattern expressions must be merged.
2346 classifier->MergeNonPatterns(&arrow_formals_classifier); 2361 classifier->MergeNonPatterns(&arrow_formals_classifier);
2347 return expression; 2362 return expression;
2348 } 2363 }
2349 2364
2350 // Now pending non-pattern expressions must be discarded. 2365 // Now pending non-pattern expressions must be discarded.
2351 arrow_formals_classifier.Discard(); 2366 arrow_formals_classifier.Discard();
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after
2798 Traits::RewriteNonPattern(classifier, CHECK_OK); 2813 Traits::RewriteNonPattern(classifier, CHECK_OK);
2799 result = factory()->NewProperty(result, index, pos); 2814 result = factory()->NewProperty(result, index, pos);
2800 Expect(Token::RBRACK, CHECK_OK); 2815 Expect(Token::RBRACK, CHECK_OK);
2801 break; 2816 break;
2802 } 2817 }
2803 2818
2804 case Token::LPAREN: { 2819 case Token::LPAREN: {
2805 CheckNoTailCallExpressions(classifier, CHECK_OK); 2820 CheckNoTailCallExpressions(classifier, CHECK_OK);
2806 int pos; 2821 int pos;
2807 Traits::RewriteNonPattern(classifier, CHECK_OK); 2822 Traits::RewriteNonPattern(classifier, CHECK_OK);
2808 BindingPatternUnexpectedToken(classifier); 2823
2824 const char* arg;
2825 MessageTemplate::Template message = MessageTemplate::kUnexpectedToken;
2826 Scanner::Location location = scanner()->peek_location();
2827 GetUnexpectedTokenMessage(peek(), &message, &location, &arg);
2828
2829 if (!is_async) {
2830 classifier->RecordBindingPatternError(location, message, arg);
2831 }
2832
2809 if (scanner()->current_token() == Token::IDENTIFIER || 2833 if (scanner()->current_token() == Token::IDENTIFIER ||
2810 scanner()->current_token() == Token::SUPER || 2834 scanner()->current_token() == Token::SUPER ||
2811 scanner()->current_token() == Token::ASYNC) { 2835 scanner()->current_token() == Token::ASYNC) {
2812 // For call of an identifier we want to report position of 2836 // For call of an identifier we want to report position of
2813 // the identifier as position of the call in the stack trace. 2837 // the identifier as position of the call in the stack trace.
2814 pos = position(); 2838 pos = position();
2815 } else { 2839 } else {
2816 // For other kinds of calls we record position of the parenthesis as 2840 // For other kinds of calls we record position of the parenthesis as
2817 // position of the call. Note that this is extremely important for 2841 // position of the call. Note that this is extremely important for
2818 // expressions of the form function(){...}() for which call position 2842 // expressions of the form function(){...}() for which call position
(...skipping 11 matching lines...) Expand all
2830 typename Traits::Type::ExpressionList args = 2854 typename Traits::Type::ExpressionList args =
2831 ParseArguments(&spread_pos, is_async, classifier, CHECK_OK); 2855 ParseArguments(&spread_pos, is_async, classifier, CHECK_OK);
2832 2856
2833 if (V8_UNLIKELY(is_async && peek() == Token::ARROW)) { 2857 if (V8_UNLIKELY(is_async && peek() == Token::ARROW)) {
2834 if (args->length()) { 2858 if (args->length()) {
2835 // async ( Arguments ) => ... 2859 // async ( Arguments ) => ...
2836 return Traits::ExpressionListToExpression(args); 2860 return Traits::ExpressionListToExpression(args);
2837 } 2861 }
2838 // async () => ... 2862 // async () => ...
2839 return factory()->NewEmptyParentheses(pos); 2863 return factory()->NewEmptyParentheses(pos);
2864 } else {
2865 classifier->ReplaceBindingPatternError(location, message, arg);
Dan Ehrenberg 2016/07/11 23:22:47 I don't understand why this case is added when we'
caitp 2016/07/11 23:32:24 ArrowFormalParameters don't really matter for asyn
Dan Ehrenberg 2016/07/11 23:37:57 Could you write a test for it?
2840 } 2866 }
2841 2867
2842 ArrowFormalParametersUnexpectedToken(classifier); 2868 ArrowFormalParametersUnexpectedToken(classifier);
2843 2869
2844 // Keep track of eval() calls since they disable all local variable 2870 // Keep track of eval() calls since they disable all local variable
2845 // optimizations. 2871 // optimizations.
2846 // The calls that need special treatment are the 2872 // The calls that need special treatment are the
2847 // direct eval calls. These calls are all of the form eval(...), with 2873 // direct eval calls. These calls are all of the form eval(...), with
2848 // no explicit receiver. 2874 // no explicit receiver.
2849 // These calls are marked as potentially direct eval calls. Whether 2875 // These calls are marked as potentially direct eval calls. Whether
(...skipping 801 matching lines...) Expand 10 before | Expand all | Expand 10 after
3651 has_seen_constructor_ = true; 3677 has_seen_constructor_ = true;
3652 return; 3678 return;
3653 } 3679 }
3654 } 3680 }
3655 3681
3656 3682
3657 } // namespace internal 3683 } // namespace internal
3658 } // namespace v8 3684 } // namespace v8
3659 3685
3660 #endif // V8_PARSING_PARSER_BASE_H 3686 #endif // V8_PARSING_PARSER_BASE_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698