📄 objects.cc.svn-base
字号:
switch (result->type()) { case NORMAL: property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value); return value; case FIELD: properties()->set(result->GetFieldIndex(), value); return value; case MAP_TRANSITION: if (attributes == result->GetAttributes()) { // Only use map transition if the attributes match. return AddFastPropertyUsingMap(result->GetTransitionMap(), name, value); } else { return AddFastProperty(name, value, attributes); } case CONSTANT_FUNCTION: if (value == result->GetConstantFunction()) return value; // Only replace the function if necessary. return ReplaceConstantFunctionProperty(name, value); case CALLBACKS: return SetPropertyWithCallback(result->GetCallbackObject(), name, value, result->holder()); case INTERCEPTOR: return SetPropertyWithInterceptor(name, value, attributes); case CONSTANT_TRANSITION: // Replace with a MAP_TRANSITION to a new map with a FIELD, even // if the value is a function. // AddProperty has been extended to do this, in this case. return AddFastProperty(name, value, attributes); case NULL_DESCRIPTOR: UNREACHABLE(); default: UNREACHABLE(); } UNREACHABLE(); return value;}// Set a real local property, even if it is READ_ONLY. If the property is not// present, add it with attributes NONE. This code is the same as in// SetProperty, except for the check for IsReadOnly and the check for a// callback setter.Object* JSObject::IgnoreAttributesAndSetLocalProperty(String* name, Object* value) { // Make sure that the top context does not change when doing callbacks or // interceptor calls. AssertNoContextChange ncc; LookupResult result; LocalLookup(name, &result); // Check access rights if needed. if (IsAccessCheckNeeded() && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); return value; } if (result.IsValid()) { switch (result.type()) { case NORMAL: property_dictionary()->ValueAtPut(result.GetDictionaryEntry(), value); return value; case FIELD: properties()->set(result.GetFieldIndex(), value); return value; case MAP_TRANSITION: return AddFastPropertyUsingMap(result.GetTransitionMap(), name, value); case CONSTANT_FUNCTION: return ReplaceConstantFunctionProperty(name, value); case CALLBACKS: return SetPropertyWithCallback(result.GetCallbackObject(), name, value, result.holder()); case INTERCEPTOR: return SetPropertyWithInterceptor(name, value, NONE); case CONSTANT_TRANSITION: case NULL_DESCRIPTOR: UNREACHABLE(); break; } } // The property was not found return AddProperty(name, value, NONE);}PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( JSObject* receiver, String* name, bool continue_search) { // Check local property, ignore interceptor. LookupResult result; LocalLookupRealNamedProperty(name, &result); if (result.IsProperty()) return result.GetAttributes(); if (continue_search) { // Continue searching via the prototype chain. Object* pt = GetPrototype(); if (pt != Heap::null_value()) { return JSObject::cast(pt)-> GetPropertyAttributeWithReceiver(receiver, name); } } return ABSENT;}PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor( JSObject* receiver, String* name, bool continue_search) { // Make sure that the top context does not change when doing // callbacks or interceptor calls. AssertNoContextChange ncc; HandleScope scope; Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); Handle<JSObject> receiver_handle(receiver); Handle<JSObject> holder_handle(this); Handle<String> name_handle(name); Handle<Object> data_handle(interceptor->data()); v8::AccessorInfo info(v8::Utils::ToLocal(receiver_handle), v8::Utils::ToLocal(data_handle), v8::Utils::ToLocal(holder_handle)); if (!interceptor->query()->IsUndefined()) { v8::NamedPropertyQuery query = v8::ToCData<v8::NamedPropertyQuery>(interceptor->query()); LOG(ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name)); v8::Handle<v8::Boolean> result; { // Leaving JavaScript. VMState state(OTHER); result = query(v8::Utils::ToLocal(name_handle), info); } if (!result.IsEmpty()) { // Convert the boolean result to a property attribute // specification. return result->IsTrue() ? NONE : ABSENT; } } else if (!interceptor->getter()->IsUndefined()) { v8::NamedPropertyGetter getter = v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter()); LOG(ApiNamedPropertyAccess("interceptor-named-get-has", this, name)); v8::Handle<v8::Value> result; { // Leaving JavaScript. VMState state(OTHER); result = getter(v8::Utils::ToLocal(name_handle), info); } if (!result.IsEmpty()) return NONE; } return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle, *name_handle, continue_search);}PropertyAttributes JSObject::GetPropertyAttributeWithReceiver( JSObject* receiver, String* key) { uint32_t index; if (key->AsArrayIndex(&index)) { if (HasElementWithReceiver(receiver, index)) return NONE; return ABSENT; } // Named property. LookupResult result; Lookup(key, &result); return GetPropertyAttribute(receiver, &result, key, true);}PropertyAttributes JSObject::GetPropertyAttribute(JSObject* receiver, LookupResult* result, String* name, bool continue_search) { // Check access rights if needed. if (IsAccessCheckNeeded() && !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) { Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); return ABSENT; } if (result->IsValid()) { switch (result->type()) { case NORMAL: // fall through case FIELD: case CONSTANT_FUNCTION: case CALLBACKS: return result->GetAttributes(); case INTERCEPTOR: return result->holder()-> GetPropertyAttributeWithInterceptor(receiver, name, continue_search); case MAP_TRANSITION: case CONSTANT_TRANSITION: case NULL_DESCRIPTOR: return ABSENT; default: UNREACHABLE(); break; } } return ABSENT;}PropertyAttributes JSObject::GetLocalPropertyAttribute(String* name) { // Check whether the name is an array index. uint32_t index; if (name->AsArrayIndex(&index)) { if (HasLocalElement(index)) return NONE; return ABSENT; } // Named property. LookupResult result; LocalLookup(name, &result); return GetPropertyAttribute(this, &result, name, false);}Object* JSObject::NormalizeProperties() { if (!HasFastProperties()) return this; // Allocate new content Object* obj = Dictionary::Allocate(map()->NumberOfDescribedProperties() * 2 + 4); if (obj->IsFailure()) return obj; Dictionary* dictionary = Dictionary::cast(obj); for (DescriptorReader r(map()->instance_descriptors()); !r.eos(); r.advance()) { PropertyDetails details = r.GetDetails(); switch (details.type()) { case CONSTANT_FUNCTION: { PropertyDetails d = PropertyDetails(details.attributes(), NORMAL, details.index()); Object* value = r.GetConstantFunction(); Object* result = dictionary->AddStringEntry(r.GetKey(), value, d); if (result->IsFailure()) return result; dictionary = Dictionary::cast(result); break; } case FIELD: { PropertyDetails d = PropertyDetails(details.attributes(), NORMAL, details.index()); Object* value = properties()->get(r.GetFieldIndex()); Object* result = dictionary->AddStringEntry(r.GetKey(), value, d); if (result->IsFailure()) return result; dictionary = Dictionary::cast(result); break; } case CALLBACKS: { PropertyDetails d = PropertyDetails(details.attributes(), CALLBACKS, details.index()); Object* value = r.GetCallbacksObject(); Object* result = dictionary->AddStringEntry(r.GetKey(), value, d); if (result->IsFailure()) return result; dictionary = Dictionary::cast(result); break; } case MAP_TRANSITION: case CONSTANT_TRANSITION: case NULL_DESCRIPTOR: case INTERCEPTOR: break; default: case NORMAL: UNREACHABLE(); break; } } // Copy the next enumeration index from instance descriptor. int index = map()->instance_descriptors()->NextEnumerationIndex(); dictionary->SetNextEnumerationIndex(index); // Allocate new map. obj = map()->Copy(); if (obj->IsFailure()) return obj; // We have now sucessfully allocated all the necessary objects. // Changes can now be made with the guarantee that all of them take effect. set_map(Map::cast(obj)); map()->set_instance_descriptors(Heap::empty_descriptor_array()); map()->set_unused_property_fields(0); set_properties(dictionary); Counters::props_to_dictionary.Increment();#ifdef DEBUG if (FLAG_trace_normalization) { PrintF("Object properties have been normalized:\n"); Print(); }#endif return this;}Object* JSObject::TransformToFastProperties(int unused_property_fields) { if (HasFastProperties()) return this; return property_dictionary()-> TransformPropertiesToFastFor(this, unused_property_fields);}Object* JSObject::NormalizeElements() { if (!HasFastElements()) return this; // Get number of entries. FixedArray* array = FixedArray::cast(elements()); // Compute the effective length. int length = IsJSArray() ? Smi::cast(JSArray::cast(this)->length())->value() : array->length(); Object* obj = Dictionary::Allocate(length); if (obj->IsFailure()) return obj; Dictionary* dictionary = Dictionary::cast(obj); // Copy entries. for (int i = 0; i < length; i++) { Object* value = array->get(i); if (!value->IsTheHole()) { PropertyDetails details = PropertyDetails(NONE, NORMAL); Object* result = dictionary->AddNumberEntry(i, array->get(i), details); if (result->IsFailure()) return result; dictionary = Dictionary::cast(result); } } // Switch to using the dictionary as the backing storage for elements. set_elements(dictionary); Counters::elements_to_dictionary.Increment();#ifdef DEBUG if (FLAG_trace_normalization) { PrintF("Object elements have been normalized:\n"); Print(); }#endif return this;}Object* JSObject::DeletePropertyPostInterceptor(String* name) { // Check local property, ignore interceptor. LookupResult result; LocalLookupRealNamedProperty(name, &result); if (!result.IsValid()) return Heap::true_value(); // Normalize object if needed. Object* obj = NormalizeProperties(); if (obj->IsFailure()) return obj; ASSERT(!HasFastProperties()); // Attempt to remove the property from the property dictionary. Dictionary* dictionary = property_dictionary(); int entry = dictionary->FindStringEntry(name); if (entry != -1) return dictionary->DeleteProperty(entry); return Heap::true_value();}Object* JSObject::DeletePropertyWithInterceptor(String* name) { HandleScope scope; Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); Handle<String> name_handle(name); Handle<JSObject> this_handle(this); if (!interceptor->deleter()->IsUndefined()) { v8::NamedPropertyDeleter deleter = v8::ToCData<v8::NamedPropertyDeleter>(interceptor->deleter()); Handle<Object> data_handle(interceptor->data()); LOG(ApiNamedPropertyAccess("interceptor-named-delete", *this_handle, name)); v8::AccessorInfo info(v8::Utils::ToLocal(this_handle), v
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -