@@ -32,7 +32,7 @@ var ArrayProxy = Object.create(Array.prototype)
32
32
methods . forEach ( function ( method ) {
33
33
def ( ArrayProxy , method , function ( ) {
34
34
var result = Array . prototype [ method ] . apply ( this , arguments )
35
- this . __observer__ . emit ( 'mutate' , this . __observer__ . path , this , {
35
+ this . __observer__ . emit ( 'mutate' , null , this , {
36
36
method : method ,
37
37
args : slice . call ( arguments ) ,
38
38
result : result
@@ -109,13 +109,12 @@ function watchObject (obj) {
109
109
* Watch an Array, overload mutation methods
110
110
* and add augmentations by intercepting the prototype chain
111
111
*/
112
- function watchArray ( arr , path ) {
112
+ function watchArray ( arr ) {
113
113
var observer = arr . __observer__
114
114
if ( ! observer ) {
115
115
observer = new Emitter ( )
116
116
def ( arr , '__observer__' , observer )
117
117
}
118
- observer . path = path
119
118
if ( hasProto ) {
120
119
arr . __proto__ = ArrayProxy
121
120
} else {
@@ -252,46 +251,61 @@ function ensurePath (obj, key) {
252
251
* Observe an object with a given path,
253
252
* and proxy get/set/mutate events to the provided observer.
254
253
*/
255
- function observe ( obj , rawPath , observer ) {
254
+ function observe ( obj , rawPath , parentOb ) {
255
+
256
256
if ( ! isWatchable ( obj ) ) return
257
+
257
258
var path = rawPath ? rawPath + '.' : '' ,
258
- ob , alreadyConverted = ! ! obj . __observer__
259
+ alreadyConverted = ! ! obj . __observer__ ,
260
+ childOb
261
+
259
262
if ( ! alreadyConverted ) {
260
263
def ( obj , '__observer__' , new Emitter ( ) )
261
264
}
262
- ob = obj . __observer__
263
- ob . values = ob . values || utils . hash ( )
264
- observer . proxies = observer . proxies || { }
265
- var proxies = observer . proxies [ path ] = {
265
+
266
+ childOb = obj . __observer__
267
+ childOb . values = childOb . values || utils . hash ( )
268
+
269
+ // setup proxy listeners on the parent observer.
270
+ // we need to keep reference to them so that they
271
+ // can be removed when the object is un-observed.
272
+ parentOb . proxies = parentOb . proxies || { }
273
+ var proxies = parentOb . proxies [ path ] = {
266
274
get : function ( key ) {
267
- observer . emit ( 'get' , path + key )
275
+ parentOb . emit ( 'get' , path + key )
268
276
} ,
269
277
set : function ( key , val , propagate ) {
270
- observer . emit ( 'set' , path + key , val )
278
+ parentOb . emit ( 'set' , path + key , val )
271
279
// also notify observer that the object itself changed
272
280
// but only do so when it's a immediate property. this
273
281
// avoids duplicate event firing.
274
282
if ( rawPath && propagate ) {
275
- observer . emit ( 'set' , rawPath , obj , true )
283
+ parentOb . emit ( 'set' , rawPath , obj , true )
276
284
}
277
285
} ,
278
286
mutate : function ( key , val , mutation ) {
279
287
// if the Array is a root value
280
288
// the key will be null
281
289
var fixedPath = key ? path + key : rawPath
282
- observer . emit ( 'mutate' , fixedPath , val , mutation )
290
+ parentOb . emit ( 'mutate' , fixedPath , val , mutation )
283
291
// also emit set for Array's length when it mutates
284
292
var m = mutation . method
285
293
if ( m !== 'sort' && m !== 'reverse' ) {
286
- observer . emit ( 'set' , fixedPath + '.length' , val . length )
294
+ parentOb . emit ( 'set' , fixedPath + '.length' , val . length )
287
295
}
288
296
}
289
297
}
290
- ob
298
+
299
+ // attach the listeners to the child observer.
300
+ // now all the events will propagate upwards.
301
+ childOb
291
302
. on ( 'get' , proxies . get )
292
303
. on ( 'set' , proxies . set )
293
304
. on ( 'mutate' , proxies . mutate )
305
+
294
306
if ( alreadyConverted ) {
307
+ // for objects that have already been converted,
308
+ // emit set events for everything inside
295
309
emitSet ( obj )
296
310
} else {
297
311
var type = typeOf ( obj )
@@ -307,14 +321,20 @@ function observe (obj, rawPath, observer) {
307
321
* Cancel observation, turn off the listeners.
308
322
*/
309
323
function unobserve ( obj , path , observer ) {
324
+
310
325
if ( ! obj || ! obj . __observer__ ) return
326
+
311
327
path = path ? path + '.' : ''
312
328
var proxies = observer . proxies [ path ]
313
329
if ( ! proxies ) return
330
+
331
+ // turn off listeners
314
332
obj . __observer__
315
333
. off ( 'get' , proxies . get )
316
334
. off ( 'set' , proxies . set )
317
335
. off ( 'mutate' , proxies . mutate )
336
+
337
+ // remove reference
318
338
observer . proxies [ path ] = null
319
339
}
320
340
0 commit comments