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