Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2678)

Unified Diff: src/objects.cc

Issue 11365111: Object.observe: generate change records for indexed properties. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« src/elements.cc ('K') | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index bc4a63cc02e2c43b24e23a2aac5a1ae99cebfd45..8ba7044e300baac558bb7e87dd4282216de7487d 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -3302,8 +3302,7 @@ PropertyAttributes JSReceiver::GetLocalPropertyAttribute(String* name) {
// Check whether the name is an array index.
uint32_t index = 0;
if (IsJSObject() && name->AsArrayIndex(&index)) {
- if (JSObject::cast(this)->HasLocalElement(index)) return NONE;
- return ABSENT;
+ return GetLocalElementAttribute(index);
}
// Named property.
LookupResult lookup(GetIsolate());
@@ -3312,6 +3311,27 @@ PropertyAttributes JSReceiver::GetLocalPropertyAttribute(String* name) {
}
+PropertyAttributes JSObject::GetLocalElementAttribute(uint32_t index) {
+ // Check access rights if needed.
+ if (IsAccessCheckNeeded()) {
+ Heap* heap = GetHeap();
+ if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
+ heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
+ return ABSENT;
+ }
+ }
+
+ if (IsJSGlobalProxy()) {
+ Object* proto = GetPrototype();
+ if (proto->IsNull()) return ABSENT;
+ ASSERT(proto->IsJSGlobalObject());
+ return JSReceiver::cast(proto)->GetLocalElementAttribute(index);
+ }
+
+ return GetElementsAccessor()->GetAttributes(this, this, index);
+}
+
+
MaybeObject* NormalizedMapCache::Get(JSObject* obj,
PropertyNormalizationMode mode) {
Isolate* isolate = obj->GetIsolate();
@@ -4033,15 +4053,43 @@ MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
return JSGlobalObject::cast(proto)->DeleteElement(index, mode);
}
- if (HasIndexedInterceptor()) {
- // Skip interceptor if forcing deletion.
- if (mode != FORCE_DELETION) {
- return DeleteElementWithInterceptor(index);
+ // From this point on everything needs to be handlified.
+ HandleScope scope(isolate);
+ Handle<JSObject> self(this);
+
+ Handle<String> name;
+ Handle<Object> old_value(isolate->heap()->the_hole_value());
+ bool preexists = false;
+ if (FLAG_harmony_observation && map()->is_observed()) {
+ name = isolate->factory()->Uint32ToString(index);
+ preexists = self->HasLocalElement(index);
+ if (preexists) {
+ // TODO(observe): only read & set old_value if it's not an accessor
+ old_value = Object::GetElement(self, index);
}
- mode = JSReceiver::FORCE_DELETION;
}
- return GetElementsAccessor()->Delete(this, index, mode);
+ MaybeObject* result;
+ // Skip interceptor if forcing deletion.
+ if (self->HasIndexedInterceptor()) {
Toon Verwaest 2012/11/07 10:06:52 Maybe use (self->HasIndexedInterceptor() && mode !
rossberg 2012/11/07 18:41:42 Done.
+ if (mode != FORCE_DELETION)
+ result = self->DeleteElementWithInterceptor(index);
+ else
+ result = self->GetElementsAccessor()->Delete(
+ *self, index, JSReceiver::FORCE_DELETION);
+ } else {
+ result = self->GetElementsAccessor()->Delete(*self, index, mode);
+ }
+
+ Handle<Object> hresult;
+ if (!result->ToHandle(&hresult)) return result;
+
+ if (FLAG_harmony_observation && map()->is_observed()) {
+ if (preexists && !self->HasLocalElement(index))
+ self->EnqueueChangeRecord("deleted", name, old_value);
+ }
+
+ return *hresult;
}
@@ -10114,28 +10162,31 @@ Handle<Object> JSObject::SetElement(Handle<JSObject> object,
MaybeObject* JSObject::SetElement(uint32_t index,
- Object* value,
+ Object* value_raw,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
bool check_prototype,
SetPropertyMode set_mode) {
+ Isolate* isolate = GetIsolate();
+ HandleScope scope(isolate);
+ Handle<JSObject> self(this);
+ Handle<Object> value(value_raw);
+
// Check access rights if needed.
if (IsAccessCheckNeeded()) {
Heap* heap = GetHeap();
- if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) {
- HandleScope scope(heap->isolate());
- Handle<Object> value_handle(value);
- heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET);
- return *value_handle;
+ if (!heap->isolate()->MayIndexedAccess(*self, index, v8::ACCESS_SET)) {
+ heap->isolate()->ReportFailedAccessCheck(*self, v8::ACCESS_SET);
+ return *value;
}
}
if (IsJSGlobalProxy()) {
Object* proto = GetPrototype();
- if (proto->IsNull()) return value;
+ if (proto->IsNull()) return *value;
ASSERT(proto->IsJSGlobalObject());
return JSObject::cast(proto)->SetElement(index,
- value,
+ *value,
attributes,
strict_mode,
check_prototype,
@@ -10144,10 +10195,8 @@ MaybeObject* JSObject::SetElement(uint32_t index,
// Don't allow element properties to be redefined for external arrays.
if (HasExternalArrayElements() && set_mode == DEFINE_PROPERTY) {
- Isolate* isolate = GetHeap()->isolate();
- Handle<Object> receiver(this);
Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
- Handle<Object> args[] = { receiver, number };
+ Handle<Object> args[] = { self, number };
Handle<Object> error = isolate->factory()->NewTypeError(
"redef_external_array_element", HandleVector(args, ARRAY_SIZE(args)));
return isolate->Throw(*error);
@@ -10162,22 +10211,56 @@ MaybeObject* JSObject::SetElement(uint32_t index,
dictionary->set_requires_slow_elements();
}
+ // From here on, everything has to be handlified.
+ Handle<String> name;
+ Handle<Object> old_value(isolate->heap()->the_hole_value());
+ PropertyAttributes old_attributes;
+ bool preexists = false;
+ if (FLAG_harmony_observation && map()->is_observed()) {
+ name = isolate->factory()->Uint32ToString(index);
+ preexists = self->HasLocalElement(index);
+ if (preexists) {
+ old_attributes = self->GetLocalPropertyAttribute(*name);
+ // TODO(observe): only read & set old_value if we have a data property
+ old_value = Object::GetElement(self, index);
+ }
+ }
+
// Check for lookup interceptor
- if (HasIndexedInterceptor()) {
- return SetElementWithInterceptor(index,
- value,
- attributes,
- strict_mode,
- check_prototype,
- set_mode);
+ MaybeObject* result = *value;
Toon Verwaest 2012/11/07 10:06:52 This initialization seems superfluous since it's o
rossberg 2012/11/07 18:41:42 Done.
+ if (self->HasIndexedInterceptor()) {
+ result = self->SetElementWithInterceptor(index,
+ *value,
+ attributes,
+ strict_mode,
+ check_prototype,
+ set_mode);
+ } else {
+ result = self->SetElementWithoutInterceptor(index,
+ *value,
+ attributes,
+ strict_mode,
+ check_prototype,
+ set_mode);
}
- return SetElementWithoutInterceptor(index,
- value,
- attributes,
- strict_mode,
- check_prototype,
- set_mode);
+ Handle<Object> hresult;
+ if (!result->ToHandle(&hresult)) return result;
+
+ if (FLAG_harmony_observation && map()->is_observed()) {
+ PropertyAttributes new_attributes = self->GetLocalPropertyAttribute(*name);
+ if (!preexists) {
+ self->EnqueueChangeRecord("new", name, old_value);
+ } else if (new_attributes != old_attributes || old_value->IsTheHole()) {
+ self->EnqueueChangeRecord("reconfigured", name, old_value);
+ } else {
+ Handle<Object> newValue = Object::GetElement(self, index);
+ if (!newValue->SameValue(*old_value))
+ self->EnqueueChangeRecord("updated", name, old_value);
+ }
+ }
+
+ return *hresult;
}
« src/elements.cc ('K') | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698