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

Side by Side Diff: src/preparser.h

Issue 217823003: Make invalid LHSs that are calls late errors (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 8 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
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 407 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok); 418 ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok);
419 ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok); 419 ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
420 ExpressionT ParseUnaryExpression(bool* ok); 420 ExpressionT ParseUnaryExpression(bool* ok);
421 ExpressionT ParsePostfixExpression(bool* ok); 421 ExpressionT ParsePostfixExpression(bool* ok);
422 ExpressionT ParseLeftHandSideExpression(bool* ok); 422 ExpressionT ParseLeftHandSideExpression(bool* ok);
423 ExpressionT ParseMemberWithNewPrefixesExpression(bool* ok); 423 ExpressionT ParseMemberWithNewPrefixesExpression(bool* ok);
424 ExpressionT ParseMemberExpression(bool* ok); 424 ExpressionT ParseMemberExpression(bool* ok);
425 ExpressionT ParseMemberExpressionContinuation(ExpressionT expression, 425 ExpressionT ParseMemberExpressionContinuation(ExpressionT expression,
426 bool* ok); 426 bool* ok);
427 427
428 // Rewrite an expression that denotes a reference value.
marja 2014/04/01 16:13:47 The comment is a bit vague if the reader doesn't k
rossberg 2014/04/01 17:20:06 Done.
429 // Allows calls for web compatibility, and rewrites them to a throw.
430 ExpressionT RewriteReferenceExpression(
431 ExpressionT expression,
432 Scanner::Location location, const char* message, bool* ok);
433
428 // Used to detect duplicates in object literals. Each of the values 434 // Used to detect duplicates in object literals. Each of the values
429 // kGetterProperty, kSetterProperty and kValueProperty represents 435 // kGetterProperty, kSetterProperty and kValueProperty represents
430 // a type of object literal property. When parsing a property, its 436 // a type of object literal property. When parsing a property, its
431 // type value is stored in the DuplicateFinder for the property name. 437 // type value is stored in the DuplicateFinder for the property name.
432 // Values are chosen so that having intersection bits means the there is 438 // Values are chosen so that having intersection bits means the there is
433 // an incompatibility. 439 // an incompatibility.
434 // I.e., you can add a getter to a property that already has a setter, since 440 // I.e., you can add a getter to a property that already has a setter, since
435 // kGetterProperty and kSetterProperty doesn't intersect, but not if it 441 // kGetterProperty and kSetterProperty doesn't intersect, but not if it
436 // already has a getter or a value. Adding the getter to an existing 442 // already has a getter or a value. Adding the getter to an existing
437 // setter will store the value (kGetterProperty | kSetterProperty), which 443 // setter will store the value (kGetterProperty | kSetterProperty), which
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 } 588 }
583 589
584 static PreParserExpression ThisProperty() { 590 static PreParserExpression ThisProperty() {
585 return PreParserExpression(kThisPropertyExpression); 591 return PreParserExpression(kThisPropertyExpression);
586 } 592 }
587 593
588 static PreParserExpression Property() { 594 static PreParserExpression Property() {
589 return PreParserExpression(kPropertyExpression); 595 return PreParserExpression(kPropertyExpression);
590 } 596 }
591 597
598 static PreParserExpression Call() {
599 return PreParserExpression(kCallExpression);
600 }
601
592 bool IsIdentifier() { return (code_ & kIdentifierFlag) != 0; } 602 bool IsIdentifier() { return (code_ & kIdentifierFlag) != 0; }
593 603
594 // Only works corretly if it is actually an identifier expression.
595 PreParserIdentifier AsIdentifier() { 604 PreParserIdentifier AsIdentifier() {
605 ASSERT(IsIdentifier());
596 return PreParserIdentifier( 606 return PreParserIdentifier(
597 static_cast<PreParserIdentifier::Type>(code_ >> kIdentifierShift)); 607 static_cast<PreParserIdentifier::Type>(code_ >> kIdentifierShift));
598 } 608 }
599 609
600 bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; } 610 bool IsStringLiteral() { return (code_ & kStringLiteralFlag) != 0; }
601 611
602 bool IsUseStrictLiteral() { 612 bool IsUseStrictLiteral() {
603 return (code_ & kStringLiteralMask) == kUseStrictString; 613 return (code_ & kStringLiteralMask) == kUseStrictString;
604 } 614 }
605 615
606 bool IsThis() { return code_ == kThisExpression; } 616 bool IsThis() { return code_ == kThisExpression; }
607 617
608 bool IsThisProperty() { return code_ == kThisPropertyExpression; } 618 bool IsThisProperty() { return code_ == kThisPropertyExpression; }
609 619
610 bool IsProperty() { 620 bool IsProperty() {
611 return code_ == kPropertyExpression || code_ == kThisPropertyExpression; 621 return code_ == kPropertyExpression || code_ == kThisPropertyExpression;
612 } 622 }
613 623
624 bool IsCall() { return code_ == kCallExpression; }
625
614 bool IsValidLeftHandSide() { 626 bool IsValidLeftHandSide() {
615 return IsIdentifier() || IsProperty(); 627 return IsIdentifier() || IsProperty();
616 } 628 }
617 629
618 // At the moment PreParser doesn't track these expression types. 630 // At the moment PreParser doesn't track these expression types.
619 bool IsFunctionLiteral() const { return false; } 631 bool IsFunctionLiteral() const { return false; }
620 bool IsCall() const { return false; }
621 bool IsCallNew() const { return false; } 632 bool IsCallNew() const { return false; }
622 633
623 PreParserExpression AsFunctionLiteral() { return *this; } 634 PreParserExpression AsFunctionLiteral() { return *this; }
624 635
625 // Dummy implementation for making expression->somefunc() work in both Parser 636 // Dummy implementation for making expression->somefunc() work in both Parser
626 // and PreParser. 637 // and PreParser.
627 PreParserExpression* operator->() { return this; } 638 PreParserExpression* operator->() { return this; }
628 639
629 // More dummy implementations of things PreParser doesn't need to track: 640 // More dummy implementations of things PreParser doesn't need to track:
630 void set_index(int index) {} // For YieldExpressions 641 void set_index(int index) {} // For YieldExpressions
(...skipping 13 matching lines...) Expand all
644 655
645 kStringLiteralFlag = 2, // Used to detect directive prologue. 656 kStringLiteralFlag = 2, // Used to detect directive prologue.
646 kUnknownStringLiteral = kStringLiteralFlag, 657 kUnknownStringLiteral = kStringLiteralFlag,
647 kUseStrictString = kStringLiteralFlag | 8, 658 kUseStrictString = kStringLiteralFlag | 8,
648 kStringLiteralMask = kUseStrictString, 659 kStringLiteralMask = kUseStrictString,
649 660
650 // Below here applies if neither identifier nor string literal. Reserve the 661 // Below here applies if neither identifier nor string literal. Reserve the
651 // 2 least significant bits for flags. 662 // 2 least significant bits for flags.
652 kThisExpression = 1 << 2, 663 kThisExpression = 1 << 2,
653 kThisPropertyExpression = 2 << 2, 664 kThisPropertyExpression = 2 << 2,
654 kPropertyExpression = 3 << 2 665 kPropertyExpression = 3 << 2,
666 kCallExpression = 4 << 2
655 }; 667 };
656 668
657 explicit PreParserExpression(int expression_code) : code_(expression_code) {} 669 explicit PreParserExpression(int expression_code) : code_(expression_code) {}
658 670
659 int code_; 671 int code_;
660 }; 672 };
661 673
662 674
663 // PreParserExpressionList doesn't actually store the expressions because 675 // PreParserExpressionList doesn't actually store the expressions because
664 // PreParser doesn't need to. 676 // PreParser doesn't need to.
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
775 } 787 }
776 PreParserExpression NewCountOperation(Token::Value op, 788 PreParserExpression NewCountOperation(Token::Value op,
777 bool is_prefix, 789 bool is_prefix,
778 PreParserExpression expression, 790 PreParserExpression expression,
779 int pos) { 791 int pos) {
780 return PreParserExpression::Default(); 792 return PreParserExpression::Default();
781 } 793 }
782 PreParserExpression NewCall(PreParserExpression expression, 794 PreParserExpression NewCall(PreParserExpression expression,
783 PreParserExpressionList arguments, 795 PreParserExpressionList arguments,
784 int pos) { 796 int pos) {
785 return PreParserExpression::Default(); 797 return PreParserExpression::Call();
786 } 798 }
787 PreParserExpression NewCallNew(PreParserExpression expression, 799 PreParserExpression NewCallNew(PreParserExpression expression,
788 PreParserExpressionList arguments, 800 PreParserExpressionList arguments,
789 int pos) { 801 int pos) {
790 return PreParserExpression::Default(); 802 return PreParserExpression::Default();
791 } 803 }
792 }; 804 };
793 805
794 806
795 class PreParser; 807 class PreParser;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 850
839 // Returns true if the expression is of type "this.foo". 851 // Returns true if the expression is of type "this.foo".
840 static bool IsThisProperty(PreParserExpression expression) { 852 static bool IsThisProperty(PreParserExpression expression) {
841 return expression.IsThisProperty(); 853 return expression.IsThisProperty();
842 } 854 }
843 855
844 static bool IsIdentifier(PreParserExpression expression) { 856 static bool IsIdentifier(PreParserExpression expression) {
845 return expression.IsIdentifier(); 857 return expression.IsIdentifier();
846 } 858 }
847 859
860 static PreParserIdentifier AsIdentifier(PreParserExpression expression) {
861 return expression.AsIdentifier();
862 }
863
848 static bool IsBoilerplateProperty(PreParserExpression property) { 864 static bool IsBoilerplateProperty(PreParserExpression property) {
849 // PreParser doesn't count boilerplate properties. 865 // PreParser doesn't count boilerplate properties.
850 return false; 866 return false;
851 } 867 }
852 868
853 static bool IsArrayIndex(PreParserIdentifier string, uint32_t* index) { 869 static bool IsArrayIndex(PreParserIdentifier string, uint32_t* index) {
854 return false; 870 return false;
855 } 871 }
856 872
857 // Functions for encapsulating the differences between parsing and preparsing; 873 // Functions for encapsulating the differences between parsing and preparsing;
(...skipping 18 matching lines...) Expand all
876 static void CheckPossibleEvalCall(PreParserExpression expression, 892 static void CheckPossibleEvalCall(PreParserExpression expression,
877 PreParserScope* scope) {} 893 PreParserScope* scope) {}
878 894
879 static PreParserExpression MarkExpressionAsLValue( 895 static PreParserExpression MarkExpressionAsLValue(
880 PreParserExpression expression) { 896 PreParserExpression expression) {
881 // TODO(marja): To be able to produce the same errors, the preparser needs 897 // TODO(marja): To be able to produce the same errors, the preparser needs
882 // to start tracking which expressions are variables and which are lvalues. 898 // to start tracking which expressions are variables and which are lvalues.
883 return expression; 899 return expression;
884 } 900 }
885 901
886 // Checks LHS expression for assignment and prefix/postfix increment/decrement
887 // in strict mode.
888 void CheckStrictModeLValue(PreParserExpression expression, bool* ok);
889
890 bool ShortcutNumericLiteralBinaryExpression(PreParserExpression* x, 902 bool ShortcutNumericLiteralBinaryExpression(PreParserExpression* x,
891 PreParserExpression y, 903 PreParserExpression y,
892 Token::Value op, 904 Token::Value op,
893 int pos, 905 int pos,
894 PreParserFactory* factory) { 906 PreParserFactory* factory) {
895 return false; 907 return false;
896 } 908 }
897 909
898 PreParserExpression BuildUnaryExpression(PreParserExpression expression, 910 PreParserExpression BuildUnaryExpression(PreParserExpression expression,
899 Token::Value op, int pos, 911 Token::Value op, int pos,
900 PreParserFactory* factory) { 912 PreParserFactory* factory) {
901 return PreParserExpression::Default(); 913 return PreParserExpression::Default();
902 } 914 }
903 915
916 PreParserExpression NewThrowReferenceError(const char* type, int pos) {
917 return PreParserExpression::Default();
918 }
919 PreParserExpression NewThrowSyntaxError(
920 const char* type, Handle<Object> arg, int pos) {
921 return PreParserExpression::Default();
922 }
923 PreParserExpression NewThrowTypeError(
924 const char* type, Handle<Object> arg1, Handle<Object> arg2, int pos) {
925 return PreParserExpression::Default();
926 }
927
904 // Reporting errors. 928 // Reporting errors.
905 void ReportMessageAt(Scanner::Location location, 929 void ReportMessageAt(Scanner::Location location,
906 const char* message, 930 const char* message,
907 Vector<const char*> args, 931 Vector<const char*> args,
908 bool is_reference_error = false); 932 bool is_reference_error = false);
909 void ReportMessageAt(Scanner::Location location, 933 void ReportMessageAt(Scanner::Location location,
910 const char* type, 934 const char* type,
911 const char* name_opt, 935 const char* name_opt,
912 bool is_reference_error = false); 936 bool is_reference_error = false);
913 void ReportMessageAt(int start_pos, 937 void ReportMessageAt(int start_pos,
(...skipping 774 matching lines...) Expand 10 before | Expand all | Expand 10 after
1688 if (fni_ != NULL) fni_->Enter(); 1712 if (fni_ != NULL) fni_->Enter();
1689 ExpressionT expression = 1713 ExpressionT expression =
1690 this->ParseConditionalExpression(accept_IN, CHECK_OK); 1714 this->ParseConditionalExpression(accept_IN, CHECK_OK);
1691 1715
1692 if (!Token::IsAssignmentOp(peek())) { 1716 if (!Token::IsAssignmentOp(peek())) {
1693 if (fni_ != NULL) fni_->Leave(); 1717 if (fni_ != NULL) fni_->Leave();
1694 // Parsed conditional expression only (no assignment). 1718 // Parsed conditional expression only (no assignment).
1695 return expression; 1719 return expression;
1696 } 1720 }
1697 1721
1698 if (!expression->IsValidLeftHandSide()) { 1722 expression = this->RewriteReferenceExpression(
1699 this->ReportMessageAt(lhs_location, "invalid_lhs_in_assignment", true); 1723 expression, lhs_location, "invalid_lhs_in_assignment", CHECK_OK);
1700 *ok = false;
1701 return this->EmptyExpression();
1702 }
1703
1704 if (strict_mode() == STRICT) {
1705 // Assignment to eval or arguments is disallowed in strict mode.
1706 this->CheckStrictModeLValue(expression, CHECK_OK);
1707 }
1708 expression = this->MarkExpressionAsLValue(expression); 1724 expression = this->MarkExpressionAsLValue(expression);
1709 1725
1710 Token::Value op = Next(); // Get assignment operator. 1726 Token::Value op = Next(); // Get assignment operator.
1711 int pos = position(); 1727 int pos = position();
1712 ExpressionT right = this->ParseAssignmentExpression(accept_IN, CHECK_OK); 1728 ExpressionT right = this->ParseAssignmentExpression(accept_IN, CHECK_OK);
1713 1729
1714 // TODO(1231235): We try to estimate the set of properties set by 1730 // TODO(1231235): We try to estimate the set of properties set by
1715 // constructors. We define a new property whenever there is an 1731 // constructors. We define a new property whenever there is an
1716 // assignment to a property of 'this'. We should probably only add 1732 // assignment to a property of 'this'. We should probably only add
1717 // properties if we haven't seen them before. Otherwise we'll 1733 // properties if we haven't seen them before. Otherwise we'll
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
1857 ReportMessage("strict_delete", Vector<const char*>::empty()); 1873 ReportMessage("strict_delete", Vector<const char*>::empty());
1858 *ok = false; 1874 *ok = false;
1859 return this->EmptyExpression(); 1875 return this->EmptyExpression();
1860 } 1876 }
1861 1877
1862 // Allow Traits do rewrite the expression. 1878 // Allow Traits do rewrite the expression.
1863 return this->BuildUnaryExpression(expression, op, pos, factory()); 1879 return this->BuildUnaryExpression(expression, op, pos, factory());
1864 } else if (Token::IsCountOp(op)) { 1880 } else if (Token::IsCountOp(op)) {
1865 op = Next(); 1881 op = Next();
1866 Scanner::Location lhs_location = scanner()->peek_location(); 1882 Scanner::Location lhs_location = scanner()->peek_location();
1867 ExpressionT expression = ParseUnaryExpression(CHECK_OK); 1883 ExpressionT expression = this->ParseUnaryExpression(CHECK_OK);
1868 if (!expression->IsValidLeftHandSide()) { 1884 expression = this->RewriteReferenceExpression(
1869 ReportMessageAt(lhs_location, "invalid_lhs_in_prefix_op", true); 1885 expression, lhs_location, "invalid_lhs_in_prefix_op", CHECK_OK);
1870 *ok = false;
1871 return this->EmptyExpression();
1872 }
1873
1874 if (strict_mode() == STRICT) {
1875 // Prefix expression operand in strict mode may not be eval or arguments.
1876 this->CheckStrictModeLValue(expression, CHECK_OK);
1877 }
1878 this->MarkExpressionAsLValue(expression); 1886 this->MarkExpressionAsLValue(expression);
1879 1887
1880 return factory()->NewCountOperation(op, 1888 return factory()->NewCountOperation(op,
1881 true /* prefix */, 1889 true /* prefix */,
1882 expression, 1890 expression,
1883 position()); 1891 position());
1884 1892
1885 } else { 1893 } else {
1886 return this->ParsePostfixExpression(ok); 1894 return this->ParsePostfixExpression(ok);
1887 } 1895 }
1888 } 1896 }
1889 1897
1890 1898
1891 template <class Traits> 1899 template <class Traits>
1892 typename ParserBase<Traits>::ExpressionT 1900 typename ParserBase<Traits>::ExpressionT
1893 ParserBase<Traits>::ParsePostfixExpression(bool* ok) { 1901 ParserBase<Traits>::ParsePostfixExpression(bool* ok) {
1894 // PostfixExpression :: 1902 // PostfixExpression ::
1895 // LeftHandSideExpression ('++' | '--')? 1903 // LeftHandSideExpression ('++' | '--')?
1896 1904
1897 Scanner::Location lhs_location = scanner()->peek_location(); 1905 Scanner::Location lhs_location = scanner()->peek_location();
1898 ExpressionT expression = this->ParseLeftHandSideExpression(CHECK_OK); 1906 ExpressionT expression = this->ParseLeftHandSideExpression(CHECK_OK);
1899 if (!scanner()->HasAnyLineTerminatorBeforeNext() && 1907 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
1900 Token::IsCountOp(peek())) { 1908 Token::IsCountOp(peek())) {
1901 if (!expression->IsValidLeftHandSide()) { 1909 expression = this->RewriteReferenceExpression(
1902 ReportMessageAt(lhs_location, "invalid_lhs_in_postfix_op", true); 1910 expression, lhs_location, "invalid_lhs_in_postfix_op", CHECK_OK);
1903 *ok = false;
1904 return this->EmptyExpression();
1905 }
1906
1907 if (strict_mode() == STRICT) {
1908 // Postfix expression operand in strict mode may not be eval or arguments.
1909 this->CheckStrictModeLValue(expression, CHECK_OK);
1910 }
1911 expression = this->MarkExpressionAsLValue(expression); 1911 expression = this->MarkExpressionAsLValue(expression);
1912 1912
1913 Token::Value next = Next(); 1913 Token::Value next = Next();
1914 expression = 1914 expression =
1915 factory()->NewCountOperation(next, 1915 factory()->NewCountOperation(next,
1916 false /* postfix */, 1916 false /* postfix */,
1917 expression, 1917 expression,
1918 position()); 1918 position());
1919 } 1919 }
1920 return expression; 1920 return expression;
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
2110 } 2110 }
2111 default: 2111 default:
2112 return expression; 2112 return expression;
2113 } 2113 }
2114 } 2114 }
2115 ASSERT(false); 2115 ASSERT(false);
2116 return this->EmptyExpression(); 2116 return this->EmptyExpression();
2117 } 2117 }
2118 2118
2119 2119
2120 template <typename Traits>
2121 typename ParserBase<Traits>::ExpressionT
2122 ParserBase<Traits>::RewriteReferenceExpression(
2123 ExpressionT expression,
2124 Scanner::Location location, const char* message, bool* ok) {
2125 if (strict_mode() == STRICT && this->IsIdentifier(expression) &&
2126 this->IsEvalOrArguments(this->AsIdentifier(expression))) {
2127 this->ReportMessageAt(location, "strict_eval_arguments", false);
2128 *ok = false;
2129 return this->EmptyExpression();
2130 } else if (expression->IsValidLeftHandSide()) {
2131 return expression;
2132 } else if (expression->IsCall()) {
2133 // If it is a call, make it a runtime error for legacy web compatibility.
2134 // Rewrite `expr' to `expr[throw ReferenceError]'.
2135 int pos = location.beg_pos;
2136 ExpressionT error = this->NewThrowReferenceError(message, pos);
2137 return factory()->NewProperty(expression, error, pos);
2138 } else {
2139 this->ReportMessageAt(location, message, true);
2140 *ok = false;
2141 return this->EmptyExpression();
2142 }
2143 }
2144
2145
2120 #undef CHECK_OK 2146 #undef CHECK_OK
2121 #undef CHECK_OK_CUSTOM 2147 #undef CHECK_OK_CUSTOM
2122 2148
2123 2149
2124 template <typename Traits> 2150 template <typename Traits>
2125 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( 2151 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty(
2126 Token::Value property, 2152 Token::Value property,
2127 PropertyKind type, 2153 PropertyKind type,
2128 bool* ok) { 2154 bool* ok) {
2129 int old; 2155 int old;
(...skipping 20 matching lines...) Expand all
2150 "accessor_get_set"); 2176 "accessor_get_set");
2151 } 2177 }
2152 *ok = false; 2178 *ok = false;
2153 } 2179 }
2154 } 2180 }
2155 2181
2156 2182
2157 } } // v8::internal 2183 } } // v8::internal
2158 2184
2159 #endif // V8_PREPARSER_H 2185 #endif // V8_PREPARSER_H
OLDNEW
« src/parser.cc ('K') | « src/parser.cc ('k') | src/preparser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698