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

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

Issue 100573003: [Mojo] Move JS bindings out of public (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix header guards Created 7 years 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 | « mojo/public/bindings/js/DEPS ('k') | mojo/public/bindings/js/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(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 function load64(memory, pointer) {
48 var low = load32(memory, pointer);
49 var high = load32(memory, pointer + 4);
50 return low + high * 0x10000;
51 }
52
53 var kAlignment = 8;
54
55 function align(size) {
56 return size + (kAlignment - (size % kAlignment)) % kAlignment;
57 }
58
59 // Buffer -------------------------------------------------------------------
60
61 function Buffer(size) {
62 this.memory = new Uint8Array(size);
63 this.next = 0;
64 }
65
66 Buffer.prototype.alloc = function(size) {
67 var pointer = this.next;
68 this.next += size;
69 if (this.next > this.memory.length) {
70 var newSize = (1.5 * (this.memory.length + size)) | 0;
71 this.grow(newSize);
72 }
73 return pointer;
74 };
75
76 Buffer.prototype.grow = function(size) {
77 var newMemory = new Uint8Array(size);
78 var oldMemory = this.memory;
79 for (var i = 0; i < oldMemory.length; ++i)
80 newMemory[i] = oldMemory[i];
81 this.memory = newMemory;
82 };
83
84 Buffer.prototype.createViewOfAllocatedMemory = function() {
85 return new Uint8Array(this.memory.buffer, 0, this.next);
86 };
87
88 // Constants ----------------------------------------------------------------
89
90 var kArrayHeaderSize = 8;
91 var kStructHeaderSize = 8;
92 var kMessageHeaderSize = 8;
93
94 // Decoder ------------------------------------------------------------------
95
96 function Decoder(memory, handles, base) {
97 this.memory = memory;
98 this.handles = handles;
99 this.base = base;
100 this.next = base;
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 = load32(this.memory, this.next);
115 this.next += 4;
116 return result;
117 };
118
119 Decoder.prototype.read64 = function() {
120 var result = load64(this.memory, this.next);
121 this.next += 8;
122 return result;
123 };
124
125 Decoder.prototype.decodePointer = function() {
126 // TODO(abarth): To correctly decode a pointer, we need to know the real
127 // base address of the array buffer.
128 var offsetPointer = this.next;
129 var offset = this.read64();
130 if (!offset)
131 return 0;
132 return offsetPointer + offset;
133 };
134
135 Decoder.prototype.decodeAndCreateDecoder = function() {
136 return new Decoder(this.memory, this.handles, this.decodePointer());
137 };
138
139 Decoder.prototype.decodeHandle = function() {
140 return this.handles[this.read32()];
141 };
142
143 Decoder.prototype.decodeString = function() {
144 // TODO(abarth): We should really support UTF-8. We might want to
145 // jump out of the VM to decode the string directly from the array
146 // buffer using v8::String::NewFromUtf8.
147 var numberOfBytes = this.read32();
148 var numberOfElements = this.read32();
149 var val = new Array(numberOfElements);
150 var memory = this.memory;
151 var base = this.next;
152 for (var i = 0; i < numberOfElements; ++i) {
153 val[i] = String.fromCharCode(memory[base + i] & 0x7F);
154 }
155 this.next += numberOfElements;
156 return val.join('');
157 };
158
159 Decoder.prototype.decodeArray = function(cls) {
160 var numberOfBytes = this.read32();
161 var numberOfElements = this.read32();
162 var val = new Array(numberOfElements);
163 for (var i = 0; i < numberOfElements; ++i) {
164 val[i] = cls.decode(this);
165 }
166 return val;
167 };
168
169 Decoder.prototype.decodeStructPointer = function(cls) {
170 return cls.decode(this.decodeAndCreateDecoder());
171 };
172
173 Decoder.prototype.decodeArrayPointer = function(cls) {
174 return this.decodeAndCreateDecoder().decodeArray(cls);
175 };
176
177 Decoder.prototype.decodeStringPointer = function() {
178 return this.decodeAndCreateDecoder().decodeString();
179 };
180
181 // Encoder ------------------------------------------------------------------
182
183 function Encoder(buffer, handles, base) {
184 this.buffer = buffer;
185 this.handles = handles;
186 this.base = base;
187 this.next = base;
188 }
189
190 Encoder.prototype.skip = function(offset) {
191 this.next += offset;
192 };
193
194 Encoder.prototype.write8 = function(val) {
195 store8(this.buffer.memory, this.next, val);
196 this.next += 1;
197 };
198
199 Encoder.prototype.write32 = function(val) {
200 store32(this.buffer.memory, this.next, val);
201 this.next += 4;
202 };
203
204 Encoder.prototype.write64 = function(val) {
205 store64(this.buffer.memory, this.next, val);
206 this.next += 8;
207 };
208
209 Encoder.prototype.encodePointer = function(pointer) {
210 if (!pointer)
211 return this.write64(0);
212 // TODO(abarth): To correctly encode a pointer, we need to know the real
213 // base address of the array buffer.
214 var offset = pointer - this.next;
215 this.write64(offset);
216 };
217
218 Encoder.prototype.createAndEncodeEncoder = function(size) {
219 var pointer = this.buffer.alloc(align(size));
220 this.encodePointer(pointer);
221 return new Encoder(this.buffer, this.handles, pointer);
222 };
223
224 Encoder.prototype.encodeHandle = function(handle) {
225 this.handles.push(handle);
226 this.write32(this.handles.length - 1);
227 };
228
229 Encoder.prototype.encodeString = function(val) {
230 var numberOfElements = val.length;
231 var numberOfBytes = kArrayHeaderSize + numberOfElements;
232 this.write32(numberOfBytes);
233 this.write32(numberOfElements);
234 // TODO(abarth): We should really support UTF-8. We might want to
235 // jump out of the VM to encode the string directly from the array
236 // buffer using v8::String::WriteUtf8.
237 var memory = this.buffer.memory;
238 var base = this.next;
239 var len = val.length;
240 for (var i = 0; i < len; ++i) {
241 memory[base + i] = val.charCodeAt(i) & 0x7F;
242 }
243 this.next += len;
244 };
245
246 Encoder.prototype.encodeArray = function(cls, val) {
247 var numberOfElements = val.length;
248 var numberOfBytes = kArrayHeaderSize + cls.encodedSize * numberOfElements;
249 this.write32(numberOfBytes);
250 this.write32(numberOfElements);
251 for (var i = 0; i < numberOfElements; ++i) {
252 cls.encode(this, val[i]);
253 }
254 };
255
256 Encoder.prototype.encodeStructPointer = function(cls, val) {
257 var encoder = this.createAndEncodeEncoder(cls.encodedSize);
258 cls.encode(encoder, val);
259 };
260
261 Encoder.prototype.encodeArrayPointer = function(cls, val) {
262 var encodedSize = kArrayHeaderSize + cls.encodedSize * val.length;
263 var encoder = this.createAndEncodeEncoder(encodedSize);
264 encoder.encodeArray(cls, val);
265 };
266
267 Encoder.prototype.encodeStringPointer = function(val) {
268 // TODO(abarth): This won't be right once we support UTF-8.
269 var encodedSize = kArrayHeaderSize + val.length;
270 var encoder = this.createAndEncodeEncoder(encodedSize);
271 encoder.encodeString(val);
272 };
273
274 // Message ------------------------------------------------------------------
275
276 function Message(memory, handles) {
277 this.memory = memory;
278 this.handles = handles;
279 }
280
281 // MessageBuilder -----------------------------------------------------------
282
283 function MessageBuilder(messageName, payloadSize) {
284 // Currently, we don't compute the payload size correctly ahead of time.
285 // Instead, we overwrite this field at the end.
286 var numberOfBytes = kMessageHeaderSize + payloadSize;
287 this.buffer = new Buffer(numberOfBytes);
288 this.handles = [];
289 var encoder = this.createEncoder(kMessageHeaderSize);
290 encoder.write32(numberOfBytes);
291 encoder.write32(messageName);
292 }
293
294 MessageBuilder.prototype.createEncoder = function(size) {
295 var pointer = this.buffer.alloc(size);
296 return new Encoder(this.buffer, this.handles, pointer);
297 }
298
299 MessageBuilder.prototype.encodeStruct = function(cls, val) {
300 cls.encode(this.createEncoder(cls.encodedSize), val);
301 };
302
303 MessageBuilder.prototype.finish = function() {
304 // TODO(abarth): Rather than resizing the buffer at the end, we could
305 // compute the size we need ahead of time, like we do in C++.
306 var memory = this.buffer.createViewOfAllocatedMemory();
307 store32(memory, 0, memory.length);
308 var message = new Message(memory, this.handles);
309 this.buffer = null;
310 this.handles = null;
311 this.encoder = null;
312 return message;
313 };
314
315 // MessageReader ------------------------------------------------------------
316
317 function MessageReader(message) {
318 this.decoder = new Decoder(message.memory, message.handles, 0);
319 this.payloadSize = this.decoder.read32() - kMessageHeaderSize;
320 this.messageName = this.decoder.read32();
321 }
322
323 MessageReader.prototype.decodeStruct = function(cls) {
324 return cls.decode(this.decoder);
325 };
326
327 // Built-in types -----------------------------------------------------------
328
329 function Uint8() {
330 }
331
332 Uint8.encodedSize = 1;
333
334 Uint8.decode = function(decoder) {
335 return decoder.read8();
336 };
337
338 Uint8.encode = function(encoder, val) {
339 encoder.write8(val);
340 };
341
342 function Uint16() {
343 }
344
345 Uint16.encodedSize = 2;
346
347 Uint16.decode = function(decoder) {
348 return decoder.read16();
349 };
350
351 Uint16.encode = function(encoder, val) {
352 encoder.write16(val);
353 };
354
355 function Uint32() {
356 }
357
358 Uint32.encodedSize = 4;
359
360 Uint32.decode = function(decoder) {
361 return decoder.read32();
362 };
363
364 Uint32.encode = function(encoder, val) {
365 encoder.write32(val);
366 };
367
368 function Uint64() {
369 };
370
371 Uint64.encodedSize = 8;
372
373 Uint64.decode = function(decoder) {
374 return decoder.read64();
375 };
376
377 Uint64.encode = function(encoder, val) {
378 encoder.write64(val);
379 };
380
381 function PointerTo(cls) {
382 this.cls = cls;
383 };
384
385 // TODO(abarth): Add missing types:
386 // * String
387 // * Float
388 // * Double
389 // * Signed integers
390
391 PointerTo.prototype.encodedSize = 8;
392
393 PointerTo.prototype.decode = function(decoder) {
394 return this.cls.decode(decoder.decodeAndCreateDecoder());
395 };
396
397 PointerTo.prototype.encode = function(encoder, val) {
398 var objectEncoder = encoder.createAndEncodeEncoder(this.cls.encodedSize);
399 this.cls.encode(objectEncoder, val);
400 };
401
402 function ArrayOf(cls) {
403 this.cls = cls;
404 };
405
406 ArrayOf.prototype.encodedSize = 8;
407
408 ArrayOf.prototype.decode = function(decoder) {
409 return decoder.decodeArrayPointer(self.cls);
410 };
411
412 ArrayOf.prototype.encode = function(encoder, val) {
413 encoder.encodeArrayPointer(self.cls, val);
414 };
415
416 function Handle() {
417 }
418
419 Handle.encodedSize = 4;
420
421 Handle.decode = function(decoder) {
422 return decoder.decodeHandle();
423 };
424
425 Handle.encode = function(encoder, val) {
426 encoder.encodeHandle(val);
427 };
428
429 var exports = {};
430 exports.align = align;
431 exports.Message = Message;
432 exports.MessageBuilder = MessageBuilder;
433 exports.MessageReader = MessageReader;
434 exports.kArrayHeaderSize = kArrayHeaderSize;
435 exports.kStructHeaderSize = kStructHeaderSize;
436 exports.kMessageHeaderSize = kMessageHeaderSize;
437 exports.Uint8 = Uint8;
438 exports.Uint16 = Uint16;
439 exports.Uint32 = Uint32;
440 exports.Uint64 = Uint64;
441 exports.PointerTo = PointerTo;
442 exports.ArrayOf = ArrayOf;
443 exports.Handle = Handle;
444 return exports;
445 });
OLDNEW
« no previous file with comments | « mojo/public/bindings/js/DEPS ('k') | mojo/public/bindings/js/codec_unittests.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698