| Index: src/object-observe.js
|
| diff --git a/src/object-observe.js b/src/object-observe.js
|
| index 3f9af641f882e5a540f49f24c31147e49bf1de37..b598e685b436a40c80c5b540666dff770aed6caf 100644
|
| --- a/src/object-observe.js
|
| +++ b/src/object-observe.js
|
| @@ -33,28 +33,83 @@
|
| // implementation of (1) and (2) have "optimized" states which represent
|
| // common cases which can be handled more efficiently.
|
|
|
| -var observationState = %GetObservationState();
|
| +var observationState;
|
| +
|
| +function GetObservationStateJS() {
|
| + 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;
|
| + observationState.lastMicrotaskId = 0;
|
| + }
|
| +
|
| + return observationState;
|
| +}
|
| +
|
| +function GetWeakMapWrapper() {
|
| + function MapWrapper(map) {
|
| + this.map_ = map;
|
| + };
|
| +
|
| + MapWrapper.prototype = {
|
| + __proto__: null,
|
| + get: function(key) {
|
| + return %WeakCollectionGet(this.map_, key);
|
| + },
|
| + set: function(key, value) {
|
| + %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 = GetObservationStateJS();
|
| + contextMaps = {
|
| + callbackInfoMap: new map(observationState.callbackInfoMap),
|
| + objectInfoMap: new map(observationState.objectInfoMap),
|
| + notifierObjectInfoMap: new map(observationState.notifierObjectInfoMap)
|
| + };
|
| + }
|
|
|
| -// This is run during the first context creation in an isolate.
|
| -if (IS_UNDEFINED(observationState.callbackInfoMap)) {
|
| - observationState.callbackInfoMap = %ObservationWeakMapCreate();
|
| - observationState.objectInfoMap = %ObservationWeakMapCreate();
|
| - observationState.notifierObjectInfoMap = %ObservationWeakMapCreate();
|
| - observationState.pendingObservers = null;
|
| - observationState.nextCallbackPriority = 0;
|
| - observationState.lastMicrotaskId = 0;
|
| + return contextMaps;
|
| +}
|
| +
|
| +function GetCallbackInfoMap() {
|
| + return GetContextMaps().callbackInfoMap;
|
| +}
|
| +
|
| +function GetObjectInfoMap() {
|
| + return GetContextMaps().objectInfoMap;
|
| +}
|
| +
|
| +function GetNotifierObjectInfoMap() {
|
| + return GetContextMaps().notifierObjectInfoMap;
|
| }
|
|
|
| function GetPendingObservers() {
|
| - return observationState.pendingObservers;
|
| + return GetObservationStateJS().pendingObservers;
|
| }
|
|
|
| function SetPendingObservers(pendingObservers) {
|
| - observationState.pendingObservers = pendingObservers;
|
| + GetObservationStateJS().pendingObservers = pendingObservers;
|
| }
|
|
|
| function GetNextCallbackPriority() {
|
| - return observationState.nextCallbackPriority++;
|
| + return GetObservationStateJS().nextCallbackPriority++;
|
| }
|
|
|
| function nullProtoObject() {
|
| @@ -149,32 +204,35 @@ function ObjectInfoGetOrCreate(object) {
|
| performing: null,
|
| performingCount: 0,
|
| };
|
| - %WeakCollectionSet(observationState.objectInfoMap, object, objectInfo);
|
| + GetObjectInfoMap().set(object, objectInfo);
|
| }
|
| return objectInfo;
|
| }
|
|
|
| function ObjectInfoGet(object) {
|
| - return %WeakCollectionGet(observationState.objectInfoMap, object);
|
| + return GetObjectInfoMap().get(object);
|
| }
|
|
|
| function ObjectInfoGetFromNotifier(notifier) {
|
| - return %WeakCollectionGet(observationState.notifierObjectInfoMap, notifier);
|
| + return GetNotifierObjectInfoMap().get(notifier);
|
| }
|
|
|
| function ObjectInfoGetNotifier(objectInfo) {
|
| if (IS_NULL(objectInfo.notifier)) {
|
| objectInfo.notifier = { __proto__: notifierPrototype };
|
| - %WeakCollectionSet(observationState.notifierObjectInfoMap,
|
| - objectInfo.notifier, objectInfo);
|
| + GetNotifierObjectInfoMap().set(objectInfo.notifier, objectInfo);
|
| }
|
|
|
| return objectInfo.notifier;
|
| }
|
|
|
| +function ObjectInfoGetObject(objectInfo) {
|
| + return objectInfo.object;
|
| +}
|
| +
|
| function ChangeObserversIsOptimized(changeObservers) {
|
| - return IS_SPEC_FUNCTION(changeObservers) ||
|
| - IS_SPEC_FUNCTION(changeObservers.callback);
|
| + return typeof changeObservers === 'function' ||
|
| + typeof changeObservers.callback === 'function';
|
| }
|
|
|
| // The set of observers on an object is called 'changeObservers'. The first
|
| @@ -270,20 +328,16 @@ function ConvertAcceptListToTypeMap(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 %WeakCollectionGet(observationState.callbackInfoMap, callback);
|
| -}
|
| -
|
| -function CallbackInfoSet(callback, callbackInfo) {
|
| - %WeakCollectionSet(observationState.callbackInfoMap, callback, callbackInfo);
|
| + return GetCallbackInfoMap().get(callback);
|
| }
|
|
|
| function CallbackInfoGetOrCreate(callback) {
|
| - var callbackInfo = CallbackInfoGet(callback);
|
| + var callbackInfo = GetCallbackInfoMap().get(callback);
|
| if (!IS_UNDEFINED(callbackInfo))
|
| return callbackInfo;
|
|
|
| - var priority = GetNextCallbackPriority();
|
| - CallbackInfoSet(callback, priority);
|
| + var priority = GetNextCallbackPriority();
|
| + GetCallbackInfoMap().set(callback, priority);
|
| return priority;
|
| }
|
|
|
| @@ -295,12 +349,12 @@ function CallbackInfoGetPriority(callbackInfo) {
|
| }
|
|
|
| function CallbackInfoNormalize(callback) {
|
| - var callbackInfo = CallbackInfoGet(callback);
|
| + var callbackInfo = GetCallbackInfoMap().get(callback);
|
| if (IS_NUMBER(callbackInfo)) {
|
| var priority = callbackInfo;
|
| callbackInfo = new InternalArray;
|
| callbackInfo.priority = priority;
|
| - CallbackInfoSet(callback, callbackInfo);
|
| + GetCallbackInfoMap().set(callback, callbackInfo);
|
| }
|
| return callbackInfo;
|
| }
|
| @@ -369,7 +423,7 @@ function ObserverEnqueueIfActive(observer, objectInfo, changeRecord) {
|
| if (IS_NULL(GetPendingObservers())) {
|
| SetPendingObservers(nullProtoObject());
|
| if (DEBUG_IS_ACTIVE) {
|
| - var id = ++observationState.lastMicrotaskId;
|
| + var id = ++GetObservationStateJS().lastMicrotaskId;
|
| var name = "Object.observe";
|
| %EnqueueMicrotask(function() {
|
| %DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name });
|
| @@ -391,8 +445,8 @@ function ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord, type) {
|
|
|
| var hasType = !IS_UNDEFINED(type);
|
| var newRecord = hasType ?
|
| - { object: objectInfo.object, type: type } :
|
| - { object: objectInfo.object };
|
| + { object: ObjectInfoGetObject(objectInfo), type: type } :
|
| + { object: ObjectInfoGetObject(objectInfo) };
|
|
|
| for (var prop in changeRecord) {
|
| if (prop === 'object' || (hasType && prop === 'type')) continue;
|
| @@ -540,18 +594,17 @@ function NativeObjectGetNotifier(object) {
|
| }
|
|
|
| function CallbackDeliverPending(callback) {
|
| - var callbackInfo = CallbackInfoGet(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;
|
| - CallbackInfoSet(callback, priority);
|
| + GetCallbackInfoMap().set(callback, priority);
|
|
|
| - var pendingObservers = GetPendingObservers();
|
| - if (!IS_NULL(pendingObservers))
|
| - delete pendingObservers[priority];
|
| + if (GetPendingObservers())
|
| + delete GetPendingObservers()[priority];
|
|
|
| var delivered = [];
|
| %MoveArrayContents(callbackInfo, delivered);
|
| @@ -571,7 +624,7 @@ function ObjectDeliverChangeRecords(callback) {
|
|
|
| function ObserveMicrotaskRunner() {
|
| var pendingObservers = GetPendingObservers();
|
| - if (!IS_NULL(pendingObservers)) {
|
| + if (pendingObservers) {
|
| SetPendingObservers(null);
|
| for (var i in pendingObservers) {
|
| CallbackDeliverPending(pendingObservers[i]);
|
|
|