-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
256 lines (214 loc) · 8.55 KB
/
index.html
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSON 3</title>
<link rel="stylesheet" href="page/style.css" media="screen">
</head>
<body>
<ul id="navigation">
</ul>
<div id="content">
<h2>Kamino.js</h2>
<blockquote>
<p><em>Kamino (pronounced /kə'minoʊ/), called Planet of Storms, was the
watery world where the Clone Army for the Galactic Republic was created,
as well as the Kamino Home Fleet. It was inhabited by a race of tall,
elegant beings called the Kaminoans, who kept to themselves and were
known for their cloning technology.</em>
</p>
<p>—<a href="http://starwars.wikia.com/wiki/Kamino">Wookiepedia</a>
</p>
</blockquote>
<p>Kamino.js is a library for passing data structures between sandboxed
environments in the browser via <code>postMessage</code>. While newer browsers
implement this automatically, older browsers only allow string
arguments. Kamino.js serializes JavaScript data structures into a string
that can be reconstituted on the other side.
</p>
<p>In keeping with the Unix philosophy, it is a modular library that does
one thing and does it well.
</p>
<p><em>"Why not just use JSON.stringify and JSON.parse?,"</em> I hear you asking.
Great question.
</p>
<p>Kamino.js implements the <a href="http://www.w3.org/TR/html5/common-dom-interfaces.html#safe-passing-of-structured-data"><em>structured clone algorithm</em> described in the
HTML5
specification</a>.
The structured clone algorithm supports more complicated data structures
than the limited subset JSON does. (See <em>Differences from JSON</em>, below.)
</p>
<p>Within the constraints of what's possible with
JavaScript (see <em>Limitations</em>, below), you will get the same results
with Kamino.js as you would by using the built-in structured clone
behavior in newer browsers.
</p>
<p>This means you can feel free to pass objects as rich as you'd like, and
not be limited to the restricted subset JSON allows.
</p>
<h3>Usage</h3>
<p>Kamino.js works just like <code>JSON</code>. To create a string representation of
an object, call <code>Kamino.stringify</code>:
</p>
<pre><code class="lang-javascript">var message = {
name: 'authorAdded',
data: {
name: "Yehuda Katz",
age: 30
}
};
var serialized = Kamino.stringify(message);
window.parent.postMessage(serialized, '*');</code></pre>
<p>On the receiving end, deserialize using <code>Kamino.parse</code>:
</p>
<pre><code class="lang-javascript">window.addEventListener('message', function(event) {
var message = Kamino.parse(event.data);
var name = message.name;
var data = message.data;
console.log('Got message ' + name + ' with data ', data);
});</code></pre>
<p>If you're not crossing memory boundaries, Kamino.js includes a shorthand
for creating a structured clone:
</p>
<pre><code class="lang-javascript">var clone = Kamino.clone(object);</code></pre>
<p>Note that this is just shorthand for:
</p>
<pre><code class="lang-javascript">Kamino.parse(Kamino.stringify(object));</code></pre>
<p>Because it involves a serialization/deserialization roundtrip, there are
probably more memory- and CPU-efficient ways to create clones in the
same memory space.
</p>
<h3>Differences from JSON</h3>
<h4>Additional Primitive Support</h4>
<p>JSON supports a very narrow subset of primitive types: strings, numbers,
<code>null</code>, arrays, and objects. If you try to serialize other types, they
will be converted to <code>null</code> (like <code>Infinity</code> or <code>NaN</code>) or to a string
(<code>Date</code>s) that must be manually deserialized on the other side.
</p>
<p>In addition to the types supported by JSON, Kamino.js supports:
</p>
<ul>
<li><code>Infinity</code></li>
<li><code>-Infinity</code></li>
<li><code>NaN</code></li>
<li><code>undefined</code></li>
<li><code>Boolean</code> objects (<code>new Boolean(true)</code> vs. the primitive <code>true</code>)</li>
<li><code>Date</code> objects</li>
<li><code>RegExp</code> objects</li>
</ul>
<h4>Identity Preservation</h4>
<p>In JSON, if an object or array contains multiple references to the same
object, the fact that they are the same object is lost during
serialization.
</p>
<pre><code class="lang-javascript">var person = {
firstName: "Tom",
lastName: "Dale"
};
var blog = {
administrator: person,
author: person
};
blog.administrator === blog.author; // true
var jsonClone = JSON.parse(JSON.stringify((blog));
jsonClone.administrator === jsonClone.author; // false</code></pre>
<p>When Kamino.js serializes an object, it includes information about the
identity of objects. If the same object is used multiple times in the
same serialized graph, its identity will be preserved during
deserialization.
</p>
<pre><code class="lang-javascript">var kaminoClone = Kamino.clone(blog);
kaminoClone.administrator === kaminoClone.author; // true</code></pre>
<h4>Circular References</h4>
<p>Because of the identity support described above, it is no problem at all
to pass an object with circular references:
</p>
<pre><code class="lang-javascript">var parent = {};
var child = {};
parent.child = child;
child.parent = parent;
JSON.stringify(parent);
// TypeError: Converting circular structure to JSON
Kamino.stringify(parent);
// OK!</code></pre>
<h3>Limitations</h3>
<h4>Structured Algorithm Limitations</h4>
<p>Some limitations of Kamino.js are inherent to the structured clone
algorithm itself.
</p>
<h6>Restricted Types</h6>
<p>For security reasons, you are not allowed to clone <code>Error</code>, <code>Function</code>
or <code>Element</code> objects. Doing so will raise a <code>DATA_CLONE_ERR</code> exception.
</p>
<h6>Imperfect Clones</h6>
<p>Property descriptors, getters, and setters are not preserved when
cloning objects, nor is the prototype chain.
</p>
<pre><code class="lang-javascript">var Person = function(name) {
this.name = name;
};
Person.prototype.isPerson = true;
var patrick = new Person("Patrick Gibson");
patrick.name;
// "Patrick Gibson"
patrick.isPerson;
// true
var clone = Kamino.clone(patrick);
clone.name;
// "Patrick Gibson"
clone.isPerson;
// undefined</code></pre>
<h4>Kamino.js Limitations</h4>
<p>Some parts of the structured algorithm specification rely on being able
to manually manage memory in the VM, which is not exposed to JavaScript.
Therefore, you should note these limitations when using Kamino.js.
</p>
<h5>Performance</h5>
<p>Because the native browser implementation of the structured clone
algorithm is able to copy the objects from one memory space to another
directly, it will always have a performance benefit over Kamino.js,
which must serialize to an intermediate string format.
</p>
<p>For most uses, the performance difference should be negligible. But you
should keep it in mind if transferring extremely large data structures.
</p>
<h5>Transferable Objects</h5>
<p>From the W3C specification:
</p>
<blockquote>
<p>Some objects support being copied and closed in one operation. This
is called transferring the object, and is used in particular to
transfer ownership of unsharable or expensive resources across worker
boundaries.
</p>
</blockquote>
<p>Because there is no API for allowing us to neuter objects, or transfer
objects from one memory space to another, this feature is not supported
in Kamino.js and will raise an error.
</p>
<h5>Compatibility</h5>
<p>It is important to note that <strong>the Kamino.js serialization format is not
designed to serve as a data interchange.</strong> It is extremely
hardcoded to JavaScript semantics and is not intended to be used in
environments outside of the browser. If you would like to pass messages
across different environments, please use JSON instead!
</p>
<p>Kamino.js is designed to be used for immediate serialization and
deserialization across memory boundaries within the same browser
context. <strong>Any other use is at your own risk.</strong>
</p>
<p>Additionally, the Kamino.js serialization format, while based on JSON,
has not undergone the same level of scrutiny and standardization. The
serialized output from <code>Kamino.stringify</code> is intended to be consumed
<em>only</em> by <code>Kamino.parse</code>. I am happy to more rigorously specify the
serialization format if there is community interest, but in the
meantime, you should only use Kamino.js to generate and consume the
serialized forms, and until a version 1.0 is released I reserve the
right to make breaking changes to the serialization format.
</p>
</div>
<div id="footer">
<p>© 2012 <a href="http://kitcambridge.github.com">Kit Cambridge</a>.</p>
</div>
</body>
</html>