-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
169 lines (128 loc) · 5.22 KB
/
atom.xml
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[Category: ember-metal | machty's thoughtz]]></title>
<link href="http://machty.github.com/blog/categories/ember-metal/atom.xml" rel="self"/>
<link href="http://machty.github.com/"/>
<updated>2015-08-26T16:10:13-04:00</updated>
<id>http://machty.github.com/</id>
<author>
<name><![CDATA[Alex Matchneer]]></name>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[Ember Meta]]></title>
<link href="http://machty.github.com/blog/2014/05/31/ember-meta/"/>
<updated>2014-05-31T07:27:00-04:00</updated>
<id>http://machty.github.com/blog/2014/05/31/ember-meta</id>
<content type="html"><![CDATA[<h3>Ember Meta</h3>
<p><em>This will start off in my typical meandering daily journal form and
hopefully evolve into something good enough for an ARCHITECTURE.md</em></p>
<p>Ember's internals make heavy use of meta objects, which are generated
and attached to objects in order to keep track of bindings, computed
properties, observers, and all sorts of other things evolving Ember magic.</p>
<h4><code>EMPTY_META</code></h4>
<p><code>EMPTY_META</code> is a default, empty meta object that represents an object
with no observers, bindings, or computed properties.</p>
<p><code>Ember.meta</code> is the function that takes an object and returns its meta
object; asking Ember.meta for a read-only meta object for a POJO
will return <code>Ember.EMPTY_META</code></p>
<pre><code>Ember.meta({}, false) === Ember.EMPTY_META // true
http://emberjs.jsbin.com/ucanam/5173/edit
</code></pre>
<p>This is an optimization that lets us pretend as if every object in
Emberland had a meta object, simplifying our binding/observer algorithms
while not wastefully generating meta objects for objects that don't need
their own separate copies. It's a form of copy-on-write.</p>
<pre><code>var pojo = {
foo: 'wat'
};
console.assert(Ember.meta(pojo, false) === Ember.EMPTY_META);
// Add a computed property, which requires writing to meta.
Ember.defineProperty(pojo, 'fooAlias', Ember.computed.alias('foo'));
console.assert(Ember.get(pojo, 'foo') === 'wat');
var newMeta = Ember.meta(pojo, false)
console.assert(newMeta !== Ember.EMPTY_META);
// http://emberjs.jsbin.com/ucanam/5176/edit
</code></pre>
<h4><code>META_DESC</code></h4>
<p>This is the ES5 descriptor for the property stashed on an object that
points to its meta object:</p>
<pre><code>{
writable: true,
configurable: false,
enumerable: false,
value: null
};
</code></pre>
<p>This makes the property non-enumerable, which is why the meta object
won't show up when iterating over an object with <code>for..in</code>.</p>
<h4>Meta obj structure</h4>
<p><code>EMPTY_META</code> is just <code>new Meta(null)</code>, and here's the meta structure:</p>
<pre><code>Meta.prototype = {
// Set to {} by constructor
// dictionary of all Ember.Descriptor properties
// defined on for the obj, e.g computed properties
descs: null,
// dictionary of properties on the object that are
// being observed, where the key is the observed
// property name and the value is the number of
// active observers of this property.
// e.g. meta.watching.foo === 2 means that two
// observers are watching obj.foo for changes.
watching: null,
// TODO
cache: null,
// TODO
cacheMeta: null,
// The owner of this meta object; important to keep track
// of because when prototypal inheritance is involved, a
// child object will initially point to the same meta obj
// as its prototype, even though they should have separate
// meta obj. `Ember.meta()` detects this by checking to see
// if meta.source equals the passed in object, and if not,
// it generates a new meta object
source: null,
// Left as null by constructor
deps: null,
listeners: null,
mixins: null,
bindings: null,
chains: null,
chainWatchers: null,
values: null,
// The prototype of source
// meta.proto.isPrototypeOf(meta.source) // true
proto: null
};
// ret = o_create(ret);
// ret.descs = o_create(ret.descs);
// why is this o_create?
// if proto.foo is being watched, and obj.foo is overwritten
// to some other value, then it's definitely disconnected at
// that point, right? Even if it's not overwritten, if you have
//
// proto = {
// }
//
// ret.watching = o_create(ret.watching);
// ret.cache = {};
// ret.cacheMeta = {};
// ret.source = obj;
// TODO: categorize this realization
// removeDependentKeys calls iterDeps, which loops
// over deps[propName] > 0,
// and then the cp.didChange method decrements
// the deps in the meta in removeDependentKeys();
// this method is called in two places:
// - didChange()
// - teardown()
//
// note that it doesn't do this for non-cacheables CPs.
</code></pre>
<p>If CP#didChange removes dependent keys, who adds it back in template situations?
The view that was installed will call get() on that CP, and .get() on a cacheable property will call addDependentKeys</p>
<p>So the rule is that if you want an observer be/stay alive, you need to
call get on that changed prop. AH HA.</p>
]]></content>
</entry>
</feed>