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); | |
| 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 kGetAccessor = 0x01, | |
| 3038 kSetAccessor = 0x02, | |
| 3039 kAccessor = kGetAccessor | kSetAccessor, | |
| 3040 kData = 0x04 | |
| 3041 }; | |
| 3042 | |
| 3043 static intptr_t GetPropertyKind(ObjectLiteral::Property* property) { | |
| 3044 switch (property->kind()) { | |
| 3045 case ObjectLiteral::Property::GETTER: | |
| 3046 return kGetAccessor; | |
| 3047 case ObjectLiteral::Property::SETTER: | |
| 3048 return kSetAccessor; | |
| 3049 default: | |
| 3050 return kData; | |
| 3051 } | |
| 3052 } | |
| 3053 | |
| 3054 HashMap props; | |
| 3055 HashMap elems; | |
| 3056 Parser* parser_; | |
| 3057 bool strict_; | |
| 3058 }; | |
| 3059 | |
| 3060 | |
| 3061 void ObjectLiteralPropertyChecker::CheckProperty( | |
| 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 // Check for array index first because symbol may still be an array index: | |
| 3076 // var y = {get "1234"() {return 42; }}; | |
| 3077 if (handle->ToArrayIndex(&hash)) { | |
|
Lasse Reichstein
2011/01/25 11:19:03
This still needs to handle array-index symbols.
Yo
Martin Maly
2011/01/25 18:29:23
Done.
| |
| 3078 key = handle.location(); | |
| 3079 map = &elems; | |
| 3080 } else if (handle->IsSymbol()) { | |
| 3081 Handle<String> name(String::cast(*handle)); | |
| 3082 key = handle.location(); | |
| 3083 hash = name->Hash(); | |
| 3084 map = &props; | |
| 3085 } else { | |
| 3086 ASSERT(handle->IsNumber()); | |
| 3087 double num = handle->Number(); | |
| 3088 char arr[100]; | |
| 3089 Vector<char> buffer(arr, ARRAY_SIZE(arr)); | |
| 3090 const char* str = DoubleToCString(num, buffer); | |
| 3091 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str)); | |
| 3092 key = name.location(); | |
| 3093 hash = name->Hash(); | |
| 3094 map = &props; | |
| 3095 } | |
| 3096 | |
| 3097 // Lookup property previously defined, if any. | |
| 3098 HashMap::Entry* entry = map->Lookup(key, hash, true); | |
| 3099 intptr_t prev = reinterpret_cast<intptr_t> (entry->value); | |
| 3100 intptr_t curr = GetPropertyKind(property); | |
| 3101 | |
| 3102 // Duplicate data properties are illegal in strict mode. | |
| 3103 if (strict_ && (curr & prev & kData) != 0) { | |
| 3104 parser_->ReportMessageAt(loc, "strict_duplicate_property", | |
| 3105 Vector<const char*>::empty()); | |
| 3106 *ok = false; | |
| 3107 return; | |
| 3108 } | |
| 3109 // Data property conflicting with an accessor. | |
| 3110 if (((curr & kData) && (prev & kAccessor)) || | |
| 3111 ((prev & kData) && (curr & kAccessor))) { | |
| 3112 parser_->ReportMessageAt(loc, "accessor_data_property", | |
| 3113 Vector<const char*>::empty()); | |
| 3114 *ok = false; | |
| 3115 return; | |
| 3116 } | |
| 3117 // Two accessors of the same type conflicting | |
| 3118 if ((curr & prev & kAccessor) != 0) { | |
| 3119 parser_->ReportMessageAt(loc, "accessor_get_set", | |
| 3120 Vector<const char*>::empty()); | |
| 3121 *ok = false; | |
| 3122 return; | |
| 3123 } | |
| 3124 | |
| 3125 // Update map | |
| 3126 entry->value = reinterpret_cast<void*> (prev | curr); | |
| 3127 *ok = true; | |
| 3128 } | |
| 3129 | |
| 3015 | 3130 |
| 3016 void Parser::BuildObjectLiteralConstantProperties( | 3131 void Parser::BuildObjectLiteralConstantProperties( |
| 3017 ZoneList<ObjectLiteral::Property*>* properties, | 3132 ZoneList<ObjectLiteral::Property*>* properties, |
| 3018 Handle<FixedArray> constant_properties, | 3133 Handle<FixedArray> constant_properties, |
| 3019 bool* is_simple, | 3134 bool* is_simple, |
| 3020 bool* fast_elements, | 3135 bool* fast_elements, |
| 3021 int* depth) { | 3136 int* depth) { |
| 3022 int position = 0; | 3137 int position = 0; |
| 3023 // Accumulate the value in local variables and store it at the end. | 3138 // Accumulate the value in local variables and store it at the end. |
| 3024 bool is_simple_acc = true; | 3139 bool is_simple_acc = true; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3110 // ObjectLiteral :: | 3225 // ObjectLiteral :: |
| 3111 // '{' ( | 3226 // '{' ( |
| 3112 // ((IdentifierName | String | Number) ':' AssignmentExpression) | 3227 // ((IdentifierName | String | Number) ':' AssignmentExpression) |
| 3113 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) | 3228 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) |
| 3114 // )*[','] '}' | 3229 // )*[','] '}' |
| 3115 | 3230 |
| 3116 ZoneList<ObjectLiteral::Property*>* properties = | 3231 ZoneList<ObjectLiteral::Property*>* properties = |
| 3117 new ZoneList<ObjectLiteral::Property*>(4); | 3232 new ZoneList<ObjectLiteral::Property*>(4); |
| 3118 int number_of_boilerplate_properties = 0; | 3233 int number_of_boilerplate_properties = 0; |
| 3119 | 3234 |
| 3235 ObjectLiteralPropertyChecker checker(this, temp_scope_->StrictMode()); | |
| 3236 | |
| 3120 Expect(Token::LBRACE, CHECK_OK); | 3237 Expect(Token::LBRACE, CHECK_OK); |
| 3238 Scanner::Location loc = scanner().location(); | |
| 3239 | |
| 3121 while (peek() != Token::RBRACE) { | 3240 while (peek() != Token::RBRACE) { |
| 3122 if (fni_ != NULL) fni_->Enter(); | 3241 if (fni_ != NULL) fni_->Enter(); |
| 3123 | 3242 |
| 3124 Literal* key = NULL; | 3243 Literal* key = NULL; |
| 3125 Token::Value next = peek(); | 3244 Token::Value next = peek(); |
| 3245 | |
| 3246 // Location of the property name token | |
| 3247 Scanner::Location loc = scanner().peek_location(); | |
| 3248 | |
| 3126 switch (next) { | 3249 switch (next) { |
| 3127 case Token::IDENTIFIER: { | 3250 case Token::IDENTIFIER: { |
| 3128 bool is_getter = false; | 3251 bool is_getter = false; |
| 3129 bool is_setter = false; | 3252 bool is_setter = false; |
| 3130 Handle<String> id = | 3253 Handle<String> id = |
| 3131 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); | 3254 ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); |
| 3132 if (fni_ != NULL) fni_->PushLiteralName(id); | 3255 if (fni_ != NULL) fni_->PushLiteralName(id); |
| 3133 | 3256 |
| 3134 if ((is_getter || is_setter) && peek() != Token::COLON) { | 3257 if ((is_getter || is_setter) && peek() != Token::COLON) { |
| 3258 // Update loc to point to the identifier | |
| 3259 loc = scanner().peek_location(); | |
| 3135 ObjectLiteral::Property* property = | 3260 ObjectLiteral::Property* property = |
| 3136 ParseObjectLiteralGetSet(is_getter, CHECK_OK); | 3261 ParseObjectLiteralGetSet(is_getter, CHECK_OK); |
| 3137 if (IsBoilerplateProperty(property)) { | 3262 if (IsBoilerplateProperty(property)) { |
| 3138 number_of_boilerplate_properties++; | 3263 number_of_boilerplate_properties++; |
| 3139 } | 3264 } |
| 3265 // Validate the property. | |
| 3266 checker.CheckProperty(property, loc, CHECK_OK); | |
| 3140 properties->Add(property); | 3267 properties->Add(property); |
| 3141 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); | 3268 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); |
| 3142 | 3269 |
| 3143 if (fni_ != NULL) { | 3270 if (fni_ != NULL) { |
| 3144 fni_->Infer(); | 3271 fni_->Infer(); |
| 3145 fni_->Leave(); | 3272 fni_->Leave(); |
| 3146 } | 3273 } |
| 3147 continue; // restart the while | 3274 continue; // restart the while |
| 3148 } | 3275 } |
| 3149 // Failed to parse as get/set property, so it's just a property | 3276 // 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 } | 3313 } |
| 3187 | 3314 |
| 3188 Expect(Token::COLON, CHECK_OK); | 3315 Expect(Token::COLON, CHECK_OK); |
| 3189 Expression* value = ParseAssignmentExpression(true, CHECK_OK); | 3316 Expression* value = ParseAssignmentExpression(true, CHECK_OK); |
| 3190 | 3317 |
| 3191 ObjectLiteral::Property* property = | 3318 ObjectLiteral::Property* property = |
| 3192 new ObjectLiteral::Property(key, value); | 3319 new ObjectLiteral::Property(key, value); |
| 3193 | 3320 |
| 3194 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. | 3321 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. |
| 3195 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++; | 3322 if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++; |
| 3323 // Validate the property | |
| 3324 checker.CheckProperty(property, loc, CHECK_OK); | |
| 3196 properties->Add(property); | 3325 properties->Add(property); |
| 3197 | 3326 |
| 3198 // TODO(1240767): Consider allowing trailing comma. | 3327 // TODO(1240767): Consider allowing trailing comma. |
| 3199 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); | 3328 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); |
| 3200 | 3329 |
| 3201 if (fni_ != NULL) { | 3330 if (fni_ != NULL) { |
| 3202 fni_->Infer(); | 3331 fni_->Infer(); |
| 3203 fni_->Leave(); | 3332 fni_->Leave(); |
| 3204 } | 3333 } |
| 3205 } | 3334 } |
| 3206 Expect(Token::RBRACE, CHECK_OK); | 3335 Expect(Token::RBRACE, CHECK_OK); |
| 3336 | |
| 3207 // Computation of literal_index must happen before pre parse bailout. | 3337 // Computation of literal_index must happen before pre parse bailout. |
| 3208 int literal_index = temp_scope_->NextMaterializedLiteralIndex(); | 3338 int literal_index = temp_scope_->NextMaterializedLiteralIndex(); |
| 3209 | 3339 |
| 3210 Handle<FixedArray> constant_properties = | 3340 Handle<FixedArray> constant_properties = |
| 3211 Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED); | 3341 Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED); |
| 3212 | 3342 |
| 3213 bool is_simple = true; | 3343 bool is_simple = true; |
| 3214 bool fast_elements = true; | 3344 bool fast_elements = true; |
| 3215 int depth = 1; | 3345 int depth = 1; |
| 3216 BuildObjectLiteralConstantProperties(properties, | 3346 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())); | 4948 Handle<String> source = Handle<String>(String::cast(script->source())); |
| 4819 result = parser.ParseProgram(source, info->is_global()); | 4949 result = parser.ParseProgram(source, info->is_global()); |
| 4820 } | 4950 } |
| 4821 } | 4951 } |
| 4822 | 4952 |
| 4823 info->SetFunction(result); | 4953 info->SetFunction(result); |
| 4824 return (result != NULL); | 4954 return (result != NULL); |
| 4825 } | 4955 } |
| 4826 | 4956 |
| 4827 } } // namespace v8::internal | 4957 } } // namespace v8::internal |
| OLD | NEW |