📄 objects.cc.svn-base
字号:
Map::cast(new_map)-> set_instance_descriptors(DescriptorArray::cast(new_descriptors)); Map::cast(new_map)-> set_unused_property_fields(map()->unused_property_fields()-1); set_map(Map::cast(new_map)); properties()->set(index, value); } else { ASSERT(map()->unused_property_fields() == 0); static const int kFastNofProperties = 20; if (properties()->length() > kFastNofProperties) { Object* obj = NormalizeProperties(); if (obj->IsFailure()) return obj; return SetProperty(name, value, NONE); } static const int kExtraFields = 5; // Make room for the more properties. Object* values = properties()->CopySize(properties()->length() + kExtraFields); if (values->IsFailure()) return values; FixedArray::cast(values)->set(index, value); // Allocate a new map for the object. Object* new_map = map()->Copy(); if (new_map->IsFailure()) return new_map; Map::cast(new_map)-> set_instance_descriptors(DescriptorArray::cast(new_descriptors)); Map::cast(new_map)-> set_unused_property_fields(kExtraFields - 1); set_map(Map::cast(new_map)); set_properties(FixedArray::cast(values)); } } return value;}// Add property in slow modeObject* JSObject::AddSlowProperty(String* name, Object* value, PropertyAttributes attributes) { PropertyDetails details = PropertyDetails(attributes, NORMAL); Object* result = property_dictionary()->AddStringEntry(name, value, details); if (result->IsFailure()) return result; if (property_dictionary() != result) { set_properties(Dictionary::cast(result)); } return value;}Object* JSObject::AddProperty(String* name, Object* value, PropertyAttributes attributes) { if (HasFastProperties()) { // Ensure the descriptor array does not get too big. if (map()->instance_descriptors()->number_of_descriptors() < DescriptorArray::kMaxNumberOfDescriptors) { if (value->IsJSFunction()) { return AddConstantFunctionProperty(name, JSFunction::cast(value), attributes); } else { return AddFastProperty(name, value, attributes); } } else { // Normalize the object to prevent very large instance descriptors. // This eliminates unwanted N^2 allocation and lookup behavior. Object* obj = NormalizeProperties(); if (obj->IsFailure()) return obj; } } return AddSlowProperty(name, value, attributes);}Object* JSObject::SetPropertyPostInterceptor(String* name, Object* value, PropertyAttributes attributes) { // Check local property, ignore interceptor. LookupResult result; LocalLookupRealNamedProperty(name, &result); if (result.IsValid()) return SetProperty(&result, name, value, attributes); // Add real property. return AddProperty(name, value, attributes);}Object* JSObject::SetPropertyWithInterceptor(String* name, Object* value, PropertyAttributes attributes) { HandleScope scope; Handle<JSObject> this_handle(this); Handle<String> name_handle(name); Handle<Object> value_handle(value); Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); if (!interceptor->setter()->IsUndefined()) { Handle<Object> data_handle(interceptor->data()); LOG(ApiNamedPropertyAccess("interceptor-named-set", this, name)); v8::AccessorInfo info(v8::Utils::ToLocal(this_handle), v8::Utils::ToLocal(data_handle), v8::Utils::ToLocal(this_handle)); v8::NamedPropertySetter setter = v8::ToCData<v8::NamedPropertySetter>(interceptor->setter()); v8::Handle<v8::Value> result; { // Leaving JavaScript. VMState state(OTHER); Handle<Object> value_unhole(value->IsTheHole() ? Heap::undefined_value() : value); result = setter(v8::Utils::ToLocal(name_handle), v8::Utils::ToLocal(value_unhole), info); } RETURN_IF_SCHEDULED_EXCEPTION(); if (!result.IsEmpty()) return *value_handle; } Object* raw_result = this_handle->SetPropertyPostInterceptor(*name_handle, *value_handle, attributes); RETURN_IF_SCHEDULED_EXCEPTION(); return raw_result;}Object* JSObject::SetProperty(String* name, Object* value, PropertyAttributes attributes) { LookupResult result; LocalLookup(name, &result); return SetProperty(&result, name, value, attributes);}Object* JSObject::SetPropertyWithCallback(Object* structure, String* name, Object* value, JSObject* holder) { HandleScope scope; // We should never get here to initialize a const with the hole // value since a const declaration would conflict with the setter. ASSERT(!value->IsTheHole()); Handle<Object> value_handle(value); // To accommodate both the old and the new api we switch on the // data structure used to store the callbacks. Eventually proxy // callbacks should be phased out. if (structure->IsProxy()) { AccessorDescriptor* callback = reinterpret_cast<AccessorDescriptor*>(Proxy::cast(structure)->proxy()); Object* obj = (callback->setter)(this, value, callback->data); RETURN_IF_SCHEDULED_EXCEPTION(); if (obj->IsFailure()) return obj; return *value_handle; } if (structure->IsAccessorInfo()) { // api style callbacks AccessorInfo* data = AccessorInfo::cast(structure); Object* call_obj = data->setter(); v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj); if (call_fun == NULL) return value; Handle<JSObject> self(this); Handle<JSObject> holder_handle(JSObject::cast(holder)); Handle<String> key(name); Handle<Object> fun_data(data->data()); LOG(ApiNamedPropertyAccess("store", this, name)); v8::AccessorInfo info(v8::Utils::ToLocal(self), v8::Utils::ToLocal(fun_data), v8::Utils::ToLocal(holder_handle)); { // Leaving JavaScript. VMState state(OTHER); call_fun(v8::Utils::ToLocal(key), v8::Utils::ToLocal(value_handle), info); } RETURN_IF_SCHEDULED_EXCEPTION(); return *value_handle; } if (structure->IsFixedArray()) { Object* setter = FixedArray::cast(structure)->get(kSetterIndex); if (setter->IsJSFunction()) { Handle<JSFunction> fun(JSFunction::cast(setter)); Handle<JSObject> self(this); bool has_pending_exception; Object** argv[] = { value_handle.location() }; Execution::Call(fun, self, 1, argv, &has_pending_exception); // Check for pending exception and return the result. if (has_pending_exception) return Failure::Exception(); } else { Handle<String> key(name); Handle<Object> holder_handle(holder); Handle<Object> args[2] = { key, holder_handle }; return Top::Throw(*Factory::NewTypeError("no_setter_in_callback", HandleVector(args, 2))); } return *value_handle; } UNREACHABLE(); return 0;}void JSObject::LookupCallbackSetterInPrototypes(String* name, LookupResult* result) { for (Object* pt = GetPrototype(); pt != Heap::null_value(); pt = pt->GetPrototype()) { JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); if (result->IsValid()) { if (!result->IsTransitionType() && result->IsReadOnly()) { result->NotFound(); return; } if (result->type() == CALLBACKS) { return; } } } result->NotFound();}void JSObject::LookupInDescriptor(String* name, LookupResult* result) { DescriptorArray* descriptors = map()->instance_descriptors(); int number = descriptors->Search(name); if (number != DescriptorArray::kNotFound) { result->DescriptorResult(this, descriptors->GetDetails(number), number); } else { result->NotFound(); }}void JSObject::LocalLookupRealNamedProperty(String* name, LookupResult* result) { if (HasFastProperties()) { LookupInDescriptor(name, result); if (result->IsValid()) { ASSERT(result->holder() == this && result->type() != NORMAL); // Disallow caching for uninitialized constants. These can only // occur as fields. if (result->IsReadOnly() && result->type() == FIELD && properties()->get(result->GetFieldIndex())->IsTheHole()) { result->DisallowCaching(); } return; } } else { int entry = property_dictionary()->FindStringEntry(name); if (entry != DescriptorArray::kNotFound) { // Make sure to disallow caching for uninitialized constants // found in the dictionary-mode objects. if (property_dictionary()->ValueAt(entry)->IsTheHole()) { result->DisallowCaching(); } result->DictionaryResult(this, entry); return; } // Slow case object skipped during lookup. Do not use inline caching. result->DisallowCaching(); } result->NotFound();}void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) { LocalLookupRealNamedProperty(name, result); if (result->IsProperty()) return; LookupRealNamedPropertyInPrototypes(name, result);}void JSObject::LookupRealNamedPropertyInPrototypes(String* name, LookupResult* result) { for (Object* pt = GetPrototype(); pt != Heap::null_value(); pt = JSObject::cast(pt)->GetPrototype()) { JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); if (result->IsValid()) { switch (result->type()) { case NORMAL: case FIELD: case CONSTANT_FUNCTION: case CALLBACKS: return; default: break; } } } result->NotFound();}// We only need to deal with CALLBACKS and INTERCEPTORSObject* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result, String* name, Object* value) { if (!result->IsProperty()) { LookupCallbackSetterInPrototypes(name, result); } if (result->IsProperty()) { if (!result->IsReadOnly()) { switch (result->type()) { case CALLBACKS: { Object* obj = result->GetCallbackObject(); if (obj->IsAccessorInfo()) { AccessorInfo* info = AccessorInfo::cast(obj); if (info->all_can_write()) { return SetPropertyWithCallback(result->GetCallbackObject(), name, value, result->holder()); } } break; } case INTERCEPTOR: { // Try lookup real named properties. Note that only property can be // set is callbacks marked as ALL_CAN_WRITE on the prototype chain. LookupResult r; LookupRealNamedProperty(name, &r); if (r.IsProperty()) { return SetPropertyWithFailedAccessCheck(&r, name, value); } break; } default: { break; } } } } Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); return value;}Object* JSObject::SetProperty(LookupResult* result, String* name, Object* value, PropertyAttributes attributes) { // Make sure that the top context does not change when doing callbacks or // interceptor calls. AssertNoContextChange ncc; // Check access rights if needed. if (IsAccessCheckNeeded() && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { return SetPropertyWithFailedAccessCheck(result, name, value); } if (result->IsNotFound() || !result->IsProperty()) { // We could not find a local property so let's check whether there is an // accessor that wants to handle the property. LookupResult accessor_result; LookupCallbackSetterInPrototypes(name, &accessor_result); if (accessor_result.IsValid()) { return SetPropertyWithCallback(accessor_result.GetCallbackObject(), name, value, accessor_result.holder()); } } if (result->IsNotFound()) { return AddProperty(name, value, attributes); } if (!result->IsLoaded()) { return SetLazyProperty(result, name, value, attributes); } if (result->IsReadOnly() && result->IsProperty()) return value; // This is a real property that is not read-only, or it is a // transition or null descriptor and there are no setters in the prototypes.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -