70452402 by Michael Richards

Implement basic array mutation observing in the default adapter.

1 parent 7ad15ba1
...@@ -6,22 +6,53 @@ Rivets.adapters['.'] = ...@@ -6,22 +6,53 @@ Rivets.adapters['.'] =
6 counter: 0 6 counter: 0
7 weakmap: {} 7 weakmap: {}
8 8
9 subscribe: (obj, keypath, callback) -> 9 weakReference: (obj) ->
10 unless obj[@id]? 10 unless obj[@id]?
11 id = @counter++ 11 id = @counter++
12 12
13 Object.defineProperty obj, @id, 13 @weakmap[id] =
14 enumerable: false 14 callbacks: {}
15 configurable: false 15
16 writable: false 16 Object.defineProperty obj, @id, value: id
17 value: id 17
18 @weakmap[obj[@id]]
19
20 stubFunction: (obj, fn) ->
21 original = obj[fn]
22 map = @weakReference obj
23 weakmap = @weakmap
24
25 obj[fn] = ->
26 response = original.apply obj, arguments
27
28 for r, k of map.pointers
29 callback() for callback in weakmap[r]?.callbacks[k] ? []
30
31 response
18 32
19 @weakmap[id] = {} 33 observeMutations: (obj, ref, keypath) ->
34 if Object.prototype.toString.call(obj) is '[object Array]'
35 map = @weakReference obj
20 36
21 map = @weakmap[obj[@id]] 37 unless map.pointers?
38 map.pointers = {}
39 functions = ['push', 'pop', 'shift', 'unshift', 'sort', 'reverse', 'splice']
40 @stubFunction obj, fn for fn in functions
22 41
23 unless map[keypath]? 42 map.pointers[ref] ?= []
24 map[keypath] = [] 43
44 unless keypath in map.pointers[ref]
45 map.pointers[ref].push keypath
46
47 unobserveMutations: (obj, ref, keypath) ->
48 if keyapths = @weakReference(obj).pointers?[ref]
49 keypaths.splice keypaths.indexOf(keypath), 1
50
51 subscribe: (obj, keypath, callback) ->
52 callbacks = @weakReference(obj).callbacks
53
54 unless callbacks[keypath]?
55 callbacks[keypath] = []
25 value = obj[keypath] 56 value = obj[keypath]
26 57
27 Object.defineProperty obj, keypath, 58 Object.defineProperty obj, keypath,
...@@ -29,14 +60,17 @@ Rivets.adapters['.'] = ...@@ -29,14 +60,17 @@ Rivets.adapters['.'] =
29 set: (newValue) -> 60 set: (newValue) ->
30 if newValue isnt value 61 if newValue isnt value
31 value = newValue 62 value = newValue
32 callback() for callback in map[keypath] 63 callback() for callback in callbacks[keypath]
64
65 unless callback in callbacks[keypath]
66 callbacks[keypath].push callback
33 67
34 unless callback in map[keypath] 68 @observeMutations obj[keypath], obj[@id], keypath
35 map[keypath].push callback
36 69
37 unsubscribe: (obj, keypath, callback) -> 70 unsubscribe: (obj, keypath, callback) ->
38 callbacks = @weakmap[obj[@id]][keypath] 71 callbacks = @weakmap[obj[@id]].callbacks[keypath]
39 callbacks.splice callbacks.indexOf(callback), 1 72 callbacks.splice callbacks.indexOf(callback), 1
73 @observeMutations obj[keypath], obj[@id], keypath
40 74
41 read: (obj, keypath) -> 75 read: (obj, keypath) ->
42 obj[keypath] 76 obj[keypath]
......