Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: mojo/apps/js/bindings/codec.js

Issue 189453003: Moves around mojo js bindings code (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | mojo/apps/js/bindings/codec_unittests.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 define("mojo/apps/js/bindings/codec", function() {
6
7 // Memory -------------------------------------------------------------------
8
9 function store8(memory, pointer, val) {
10 memory[pointer] = val;
11 }
12
13 function store16(memory, pointer, val) {
14 memory[pointer + 0] = val >> 0;
15 memory[pointer + 1] = val >> 8;
16 }
17
18 function store32(memory, pointer, val) {
19 memory[pointer + 0] = val >> 0;
20 memory[pointer + 1] = val >> 8;
21 memory[pointer + 2] = val >> 16;
22 memory[pointer + 3] = val >> 24;
23 }
24
25 function store64(memory, pointer, val) {
26 store32(memory, pointer, val);
27 var high = (val / 0x10000) | 0;
28 store32(memory, pointer + 4, high);
29 }
30
31 function load8(memory, pointer) {
32 return memory[pointer];
33 }
34
35 function load16(memory, pointer) {
36 return (memory[pointer + 0] << 0) +
37 (memory[pointer + 1] << 8);
38 }
39
40 function load32(memory, pointer) {
41 return (memory[pointer + 0] << 0) +
42 (memory[pointer + 1] << 8) +
43 (memory[pointer + 2] << 16) +
44 (memory[pointer + 3] << 24);
45 }
46
47 var kAlignment = 8;
48
49 function align(size) {
50 return size + (kAlignment - (size % kAlignment)) % kAlignment;
51 }
52
53 // Buffer -------------------------------------------------------------------
54
55 function Buffer(size) {
56 this.memory = new Uint8Array(size);
57 this.next = 0;
58 }
59
60 Buffer.prototype.alloc = function(size) {
61 var pointer = this.next;
62 this.next += size;
63 if (this.next > this.memory.length) {
64 var newSize = (1.5 * (this.memory.length + size)) | 0;
65 this.grow(newSize);
66 }
67 return pointer;
68 };
69
70 Buffer.prototype.grow = function(size) {
71 var newMemory = new Uint8Array(size);
72 var oldMemory = this.memory;
73 for (var i = 0; i < oldMemory.length; ++i)
74 newMemory[i] = oldMemory[i];
75 this.memory = newMemory;
76 };
77
78 Buffer.prototype.createViewOfAllocatedMemory = function() {
79 return new Uint8Array(this.memory.buffer, 0, this.next);
80 };
81
82 // Constants ----------------------------------------------------------------
83
84 var kArrayHeaderSize = 8;
85 var kStructHeaderSize = 8;
86 var kMessageHeaderSize = 8;
87
88 // Decoder ------------------------------------------------------------------
89
90 function Decoder(memory, handles, base) {
91 this.memory = memory;
92 this.handles = handles;
93 this.base = base;
94 this.next = base;
95 this.viewU32 = new Uint32Array(
96 this.memory.buffer, 0,
97 Math.floor(this.memory.length / Uint32Array.BYTES_PER_ELEMENT));
98 this.viewFloat = new Float32Array(
99 this.memory.buffer, 0,
100 Math.floor(this.memory.length / Float32Array.BYTES_PER_ELEMENT));
101 }
102
103 Decoder.prototype.skip = function(offset) {
104 this.next += offset;
105 };
106
107 Decoder.prototype.read8 = function() {
108 var result = load8(this.memory, this.next);
109 this.next += 1;
110 return result;
111 };
112
113 Decoder.prototype.read32 = function() {
114 var result = this.viewU32[this.next / this.viewU32.BYTES_PER_ELEMENT];
115 this.next += this.viewU32.BYTES_PER_ELEMENT;
116 return result;
117 };
118
119 Decoder.prototype.read64 = function() {
120 var low = this.read32();
121 var high = this.read32();
122 return low + high * 0x100000000;
123 };
124
125 Decoder.prototype.decodeFloat = function() {
126 var result = this.viewFloat[this.next / this.viewFloat.BYTES_PER_ELEMENT];
127 this.next += this.viewFloat.BYTES_PER_ELEMENT;
128 return result;
129 };
130
131 Decoder.prototype.decodePointer = function() {
132 // TODO(abarth): To correctly decode a pointer, we need to know the real
133 // base address of the array buffer.
134 var offsetPointer = this.next;
135 var offset = this.read64();
136 if (!offset)
137 return 0;
138 return offsetPointer + offset;
139 };
140
141 Decoder.prototype.decodeAndCreateDecoder = function() {
142 return new Decoder(this.memory, this.handles, this.decodePointer());
143 };
144
145 Decoder.prototype.decodeHandle = function() {
146 return this.handles[this.read32()];
147 };
148
149 Decoder.prototype.decodeString = function() {
150 // TODO(abarth): We should really support UTF-8. We might want to
151 // jump out of the VM to decode the string directly from the array
152 // buffer using v8::String::NewFromUtf8.
153 var numberOfBytes = this.read32();
154 var numberOfElements = this.read32();
155 var val = new Array(numberOfElements);
156 var memory = this.memory;
157 var base = this.next;
158 for (var i = 0; i < numberOfElements; ++i) {
159 val[i] = String.fromCharCode(memory[base + i] & 0x7F);
160 }
161 this.next += numberOfElements;
162 return val.join('');
163 };
164
165 Decoder.prototype.decodeArray = function(cls) {
166 var numberOfBytes = this.read32();
167 var numberOfElements = this.read32();
168 var val = new Array(numberOfElements);
169 for (var i = 0; i < numberOfElements; ++i) {
170 val[i] = cls.decode(this);
171 }
172 return val;
173 };
174
175 Decoder.prototype.decodeStructPointer = function(cls) {
176 return cls.decode(this.decodeAndCreateDecoder());
177 };
178
179 Decoder.prototype.decodeArrayPointer = function(cls) {
180 return this.decodeAndCreateDecoder().decodeArray(cls);
181 };
182
183 Decoder.prototype.decodeStringPointer = function() {
184 return this.decodeAndCreateDecoder().decodeString();
185 };
186
187 // Encoder ------------------------------------------------------------------
188
189 function Encoder(buffer, handles, base) {
190 this.buffer = buffer;
191 this.handles = handles;
192 this.base = base;
193 this.next = base;
194 }
195
196 Encoder.prototype.skip = function(offset) {
197 this.next += offset;
198 };
199
200 Encoder.prototype.write8 = function(val) {
201 store8(this.buffer.memory, this.next, val);
202 this.next += 1;
203 };
204
205 Encoder.prototype.write32 = function(val) {
206 store32(this.buffer.memory, this.next, val);
207 this.next += 4;
208 };
209
210 Encoder.prototype.write64 = function(val) {
211 store64(this.buffer.memory, this.next, val);
212 this.next += 8;
213 };
214
215 Encoder.prototype.encodeFloat = function(val) {
216 var floatBuffer = new Float32Array(1);
217 floatBuffer[0] = val;
218 var buffer = new Uint8Array(floatBuffer.buffer, 0);
219 for (var i = 0; i < buffer.length; ++i)
220 this.buffer.memory[this.next++] = buffer[i];
221 };
222
223 Encoder.prototype.encodePointer = function(pointer) {
224 if (!pointer)
225 return this.write64(0);
226 // TODO(abarth): To correctly encode a pointer, we need to know the real
227 // base address of the array buffer.
228 var offset = pointer - this.next;
229 this.write64(offset);
230 };
231
232 Encoder.prototype.createAndEncodeEncoder = function(size) {
233 var pointer = this.buffer.alloc(align(size));
234 this.encodePointer(pointer);
235 return new Encoder(this.buffer, this.handles, pointer);
236 };
237
238 Encoder.prototype.encodeHandle = function(handle) {
239 this.handles.push(handle);
240 this.write32(this.handles.length - 1);
241 };
242
243 Encoder.prototype.encodeString = function(val) {
244 var numberOfElements = val.length;
245 var numberOfBytes = kArrayHeaderSize + numberOfElements;
246 this.write32(numberOfBytes);
247 this.write32(numberOfElements);
248 // TODO(abarth): We should really support UTF-8. We might want to
249 // jump out of the VM to encode the string directly from the array
250 // buffer using v8::String::WriteUtf8.
251 var memory = this.buffer.memory;
252 var base = this.next;
253 var len = val.length;
254 for (var i = 0; i < len; ++i) {
255 memory[base + i] = val.charCodeAt(i) & 0x7F;
256 }
257 this.next += len;
258 };
259
260 Encoder.prototype.encodeArray = function(cls, val) {
261 var numberOfElements = val.length;
262 var numberOfBytes = kArrayHeaderSize + cls.encodedSize * numberOfElements;
263 this.write32(numberOfBytes);
264 this.write32(numberOfElements);
265 for (var i = 0; i < numberOfElements; ++i) {
266 cls.encode(this, val[i]);
267 }
268 };
269
270 Encoder.prototype.encodeStructPointer = function(cls, val) {
271 var encoder = this.createAndEncodeEncoder(cls.encodedSize);
272 cls.encode(encoder, val);
273 };
274
275 Encoder.prototype.encodeArrayPointer = function(cls, val) {
276 var encodedSize = kArrayHeaderSize + cls.encodedSize * val.length;
277 var encoder = this.createAndEncodeEncoder(encodedSize);
278 encoder.encodeArray(cls, val);
279 };
280
281 Encoder.prototype.encodeStringPointer = function(val) {
282 // TODO(abarth): This won't be right once we support UTF-8.
283 var encodedSize = kArrayHeaderSize + val.length;
284 var encoder = this.createAndEncodeEncoder(encodedSize);
285 encoder.encodeString(val);
286 };
287
288 // Message ------------------------------------------------------------------
289
290 function Message(memory, handles) {
291 this.memory = memory;
292 this.handles = handles;
293 }
294
295 // MessageBuilder -----------------------------------------------------------
296
297 function MessageBuilder(messageName, payloadSize) {
298 // Currently, we don't compute the payload size correctly ahead of time.
299 // Instead, we overwrite this field at the end.
300 var numberOfBytes = kMessageHeaderSize + payloadSize;
301 this.buffer = new Buffer(numberOfBytes);
302 this.handles = [];
303 var encoder = this.createEncoder(kMessageHeaderSize);
304 encoder.write32(numberOfBytes);
305 encoder.write32(messageName);
306 }
307
308 MessageBuilder.prototype.createEncoder = function(size) {
309 var pointer = this.buffer.alloc(size);
310 return new Encoder(this.buffer, this.handles, pointer);
311 }
312
313 MessageBuilder.prototype.encodeStruct = function(cls, val) {
314 cls.encode(this.createEncoder(cls.encodedSize), val);
315 };
316
317 MessageBuilder.prototype.finish = function() {
318 // TODO(abarth): Rather than resizing the buffer at the end, we could
319 // compute the size we need ahead of time, like we do in C++.
320 var memory = this.buffer.createViewOfAllocatedMemory();
321 store32(memory, 0, memory.length);
322 var message = new Message(memory, this.handles);
323 this.buffer = null;
324 this.handles = null;
325 this.encoder = null;
326 return message;
327 };
328
329 // MessageReader ------------------------------------------------------------
330
331 function MessageReader(message) {
332 this.decoder = new Decoder(message.memory, message.handles, 0);
333 this.payloadSize = this.decoder.read32() - kMessageHeaderSize;
334 this.messageName = this.decoder.read32();
335 }
336
337 MessageReader.prototype.decodeStruct = function(cls) {
338 return cls.decode(this.decoder);
339 };
340
341 // Built-in types -----------------------------------------------------------
342
343 function Uint8() {
344 }
345
346 Uint8.encodedSize = 1;
347
348 Uint8.decode = function(decoder) {
349 return decoder.read8();
350 };
351
352 Uint8.encode = function(encoder, val) {
353 encoder.write8(val);
354 };
355
356 function Uint16() {
357 }
358
359 Uint16.encodedSize = 2;
360
361 Uint16.decode = function(decoder) {
362 return decoder.read16();
363 };
364
365 Uint16.encode = function(encoder, val) {
366 encoder.write16(val);
367 };
368
369 function Uint32() {
370 }
371
372 Uint32.encodedSize = 4;
373
374 Uint32.decode = function(decoder) {
375 return decoder.read32();
376 };
377
378 Uint32.encode = function(encoder, val) {
379 encoder.write32(val);
380 };
381
382 function Uint64() {
383 };
384
385 Uint64.encodedSize = 8;
386
387 Uint64.decode = function(decoder) {
388 return decoder.read64();
389 };
390
391 Uint64.encode = function(encoder, val) {
392 encoder.write64(val);
393 };
394
395 function PointerTo(cls) {
396 this.cls = cls;
397 };
398
399 // TODO(abarth): Add missing types:
400 // * String
401 // * Float
402 // * Double
403 // * Signed integers
404
405 PointerTo.prototype.encodedSize = 8;
406
407 PointerTo.prototype.decode = function(decoder) {
408 return this.cls.decode(decoder.decodeAndCreateDecoder());
409 };
410
411 PointerTo.prototype.encode = function(encoder, val) {
412 var objectEncoder = encoder.createAndEncodeEncoder(this.cls.encodedSize);
413 this.cls.encode(objectEncoder, val);
414 };
415
416 function ArrayOf(cls) {
417 this.cls = cls;
418 };
419
420 ArrayOf.prototype.encodedSize = 8;
421
422 ArrayOf.prototype.decode = function(decoder) {
423 return decoder.decodeArrayPointer(self.cls);
424 };
425
426 ArrayOf.prototype.encode = function(encoder, val) {
427 encoder.encodeArrayPointer(self.cls, val);
428 };
429
430 function Handle() {
431 }
432
433 Handle.encodedSize = 4;
434
435 Handle.decode = function(decoder) {
436 return decoder.decodeHandle();
437 };
438
439 Handle.encode = function(encoder, val) {
440 encoder.encodeHandle(val);
441 };
442
443 var exports = {};
444 exports.align = align;
445 exports.Message = Message;
446 exports.MessageBuilder = MessageBuilder;
447 exports.MessageReader = MessageReader;
448 exports.kArrayHeaderSize = kArrayHeaderSize;
449 exports.kStructHeaderSize = kStructHeaderSize;
450 exports.kMessageHeaderSize = kMessageHeaderSize;
451 exports.Uint8 = Uint8;
452 exports.Uint16 = Uint16;
453 exports.Uint32 = Uint32;
454 exports.Uint64 = Uint64;
455 exports.PointerTo = PointerTo;
456 exports.ArrayOf = ArrayOf;
457 exports.Handle = Handle;
458 return exports;
459 });
OLDNEW
« no previous file with comments | « no previous file | mojo/apps/js/bindings/codec_unittests.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698