Index: src/object-observe.js |
diff --git a/src/object-observe.js b/src/object-observe.js |
index 90c9a699e0569281ca3d415f880e04c21423600e..1c147d95e30f9e82d45797d500b2d32bb198b064 100644 |
--- a/src/object-observe.js |
+++ b/src/object-observe.js |
@@ -28,12 +28,12 @@ |
"use strict"; |
var observationState = %GetObservationState(); |
-if (IS_UNDEFINED(observationState.observerInfoMap)) { |
- observationState.observerInfoMap = %ObservationWeakMapCreate(); |
+if (IS_UNDEFINED(observationState.callbackInfoMap)) { |
+ observationState.callbackInfoMap = %ObservationWeakMapCreate(); |
observationState.objectInfoMap = %ObservationWeakMapCreate(); |
observationState.notifierTargetMap = %ObservationWeakMapCreate(); |
observationState.pendingObservers = new InternalArray; |
- observationState.observerPriority = 0; |
+ observationState.nextCallbackPriority = 0; |
} |
function ObservationWeakMap(map) { |
@@ -56,8 +56,8 @@ ObservationWeakMap.prototype = { |
} |
}; |
-var observerInfoMap = |
- new ObservationWeakMap(observationState.observerInfoMap); |
+var callbackInfoMap = |
+ new ObservationWeakMap(observationState.callbackInfoMap); |
var objectInfoMap = new ObservationWeakMap(observationState.objectInfoMap); |
var notifierTargetMap = |
new ObservationWeakMap(observationState.notifierTargetMap); |
@@ -198,6 +198,22 @@ function AcceptArgIsValid(arg) { |
return true; |
} |
+function EnsureCallbackPriority(callback) { |
+ if (!callbackInfoMap.has(callback)) |
+ callbackInfoMap.set(callback, observationState.nextCallbackPriority++); |
+} |
+ |
+function NormalizeCallbackInfo(callback) { |
+ var callbackInfo = callbackInfoMap.get(callback); |
+ if (IS_NUMBER(callbackInfo)) { |
+ var priority = callbackInfo; |
+ callbackInfo = new InternalArray; |
+ callbackInfo.priority = priority; |
+ callbackInfoMap.set(callback, callbackInfo); |
+ } |
+ return callbackInfo; |
+} |
+ |
function ObjectObserve(object, callback, accept) { |
if (!IS_SPEC_OBJECT(object)) |
throw MakeTypeError("observe_non_object", ["observe"]); |
@@ -208,12 +224,7 @@ function ObjectObserve(object, callback, accept) { |
if (!AcceptArgIsValid(accept)) |
throw MakeTypeError("observe_accept_invalid"); |
- if (!observerInfoMap.has(callback)) { |
- observerInfoMap.set(callback, { |
- pendingChangeRecords: null, |
- priority: observationState.observerPriority++, |
- }); |
- } |
+ EnsureCallbackPriority(callback); |
var objectInfo = objectInfoMap.get(object); |
if (IS_UNDEFINED(objectInfo)) { |
@@ -257,6 +268,13 @@ function ArrayUnobserve(object, callback) { |
return ObjectUnobserve(object, callback); |
} |
+function EnqueueToCallback(callback, changeRecord) { |
+ var callbackInfo = NormalizeCallbackInfo(callback); |
+ observationState.pendingObservers[callbackInfo.priority] = callback; |
+ callbackInfo.push(changeRecord); |
+ %SetObserverDeliveryPending(); |
+} |
+ |
function EnqueueChangeRecord(changeRecord, observers) { |
// TODO(rossberg): adjust once there is a story for symbols vs proxies. |
if (IS_SYMBOL(changeRecord.name)) return; |
@@ -266,15 +284,7 @@ function EnqueueChangeRecord(changeRecord, observers) { |
if (IS_UNDEFINED(observer.accept[changeRecord.type])) |
continue; |
- var callback = observer.callback; |
- var observerInfo = observerInfoMap.get(callback); |
- observationState.pendingObservers[observerInfo.priority] = callback; |
- %SetObserverDeliveryPending(); |
- if (IS_NULL(observerInfo.pendingChangeRecords)) { |
- observerInfo.pendingChangeRecords = new InternalArray(changeRecord); |
- } else { |
- observerInfo.pendingChangeRecords.push(changeRecord); |
- } |
+ EnqueueToCallback(observer.callback, changeRecord); |
} |
} |
@@ -394,21 +404,22 @@ function ObjectGetNotifier(object) { |
return objectInfo.notifier; |
} |
-function DeliverChangeRecordsForObserver(observer) { |
- var observerInfo = observerInfoMap.get(observer); |
- if (IS_UNDEFINED(observerInfo)) |
+function CallbackDeliverPending(callback) { |
+ var callbackInfo = callbackInfoMap.get(callback); |
+ if (IS_UNDEFINED(callbackInfo) || IS_NUMBER(callbackInfo)) |
return false; |
- var pendingChangeRecords = observerInfo.pendingChangeRecords; |
- if (IS_NULL(pendingChangeRecords)) |
- return false; |
+ // Clear the pending change records from callback and return it to its |
+ // "optimized" state. |
+ var priority = callbackInfo.priority; |
+ callbackInfoMap.set(callback, priority); |
- observerInfo.pendingChangeRecords = null; |
- delete observationState.pendingObservers[observerInfo.priority]; |
+ delete observationState.pendingObservers[priority]; |
var delivered = []; |
- %MoveArrayContents(pendingChangeRecords, delivered); |
+ %MoveArrayContents(callbackInfo, delivered); |
+ |
try { |
- %Call(void 0, delivered, observer); |
+ %Call(void 0, delivered, callback); |
} catch (ex) {} |
return true; |
} |
@@ -417,7 +428,7 @@ function ObjectDeliverChangeRecords(callback) { |
if (!IS_SPEC_FUNCTION(callback)) |
throw MakeTypeError("observe_non_function", ["deliverChangeRecords"]); |
- while (DeliverChangeRecordsForObserver(callback)) {} |
+ while (CallbackDeliverPending(callback)) {} |
} |
function DeliverChangeRecords() { |
@@ -425,7 +436,7 @@ function DeliverChangeRecords() { |
var pendingObservers = observationState.pendingObservers; |
observationState.pendingObservers = new InternalArray; |
for (var i in pendingObservers) { |
- DeliverChangeRecordsForObserver(pendingObservers[i]); |
+ CallbackDeliverPending(pendingObservers[i]); |
} |
} |
} |