Chromium Code Reviews| Index: src/object-observe.js |
| diff --git a/src/object-observe.js b/src/object-observe.js |
| index 086159f9cb81db03ecfa87ec87a1a4fdb588e4ef..23bfea717e48ef48e1b70acbcda55bd40d4a8448 100644 |
| --- a/src/object-observe.js |
| +++ b/src/object-observe.js |
| @@ -34,6 +34,7 @@ var observationState = %GetObservationState(); |
| if (IS_UNDEFINED(observationState.observerInfoMap)) { |
| observationState.observerInfoMap = %CreateObjectHashTable(); |
| observationState.objectInfoMap = %CreateObjectHashTable(); |
| + observationState.notifierTargetMap = %CreateObjectHashTable(); |
| observationState.activeObservers = new InternalArray; |
| observationState.observerPriority = 0; |
| } |
| @@ -57,6 +58,16 @@ InternalObjectHashTable.prototype = { |
| var observerInfoMap = new InternalObjectHashTable('observerInfoMap'); |
| var objectInfoMap = new InternalObjectHashTable('objectInfoMap'); |
| +var notifierTargetMap = new InternalObjectHashTable('notifierTargetMap'); |
| + |
| +function CreateObjectInfo(object) { |
| + var info = { |
| + changeObservers: new InternalArray, |
|
rossberg
2012/11/09 14:41:25
Nit: can we perhaps rename that property to just "
adamk
2012/11/09 14:48:41
It's named like this to match the spec's [[ChangeO
|
| + notifier: null, |
| + }; |
| + objectInfoMap.set(object, info); |
| + return info; |
| +} |
| function ObjectObserve(object, callback) { |
| if (!IS_SPEC_OBJECT(object)) |
| @@ -75,13 +86,8 @@ function ObjectObserve(object, callback) { |
| var objectInfo = objectInfoMap.get(object); |
| if (IS_UNDEFINED(objectInfo)) { |
| - // TODO: setup objectInfo.notifier |
| - objectInfo = { |
| - changeObservers: new InternalArray(callback) |
| - }; |
| - objectInfoMap.set(object, objectInfo); |
| + objectInfo = CreateObjectInfo(object); |
| %SetIsObserved(object, true); |
| - return; |
| } |
| var changeObservers = objectInfo.changeObservers; |
| @@ -130,17 +136,28 @@ function NotifyChange(type, object, name, oldValue) { |
| EnqueueChangeRecord(changeRecord, objectInfo.changeObservers); |
| } |
| -function ObjectNotify(object, changeRecord) { |
| - // TODO: notifier needs to be [[THIS]] |
| +var notifierPrototype = {}; |
| + |
| +function ObjectNotifierNotify(changeRecord) { |
| + if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) |
| + throw MakeTypeError("called_on_null_or_undefined", ["notify"]); |
| + |
| + var target = notifierTargetMap.get(this); |
| + if (IS_UNDEFINED(target)) |
| + return; |
|
rossberg
2012/11/09 14:41:25
This is calling the notify method on something tha
adamk
2012/11/09 14:48:41
Here's what arv said about this when I asked him a
rossberg
2012/11/09 15:06:17
Hm, I don't buy that -- I think "nominal typing" i
arv (Not doing code reviews)
2012/11/09 15:22:22
I don't remember my logic.
|
| + |
| if (!IS_STRING(changeRecord.type)) |
| throw MakeTypeError("observe_type_non_string"); |
| - var objectInfo = objectInfoMap.get(object); |
| + var objectInfo = objectInfoMap.get(target); |
| if (IS_UNDEFINED(objectInfo)) |
| return; |
| + if (!objectInfo.changeObservers.length) |
| + return; |
| + |
| var newRecord = { |
| - object: object // TODO: Needs to be 'object' retrieved from notifier |
| + object: target |
| }; |
| for (var prop in changeRecord) { |
| if (prop === 'object') |
| @@ -152,6 +169,27 @@ function ObjectNotify(object, changeRecord) { |
| EnqueueChangeRecord(newRecord, objectInfo.changeObservers); |
| } |
| +function ObjectGetNotifier(object) { |
| + if (!IS_SPEC_OBJECT(object)) |
| + throw MakeTypeError("observe_non_object", ["getNotifier"]); |
| + |
| + if (InternalObjectIsFrozen(object)) |
| + return null; |
| + |
| + var objectInfo = objectInfoMap.get(object); |
| + if (IS_UNDEFINED(objectInfo)) |
| + objectInfo = CreateObjectInfo(object); |
| + |
| + if (IS_NULL(objectInfo.notifier)) { |
| + objectInfo.notifier = { |
| + __proto__: notifierPrototype |
| + }; |
| + notifierTargetMap.set(objectInfo.notifier, object); |
| + } |
| + |
| + return objectInfo.notifier; |
| +} |
| + |
| function DeliverChangeRecordsForObserver(observer) { |
| var observerInfo = observerInfoMap.get(observer); |
| if (IS_UNDEFINED(observerInfo)) |
| @@ -190,10 +228,13 @@ function SetupObjectObserve() { |
| %CheckIsBootstrapping(); |
| InstallFunctions($Object, DONT_ENUM, $Array( |
| "deliverChangeRecords", ObjectDeliverChangeRecords, |
| - "notify", ObjectNotify, // TODO: Remove when getNotifier is implemented. |
| + "getNotifier", ObjectGetNotifier, |
| "observe", ObjectObserve, |
| "unobserve", ObjectUnobserve |
| )); |
| + InstallFunctions(notifierPrototype, DONT_ENUM, $Array( |
| + "notify", ObjectNotifierNotify |
| + )); |
| } |
| SetupObjectObserve(); |