OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |