Revision: 12914
Author:   [email protected]
Date:     Fri Nov  9 02:57:54 2012
Log:      Object.observe: notify when element addition causes array growth

Review URL: https://codereview.chromium.org/11369135
Patch from Adam Klein <[email protected]>.
http://code.google.com/p/v8/source/detail?r=12914

Modified:
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/test/mjsunit/harmony/object-observe.js

=======================================
--- /branches/bleeding_edge/src/objects.cc      Thu Nov  8 23:26:05 2012
+++ /branches/bleeding_edge/src/objects.cc      Fri Nov  9 02:57:54 2012
@@ -10308,6 +10308,7 @@
   // From here on, everything has to be handlified.
   Handle<String> name;
   Handle<Object> old_value(isolate->heap()->the_hole_value());
+  Handle<Object> old_array_length;
   PropertyAttributes old_attributes = ABSENT;
   bool preexists = false;
   if (FLAG_harmony_observation && map()->is_observed()) {
@@ -10317,6 +10318,9 @@
       old_attributes = self->GetLocalPropertyAttribute(*name);
// TODO(observe): only read & set old_value if we have a data property
       old_value = Object::GetElement(self, index);
+    } else if (self->IsJSArray()) {
+      // Store old array length in case adding an element grows the array.
+      old_array_length = handle(Handle<JSArray>::cast(self)->length());
     }
   }

@@ -10334,11 +10338,17 @@
PropertyAttributes new_attributes = self->GetLocalPropertyAttribute(*name);
     if (!preexists) {
       EnqueueChangeRecord(self, "new", name, old_value);
+      if (self->IsJSArray() &&
+ !old_array_length->SameValue(Handle<JSArray>::cast(self)->length())) {
+        EnqueueChangeRecord(self, "updated",
+                            isolate->factory()->length_symbol(),
+                            old_array_length);
+      }
} else if (new_attributes != old_attributes || old_value->IsTheHole()) {
       EnqueueChangeRecord(self, "reconfigured", name, old_value);
     } else {
-      Handle<Object> newValue = Object::GetElement(self, index);
-      if (!newValue->SameValue(*old_value))
+      Handle<Object> new_value = Object::GetElement(self, index);
+      if (!new_value->SameValue(*old_value))
         EnqueueChangeRecord(self, "updated", name, old_value);
     }
   }
=======================================
--- /branches/bleeding_edge/test/mjsunit/harmony/object-observe.js Thu Nov 8 08:12:12 2012 +++ /branches/bleeding_edge/test/mjsunit/harmony/object-observe.js Fri Nov 9 02:57:54 2012
@@ -399,3 +399,25 @@
   { object: obj, name: "3", type: "new" },
   { object: obj, name: "4", type: "new" },
 ]);
+
+// Adding elements past the end of an array should notify on length
+reset();
+var arr = [1, 2, 3];
+Object.observe(arr, observer.callback);
+arr[3] = 10;
+arr[100] = 20;
+Object.defineProperty(arr, '200', {value: 7});
+Object.defineProperty(arr, '400', {get: function(){}});
+arr[50] = 30; // no length change expected
+Object.deliverChangeRecords(observer.callback);
+observer.assertCallbackRecords([
+  { object: arr, name: '3', type: 'new' },
+  { object: arr, name: 'length', type: 'updated', oldValue: 3 },
+  { object: arr, name: '100', type: 'new' },
+  { object: arr, name: 'length', type: 'updated', oldValue: 4 },
+  { object: arr, name: '200', type: 'new' },
+  { object: arr, name: 'length', type: 'updated', oldValue: 101 },
+  { object: arr, name: '400', type: 'new' },
+  { object: arr, name: 'length', type: 'updated', oldValue: 201 },
+  { object: arr, name: '50', type: 'new' },
+]);

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to