-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
/
watching.js
110 lines (97 loc) · 2.51 KB
/
watching.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/**
@module ember-metal
*/
import {
typeOf
} from "ember-metal/utils";
import {
removeChainWatcher,
flushPendingChains
} from "ember-metal/chains";
import {
watchKey,
unwatchKey
} from "ember-metal/watch_key";
import {
watchPath,
unwatchPath
} from "ember-metal/watch_path";
import {
isPath
} from "ember-metal/path_cache";
/**
Starts watching a property on an object. Whenever the property changes,
invokes `Ember.propertyWillChange` and `Ember.propertyDidChange`. This is the
primitive used by observers and dependent keys; usually you will never call
this method directly but instead use higher level methods like
`Ember.addObserver()`
@private
@method watch
@for Ember
@param obj
@param {String} keyName
*/
function watch(obj, _keyPath, m) {
// can't watch length on Array - it is special...
if (_keyPath === 'length' && typeOf(obj) === 'array') { return; }
if (!isPath(_keyPath)) {
watchKey(obj, _keyPath, m);
} else {
watchPath(obj, _keyPath, m);
}
}
export { watch };
export function isWatching(obj, key) {
var meta = obj['__ember_meta__'];
return (meta && meta.watching[key]) > 0;
}
watch.flushPending = flushPendingChains;
export function unwatch(obj, _keyPath, m) {
// can't watch length on Array - it is special...
if (_keyPath === 'length' && typeOf(obj) === 'array') { return; }
if (!isPath(_keyPath)) {
unwatchKey(obj, _keyPath, m);
} else {
unwatchPath(obj, _keyPath, m);
}
}
var NODE_STACK = [];
/**
Tears down the meta on an object so that it can be garbage collected.
Multiple calls will have no effect.
@method destroy
@for Ember
@param {Object} obj the object to destroy
@return {void}
*/
export function destroy(obj) {
var meta = obj['__ember_meta__'], node, nodes, key, nodeObject;
if (meta) {
obj['__ember_meta__'] = null;
// remove chainWatchers to remove circular references that would prevent GC
node = meta.chains;
if (node) {
NODE_STACK.push(node);
// process tree
while (NODE_STACK.length > 0) {
node = NODE_STACK.pop();
// push children
nodes = node._chains;
if (nodes) {
for (key in nodes) {
if (nodes.hasOwnProperty(key)) {
NODE_STACK.push(nodes[key]);
}
}
}
// remove chainWatcher in node object
if (node._watching) {
nodeObject = node._object;
if (nodeObject) {
removeChainWatcher(nodeObject, node._key, node);
}
}
}
}
}
}