OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 5953 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5964 } | 5964 } |
5965 break; | 5965 break; |
5966 } | 5966 } |
5967 } | 5967 } |
5968 | 5968 |
5969 Isolate* isolate = object->GetIsolate(); | 5969 Isolate* isolate = object->GetIsolate(); |
5970 Handle<AccessorPair> accessors = isolate->factory()->NewAccessorPair(); | 5970 Handle<AccessorPair> accessors = isolate->factory()->NewAccessorPair(); |
5971 accessors->SetComponents(*getter, *setter); | 5971 accessors->SetComponents(*getter, *setter); |
5972 accessors->set_access_flags(access_control); | 5972 accessors->set_access_flags(access_control); |
5973 | 5973 |
5974 CALL_HEAP_FUNCTION_VOID( | 5974 SetElementCallback(object, index, accessors, attributes); |
5975 isolate, object->SetElementCallback(index, *accessors, attributes)); | |
5976 } | 5975 } |
5977 | 5976 |
5978 | 5977 |
5979 Handle<AccessorPair> JSObject::CreateAccessorPairFor(Handle<JSObject> object, | 5978 Handle<AccessorPair> JSObject::CreateAccessorPairFor(Handle<JSObject> object, |
5980 Handle<Name> name) { | 5979 Handle<Name> name) { |
5981 Isolate* isolate = object->GetIsolate(); | 5980 Isolate* isolate = object->GetIsolate(); |
5982 LookupResult result(isolate); | 5981 LookupResult result(isolate); |
5983 object->LocalLookupRealNamedProperty(*name, &result); | 5982 object->LocalLookupRealNamedProperty(*name, &result); |
5984 if (result.IsPropertyCallbacks()) { | 5983 if (result.IsPropertyCallbacks()) { |
5985 // Note that the result can actually have IsDontDelete() == true when we | 5984 // Note that the result can actually have IsDontDelete() == true when we |
(...skipping 28 matching lines...) Expand all Loading... |
6014 DefineFastAccessor(object, name, ACCESSOR_GETTER, getter, attributes); | 6013 DefineFastAccessor(object, name, ACCESSOR_GETTER, getter, attributes); |
6015 bool setterOk = !getterOk || setter->IsNull() || | 6014 bool setterOk = !getterOk || setter->IsNull() || |
6016 DefineFastAccessor(object, name, ACCESSOR_SETTER, setter, attributes); | 6015 DefineFastAccessor(object, name, ACCESSOR_SETTER, setter, attributes); |
6017 if (getterOk && setterOk) return; | 6016 if (getterOk && setterOk) return; |
6018 } | 6017 } |
6019 | 6018 |
6020 Handle<AccessorPair> accessors = CreateAccessorPairFor(object, name); | 6019 Handle<AccessorPair> accessors = CreateAccessorPairFor(object, name); |
6021 accessors->SetComponents(*getter, *setter); | 6020 accessors->SetComponents(*getter, *setter); |
6022 accessors->set_access_flags(access_control); | 6021 accessors->set_access_flags(access_control); |
6023 | 6022 |
6024 CALL_HEAP_FUNCTION_VOID( | 6023 SetPropertyCallback(object, name, accessors, attributes); |
6025 object->GetIsolate(), | |
6026 object->SetPropertyCallback(*name, *accessors, attributes)); | |
6027 } | 6024 } |
6028 | 6025 |
6029 | 6026 |
6030 bool JSObject::CanSetCallback(Name* name) { | 6027 bool JSObject::CanSetCallback(Name* name) { |
6031 ASSERT(!IsAccessCheckNeeded() || | 6028 ASSERT(!IsAccessCheckNeeded() || |
6032 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); | 6029 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); |
6033 | 6030 |
6034 // Check if there is an API defined callback object which prohibits | 6031 // Check if there is an API defined callback object which prohibits |
6035 // callback overwriting in this object or its prototype chain. | 6032 // callback overwriting in this object or its prototype chain. |
6036 // This mechanism is needed for instance in a browser setting, where | 6033 // This mechanism is needed for instance in a browser setting, where |
6037 // certain accessors such as window.location should not be allowed | 6034 // certain accessors such as window.location should not be allowed |
6038 // to be overwritten because allowing overwriting could potentially | 6035 // to be overwritten because allowing overwriting could potentially |
6039 // cause security problems. | 6036 // cause security problems. |
6040 LookupResult callback_result(GetIsolate()); | 6037 LookupResult callback_result(GetIsolate()); |
6041 LookupCallbackProperty(name, &callback_result); | 6038 LookupCallbackProperty(name, &callback_result); |
6042 if (callback_result.IsFound()) { | 6039 if (callback_result.IsFound()) { |
6043 Object* obj = callback_result.GetCallbackObject(); | 6040 Object* obj = callback_result.GetCallbackObject(); |
6044 if (obj->IsAccessorInfo()) { | 6041 if (obj->IsAccessorInfo()) { |
6045 return !AccessorInfo::cast(obj)->prohibits_overwriting(); | 6042 return !AccessorInfo::cast(obj)->prohibits_overwriting(); |
6046 } | 6043 } |
6047 if (obj->IsAccessorPair()) { | 6044 if (obj->IsAccessorPair()) { |
6048 return !AccessorPair::cast(obj)->prohibits_overwriting(); | 6045 return !AccessorPair::cast(obj)->prohibits_overwriting(); |
6049 } | 6046 } |
6050 } | 6047 } |
6051 return true; | 6048 return true; |
6052 } | 6049 } |
6053 | 6050 |
6054 | 6051 |
6055 MaybeObject* JSObject::SetElementCallback(uint32_t index, | 6052 void JSObject::SetElementCallback(Handle<JSObject> object, |
6056 Object* structure, | 6053 uint32_t index, |
6057 PropertyAttributes attributes) { | 6054 Handle<Object> structure, |
| 6055 PropertyAttributes attributes) { |
| 6056 Heap* heap = object->GetHeap(); |
6058 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); | 6057 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); |
6059 | 6058 |
6060 // Normalize elements to make this operation simple. | 6059 // Normalize elements to make this operation simple. |
6061 SeededNumberDictionary* dictionary; | 6060 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
6062 { MaybeObject* maybe_dictionary = NormalizeElements(); | 6061 ASSERT(object->HasDictionaryElements() || |
6063 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; | 6062 object->HasDictionaryArgumentsElements()); |
6064 } | |
6065 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); | |
6066 | 6063 |
6067 // Update the dictionary with the new CALLBACKS property. | 6064 // Update the dictionary with the new CALLBACKS property. |
6068 { MaybeObject* maybe_dictionary = dictionary->Set(index, structure, details); | 6065 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, |
6069 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; | 6066 details); |
6070 } | 6067 dictionary->set_requires_slow_elements(); |
6071 | 6068 |
6072 dictionary->set_requires_slow_elements(); | |
6073 // Update the dictionary backing store on the object. | 6069 // Update the dictionary backing store on the object. |
6074 if (elements()->map() == GetHeap()->non_strict_arguments_elements_map()) { | 6070 if (object->elements()->map() == heap->non_strict_arguments_elements_map()) { |
6075 // Also delete any parameter alias. | 6071 // Also delete any parameter alias. |
6076 // | 6072 // |
6077 // TODO(kmillikin): when deleting the last parameter alias we could | 6073 // TODO(kmillikin): when deleting the last parameter alias we could |
6078 // switch to a direct backing store without the parameter map. This | 6074 // switch to a direct backing store without the parameter map. This |
6079 // would allow GC of the context. | 6075 // would allow GC of the context. |
6080 FixedArray* parameter_map = FixedArray::cast(elements()); | 6076 FixedArray* parameter_map = FixedArray::cast(object->elements()); |
6081 if (index < static_cast<uint32_t>(parameter_map->length()) - 2) { | 6077 if (index < static_cast<uint32_t>(parameter_map->length()) - 2) { |
6082 parameter_map->set(index + 2, GetHeap()->the_hole_value()); | 6078 parameter_map->set(index + 2, heap->the_hole_value()); |
6083 } | 6079 } |
6084 parameter_map->set(1, dictionary); | 6080 parameter_map->set(1, *dictionary); |
6085 } else { | 6081 } else { |
6086 set_elements(dictionary); | 6082 object->set_elements(*dictionary); |
6087 } | 6083 } |
6088 | |
6089 return GetHeap()->undefined_value(); | |
6090 } | 6084 } |
6091 | 6085 |
6092 | 6086 |
6093 MaybeObject* JSObject::SetPropertyCallback(Name* name, | 6087 void JSObject::SetPropertyCallback(Handle<JSObject> object, |
6094 Object* structure, | 6088 Handle<Name> name, |
6095 PropertyAttributes attributes) { | 6089 Handle<Object> structure, |
| 6090 PropertyAttributes attributes) { |
6096 // Normalize object to make this operation simple. | 6091 // Normalize object to make this operation simple. |
6097 MaybeObject* maybe_ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 6092 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
6098 if (maybe_ok->IsFailure()) return maybe_ok; | |
6099 | 6093 |
6100 // For the global object allocate a new map to invalidate the global inline | 6094 // For the global object allocate a new map to invalidate the global inline |
6101 // caches which have a global property cell reference directly in the code. | 6095 // caches which have a global property cell reference directly in the code. |
6102 if (IsGlobalObject()) { | 6096 if (object->IsGlobalObject()) { |
6103 Map* new_map; | 6097 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); |
6104 MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); | |
6105 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
6106 ASSERT(new_map->is_dictionary_map()); | 6098 ASSERT(new_map->is_dictionary_map()); |
| 6099 object->set_map(*new_map); |
6107 | 6100 |
6108 set_map(new_map); | |
6109 // When running crankshaft, changing the map is not enough. We | 6101 // When running crankshaft, changing the map is not enough. We |
6110 // need to deoptimize all functions that rely on this global | 6102 // need to deoptimize all functions that rely on this global |
6111 // object. | 6103 // object. |
6112 Deoptimizer::DeoptimizeGlobalObject(this); | 6104 Deoptimizer::DeoptimizeGlobalObject(*object); |
6113 } | 6105 } |
6114 | 6106 |
6115 // Update the dictionary with the new CALLBACKS property. | 6107 // Update the dictionary with the new CALLBACKS property. |
6116 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); | 6108 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); |
6117 maybe_ok = SetNormalizedProperty(name, structure, details); | 6109 SetNormalizedProperty(object, name, structure, details); |
6118 if (maybe_ok->IsFailure()) return maybe_ok; | |
6119 | |
6120 return GetHeap()->undefined_value(); | |
6121 } | 6110 } |
6122 | 6111 |
6123 | 6112 |
6124 void JSObject::DefineAccessor(Handle<JSObject> object, | 6113 void JSObject::DefineAccessor(Handle<JSObject> object, |
6125 Handle<Name> name, | 6114 Handle<Name> name, |
6126 Handle<Object> getter, | 6115 Handle<Object> getter, |
6127 Handle<Object> setter, | 6116 Handle<Object> setter, |
6128 PropertyAttributes attributes, | 6117 PropertyAttributes attributes, |
6129 v8::AccessControl access_control) { | 6118 v8::AccessControl access_control) { |
6130 Isolate* isolate = object->GetIsolate(); | 6119 Isolate* isolate = object->GetIsolate(); |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6306 ? AccessorPair::Copy(Handle<AccessorPair>(source_accessors)) | 6295 ? AccessorPair::Copy(Handle<AccessorPair>(source_accessors)) |
6307 : isolate->factory()->NewAccessorPair(); | 6296 : isolate->factory()->NewAccessorPair(); |
6308 accessors->set(component, *accessor); | 6297 accessors->set(component, *accessor); |
6309 Handle<Map> new_map = CopyInsertDescriptor(Handle<Map>(object->map()), | 6298 Handle<Map> new_map = CopyInsertDescriptor(Handle<Map>(object->map()), |
6310 name, accessors, attributes); | 6299 name, accessors, attributes); |
6311 object->set_map(*new_map); | 6300 object->set_map(*new_map); |
6312 return true; | 6301 return true; |
6313 } | 6302 } |
6314 | 6303 |
6315 | 6304 |
6316 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { | 6305 Handle<Object> JSObject::SetAccessor(Handle<JSObject> object, |
6317 Isolate* isolate = GetIsolate(); | 6306 Handle<AccessorInfo> info) { |
6318 Name* name = Name::cast(info->name()); | 6307 Isolate* isolate = object->GetIsolate(); |
| 6308 Factory* factory = isolate->factory(); |
| 6309 Handle<Name> name(Name::cast(info->name())); |
| 6310 |
6319 // Check access rights if needed. | 6311 // Check access rights if needed. |
6320 if (IsAccessCheckNeeded() && | 6312 if (object->IsAccessCheckNeeded() && |
6321 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { | 6313 !isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { |
6322 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); | 6314 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_SET); |
6323 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 6315 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
6324 return isolate->heap()->undefined_value(); | 6316 return factory->undefined_value(); |
6325 } | 6317 } |
6326 | 6318 |
6327 if (IsJSGlobalProxy()) { | 6319 if (object->IsJSGlobalProxy()) { |
6328 Object* proto = GetPrototype(); | 6320 Handle<Object> proto(object->GetPrototype(), isolate); |
6329 if (proto->IsNull()) return this; | 6321 if (proto->IsNull()) return object; |
6330 ASSERT(proto->IsJSGlobalObject()); | 6322 ASSERT(proto->IsJSGlobalObject()); |
6331 return JSObject::cast(proto)->DefineAccessor(info); | 6323 return SetAccessor(Handle<JSObject>::cast(proto), info); |
6332 } | 6324 } |
6333 | 6325 |
6334 // Make sure that the top context does not change when doing callbacks or | 6326 // Make sure that the top context does not change when doing callbacks or |
6335 // interceptor calls. | 6327 // interceptor calls. |
6336 AssertNoContextChangeWithHandleScope ncc; | 6328 AssertNoContextChange ncc; |
6337 | 6329 |
6338 // Try to flatten before operating on the string. | 6330 // Try to flatten before operating on the string. |
6339 if (name->IsString()) String::cast(name)->TryFlatten(); | 6331 if (name->IsString()) FlattenString(Handle<String>::cast(name)); |
6340 | 6332 |
6341 if (!CanSetCallback(name)) return isolate->heap()->undefined_value(); | 6333 if (!object->CanSetCallback(*name)) return factory->undefined_value(); |
6342 | 6334 |
6343 uint32_t index = 0; | 6335 uint32_t index = 0; |
6344 bool is_element = name->AsArrayIndex(&index); | 6336 bool is_element = name->AsArrayIndex(&index); |
6345 | 6337 |
6346 if (is_element) { | 6338 if (is_element) { |
6347 if (IsJSArray()) return isolate->heap()->undefined_value(); | 6339 if (object->IsJSArray()) return factory->undefined_value(); |
6348 | 6340 |
6349 // Accessors overwrite previous callbacks (cf. with getters/setters). | 6341 // Accessors overwrite previous callbacks (cf. with getters/setters). |
6350 switch (GetElementsKind()) { | 6342 switch (object->GetElementsKind()) { |
6351 case FAST_SMI_ELEMENTS: | 6343 case FAST_SMI_ELEMENTS: |
6352 case FAST_ELEMENTS: | 6344 case FAST_ELEMENTS: |
6353 case FAST_DOUBLE_ELEMENTS: | 6345 case FAST_DOUBLE_ELEMENTS: |
6354 case FAST_HOLEY_SMI_ELEMENTS: | 6346 case FAST_HOLEY_SMI_ELEMENTS: |
6355 case FAST_HOLEY_ELEMENTS: | 6347 case FAST_HOLEY_ELEMENTS: |
6356 case FAST_HOLEY_DOUBLE_ELEMENTS: | 6348 case FAST_HOLEY_DOUBLE_ELEMENTS: |
6357 break; | 6349 break; |
6358 case EXTERNAL_PIXEL_ELEMENTS: | 6350 case EXTERNAL_PIXEL_ELEMENTS: |
6359 case EXTERNAL_BYTE_ELEMENTS: | 6351 case EXTERNAL_BYTE_ELEMENTS: |
6360 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 6352 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
6361 case EXTERNAL_SHORT_ELEMENTS: | 6353 case EXTERNAL_SHORT_ELEMENTS: |
6362 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 6354 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
6363 case EXTERNAL_INT_ELEMENTS: | 6355 case EXTERNAL_INT_ELEMENTS: |
6364 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 6356 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
6365 case EXTERNAL_FLOAT_ELEMENTS: | 6357 case EXTERNAL_FLOAT_ELEMENTS: |
6366 case EXTERNAL_DOUBLE_ELEMENTS: | 6358 case EXTERNAL_DOUBLE_ELEMENTS: |
6367 // Ignore getters and setters on pixel and external array | 6359 // Ignore getters and setters on pixel and external array |
6368 // elements. | 6360 // elements. |
6369 return isolate->heap()->undefined_value(); | 6361 return factory->undefined_value(); |
6370 case DICTIONARY_ELEMENTS: | 6362 case DICTIONARY_ELEMENTS: |
6371 break; | 6363 break; |
6372 case NON_STRICT_ARGUMENTS_ELEMENTS: | 6364 case NON_STRICT_ARGUMENTS_ELEMENTS: |
6373 UNIMPLEMENTED(); | 6365 UNIMPLEMENTED(); |
6374 break; | 6366 break; |
6375 } | 6367 } |
6376 | 6368 |
6377 MaybeObject* maybe_ok = | 6369 SetElementCallback(object, index, info, info->property_attributes()); |
6378 SetElementCallback(index, info, info->property_attributes()); | |
6379 if (maybe_ok->IsFailure()) return maybe_ok; | |
6380 } else { | 6370 } else { |
6381 // Lookup the name. | 6371 // Lookup the name. |
6382 LookupResult result(isolate); | 6372 LookupResult result(isolate); |
6383 LocalLookup(name, &result, true); | 6373 object->LocalLookup(*name, &result, true); |
6384 // ES5 forbids turning a property into an accessor if it's not | 6374 // ES5 forbids turning a property into an accessor if it's not |
6385 // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5). | 6375 // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5). |
6386 if (result.IsFound() && (result.IsReadOnly() || result.IsDontDelete())) { | 6376 if (result.IsFound() && (result.IsReadOnly() || result.IsDontDelete())) { |
6387 return isolate->heap()->undefined_value(); | 6377 return factory->undefined_value(); |
6388 } | 6378 } |
6389 | 6379 |
6390 MaybeObject* maybe_ok = | 6380 SetPropertyCallback(object, name, info, info->property_attributes()); |
6391 SetPropertyCallback(name, info, info->property_attributes()); | |
6392 if (maybe_ok->IsFailure()) return maybe_ok; | |
6393 } | 6381 } |
6394 | 6382 |
6395 return this; | 6383 return object; |
6396 } | 6384 } |
6397 | 6385 |
6398 | 6386 |
6399 MaybeObject* JSObject::LookupAccessor(Name* name, AccessorComponent component) { | 6387 MaybeObject* JSObject::LookupAccessor(Name* name, AccessorComponent component) { |
6400 Heap* heap = GetHeap(); | 6388 Heap* heap = GetHeap(); |
6401 | 6389 |
6402 // Make sure that the top context does not change when doing callbacks or | 6390 // Make sure that the top context does not change when doing callbacks or |
6403 // interceptor calls. | 6391 // interceptor calls. |
6404 AssertNoContextChangeWithHandleScope ncc; | 6392 AssertNoContextChangeWithHandleScope ncc; |
6405 | 6393 |
(...skipping 9588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15994 #define ERROR_MESSAGES_TEXTS(C, T) T, | 15982 #define ERROR_MESSAGES_TEXTS(C, T) T, |
15995 static const char* error_messages_[] = { | 15983 static const char* error_messages_[] = { |
15996 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 15984 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
15997 }; | 15985 }; |
15998 #undef ERROR_MESSAGES_TEXTS | 15986 #undef ERROR_MESSAGES_TEXTS |
15999 return error_messages_[reason]; | 15987 return error_messages_[reason]; |
16000 } | 15988 } |
16001 | 15989 |
16002 | 15990 |
16003 } } // namespace v8::internal | 15991 } } // namespace v8::internal |
OLD | NEW |