Index: src/object-observe.js |
diff --git a/src/object-observe.js b/src/object-observe.js |
index 086159f9cb81db03ecfa87ec87a1a4fdb588e4ef..28aa1f4e4e988caf624efcfd72df9c5d83325e30 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, |
+ 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_SPEC_OBJECT(this)) |
+ throw MakeTypeError("called_on_non_object", ["notify"]); |
+ |
+ var target = notifierTargetMap.get(this); |
+ if (IS_UNDEFINED(target)) |
+ throw MakeTypeError("observe_notify_non_notifier"); |
+ |
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(); |