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

Side by Side Diff: src/parser.cc

Issue 200473003: Make invalid LHSs a parse-time (reference) error (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Comment Created 6 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 438 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 void ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left, 449 void ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left,
450 Expression* right) { 450 Expression* right) {
451 ASSERT(left != NULL); 451 ASSERT(left != NULL);
452 if (left->AsProperty() != NULL && 452 if (left->AsProperty() != NULL &&
453 right->AsFunctionLiteral() != NULL) { 453 right->AsFunctionLiteral() != NULL) {
454 right->AsFunctionLiteral()->set_pretenure(); 454 right->AsFunctionLiteral()->set_pretenure();
455 } 455 }
456 } 456 }
457 457
458 458
459 Expression* ParserTraits::ValidateAssignmentLeftHandSide(
460 Expression* expression) const {
461 ASSERT(expression != NULL);
462 if (!expression->IsValidLeftHandSide()) {
463 Handle<String> message =
464 parser_->isolate()->factory()->invalid_lhs_in_assignment_string();
465 expression = parser_->NewThrowReferenceError(message);
466 }
467 return expression;
468 }
469
470
471 Expression* ParserTraits::MarkExpressionAsLValue(Expression* expression) { 459 Expression* ParserTraits::MarkExpressionAsLValue(Expression* expression) {
472 VariableProxy* proxy = expression != NULL 460 VariableProxy* proxy = expression != NULL
473 ? expression->AsVariableProxy() 461 ? expression->AsVariableProxy()
474 : NULL; 462 : NULL;
475 if (proxy != NULL) proxy->MarkAsLValue(); 463 if (proxy != NULL) proxy->MarkAsLValue();
476 return expression; 464 return expression;
477 } 465 }
478 466
479 467
480 void ParserTraits::CheckStrictModeLValue(Expression* expression, 468 void ParserTraits::CheckStrictModeLValue(Expression* expression,
481 bool* ok) { 469 bool* ok) {
482 VariableProxy* lhs = expression != NULL 470 VariableProxy* lhs = expression != NULL
483 ? expression->AsVariableProxy() 471 ? expression->AsVariableProxy()
484 : NULL; 472 : NULL;
485 if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) { 473 if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
486 parser_->ReportMessage("strict_eval_arguments", 474 parser_->ReportMessage("strict_eval_arguments",
487 Vector<const char*>::empty()); 475 Vector<const char*>::empty());
488 *ok = false; 476 *ok = false;
489 } 477 }
490 } 478 }
491 479
492 480
493 void ParserTraits::ReportMessageAt(Scanner::Location source_location, 481 void ParserTraits::ReportMessageAt(Scanner::Location source_location,
494 const char* message, 482 const char* message,
495 Vector<const char*> args) { 483 Vector<const char*> args,
484 bool is_reference_error) {
496 if (parser_->stack_overflow()) { 485 if (parser_->stack_overflow()) {
497 // Suppress the error message (syntax error or such) in the presence of a 486 // Suppress the error message (syntax error or such) in the presence of a
498 // stack overflow. The isolate allows only one pending exception at at time 487 // stack overflow. The isolate allows only one pending exception at at time
499 // and we want to report the stack overflow later. 488 // and we want to report the stack overflow later.
500 return; 489 return;
501 } 490 }
502 MessageLocation location(parser_->script_, 491 MessageLocation location(parser_->script_,
503 source_location.beg_pos, 492 source_location.beg_pos,
504 source_location.end_pos); 493 source_location.end_pos);
505 Factory* factory = parser_->isolate()->factory(); 494 Factory* factory = parser_->isolate()->factory();
506 Handle<FixedArray> elements = factory->NewFixedArray(args.length()); 495 Handle<FixedArray> elements = factory->NewFixedArray(args.length());
507 for (int i = 0; i < args.length(); i++) { 496 for (int i = 0; i < args.length(); i++) {
508 Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i])); 497 Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i]));
509 elements->set(i, *arg_string); 498 elements->set(i, *arg_string);
510 } 499 }
511 Handle<JSArray> array = factory->NewJSArrayWithElements(elements); 500 Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
512 Handle<Object> result = factory->NewSyntaxError(message, array); 501 Handle<Object> result = is_reference_error
502 ? factory->NewReferenceError(message, array)
503 : factory->NewSyntaxError(message, array);
513 parser_->isolate()->Throw(*result, &location); 504 parser_->isolate()->Throw(*result, &location);
514 } 505 }
515 506
516 507
517 void ParserTraits::ReportMessage(const char* message, 508 void ParserTraits::ReportMessage(const char* message,
518 Vector<Handle<String> > args) { 509 Vector<Handle<String> > args,
510 bool is_reference_error) {
519 Scanner::Location source_location = parser_->scanner()->location(); 511 Scanner::Location source_location = parser_->scanner()->location();
520 ReportMessageAt(source_location, message, args); 512 ReportMessageAt(source_location, message, args, is_reference_error);
521 } 513 }
522 514
523 515
524 void ParserTraits::ReportMessageAt(Scanner::Location source_location, 516 void ParserTraits::ReportMessageAt(Scanner::Location source_location,
525 const char* message, 517 const char* message,
526 Vector<Handle<String> > args) { 518 Vector<Handle<String> > args,
519 bool is_reference_error) {
527 if (parser_->stack_overflow()) { 520 if (parser_->stack_overflow()) {
528 // Suppress the error message (syntax error or such) in the presence of a 521 // Suppress the error message (syntax error or such) in the presence of a
529 // stack overflow. The isolate allows only one pending exception at at time 522 // stack overflow. The isolate allows only one pending exception at at time
530 // and we want to report the stack overflow later. 523 // and we want to report the stack overflow later.
531 return; 524 return;
532 } 525 }
533 MessageLocation location(parser_->script_, 526 MessageLocation location(parser_->script_,
534 source_location.beg_pos, 527 source_location.beg_pos,
535 source_location.end_pos); 528 source_location.end_pos);
536 Factory* factory = parser_->isolate()->factory(); 529 Factory* factory = parser_->isolate()->factory();
537 Handle<FixedArray> elements = factory->NewFixedArray(args.length()); 530 Handle<FixedArray> elements = factory->NewFixedArray(args.length());
538 for (int i = 0; i < args.length(); i++) { 531 for (int i = 0; i < args.length(); i++) {
539 elements->set(i, *args[i]); 532 elements->set(i, *args[i]);
540 } 533 }
541 Handle<JSArray> array = factory->NewJSArrayWithElements(elements); 534 Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
542 Handle<Object> result = factory->NewSyntaxError(message, array); 535 Handle<Object> result = is_reference_error
536 ? factory->NewReferenceError(message, array)
537 : factory->NewSyntaxError(message, array);
543 parser_->isolate()->Throw(*result, &location); 538 parser_->isolate()->Throw(*result, &location);
544 } 539 }
545 540
546 541
547 Handle<String> ParserTraits::GetSymbol(Scanner* scanner) { 542 Handle<String> ParserTraits::GetSymbol(Scanner* scanner) {
548 int symbol_id = -1; 543 int symbol_id = -1;
549 if (parser_->pre_parse_data() != NULL) { 544 if (parser_->pre_parse_data() != NULL) {
550 symbol_id = parser_->pre_parse_data()->GetSymbolIdentifier(); 545 symbol_id = parser_->pre_parse_data()->GetSymbolIdentifier();
551 } 546 }
552 return parser_->LookupSymbol(symbol_id); 547 return parser_->LookupSymbol(symbol_id);
(...skipping 2284 matching lines...) Expand 10 before | Expand all | Expand 10 after
2837 for_scope->set_end_position(scanner()->location().end_pos); 2832 for_scope->set_end_position(scanner()->location().end_pos);
2838 for_scope = for_scope->FinalizeBlockScope(); 2833 for_scope = for_scope->FinalizeBlockScope();
2839 body_block->set_scope(for_scope); 2834 body_block->set_scope(for_scope);
2840 // Parsed for-in loop w/ let declaration. 2835 // Parsed for-in loop w/ let declaration.
2841 return loop; 2836 return loop;
2842 2837
2843 } else { 2838 } else {
2844 init = variable_statement; 2839 init = variable_statement;
2845 } 2840 }
2846 } else { 2841 } else {
2842 Scanner::Location lhs_location = scanner()->peek_location();
2847 Expression* expression = ParseExpression(false, CHECK_OK); 2843 Expression* expression = ParseExpression(false, CHECK_OK);
2848 ForEachStatement::VisitMode mode; 2844 ForEachStatement::VisitMode mode;
2849 bool accept_OF = expression->AsVariableProxy(); 2845 bool accept_OF = expression->AsVariableProxy();
2850 2846
2851 if (CheckInOrOf(accept_OF, &mode)) { 2847 if (CheckInOrOf(accept_OF, &mode)) {
2852 // Signal a reference error if the expression is an invalid
2853 // left-hand side expression. We could report this as a syntax
2854 // error here but for compatibility with JSC we choose to report
2855 // the error at runtime.
2856 if (expression == NULL || !expression->IsValidLeftHandSide()) { 2848 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2857 Handle<String> message = 2849 ReportMessageAt(lhs_location, "invalid_lhs_in_for", true);
2858 isolate()->factory()->invalid_lhs_in_for_in_string(); 2850 *ok = false;
2859 expression = NewThrowReferenceError(message); 2851 return NULL;
2860 } 2852 }
2861 ForEachStatement* loop = 2853 ForEachStatement* loop =
2862 factory()->NewForEachStatement(mode, labels, pos); 2854 factory()->NewForEachStatement(mode, labels, pos);
2863 Target target(&this->target_stack_, loop); 2855 Target target(&this->target_stack_, loop);
2864 2856
2865 Expression* enumerable = ParseExpression(true, CHECK_OK); 2857 Expression* enumerable = ParseExpression(true, CHECK_OK);
2866 Expect(Token::RPAREN, CHECK_OK); 2858 Expect(Token::RPAREN, CHECK_OK);
2867 2859
2868 Statement* body = ParseStatement(NULL, CHECK_OK); 2860 Statement* body = ParseStatement(NULL, CHECK_OK);
2869 InitializeForEachStatement(loop, expression, enumerable, body); 2861 InitializeForEachStatement(loop, expression, enumerable, body);
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
3118 return factory()->NewBinaryOperation(Token::BIT_XOR, 3110 return factory()->NewBinaryOperation(Token::BIT_XOR,
3119 expression, 3111 expression,
3120 factory()->NewNumberLiteral(~0, pos), 3112 factory()->NewNumberLiteral(~0, pos),
3121 pos); 3113 pos);
3122 } 3114 }
3123 3115
3124 return factory()->NewUnaryOperation(op, expression, pos); 3116 return factory()->NewUnaryOperation(op, expression, pos);
3125 3117
3126 } else if (Token::IsCountOp(op)) { 3118 } else if (Token::IsCountOp(op)) {
3127 op = Next(); 3119 op = Next();
3120 Scanner::Location lhs_location = scanner()->peek_location();
3128 Expression* expression = ParseUnaryExpression(CHECK_OK); 3121 Expression* expression = ParseUnaryExpression(CHECK_OK);
3129 // Signal a reference error if the expression is an invalid
3130 // left-hand side expression. We could report this as a syntax
3131 // error here but for compatibility with JSC we choose to report the
3132 // error at runtime.
3133 if (expression == NULL || !expression->IsValidLeftHandSide()) { 3122 if (expression == NULL || !expression->IsValidLeftHandSide()) {
3134 Handle<String> message = 3123 ReportMessageAt(lhs_location, "invalid_lhs_in_prefix_op", true);
3135 isolate()->factory()->invalid_lhs_in_prefix_op_string(); 3124 *ok = false;
3136 expression = NewThrowReferenceError(message); 3125 return NULL;
3137 } 3126 }
3138 3127
3139 if (strict_mode() == STRICT) { 3128 if (strict_mode() == STRICT) {
3140 // Prefix expression operand in strict mode may not be eval or arguments. 3129 // Prefix expression operand in strict mode may not be eval or arguments.
3141 CheckStrictModeLValue(expression, CHECK_OK); 3130 CheckStrictModeLValue(expression, CHECK_OK);
3142 } 3131 }
3143 MarkExpressionAsLValue(expression); 3132 MarkExpressionAsLValue(expression);
3144 3133
3145 return factory()->NewCountOperation(op, 3134 return factory()->NewCountOperation(op,
3146 true /* prefix */, 3135 true /* prefix */,
3147 expression, 3136 expression,
3148 position()); 3137 position());
3149 3138
3150 } else { 3139 } else {
3151 return ParsePostfixExpression(ok); 3140 return ParsePostfixExpression(ok);
3152 } 3141 }
3153 } 3142 }
3154 3143
3155 3144
3156 Expression* Parser::ParsePostfixExpression(bool* ok) { 3145 Expression* Parser::ParsePostfixExpression(bool* ok) {
3157 // PostfixExpression :: 3146 // PostfixExpression ::
3158 // LeftHandSideExpression ('++' | '--')? 3147 // LeftHandSideExpression ('++' | '--')?
3159 3148
3149 Scanner::Location lhs_location = scanner()->peek_location();
3160 Expression* expression = ParseLeftHandSideExpression(CHECK_OK); 3150 Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
3161 if (!scanner()->HasAnyLineTerminatorBeforeNext() && 3151 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
3162 Token::IsCountOp(peek())) { 3152 Token::IsCountOp(peek())) {
3163 // Signal a reference error if the expression is an invalid
3164 // left-hand side expression. We could report this as a syntax
3165 // error here but for compatibility with JSC we choose to report the
3166 // error at runtime.
3167 if (expression == NULL || !expression->IsValidLeftHandSide()) { 3153 if (expression == NULL || !expression->IsValidLeftHandSide()) {
3168 Handle<String> message = 3154 ReportMessageAt(lhs_location, "invalid_lhs_in_postfix_op", true);
3169 isolate()->factory()->invalid_lhs_in_postfix_op_string(); 3155 *ok = false;
3170 expression = NewThrowReferenceError(message); 3156 return NULL;
3171 } 3157 }
3172 3158
3173 if (strict_mode() == STRICT) { 3159 if (strict_mode() == STRICT) {
3174 // Postfix expression operand in strict mode may not be eval or arguments. 3160 // Postfix expression operand in strict mode may not be eval or arguments.
3175 CheckStrictModeLValue(expression, CHECK_OK); 3161 CheckStrictModeLValue(expression, CHECK_OK);
3176 } 3162 }
3177 MarkExpressionAsLValue(expression); 3163 MarkExpressionAsLValue(expression);
3178 3164
3179 Token::Value next = Next(); 3165 Token::Value next = Next();
3180 expression = 3166 expression =
(...skipping 1825 matching lines...) Expand 10 before | Expand all | Expand 10 after
5006 ASSERT(info()->isolate()->has_pending_exception()); 4992 ASSERT(info()->isolate()->has_pending_exception());
5007 } else { 4993 } else {
5008 result = ParseProgram(); 4994 result = ParseProgram();
5009 } 4995 }
5010 } 4996 }
5011 info()->SetFunction(result); 4997 info()->SetFunction(result);
5012 return (result != NULL); 4998 return (result != NULL);
5013 } 4999 }
5014 5000
5015 } } // namespace v8::internal 5001 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698