Revision: 12951
Author:   [email protected]
Date:     Tue Nov 13 07:53:28 2012
Log: Object.deliverChangeRecords should remove the observer from activeObservers

To preserve ordering guarantees during end-of-turn delivery, Object.deliverChangeRecords needs to remove the delivered-to observer from the list of active observers.

The added test demonstrates this behavior.

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

Modified:
 /branches/bleeding_edge/src/object-observe.js
 /branches/bleeding_edge/test/cctest/test-object-observe.cc

=======================================
--- /branches/bleeding_edge/src/object-observe.js       Tue Nov 13 07:50:59 2012
+++ /branches/bleeding_edge/src/object-observe.js       Tue Nov 13 07:53:28 2012
@@ -35,7 +35,7 @@
   observationState.observerInfoMap = %CreateObjectHashTable();
   observationState.objectInfoMap = %CreateObjectHashTable();
   observationState.notifierTargetMap = %CreateObjectHashTable();
-  observationState.activeObservers = new InternalArray;
+  observationState.pendingObservers = new InternalArray;
   observationState.observerPriority = 0;
 }

@@ -119,7 +119,7 @@
   for (var i = 0; i < observers.length; i++) {
     var observer = observers[i];
     var observerInfo = observerInfoMap.get(observer);
-    observationState.activeObservers[observerInfo.priority] = observer;
+    observationState.pendingObservers[observerInfo.priority] = observer;
     %SetObserverDeliveryPending();
     if (IS_NULL(observerInfo.pendingChangeRecords)) {
       observerInfo.pendingChangeRecords = new InternalArray(changeRecord);
@@ -202,6 +202,7 @@
     return;

   observerInfo.pendingChangeRecords = null;
+  delete observationState.pendingObservers[observerInfo.priority];
   var delivered = [];
   %MoveArrayContents(pendingChangeRecords, delivered);
   try {
@@ -217,11 +218,11 @@
 }

 function DeliverChangeRecords() {
-  while (observationState.activeObservers.length) {
-    var activeObservers = observationState.activeObservers;
-    observationState.activeObservers = new InternalArray;
-    for (var i in activeObservers) {
-      DeliverChangeRecordsForObserver(activeObservers[i]);
+  while (observationState.pendingObservers.length) {
+    var pendingObservers = observationState.pendingObservers;
+    observationState.pendingObservers = new InternalArray;
+    for (var i in pendingObservers) {
+      DeliverChangeRecordsForObserver(pendingObservers[i]);
     }
   }
 }
=======================================
--- /branches/bleeding_edge/test/cctest/test-object-observe.cc Fri Nov 9 08:14:42 2012 +++ /branches/bleeding_edge/test/cctest/test-object-observe.cc Tue Nov 13 07:53:28 2012
@@ -165,6 +165,30 @@
   CHECK_EQ(1, CompileRun("ordering[3]")->Int32Value());
   CHECK_EQ(2, CompileRun("ordering[1]")->Int32Value());
 }
+
+TEST(DeliveryOrderingDeliverChangeRecords) {
+  HarmonyIsolate isolate;
+  HandleScope scope;
+  LocalContext context;
+  CompileRun(
+      "var obj = {};"
+      "var ordering = [];"
+ "function observer1() { ordering.push(1); if (!obj.b) obj.b = true };"
+      "function observer2() { ordering.push(2); };"
+      "Object.observe(obj, observer1);"
+      "Object.observe(obj, observer2);"
+      "obj.a = 1;"
+      "Object.deliverChangeRecords(observer2);");
+  CHECK_EQ(4, CompileRun("ordering.length")->Int32Value());
+  // First, observer2 is called due to deliverChangeRecords
+  CHECK_EQ(2, CompileRun("ordering[0]")->Int32Value());
+  // Then, observer1 is called when the stack unwinds
+  CHECK_EQ(1, CompileRun("ordering[1]")->Int32Value());
+  // observer1's mutation causes both 1 and 2 to be reactivated,
+  // with 1 having priority.
+  CHECK_EQ(1, CompileRun("ordering[2]")->Int32Value());
+  CHECK_EQ(2, CompileRun("ordering[3]")->Int32Value());
+}

 TEST(ObjectHashTableGrowth) {
   HarmonyIsolate isolate;

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

Reply via email to