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

Side by Side Diff: src/parser.cc

Issue 8688007: Statically check for assignments to const in harmony mode. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed second round of comments. Created 9 years 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 | Annotate | Revision Log
« no previous file with comments | « src/parser.h ('k') | src/preparser.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 1245 matching lines...) Expand 10 before | Expand all | Expand 10 after
1256 // parsed into an empty statement. 1256 // parsed into an empty statement.
1257 1257
1258 // Keep the source position of the statement 1258 // Keep the source position of the statement
1259 int statement_pos = scanner().peek_location().beg_pos; 1259 int statement_pos = scanner().peek_location().beg_pos;
1260 Statement* stmt = NULL; 1260 Statement* stmt = NULL;
1261 switch (peek()) { 1261 switch (peek()) {
1262 case Token::LBRACE: 1262 case Token::LBRACE:
1263 return ParseBlock(labels, ok); 1263 return ParseBlock(labels, ok);
1264 1264
1265 case Token::CONST: // fall through 1265 case Token::CONST: // fall through
1266 case Token::LET:
1266 case Token::VAR: 1267 case Token::VAR:
1267 stmt = ParseVariableStatement(kStatement, ok); 1268 stmt = ParseVariableStatement(kStatement, ok);
1268 break; 1269 break;
1269 1270
1270 case Token::SEMICOLON: 1271 case Token::SEMICOLON:
1271 Next(); 1272 Next();
1272 return EmptyStatement(); 1273 return EmptyStatement();
1273 1274
1274 case Token::IF: 1275 case Token::IF:
1275 stmt = ParseIfStatement(labels, ok); 1276 stmt = ParseIfStatement(labels, ok);
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after
1697 // True if the binding needs initialization. 'let' and 'const' declared 1698 // True if the binding needs initialization. 'let' and 'const' declared
1698 // bindings are created uninitialized by their declaration nodes and 1699 // bindings are created uninitialized by their declaration nodes and
1699 // need initialization. 'var' declared bindings are always initialized 1700 // need initialization. 'var' declared bindings are always initialized
1700 // immediately by their declaration nodes. 1701 // immediately by their declaration nodes.
1701 bool needs_init = false; 1702 bool needs_init = false;
1702 bool is_const = false; 1703 bool is_const = false;
1703 Token::Value init_op = Token::INIT_VAR; 1704 Token::Value init_op = Token::INIT_VAR;
1704 if (peek() == Token::VAR) { 1705 if (peek() == Token::VAR) {
1705 Consume(Token::VAR); 1706 Consume(Token::VAR);
1706 } else if (peek() == Token::CONST) { 1707 } else if (peek() == Token::CONST) {
1708 // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
1709 //
1710 // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';'
1711 //
1712 // * It is a Syntax Error if the code that matches this production is not
1713 // contained in extended code.
1714 //
1715 // However disallowing const in classic mode will break compatibility with
1716 // existing pages. Therefore we keep allowing const with the old
1717 // non-harmony semantics in classic mode.
1707 Consume(Token::CONST); 1718 Consume(Token::CONST);
1708 switch (top_scope_->language_mode()) { 1719 switch (top_scope_->language_mode()) {
1709 case CLASSIC_MODE: 1720 case CLASSIC_MODE:
1710 mode = CONST; 1721 mode = CONST;
1711 init_op = Token::INIT_CONST; 1722 init_op = Token::INIT_CONST;
1712 break; 1723 break;
1713 case STRICT_MODE: 1724 case STRICT_MODE:
1714 ReportMessage("strict_const", Vector<const char*>::empty()); 1725 ReportMessage("strict_const", Vector<const char*>::empty());
1715 *ok = false; 1726 *ok = false;
1716 return NULL; 1727 return NULL;
1717 case EXTENDED_MODE: 1728 case EXTENDED_MODE:
1718 if (var_context != kSourceElement && 1729 if (var_context != kSourceElement &&
1719 var_context != kForStatement) { 1730 var_context != kForStatement) {
1720 // In extended mode 'const' declarations are only allowed in source 1731 // In extended mode 'const' declarations are only allowed in source
1721 // element positions. 1732 // element positions.
1722 ReportMessage("unprotected_const", Vector<const char*>::empty()); 1733 ReportMessage("unprotected_const", Vector<const char*>::empty());
1723 *ok = false; 1734 *ok = false;
1724 return NULL; 1735 return NULL;
1725 } 1736 }
1726 mode = CONST_HARMONY; 1737 mode = CONST_HARMONY;
1727 init_op = Token::INIT_CONST_HARMONY; 1738 init_op = Token::INIT_CONST_HARMONY;
1728 } 1739 }
1729 is_const = true; 1740 is_const = true;
1730 needs_init = true; 1741 needs_init = true;
1731 } else if (peek() == Token::LET) { 1742 } else if (peek() == Token::LET) {
1732 ASSERT(top_scope_->is_extended_mode()); 1743 // ES6 Draft Rev4 section 12.2.1:
1744 //
1745 // LetDeclaration : let LetBindingList ;
1746 //
1747 // * It is a Syntax Error if the code that matches this production is not
1748 // contained in extended code.
1749 if (!is_extended_mode()) {
1750 ReportMessage("illegal_let", Vector<const char*>::empty());
1751 *ok = false;
1752 return NULL;
1753 }
1733 Consume(Token::LET); 1754 Consume(Token::LET);
1734 if (var_context != kSourceElement && 1755 if (var_context != kSourceElement &&
1735 var_context != kForStatement) { 1756 var_context != kForStatement) {
1736 // Let declarations are only allowed in source element positions. 1757 // Let declarations are only allowed in source element positions.
1737 ASSERT(var_context == kStatement); 1758 ASSERT(var_context == kStatement);
1738 ReportMessage("unprotected_let", Vector<const char*>::empty()); 1759 ReportMessage("unprotected_let", Vector<const char*>::empty());
1739 *ok = false; 1760 *ok = false;
1740 return NULL; 1761 return NULL;
1741 } 1762 }
1742 mode = LET; 1763 mode = LET;
(...skipping 918 matching lines...) Expand 10 before | Expand all | Expand 10 after
2661 if (expression == NULL || !expression->IsValidLeftHandSide()) { 2682 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2662 Handle<String> type = 2683 Handle<String> type =
2663 isolate()->factory()->invalid_lhs_in_assignment_symbol(); 2684 isolate()->factory()->invalid_lhs_in_assignment_symbol();
2664 expression = NewThrowReferenceError(type); 2685 expression = NewThrowReferenceError(type);
2665 } 2686 }
2666 2687
2667 if (!top_scope_->is_classic_mode()) { 2688 if (!top_scope_->is_classic_mode()) {
2668 // Assignment to eval or arguments is disallowed in strict mode. 2689 // Assignment to eval or arguments is disallowed in strict mode.
2669 CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK); 2690 CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK);
2670 } 2691 }
2692 MarkAsLValue(expression);
2671 2693
2672 Token::Value op = Next(); // Get assignment operator. 2694 Token::Value op = Next(); // Get assignment operator.
2673 int pos = scanner().location().beg_pos; 2695 int pos = scanner().location().beg_pos;
2674 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK); 2696 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
2675 2697
2676 // TODO(1231235): We try to estimate the set of properties set by 2698 // TODO(1231235): We try to estimate the set of properties set by
2677 // constructors. We define a new property whenever there is an 2699 // constructors. We define a new property whenever there is an
2678 // assignment to a property of 'this'. We should probably only add 2700 // assignment to a property of 'this'. We should probably only add
2679 // properties if we haven't seen them before. Otherwise we'll 2701 // properties if we haven't seen them before. Otherwise we'll
2680 // probably overestimate the number of properties. 2702 // probably overestimate the number of properties.
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
2894 if (expression == NULL || !expression->IsValidLeftHandSide()) { 2916 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2895 Handle<String> type = 2917 Handle<String> type =
2896 isolate()->factory()->invalid_lhs_in_prefix_op_symbol(); 2918 isolate()->factory()->invalid_lhs_in_prefix_op_symbol();
2897 expression = NewThrowReferenceError(type); 2919 expression = NewThrowReferenceError(type);
2898 } 2920 }
2899 2921
2900 if (!top_scope_->is_classic_mode()) { 2922 if (!top_scope_->is_classic_mode()) {
2901 // Prefix expression operand in strict mode may not be eval or arguments. 2923 // Prefix expression operand in strict mode may not be eval or arguments.
2902 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK); 2924 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2903 } 2925 }
2926 MarkAsLValue(expression);
2904 2927
2905 int position = scanner().location().beg_pos; 2928 int position = scanner().location().beg_pos;
2906 return new(zone()) CountOperation(isolate(), 2929 return new(zone()) CountOperation(isolate(),
2907 op, 2930 op,
2908 true /* prefix */, 2931 true /* prefix */,
2909 expression, 2932 expression,
2910 position); 2933 position);
2911 2934
2912 } else { 2935 } else {
2913 return ParsePostfixExpression(ok); 2936 return ParsePostfixExpression(ok);
(...skipping 15 matching lines...) Expand all
2929 if (expression == NULL || !expression->IsValidLeftHandSide()) { 2952 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2930 Handle<String> type = 2953 Handle<String> type =
2931 isolate()->factory()->invalid_lhs_in_postfix_op_symbol(); 2954 isolate()->factory()->invalid_lhs_in_postfix_op_symbol();
2932 expression = NewThrowReferenceError(type); 2955 expression = NewThrowReferenceError(type);
2933 } 2956 }
2934 2957
2935 if (!top_scope_->is_classic_mode()) { 2958 if (!top_scope_->is_classic_mode()) {
2936 // Postfix expression operand in strict mode may not be eval or arguments. 2959 // Postfix expression operand in strict mode may not be eval or arguments.
2937 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK); 2960 CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
2938 } 2961 }
2962 MarkAsLValue(expression);
2939 2963
2940 Token::Value next = Next(); 2964 Token::Value next = Next();
2941 int position = scanner().location().beg_pos; 2965 int position = scanner().location().beg_pos;
2942 expression = 2966 expression =
2943 new(zone()) CountOperation(isolate(), 2967 new(zone()) CountOperation(isolate(),
2944 next, 2968 next,
2945 false /* postfix */, 2969 false /* postfix */,
2946 expression, 2970 expression,
2947 position); 2971 position);
2948 } 2972 }
(...skipping 1338 matching lines...) Expand 10 before | Expand all | Expand 10 after
4287 next != Token::FUTURE_STRICT_RESERVED_WORD && 4311 next != Token::FUTURE_STRICT_RESERVED_WORD &&
4288 !Token::IsKeyword(next)) { 4312 !Token::IsKeyword(next)) {
4289 ReportUnexpectedToken(next); 4313 ReportUnexpectedToken(next);
4290 *ok = false; 4314 *ok = false;
4291 return Handle<String>(); 4315 return Handle<String>();
4292 } 4316 }
4293 return GetSymbol(ok); 4317 return GetSymbol(ok);
4294 } 4318 }
4295 4319
4296 4320
4321 void Parser::MarkAsLValue(Expression* expression) {
4322 VariableProxy* proxy = expression != NULL
4323 ? expression->AsVariableProxy()
4324 : NULL;
4325
4326 if (proxy != NULL) proxy->MarkAsLValue();
4327 }
4328
4329
4297 // Checks LHS expression for assignment and prefix/postfix increment/decrement 4330 // Checks LHS expression for assignment and prefix/postfix increment/decrement
4298 // in strict mode. 4331 // in strict mode.
4299 void Parser::CheckStrictModeLValue(Expression* expression, 4332 void Parser::CheckStrictModeLValue(Expression* expression,
4300 const char* error, 4333 const char* error,
4301 bool* ok) { 4334 bool* ok) {
4302 ASSERT(!top_scope_->is_classic_mode()); 4335 ASSERT(!top_scope_->is_classic_mode());
4303 VariableProxy* lhs = expression != NULL 4336 VariableProxy* lhs = expression != NULL
4304 ? expression->AsVariableProxy() 4337 ? expression->AsVariableProxy()
4305 : NULL; 4338 : NULL;
4306 4339
(...skipping 1152 matching lines...) Expand 10 before | Expand all | Expand 10 after
5459 ASSERT(info->isolate()->has_pending_exception()); 5492 ASSERT(info->isolate()->has_pending_exception());
5460 } else { 5493 } else {
5461 result = parser.ParseProgram(info); 5494 result = parser.ParseProgram(info);
5462 } 5495 }
5463 } 5496 }
5464 info->SetFunction(result); 5497 info->SetFunction(result);
5465 return (result != NULL); 5498 return (result != NULL);
5466 } 5499 }
5467 5500
5468 } } // namespace v8::internal 5501 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/preparser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698