Chromium Code Reviews| Index: src/object-observe.js |
| diff --git a/src/object-observe.js b/src/object-observe.js |
| index 90c9a699e0569281ca3d415f880e04c21423600e..6d00bffc75d6787872168af14730e76d56a8e95b 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 NormalizeCallback(callback) { |
|
rossberg
2013/07/15 17:02:43
Nit: Not sure I like the name too much, since it's
rafaelw
2013/07/15 19:13:11
Agreed. I'd like to be explicit that this call is
|
| + 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 = NormalizeCallback(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]); |
| } |
| } |
| } |