Index: src/lookup.cc |
diff --git a/src/lookup.cc b/src/lookup.cc |
index 1b46f2c8292362c054c0239d6a4c9cdacb52ed2d..c3c8051bd31002ad473a86894e86404a3d2179a8 100644 |
--- a/src/lookup.cc |
+++ b/src/lookup.cc |
@@ -116,8 +116,7 @@ bool LookupIterator::HasProperty() { |
property_details_ = GetHolder()->property_dictionary()->DetailsAt(number_); |
// Holes in dictionary cells are absent values unless marked as read-only. |
if (holder->IsGlobalObject() && |
- (property_details_.IsDeleted() || |
- (!property_details_.IsReadOnly() && FetchValue()->IsTheHole()))) { |
+ (property_details_.IsDeleted() || FetchValue()->IsTheHole())) { |
return false; |
} |
} else { |
@@ -145,6 +144,76 @@ bool LookupIterator::HasProperty() { |
} |
+void LookupIterator::PrepareForDataProperty(Handle<Object> value) { |
+ ASSERT(has_property_); |
+ ASSERT(HolderIsReceiver()); |
+ if (property_encoding_ == DICTIONARY) return; |
+ holder_map_ = Map::PrepareForDataProperty(holder_map_, number_, value); |
+ JSObject::MigrateToMap(GetHolder(), holder_map_); |
+ // Reload property information. |
+ if (holder_map_->is_dictionary_map()) { |
+ property_encoding_ = DICTIONARY; |
+ } else { |
+ property_encoding_ = DESCRIPTOR; |
+ } |
+ CHECK(HasProperty()); |
+} |
+ |
+ |
+void LookupIterator::TransitionToDataProperty( |
+ Handle<Object> value, PropertyAttributes attributes, |
+ Object::StoreFromKeyed store_mode) { |
+ ASSERT(!has_property_ || !HolderIsReceiver()); |
+ |
+ // Can only be called when the receiver is a JSObject. JSProxy has to be |
+ // handled via a trap. Adding properties to primitive values is not |
+ // observable. |
+ Handle<JSObject> receiver = Handle<JSObject>::cast(GetReceiver()); |
+ |
+ // Properties have to be added to context extension objects through |
+ // SetOwnPropertyIgnoreAttributes. |
+ ASSERT(!receiver->IsJSContextExtensionObject()); |
+ |
+ if (receiver->IsJSGlobalProxy()) { |
+ receiver = handle(JSGlobalObject::cast(receiver->GetPrototype())); |
+ } |
+ |
+ maybe_holder_ = receiver; |
+ holder_map_ = Map::TransitionToDataProperty(handle(receiver->map()), name_, |
+ value, attributes, store_mode); |
+ JSObject::MigrateToMap(receiver, holder_map_); |
+ |
+ // Reload the information. |
+ state_ = NOT_FOUND; |
+ configuration_ = CHECK_OWN_REAL; |
+ state_ = LookupInHolder(); |
+ ASSERT(IsFound()); |
+ HasProperty(); |
+} |
+ |
+ |
+bool LookupIterator::HolderIsReceiver() const { |
+ ASSERT(has_property_ || state_ == INTERCEPTOR || state_ == JSPROXY); |
+ DisallowHeapAllocation no_gc; |
+ Handle<Object> receiver = GetReceiver(); |
+ if (!receiver->IsJSReceiver()) return false; |
+ Object* current = *receiver; |
+ JSReceiver* holder = *maybe_holder_.ToHandleChecked(); |
+ // JSProxy do not occur as hidden prototypes. |
+ if (current->IsJSProxy()) { |
+ return JSReceiver::cast(current) == holder; |
+ } |
+ do { |
+ if (JSReceiver::cast(current) == holder) return true; |
+ ASSERT(!current->IsJSProxy()); |
+ current = JSObject::cast(current)->GetPrototype(); |
+ } while (!current->IsNull() && |
+ (current->IsJSGlobalObject() || |
+ JSReceiver::cast(current)->map()->is_hidden_prototype())); |
+ return false; |
+} |
+ |
+ |
Handle<Object> LookupIterator::FetchValue() const { |
Object* result = NULL; |
switch (property_encoding_) { |
@@ -186,4 +255,29 @@ Handle<Object> LookupIterator::GetDataValue() const { |
} |
+void LookupIterator::WriteDataValue(Handle<Object> value) { |
+ ASSERT(is_guaranteed_to_have_holder()); |
+ ASSERT(has_property_); |
+ if (property_encoding_ == DICTIONARY) { |
+ Handle<JSObject> holder = GetHolder(); |
+ NameDictionary* property_dictionary = holder->property_dictionary(); |
+ if (holder->IsGlobalObject()) { |
+ Handle<PropertyCell> cell( |
+ PropertyCell::cast(property_dictionary->ValueAt(number_))); |
+ PropertyCell::SetValueInferType(cell, value); |
+ } else { |
+ property_dictionary->ValueAtPut(number_, *value); |
+ } |
+ } else if (property_details_.type() == v8::internal::FIELD) { |
+ GetHolder()->WriteToField(number_, *value); |
+ } else { |
+ ASSERT_EQ(v8::internal::CONSTANT, property_details_.type()); |
+ } |
+} |
+ |
+ |
+void LookupIterator::InternalizeName() { |
+ if (name_->IsUniqueName()) return; |
+ name_ = factory()->InternalizeString(Handle<String>::cast(name_)); |
+} |
} } // namespace v8::internal |