Chromium Code Reviews| Index: src/object-observe.js |
| diff --git a/src/object-observe.js b/src/object-observe.js |
| index 468da31ec2588958b985e4cb4346cf20e54122f0..ed90b5f73ec71543198c800b9186f9cd4bdd4101 100644 |
| --- a/src/object-observe.js |
| +++ b/src/object-observe.js |
| @@ -25,8 +25,6 @@ |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| -"use strict"; |
|
rafaelw
2014/03/05 00:48:46
it seems like all the built-in native js files are
rossberg
2014/03/06 08:41:35
That's surprising. The directive here should only
rafaelw
2014/03/07 04:33:06
You are right. I tried adding it back and got not
rossberg
2014/03/07 07:14:44
Please keep it nevertheless -- we have a midterm g
rafaelw
2014/03/08 02:48:19
Ok. Seems wrong, but I'll leave it in.
On 2014/03
|
| - |
| // Overview: |
| // |
| // This file contains all of the routing and accounting for Object.observe. |
| @@ -56,40 +54,86 @@ |
| // implementation of (1) and (2) have "optimized" states which represent |
| // common cases which can be handled more efficiently. |
| -var observationState = %GetObservationState(); |
| -if (IS_UNDEFINED(observationState.callbackInfoMap)) { |
| - observationState.callbackInfoMap = %ObservationWeakMapCreate(); |
| - observationState.objectInfoMap = %ObservationWeakMapCreate(); |
| - observationState.notifierObjectInfoMap = %ObservationWeakMapCreate(); |
| - observationState.pendingObservers = null; |
| - observationState.nextCallbackPriority = 0; |
| -} |
| - |
| -function ObservationWeakMap(map) { |
| - this.map_ = map; |
| -} |
| - |
| -ObservationWeakMap.prototype = { |
| - get: function(key) { |
| - key = %UnwrapGlobalProxy(key); |
| - if (!IS_SPEC_OBJECT(key)) return UNDEFINED; |
| - return %WeakCollectionGet(this.map_, key); |
| - }, |
| - set: function(key, value) { |
| - key = %UnwrapGlobalProxy(key); |
| - if (!IS_SPEC_OBJECT(key)) return UNDEFINED; |
| - %WeakCollectionSet(this.map_, key, value); |
| - }, |
| - has: function(key) { |
| - return !IS_UNDEFINED(this.get(key)); |
| +var observationState; |
| + |
| +function GetObservationState() { |
| + if (IS_UNDEFINED(observationState)) |
| + observationState = %GetObservationState(); |
| + |
| + if (IS_UNDEFINED(observationState.callbackInfoMap)) { |
| + observationState.callbackInfoMap = %ObservationWeakMapCreate(); |
| + observationState.objectInfoMap = %ObservationWeakMapCreate(); |
| + observationState.notifierObjectInfoMap = %ObservationWeakMapCreate(); |
| + observationState.pendingObservers = null; |
| + observationState.nextCallbackPriority = 0; |
| } |
| -}; |
| -var callbackInfoMap = |
| - new ObservationWeakMap(observationState.callbackInfoMap); |
| -var objectInfoMap = new ObservationWeakMap(observationState.objectInfoMap); |
| -var notifierObjectInfoMap = |
| - new ObservationWeakMap(observationState.notifierObjectInfoMap); |
| + return observationState; |
| +} |
| + |
| +function GetWeakMapWrapper() { |
| + function MapWrapper(map) { |
| + this.map_ = map; |
| + }; |
| + |
| + MapWrapper.prototype = { |
| + get: function(key) { |
| + key = %UnwrapGlobalProxy(key); |
| + if (!IS_SPEC_OBJECT(key)) return UNDEFINED; |
| + return %WeakCollectionGet(this.map_, key); |
| + }, |
| + set: function(key, value) { |
| + key = %UnwrapGlobalProxy(key); |
| + if (!IS_SPEC_OBJECT(key)) return UNDEFINED; |
| + %WeakCollectionSet(this.map_, key, value); |
| + }, |
| + has: function(key) { |
| + return !IS_UNDEFINED(this.get(key)); |
| + } |
| + }; |
| + |
| + return MapWrapper; |
| +} |
| + |
| +var contextMaps; |
| + |
| +function GetContextMaps() { |
| + if (IS_UNDEFINED(contextMaps)) { |
| + var map = GetWeakMapWrapper(); |
| + var observationState = GetObservationState(); |
| + contextMaps = { |
| + callbackInfoMap: new map(observationState.callbackInfoMap), |
| + objectInfoMap: new map(observationState.objectInfoMap), |
| + notifierObjectInfoMap: new map(observationState.notifierObjectInfoMap) |
| + }; |
| + } |
| + |
| + return contextMaps; |
| +} |
| + |
| +function GetCallbackInfoMap() { |
| + return GetContextMaps().callbackInfoMap; |
| +} |
| + |
| +function GetObjectInfoMap() { |
| + return GetContextMaps().objectInfoMap; |
| +} |
| + |
| +function GetNotifierObjectInfoMap() { |
| + return GetContextMaps().notifierObjectInfoMap; |
| +} |
| + |
| +function GetPendingObservers() { |
| + return GetObservationState().pendingObservers; |
| +} |
| + |
| +function SetPendingObservers(pendingObservers) { |
| + GetObservationState().pendingObservers = pendingObservers; |
| +} |
| + |
| +function GetNextCallbackPriority() { |
| + return GetObservationState().nextCallbackPriority++; |
| +} |
| function nullProtoObject() { |
| return { __proto__: null }; |
| @@ -180,23 +224,23 @@ function ObjectInfoGetOrCreate(object) { |
| performing: null, |
| performingCount: 0, |
| }; |
| - objectInfoMap.set(object, objectInfo); |
| + GetObjectInfoMap().set(object, objectInfo); |
| } |
| return objectInfo; |
| } |
| function ObjectInfoGet(object) { |
| - return objectInfoMap.get(object); |
| + return GetObjectInfoMap().get(object); |
| } |
| function ObjectInfoGetFromNotifier(notifier) { |
| - return notifierObjectInfoMap.get(notifier); |
| + return GetNotifierObjectInfoMap().get(notifier); |
| } |
| function ObjectInfoGetNotifier(objectInfo) { |
| if (IS_NULL(objectInfo.notifier)) { |
| objectInfo.notifier = { __proto__: notifierPrototype }; |
| - notifierObjectInfoMap.set(objectInfo.notifier, objectInfo); |
| + GetNotifierObjectInfoMap().set(objectInfo.notifier, objectInfo); |
| } |
| return objectInfo.notifier; |
| @@ -302,16 +346,16 @@ function AcceptArgIsValid(arg) { |
| // priority. When a change record must be enqueued for the callback, it |
| // normalizes. When delivery clears any pending change records, it re-optimizes. |
| function CallbackInfoGet(callback) { |
| - return callbackInfoMap.get(callback); |
| + return GetCallbackInfoMap().get(callback); |
| } |
| function CallbackInfoGetOrCreate(callback) { |
| - var callbackInfo = callbackInfoMap.get(callback); |
| + var callbackInfo = GetCallbackInfoMap().get(callback); |
| if (!IS_UNDEFINED(callbackInfo)) |
| return callbackInfo; |
| - var priority = observationState.nextCallbackPriority++ |
| - callbackInfoMap.set(callback, priority); |
| + var priority = GetNextCallbackPriority(); |
| + GetCallbackInfoMap().set(callback, priority); |
| return priority; |
| } |
| @@ -323,12 +367,12 @@ function CallbackInfoGetPriority(callbackInfo) { |
| } |
| function CallbackInfoNormalize(callback) { |
| - var callbackInfo = callbackInfoMap.get(callback); |
| + var callbackInfo = GetCallbackInfoMap().get(callback); |
| if (IS_NUMBER(callbackInfo)) { |
| var priority = callbackInfo; |
| callbackInfo = new InternalArray; |
| callbackInfo.priority = priority; |
| - callbackInfoMap.set(callback, callbackInfo); |
| + GetCallbackInfoMap().set(callback, callbackInfo); |
| } |
| return callbackInfo; |
| } |
| @@ -390,12 +434,12 @@ function ObserverEnqueueIfActive(observer, objectInfo, changeRecord, |
| } |
| var callbackInfo = CallbackInfoNormalize(callback); |
| - if (IS_NULL(observationState.pendingObservers)) { |
| - observationState.pendingObservers = nullProtoObject(); |
| + if (IS_NULL(GetPendingObservers())) { |
| + SetPendingObservers(nullProtoObject()) |
| GetMicrotaskQueue().push(ObserveMicrotaskRunner); |
| %SetMicrotaskPending(true); |
| } |
| - observationState.pendingObservers[callbackInfo.priority] = callback; |
| + GetPendingObservers()[callbackInfo.priority] = callback; |
| callbackInfo.push(changeRecord); |
| } |
| @@ -548,17 +592,17 @@ function ObjectGetNotifier(object) { |
| } |
| function CallbackDeliverPending(callback) { |
| - var callbackInfo = callbackInfoMap.get(callback); |
| + var callbackInfo = GetCallbackInfoMap().get(callback); |
| if (IS_UNDEFINED(callbackInfo) || IS_NUMBER(callbackInfo)) |
| return false; |
| // Clear the pending change records from callback and return it to its |
| // "optimized" state. |
| var priority = callbackInfo.priority; |
| - callbackInfoMap.set(callback, priority); |
| + GetCallbackInfoMap().set(callback, priority); |
| - if (observationState.pendingObservers) |
| - delete observationState.pendingObservers[priority]; |
| + if (GetPendingObservers()) |
| + delete GetPendingObservers()[priority]; |
| var delivered = []; |
| %MoveArrayContents(callbackInfo, delivered); |
| @@ -577,9 +621,9 @@ function ObjectDeliverChangeRecords(callback) { |
| } |
| function ObserveMicrotaskRunner() { |
| - var pendingObservers = observationState.pendingObservers; |
| + var pendingObservers = GetPendingObservers(); |
| if (pendingObservers) { |
| - observationState.pendingObservers = null; |
| + SetPendingObservers(null); |
| for (var i in pendingObservers) { |
| CallbackDeliverPending(pendingObservers[i]); |
| } |