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

Side by Side Diff: src/parser.cc

Issue 26375004: Unify and fix checkers for duplicate object literal properties. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix check for illegal getter/setter name. Created 7 years, 2 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 3753 matching lines...) Expand 10 before | Expand all | Expand 10 after
3764 if (expression->AsLiteral() != NULL) { 3764 if (expression->AsLiteral() != NULL) {
3765 return expression->AsLiteral()->value(); 3765 return expression->AsLiteral()->value();
3766 } 3766 }
3767 if (CompileTimeValue::IsCompileTimeValue(expression)) { 3767 if (CompileTimeValue::IsCompileTimeValue(expression)) {
3768 return CompileTimeValue::GetValue(isolate(), expression); 3768 return CompileTimeValue::GetValue(isolate(), expression);
3769 } 3769 }
3770 return isolate()->factory()->uninitialized_value(); 3770 return isolate()->factory()->uninitialized_value();
3771 } 3771 }
3772 3772
3773 3773
3774 // Validation per 11.1.5 Object Initialiser
3775 class ObjectLiteralPropertyChecker {
3776 public:
3777 ObjectLiteralPropertyChecker(Parser* parser, LanguageMode language_mode) :
3778 props_(Literal::Match),
3779 parser_(parser),
3780 language_mode_(language_mode) {
3781 }
3782
3783 void CheckProperty(
3784 ObjectLiteral::Property* property,
3785 Scanner::Location loc,
3786 bool* ok);
3787
3788 private:
3789 enum PropertyKind {
3790 kGetAccessor = 0x01,
3791 kSetAccessor = 0x02,
3792 kAccessor = kGetAccessor | kSetAccessor,
3793 kData = 0x04
3794 };
3795
3796 static intptr_t GetPropertyKind(ObjectLiteral::Property* property) {
3797 switch (property->kind()) {
3798 case ObjectLiteral::Property::GETTER:
3799 return kGetAccessor;
3800 case ObjectLiteral::Property::SETTER:
3801 return kSetAccessor;
3802 default:
3803 return kData;
3804 }
3805 }
3806
3807 HashMap props_;
3808 Parser* parser_;
3809 LanguageMode language_mode_;
3810 };
3811
3812
3813 void ObjectLiteralPropertyChecker::CheckProperty(
3814 ObjectLiteral::Property* property,
3815 Scanner::Location loc,
3816 bool* ok) {
3817 ASSERT(property != NULL);
3818 Literal* literal = property->key();
3819 HashMap::Entry* entry = props_.Lookup(literal, literal->Hash(), true);
3820 intptr_t prev = reinterpret_cast<intptr_t> (entry->value);
3821 intptr_t curr = GetPropertyKind(property);
3822
3823 // Duplicate data properties are illegal in strict or extended mode.
3824 if (language_mode_ != CLASSIC_MODE && (curr & prev & kData) != 0) {
3825 parser_->ReportMessageAt(loc, "strict_duplicate_property",
3826 Vector<const char*>::empty());
3827 *ok = false;
3828 return;
3829 }
3830 // Data property conflicting with an accessor.
3831 if (((curr & kData) && (prev & kAccessor)) ||
3832 ((prev & kData) && (curr & kAccessor))) {
3833 parser_->ReportMessageAt(loc, "accessor_data_property",
3834 Vector<const char*>::empty());
3835 *ok = false;
3836 return;
3837 }
3838 // Two accessors of the same type conflicting
3839 if ((curr & prev & kAccessor) != 0) {
3840 parser_->ReportMessageAt(loc, "accessor_get_set",
3841 Vector<const char*>::empty());
3842 *ok = false;
3843 return;
3844 }
3845
3846 // Update map
3847 entry->value = reinterpret_cast<void*> (prev | curr);
3848 *ok = true;
3849 }
3850
3851
3852 void Parser::BuildObjectLiteralConstantProperties( 3774 void Parser::BuildObjectLiteralConstantProperties(
3853 ZoneList<ObjectLiteral::Property*>* properties, 3775 ZoneList<ObjectLiteral::Property*>* properties,
3854 Handle<FixedArray> constant_properties, 3776 Handle<FixedArray> constant_properties,
3855 bool* is_simple, 3777 bool* is_simple,
3856 bool* fast_elements, 3778 bool* fast_elements,
3857 int* depth, 3779 int* depth,
3858 bool* may_store_doubles) { 3780 bool* may_store_doubles) {
3859 int position = 0; 3781 int position = 0;
3860 // Accumulate the value in local variables and store it at the end. 3782 // Accumulate the value in local variables and store it at the end.
3861 bool is_simple_acc = true; 3783 bool is_simple_acc = true;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
3914 constant_properties->set(position++, *key); 3836 constant_properties->set(position++, *key);
3915 constant_properties->set(position++, *value); 3837 constant_properties->set(position++, *value);
3916 } 3838 }
3917 *fast_elements = 3839 *fast_elements =
3918 (max_element_index <= 32) || ((2 * elements) >= max_element_index); 3840 (max_element_index <= 32) || ((2 * elements) >= max_element_index);
3919 *is_simple = is_simple_acc; 3841 *is_simple = is_simple_acc;
3920 *depth = depth_acc; 3842 *depth = depth_acc;
3921 } 3843 }
3922 3844
3923 3845
3924 ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter, 3846 // Force instantiation of template instances class.
3925 bool* ok) { 3847 template void ObjectLiteralChecker<Parser>::CheckProperty(
3926 // Special handling of getter and setter syntax: 3848 Token::Value property, PropertyKind type, bool* ok);
3927 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
3928 // We have already read the "get" or "set" keyword.
3929 Token::Value next = Next();
3930 bool is_keyword = Token::IsKeyword(next);
3931 if (next == Token::IDENTIFIER || next == Token::NUMBER ||
3932 next == Token::FUTURE_RESERVED_WORD ||
3933 next == Token::FUTURE_STRICT_RESERVED_WORD ||
3934 next == Token::STRING || is_keyword) {
3935 Handle<String> name;
3936 if (is_keyword) {
3937 name = isolate_->factory()->InternalizeUtf8String(Token::String(next));
3938 } else {
3939 name = GetSymbol();
3940 }
3941 FunctionLiteral* value =
3942 ParseFunctionLiteral(name,
3943 false, // reserved words are allowed here
3944 false, // not a generator
3945 RelocInfo::kNoPosition,
3946 FunctionLiteral::ANONYMOUS_EXPRESSION,
3947 CHECK_OK);
3948 // Allow any number of parameters for compatibilty with JSC.
3949 // Specification only allows zero parameters for get and one for set.
3950 return factory()->NewObjectLiteralProperty(is_getter, value);
3951 } else {
3952 ReportUnexpectedToken(next);
3953 *ok = false;
3954 return NULL;
3955 }
3956 }
3957 3849
3958 3850
3959 Expression* Parser::ParseObjectLiteral(bool* ok) { 3851 Expression* Parser::ParseObjectLiteral(bool* ok) {
3960 // ObjectLiteral :: 3852 // ObjectLiteral ::
3961 // '{' ( 3853 // '{' (
3962 // ((IdentifierName | String | Number) ':' AssignmentExpression) 3854 // ((IdentifierName | String | Number) ':' AssignmentExpression)
3963 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) 3855 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
3964 // )*[','] '}' 3856 // )*[','] '}'
3965 3857
3966 ZoneList<ObjectLiteral::Property*>* properties = 3858 ZoneList<ObjectLiteral::Property*>* properties =
3967 new(zone()) ZoneList<ObjectLiteral::Property*>(4, zone()); 3859 new(zone()) ZoneList<ObjectLiteral::Property*>(4, zone());
3968 int number_of_boilerplate_properties = 0; 3860 int number_of_boilerplate_properties = 0;
3969 bool has_function = false; 3861 bool has_function = false;
3970 3862
3971 ObjectLiteralPropertyChecker checker(this, top_scope_->language_mode()); 3863 ObjectLiteralChecker<Parser> checker(this, &scanner_,
3864 top_scope_->language_mode());
3972 3865
3973 Expect(Token::LBRACE, CHECK_OK); 3866 Expect(Token::LBRACE, CHECK_OK);
3974 3867
3975 while (peek() != Token::RBRACE) { 3868 while (peek() != Token::RBRACE) {
3976 if (fni_ != NULL) fni_->Enter(); 3869 if (fni_ != NULL) fni_->Enter();
3977 3870
3978 Literal* key = NULL; 3871 Literal* key = NULL;
3979 Token::Value next = peek(); 3872 Token::Value next = peek();
3980 3873
3981 // Location of the property name token
3982 Scanner::Location loc = scanner().peek_location();
3983
3984 switch (next) { 3874 switch (next) {
3985 case Token::FUTURE_RESERVED_WORD: 3875 case Token::FUTURE_RESERVED_WORD:
3986 case Token::FUTURE_STRICT_RESERVED_WORD: 3876 case Token::FUTURE_STRICT_RESERVED_WORD:
3987 case Token::IDENTIFIER: { 3877 case Token::IDENTIFIER: {
3988 bool is_getter = false; 3878 bool is_getter = false;
3989 bool is_setter = false; 3879 bool is_setter = false;
3990 Handle<String> id = 3880 Handle<String> id =
3991 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); 3881 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
3992 if (fni_ != NULL) fni_->PushLiteralName(id); 3882 if (fni_ != NULL) fni_->PushLiteralName(id);
3993 3883
3994 if ((is_getter || is_setter) && peek() != Token::COLON) { 3884 if ((is_getter || is_setter) && peek() != Token::COLON) {
3995 // Update loc to point to the identifier 3885 // Special handling of getter and setter syntax:
3996 loc = scanner().peek_location(); 3886 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
3997 ObjectLiteral::Property* property = 3887 // We have already read the "get" or "set" keyword.
3998 ParseObjectLiteralGetSet(is_getter, CHECK_OK); 3888 Token::Value next = Next();
3999 if (IsBoilerplateProperty(property)) { 3889 bool is_keyword = Token::IsKeyword(next);
4000 number_of_boilerplate_properties++; 3890 if (next != i::Token::IDENTIFIER &&
4001 } 3891 next != i::Token::FUTURE_RESERVED_WORD &&
4002 // Validate the property. 3892 next != i::Token::FUTURE_STRICT_RESERVED_WORD &&
4003 checker.CheckProperty(property, loc, CHECK_OK); 3893 next != i::Token::NUMBER &&
4004 properties->Add(property, zone()); 3894 next != i::Token::STRING &&
4005 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); 3895 !is_keyword) {
3896 // Unexpected token.
3897 ReportUnexpectedToken(next);
3898 *ok = false;
3899 return NULL;
3900 }
3901 // Validate the property.
3902 PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
3903 checker.CheckProperty(next, type, CHECK_OK);
3904 Handle<String> name = is_keyword
3905 ? isolate_->factory()->InternalizeUtf8String(Token::String(next))
3906 : GetSymbol();
3907 FunctionLiteral* value =
3908 ParseFunctionLiteral(name,
3909 false, // reserved words are allowed here
3910 false, // not a generator
3911 RelocInfo::kNoPosition,
3912 FunctionLiteral::ANONYMOUS_EXPRESSION,
3913 CHECK_OK);
3914 // Allow any number of parameters for compatibilty with JSC.
3915 // Specification only allows zero parameters for get and one for set.
3916 ObjectLiteral::Property* property =
3917 factory()->NewObjectLiteralProperty(is_getter, value);
3918 if (IsBoilerplateProperty(property)) {
3919 number_of_boilerplate_properties++;
3920 }
3921 properties->Add(property, zone());
3922 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
4006 3923
4007 if (fni_ != NULL) { 3924 if (fni_ != NULL) {
4008 fni_->Infer(); 3925 fni_->Infer();
4009 fni_->Leave(); 3926 fni_->Leave();
4010 } 3927 }
4011 continue; // restart the while 3928 continue; // restart the while
4012 } 3929 }
4013 // Failed to parse as get/set property, so it's just a property 3930 // Failed to parse as get/set property, so it's just a property
4014 // called "get" or "set". 3931 // called "get" or "set".
4015 key = factory()->NewLiteral(id); 3932 key = factory()->NewLiteral(id);
4016 break; 3933 break;
4017 } 3934 }
4018 case Token::STRING: { 3935 case Token::STRING: {
4019 Consume(Token::STRING); 3936 Consume(Token::STRING);
4020 Handle<String> string = GetSymbol(); 3937 Handle<String> string = GetSymbol();
4021 if (fni_ != NULL) fni_->PushLiteralName(string); 3938 if (fni_ != NULL) fni_->PushLiteralName(string);
(...skipping 22 matching lines...) Expand all
4044 key = factory()->NewLiteral(string); 3961 key = factory()->NewLiteral(string);
4045 } else { 3962 } else {
4046 // Unexpected token. 3963 // Unexpected token.
4047 Token::Value next = Next(); 3964 Token::Value next = Next();
4048 ReportUnexpectedToken(next); 3965 ReportUnexpectedToken(next);
4049 *ok = false; 3966 *ok = false;
4050 return NULL; 3967 return NULL;
4051 } 3968 }
4052 } 3969 }
4053 3970
3971 // Validate the property
3972 checker.CheckProperty(next, kValueProperty, CHECK_OK);
3973
4054 Expect(Token::COLON, CHECK_OK); 3974 Expect(Token::COLON, CHECK_OK);
4055 Expression* value = ParseAssignmentExpression(true, CHECK_OK); 3975 Expression* value = ParseAssignmentExpression(true, CHECK_OK);
4056 3976
4057 ObjectLiteral::Property* property = 3977 ObjectLiteral::Property* property =
4058 new(zone()) ObjectLiteral::Property(key, value, isolate()); 3978 new(zone()) ObjectLiteral::Property(key, value, isolate());
4059 3979
4060 // Mark top-level object literals that contain function literals and 3980 // Mark top-level object literals that contain function literals and
4061 // pretenure the literal so it can be added as a constant function 3981 // pretenure the literal so it can be added as a constant function
4062 // property. 3982 // property.
4063 if (top_scope_->DeclarationScope()->is_global_scope() && 3983 if (top_scope_->DeclarationScope()->is_global_scope() &&
4064 value->AsFunctionLiteral() != NULL) { 3984 value->AsFunctionLiteral() != NULL) {
4065 has_function = true; 3985 has_function = true;
4066 value->AsFunctionLiteral()->set_pretenure(); 3986 value->AsFunctionLiteral()->set_pretenure();
4067 } 3987 }
4068 3988
4069 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. 3989 // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
4070 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++; 3990 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
4071 // Validate the property
4072 checker.CheckProperty(property, loc, CHECK_OK);
4073 properties->Add(property, zone()); 3991 properties->Add(property, zone());
4074 3992
4075 // TODO(1240767): Consider allowing trailing comma. 3993 // TODO(1240767): Consider allowing trailing comma.
4076 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); 3994 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
4077 3995
4078 if (fni_ != NULL) { 3996 if (fni_ != NULL) {
4079 fni_->Infer(); 3997 fni_->Infer();
4080 fni_->Leave(); 3998 fni_->Leave();
4081 } 3999 }
4082 } 4000 }
(...skipping 1871 matching lines...) Expand 10 before | Expand all | Expand 10 after
5954 ASSERT(info()->isolate()->has_pending_exception()); 5872 ASSERT(info()->isolate()->has_pending_exception());
5955 } else { 5873 } else {
5956 result = ParseProgram(); 5874 result = ParseProgram();
5957 } 5875 }
5958 } 5876 }
5959 info()->SetFunction(result); 5877 info()->SetFunction(result);
5960 return (result != NULL); 5878 return (result != NULL);
5961 } 5879 }
5962 5880
5963 } } // namespace v8::internal 5881 } } // 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