Chromium Code Reviews| 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 |