OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 2994 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3005 Handle<Object> Parser::GetBoilerplateValue(Expression* expression) { | 3005 Handle<Object> Parser::GetBoilerplateValue(Expression* expression) { |
3006 if (expression->AsLiteral() != NULL) { | 3006 if (expression->AsLiteral() != NULL) { |
3007 return expression->AsLiteral()->handle(); | 3007 return expression->AsLiteral()->handle(); |
3008 } | 3008 } |
3009 if (CompileTimeValue::IsCompileTimeValue(expression)) { | 3009 if (CompileTimeValue::IsCompileTimeValue(expression)) { |
3010 return CompileTimeValue::GetValue(expression); | 3010 return CompileTimeValue::GetValue(expression); |
3011 } | 3011 } |
3012 return Factory::undefined_value(); | 3012 return Factory::undefined_value(); |
3013 } | 3013 } |
3014 | 3014 |
3015 // Defined in ast.cc | |
3016 bool IsEqualString(void* first, void* second); | |
Martin Maly
2011/01/21 00:41:06
These 2 are defined in ast.cc, ideally I'd want to
| |
3017 bool IsEqualSmi(void* first, void* second); | |
3018 | |
3019 | |
3020 // Validation per 11.1.5 Object Initialiser | |
3021 class ObjectLiteralPropertyChecker { | |
3022 public: | |
3023 ObjectLiteralPropertyChecker(Parser* parser, bool strict) : | |
3024 props(&IsEqualString), | |
3025 elems(&IsEqualSmi), | |
3026 parser_(parser), | |
3027 strict_(strict) { | |
3028 } | |
3029 | |
3030 void CheckProperty( | |
3031 ObjectLiteral::Property* property, | |
3032 Scanner::Location loc, | |
3033 bool* ok); | |
3034 | |
3035 private: | |
3036 enum PropertyKind { | |
3037 GetAccessor = 0x01, | |
Lasse Reichstein
2011/01/21 12:01:13
Add a "k" in front of constants, i.e., kGetAccesso
Martin Maly
2011/01/21 20:00:37
Done.
| |
3038 SetAccessor = 0x02, | |
3039 Accessor = GetAccessor | SetAccessor, | |
3040 Data = 0x04 | |
3041 }; | |
3042 | |
3043 HashMap props; | |
Lasse Reichstein
2011/01/21 12:01:13
Properties should be at the end of the class, afte
Martin Maly
2011/01/21 20:00:37
Done.
| |
3044 HashMap elems; | |
3045 Parser* parser_; | |
3046 bool strict_; | |
3047 | |
3048 static intptr_t GetPropertyKind(ObjectLiteral::Property* property) { | |
3049 switch (property->kind()) { | |
3050 default: | |
Lasse Reichstein
2011/01/21 12:01:13
Move the default to the end instead.
I just think
Martin Maly
2011/01/21 20:00:37
Done.
| |
3051 return Data; | |
3052 case ObjectLiteral::Property::GETTER: | |
3053 return GetAccessor; | |
3054 case ObjectLiteral::Property::SETTER: | |
3055 return SetAccessor; | |
3056 } | |
3057 } | |
3058 }; | |
3059 | |
3060 | |
3061 void ObjectLiteralPropertyChecker::CheckProperty( | |
Martin Maly
2011/01/21 00:41:06
Similar code exists in ast.cc and is executed when
| |
3062 ObjectLiteral::Property* property, | |
3063 Scanner::Location loc, | |
3064 bool* ok) { | |
3065 | |
3066 ASSERT(property != NULL); | |
3067 | |
3068 Literal *lit = property->key(); | |
3069 Handle<Object> handle = lit->handle(); | |
3070 | |
3071 uint32_t hash; | |
3072 HashMap* map; | |
3073 void* key; | |
3074 | |
3075 if (handle->IsSymbol()) { | |
3076 Handle<String> name(String::cast(*handle)); | |
3077 ASSERT(!name->AsArrayIndex(&hash)); | |
Lasse Reichstein
2011/01/21 12:01:13
I'm a little worried that we might have a symbol t
Martin Maly
2011/01/21 20:00:37
I am less concerned since the same checks are perf
Lasse Reichstein
2011/01/24 07:57:01
Damnit. I fixed one such place already, but it see
Martin Maly
2011/01/24 18:09:09
Great catch. I fixed both locations and added more
| |
3078 key = handle.location(); | |
3079 hash = name->Hash(); | |
3080 map = &props; | |
3081 } else if (handle->ToArrayIndex(&hash)) { | |
3082 key = handle.location(); | |
3083 map = &elems; | |
3084 } else { | |
3085 ASSERT(handle->IsNumber()); | |
3086 double num = handle->Number(); | |
3087 char arr[100]; | |
3088 Vector<char> buffer(arr, ARRAY_SIZE(arr)); | |
3089 const char* str = DoubleToCString(num, buffer); | |
3090 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str)); | |
3091 key = name.location(); | |
3092 hash = name->Hash(); | |
3093 map = &props; | |
3094 } | |
3095 | |
3096 // Lookup property previously defined, if any. | |
3097 HashMap::Entry* entry = map->Lookup(key, hash, true); | |
3098 intptr_t prev = reinterpret_cast<intptr_t> (entry->value); | |
3099 intptr_t curr = GetPropertyKind(property); | |
3100 | |
3101 // Duplicate data properties are illegal in strict mode. | |
3102 if (strict_ && (curr & prev & Data) != 0) { | |
3103 parser_->ReportMessageAt(loc, "strict_duplicate_property", | |
3104 Vector<const char*>::empty()); | |
3105 *ok = false; | |
3106 return; | |
3107 } | |
3108 // Data property conflicting with an accessor. | |
Martin Maly
2011/01/21 00:41:06
Most of these checks should execute even outside o
Lasse Reichstein
2011/01/21 12:01:13
We should be careful when adding restrictions to n
MarkM
2011/01/21 17:37:55
On WebKit nightly Version 5.0.1 (5533.17.8, r75891
Martin Maly
2011/01/21 20:00:37
Thank you, Mark, for doing the research. The shipp
| |
3109 if (((curr & Data) && (prev & Accessor)) || | |
3110 ((prev & Data) && (curr & Accessor))) { | |
3111 parser_->ReportMessageAt(loc, "accessor_data_property", | |
3112 Vector<const char*>::empty()); | |
3113 *ok = false; | |
3114 return; | |
3115 } | |
3116 // Two accessors of the same type conflicting | |
3117 if ((curr & prev & Accessor) != 0) { | |
3118 parser_->ReportMessageAt(loc, "accessor_get_set", | |
3119 Vector<const char*>::empty()); | |
3120 *ok = false; | |
3121 return; | |
3122 } | |
3123 | |
3124 // Update map | |
3125 entry->value = reinterpret_cast<void*> (prev | curr); | |
3126 *ok = true; | |
3127 } | |
3128 | |
3015 | 3129 |
3016 void Parser::BuildObjectLiteralConstantProperties( | 3130 void Parser::BuildObjectLiteralConstantProperties( |
3017 ZoneList<ObjectLiteral::Property*>* properties, | 3131 ZoneList<ObjectLiteral::Property*>* properties, |
3018 Handle<FixedArray> constant_properties, | 3132 Handle<FixedArray> constant_properties, |
3019 bool* is_simple, | 3133 bool* is_simple, |
3020 bool* fast_elements, | 3134 bool* fast_elements, |
3021 int* depth) { | 3135 int* depth) { |
3022 int position = 0; | 3136 int position = 0; |
3023 // Accumulate the value in local variables and store it at the end. | 3137 // Accumulate the value in local variables and store it at the end. |
3024 bool is_simple_acc = true; | 3138 bool is_simple_acc = true; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3110 // ObjectLiteral :: | 3224 // ObjectLiteral :: |
3111 // '{' ( | 3225 // '{' ( |
3112 // ((IdentifierName | String | Number) ':' AssignmentExpression) | 3226 // ((IdentifierName | String | Number) ':' AssignmentExpression) |
3113 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) | 3227 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) |
3114 // )*[','] '}' | 3228 // )*[','] '}' |
3115 | 3229 |
3116 ZoneList<ObjectLiteral::Property*>* properties = | 3230 ZoneList<ObjectLiteral::Property*>* properties = |
3117 new ZoneList<ObjectLiteral::Property*>(4); | 3231 new ZoneList<ObjectLiteral::Property*>(4); |
3118 int number_of_boilerplate_properties = 0; | 3232 int number_of_boilerplate_properties = 0; |
3119 | 3233 |
3234 ObjectLiteralPropertyChecker checker(this, temp_scope_->StrictMode()); | |
3235 | |
3120 Expect(Token::LBRACE, CHECK_OK); | 3236 Expect(Token::LBRACE, CHECK_OK); |
3237 Scanner::Location loc = scanner().location(); | |
3238 | |
3121 while (peek() != Token::RBRACE) { | 3239 while (peek() != Token::RBRACE) { |
3122 if (fni_ != NULL) fni_->Enter(); | 3240 if (fni_ != NULL) fni_->Enter(); |
3123 | 3241 |
3124 Literal* key = NULL; | 3242 Literal* key = NULL; |
3125 Token::Value next = peek(); | 3243 Token::Value next = peek(); |
3244 | |
3245 // Location of the property name token | |
3246 Scanner::Location loc = scanner().peek_location(); | |
3247 | |
3126 switch (next) { | 3248 switch (next) { |
3127 case Token::IDENTIFIER: { | 3249 case Token::IDENTIFIER: { |
3128 bool is_getter = false; | 3250 bool is_getter = false; |
3129 bool is_setter = false; | 3251 bool is_setter = false; |
3130 Handle<String> id = | 3252 Handle<String> id = |
3131 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); | 3253 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); |
3132 if (fni_ != NULL) fni_->PushLiteralName(id); | 3254 if (fni_ != NULL) fni_->PushLiteralName(id); |
3133 | 3255 |
3134 if ((is_getter || is_setter) && peek() != Token::COLON) { | 3256 if ((is_getter || is_setter) && peek() != Token::COLON) { |
3257 // Update loc to point to the identifier | |
3258 loc = scanner().peek_location(); | |
3135 ObjectLiteral::Property* property = | 3259 ObjectLiteral::Property* property = |
3136 ParseObjectLiteralGetSet(is_getter, CHECK_OK); | 3260 ParseObjectLiteralGetSet(is_getter, CHECK_OK); |
3137 if (IsBoilerplateProperty(property)) { | 3261 if (IsBoilerplateProperty(property)) { |
3138 number_of_boilerplate_properties++; | 3262 number_of_boilerplate_properties++; |
3139 } | 3263 } |
3264 // Validate the property. | |
3265 checker.CheckProperty(property, loc, CHECK_OK); | |
3140 properties->Add(property); | 3266 properties->Add(property); |
3141 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); | 3267 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); |
3142 | 3268 |
3143 if (fni_ != NULL) { | 3269 if (fni_ != NULL) { |
3144 fni_->Infer(); | 3270 fni_->Infer(); |
3145 fni_->Leave(); | 3271 fni_->Leave(); |
3146 } | 3272 } |
3147 continue; // restart the while | 3273 continue; // restart the while |
3148 } | 3274 } |
3149 // Failed to parse as get/set property, so it's just a property | 3275 // Failed to parse as get/set property, so it's just a property |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3186 } | 3312 } |
3187 | 3313 |
3188 Expect(Token::COLON, CHECK_OK); | 3314 Expect(Token::COLON, CHECK_OK); |
3189 Expression* value = ParseAssignmentExpression(true, CHECK_OK); | 3315 Expression* value = ParseAssignmentExpression(true, CHECK_OK); |
3190 | 3316 |
3191 ObjectLiteral::Property* property = | 3317 ObjectLiteral::Property* property = |
3192 new ObjectLiteral::Property(key, value); | 3318 new ObjectLiteral::Property(key, value); |
3193 | 3319 |
3194 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. | 3320 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. |
3195 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++; | 3321 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++; |
3322 // Validate the property | |
3323 checker.CheckProperty(property, loc, CHECK_OK); | |
3196 properties->Add(property); | 3324 properties->Add(property); |
3197 | 3325 |
3198 // TODO(1240767): Consider allowing trailing comma. | 3326 // TODO(1240767): Consider allowing trailing comma. |
3199 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); | 3327 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); |
3200 | 3328 |
3201 if (fni_ != NULL) { | 3329 if (fni_ != NULL) { |
3202 fni_->Infer(); | 3330 fni_->Infer(); |
3203 fni_->Leave(); | 3331 fni_->Leave(); |
3204 } | 3332 } |
3205 } | 3333 } |
3206 Expect(Token::RBRACE, CHECK_OK); | 3334 Expect(Token::RBRACE, CHECK_OK); |
3335 | |
3207 // Computation of literal_index must happen before pre parse bailout. | 3336 // Computation of literal_index must happen before pre parse bailout. |
3208 int literal_index = temp_scope_->NextMaterializedLiteralIndex(); | 3337 int literal_index = temp_scope_->NextMaterializedLiteralIndex(); |
3209 | 3338 |
3210 Handle<FixedArray> constant_properties = | 3339 Handle<FixedArray> constant_properties = |
3211 Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED); | 3340 Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED); |
3212 | 3341 |
3213 bool is_simple = true; | 3342 bool is_simple = true; |
3214 bool fast_elements = true; | 3343 bool fast_elements = true; |
3215 int depth = 1; | 3344 int depth = 1; |
3216 BuildObjectLiteralConstantProperties(properties, | 3345 BuildObjectLiteralConstantProperties(properties, |
(...skipping 1601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4818 Handle<String> source = Handle<String>(String::cast(script->source())); | 4947 Handle<String> source = Handle<String>(String::cast(script->source())); |
4819 result = parser.ParseProgram(source, info->is_global()); | 4948 result = parser.ParseProgram(source, info->is_global()); |
4820 } | 4949 } |
4821 } | 4950 } |
4822 | 4951 |
4823 info->SetFunction(result); | 4952 info->SetFunction(result); |
4824 return (result != NULL); | 4953 return (result != NULL); |
4825 } | 4954 } |
4826 | 4955 |
4827 } } // namespace v8::internal | 4956 } } // namespace v8::internal |
OLD | NEW |