Index: src/lookup.cc |
diff --git a/src/lookup.cc b/src/lookup.cc |
index 19ae1f021db110b1beb2fea4e368d902020cc8be..e98e111e3ea9db77883822ad6d2ca258eb21cd56 100644 |
--- a/src/lookup.cc |
+++ b/src/lookup.cc |
@@ -144,6 +144,78 @@ 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()) { |
+ PrototypeIterator iter(isolate(), receiver); |
+ receiver = |
+ Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter)); |
+ } |
+ |
+ 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; |
+ } |
+ PrototypeIterator iter(isolate(), current, |
+ PrototypeIterator::START_AT_RECEIVER); |
+ do { |
+ if (JSReceiver::cast(iter.GetCurrent()) == holder) return true; |
+ ASSERT(!current->IsJSProxy()); |
+ iter.Advance(); |
+ } while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)); |
+ return false; |
+} |
+ |
+ |
Handle<Object> LookupIterator::FetchValue() const { |
Object* result = NULL; |
switch (property_encoding_) { |
@@ -181,4 +253,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 |