| 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 |
| 3774 void Parser::BuildObjectLiteralConstantProperties( | 3852 void Parser::BuildObjectLiteralConstantProperties( |
| 3775 ZoneList<ObjectLiteral::Property*>* properties, | 3853 ZoneList<ObjectLiteral::Property*>* properties, |
| 3776 Handle<FixedArray> constant_properties, | 3854 Handle<FixedArray> constant_properties, |
| 3777 bool* is_simple, | 3855 bool* is_simple, |
| 3778 bool* fast_elements, | 3856 bool* fast_elements, |
| 3779 int* depth, | 3857 int* depth, |
| 3780 bool* may_store_doubles) { | 3858 bool* may_store_doubles) { |
| 3781 int position = 0; | 3859 int position = 0; |
| 3782 // Accumulate the value in local variables and store it at the end. | 3860 // Accumulate the value in local variables and store it at the end. |
| 3783 bool is_simple_acc = true; | 3861 bool is_simple_acc = true; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3836 constant_properties->set(position++, *key); | 3914 constant_properties->set(position++, *key); |
| 3837 constant_properties->set(position++, *value); | 3915 constant_properties->set(position++, *value); |
| 3838 } | 3916 } |
| 3839 *fast_elements = | 3917 *fast_elements = |
| 3840 (max_element_index <= 32) || ((2 * elements) >= max_element_index); | 3918 (max_element_index <= 32) || ((2 * elements) >= max_element_index); |
| 3841 *is_simple = is_simple_acc; | 3919 *is_simple = is_simple_acc; |
| 3842 *depth = depth_acc; | 3920 *depth = depth_acc; |
| 3843 } | 3921 } |
| 3844 | 3922 |
| 3845 | 3923 |
| 3846 // Force instantiation of template instances class. | |
| 3847 template void ObjectLiteralChecker<Parser>::CheckProperty( | |
| 3848 Token::Value property, PropertyKind type, bool* ok); | |
| 3849 | |
| 3850 | |
| 3851 ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter, | 3924 ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter, |
| 3852 bool* ok) { | 3925 bool* ok) { |
| 3853 // Special handling of getter and setter syntax: | 3926 // Special handling of getter and setter syntax: |
| 3854 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... } | 3927 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... } |
| 3855 // We have already read the "get" or "set" keyword and the name. | 3928 // We have already read the "get" or "set" keyword. |
| 3856 Token::Value next = scanner().current_token(); | 3929 Token::Value next = Next(); |
| 3857 bool is_keyword = Token::IsKeyword(next); | 3930 bool is_keyword = Token::IsKeyword(next); |
| 3858 if (next == Token::IDENTIFIER || next == Token::NUMBER || | 3931 if (next == Token::IDENTIFIER || next == Token::NUMBER || |
| 3859 next == Token::FUTURE_RESERVED_WORD || | 3932 next == Token::FUTURE_RESERVED_WORD || |
| 3860 next == Token::FUTURE_STRICT_RESERVED_WORD || | 3933 next == Token::FUTURE_STRICT_RESERVED_WORD || |
| 3861 next == Token::STRING || is_keyword) { | 3934 next == Token::STRING || is_keyword) { |
| 3862 Handle<String> name; | 3935 Handle<String> name; |
| 3863 if (is_keyword) { | 3936 if (is_keyword) { |
| 3864 name = isolate_->factory()->InternalizeUtf8String(Token::String(next)); | 3937 name = isolate_->factory()->InternalizeUtf8String(Token::String(next)); |
| 3865 } else { | 3938 } else { |
| 3866 name = GetSymbol(); | 3939 name = GetSymbol(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 3888 // '{' ( | 3961 // '{' ( |
| 3889 // ((IdentifierName | String | Number) ':' AssignmentExpression) | 3962 // ((IdentifierName | String | Number) ':' AssignmentExpression) |
| 3890 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) | 3963 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) |
| 3891 // )*[','] '}' | 3964 // )*[','] '}' |
| 3892 | 3965 |
| 3893 ZoneList<ObjectLiteral::Property*>* properties = | 3966 ZoneList<ObjectLiteral::Property*>* properties = |
| 3894 new(zone()) ZoneList<ObjectLiteral::Property*>(4, zone()); | 3967 new(zone()) ZoneList<ObjectLiteral::Property*>(4, zone()); |
| 3895 int number_of_boilerplate_properties = 0; | 3968 int number_of_boilerplate_properties = 0; |
| 3896 bool has_function = false; | 3969 bool has_function = false; |
| 3897 | 3970 |
| 3898 ObjectLiteralChecker<Parser> checker(this, &scanner_, | 3971 ObjectLiteralPropertyChecker checker(this, top_scope_->language_mode()); |
| 3899 top_scope_->language_mode()); | |
| 3900 | 3972 |
| 3901 Expect(Token::LBRACE, CHECK_OK); | 3973 Expect(Token::LBRACE, CHECK_OK); |
| 3902 | 3974 |
| 3903 while (peek() != Token::RBRACE) { | 3975 while (peek() != Token::RBRACE) { |
| 3904 if (fni_ != NULL) fni_->Enter(); | 3976 if (fni_ != NULL) fni_->Enter(); |
| 3905 | 3977 |
| 3906 Literal* key = NULL; | 3978 Literal* key = NULL; |
| 3907 Token::Value next = peek(); | 3979 Token::Value next = peek(); |
| 3908 | 3980 |
| 3981 // Location of the property name token |
| 3982 Scanner::Location loc = scanner().peek_location(); |
| 3983 |
| 3909 switch (next) { | 3984 switch (next) { |
| 3910 case Token::FUTURE_RESERVED_WORD: | 3985 case Token::FUTURE_RESERVED_WORD: |
| 3911 case Token::FUTURE_STRICT_RESERVED_WORD: | 3986 case Token::FUTURE_STRICT_RESERVED_WORD: |
| 3912 case Token::IDENTIFIER: { | 3987 case Token::IDENTIFIER: { |
| 3913 bool is_getter = false; | 3988 bool is_getter = false; |
| 3914 bool is_setter = false; | 3989 bool is_setter = false; |
| 3915 Handle<String> id = | 3990 Handle<String> id = |
| 3916 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); | 3991 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); |
| 3917 if (fni_ != NULL) fni_->PushLiteralName(id); | 3992 if (fni_ != NULL) fni_->PushLiteralName(id); |
| 3918 | 3993 |
| 3919 if ((is_getter || is_setter) && peek() != Token::COLON) { | 3994 if ((is_getter || is_setter) && peek() != Token::COLON) { |
| 3920 // Validate the property. | 3995 // Update loc to point to the identifier |
| 3921 PropertyKind type = is_getter ? kGetterProperty : kSetterProperty; | 3996 loc = scanner().peek_location(); |
| 3922 checker.CheckProperty(Next(), type, CHECK_OK); | |
| 3923 ObjectLiteral::Property* property = | 3997 ObjectLiteral::Property* property = |
| 3924 ParseObjectLiteralGetSet(is_getter, CHECK_OK); | 3998 ParseObjectLiteralGetSet(is_getter, CHECK_OK); |
| 3925 if (IsBoilerplateProperty(property)) { | 3999 if (IsBoilerplateProperty(property)) { |
| 3926 number_of_boilerplate_properties++; | 4000 number_of_boilerplate_properties++; |
| 3927 } | 4001 } |
| 4002 // Validate the property. |
| 4003 checker.CheckProperty(property, loc, CHECK_OK); |
| 3928 properties->Add(property, zone()); | 4004 properties->Add(property, zone()); |
| 3929 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); | 4005 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); |
| 3930 | 4006 |
| 3931 if (fni_ != NULL) { | 4007 if (fni_ != NULL) { |
| 3932 fni_->Infer(); | 4008 fni_->Infer(); |
| 3933 fni_->Leave(); | 4009 fni_->Leave(); |
| 3934 } | 4010 } |
| 3935 continue; // restart the while | 4011 continue; // restart the while |
| 3936 } | 4012 } |
| 3937 // Failed to parse as get/set property, so it's just a property | 4013 // Failed to parse as get/set property, so it's just a property |
| (...skipping 30 matching lines...) Expand all Loading... |
| 3968 key = factory()->NewLiteral(string); | 4044 key = factory()->NewLiteral(string); |
| 3969 } else { | 4045 } else { |
| 3970 // Unexpected token. | 4046 // Unexpected token. |
| 3971 Token::Value next = Next(); | 4047 Token::Value next = Next(); |
| 3972 ReportUnexpectedToken(next); | 4048 ReportUnexpectedToken(next); |
| 3973 *ok = false; | 4049 *ok = false; |
| 3974 return NULL; | 4050 return NULL; |
| 3975 } | 4051 } |
| 3976 } | 4052 } |
| 3977 | 4053 |
| 3978 // Validate the property | |
| 3979 checker.CheckProperty(next, kValueProperty, CHECK_OK); | |
| 3980 | |
| 3981 Expect(Token::COLON, CHECK_OK); | 4054 Expect(Token::COLON, CHECK_OK); |
| 3982 Expression* value = ParseAssignmentExpression(true, CHECK_OK); | 4055 Expression* value = ParseAssignmentExpression(true, CHECK_OK); |
| 3983 | 4056 |
| 3984 ObjectLiteral::Property* property = | 4057 ObjectLiteral::Property* property = |
| 3985 new(zone()) ObjectLiteral::Property(key, value, isolate()); | 4058 new(zone()) ObjectLiteral::Property(key, value, isolate()); |
| 3986 | 4059 |
| 3987 // Mark top-level object literals that contain function literals and | 4060 // Mark top-level object literals that contain function literals and |
| 3988 // pretenure the literal so it can be added as a constant function | 4061 // pretenure the literal so it can be added as a constant function |
| 3989 // property. | 4062 // property. |
| 3990 if (top_scope_->DeclarationScope()->is_global_scope() && | 4063 if (top_scope_->DeclarationScope()->is_global_scope() && |
| 3991 value->AsFunctionLiteral() != NULL) { | 4064 value->AsFunctionLiteral() != NULL) { |
| 3992 has_function = true; | 4065 has_function = true; |
| 3993 value->AsFunctionLiteral()->set_pretenure(); | 4066 value->AsFunctionLiteral()->set_pretenure(); |
| 3994 } | 4067 } |
| 3995 | 4068 |
| 3996 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. | 4069 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. |
| 3997 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++; | 4070 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++; |
| 4071 // Validate the property |
| 4072 checker.CheckProperty(property, loc, CHECK_OK); |
| 3998 properties->Add(property, zone()); | 4073 properties->Add(property, zone()); |
| 3999 | 4074 |
| 4000 // TODO(1240767): Consider allowing trailing comma. | 4075 // TODO(1240767): Consider allowing trailing comma. |
| 4001 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); | 4076 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); |
| 4002 | 4077 |
| 4003 if (fni_ != NULL) { | 4078 if (fni_ != NULL) { |
| 4004 fni_->Infer(); | 4079 fni_->Infer(); |
| 4005 fni_->Leave(); | 4080 fni_->Leave(); |
| 4006 } | 4081 } |
| 4007 } | 4082 } |
| (...skipping 1871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5879 ASSERT(info()->isolate()->has_pending_exception()); | 5954 ASSERT(info()->isolate()->has_pending_exception()); |
| 5880 } else { | 5955 } else { |
| 5881 result = ParseProgram(); | 5956 result = ParseProgram(); |
| 5882 } | 5957 } |
| 5883 } | 5958 } |
| 5884 info()->SetFunction(result); | 5959 info()->SetFunction(result); |
| 5885 return (result != NULL); | 5960 return (result != NULL); |
| 5886 } | 5961 } |
| 5887 | 5962 |
| 5888 } } // namespace v8::internal | 5963 } } // namespace v8::internal |
| OLD | NEW |