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

Unified Diff: mojo/public/bindings/js/codec.js

Issue 69843003: Implement Mojo message codec in JavaScript (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Structs Created 7 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mojo/public/bindings/js/codec.js
diff --git a/mojo/public/bindings/js/codec.js b/mojo/public/bindings/js/codec.js
new file mode 100644
index 0000000000000000000000000000000000000000..0f6f71ce7514d4daacb5eaad7547c9d9f134c999
--- /dev/null
+++ b/mojo/public/bindings/js/codec.js
@@ -0,0 +1,394 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Memory ---------------------------------------------------------------------
+
+function store8(memory, ptr, val) {
Aaron Boodman 2013/11/13 19:32:36 What is intended to be the public API out of all t
abarth-chromium 2013/11/13 19:41:51 Definitely! I was hoping we'd have a module syste
+ memory[ptr] = val;
+}
+
+function load8(memory, ptr, val) {
+ return memory[ptr];
+}
+
+function store16(memory, ptr, val) {
+ memory[ptr + 0] = val >> 0;
+ memory[ptr + 1] = val >> 8;
+}
+
+function load16(memory, ptr, val) {
+ return memory[ptr + 0] << 0 +
+ memory[ptr + 1] << 8;
+}
+
+function store32(memory, ptr, val) {
+ memory[ptr + 0] = val >> 0;
+ memory[ptr + 1] = val >> 8;
+ memory[ptr + 2] = val >> 16;
+ memory[ptr + 3] = val >> 24;
+}
+
+function load32(memory, ptr, val) {
+ return memory[ptr + 0] << 0 +
+ memory[ptr + 1] << 8 +
+ memory[ptr + 2] << 16 +
+ memory[ptr + 3] << 24;
+}
+
+function store64(memory, ptr, val) {
+ memory[ptr + 0] = val >> 0;
+ memory[ptr + 1] = val >> 8;
+ memory[ptr + 2] = val >> 16;
+ memory[ptr + 3] = val >> 24;
+ memory[ptr + 4] = val >> 32;
+ memory[ptr + 5] = val >> 40;
+ memory[ptr + 6] = val >> 48;
+ memory[ptr + 7] = val >> 56;
+}
+
+function load64(memory, ptr, val) {
+ return memory[ptr + 0] << 0 +
+ memory[ptr + 1] << 8 +
+ memory[ptr + 2] << 16 +
+ memory[ptr + 3] << 24 +
+ memory[ptr + 4] << 32 +
+ memory[ptr + 5] << 40 +
+ memory[ptr + 6] << 48 +
+ memory[ptr + 7] << 56;
+}
+
+function align(size) {
+ var kAlignment = 8;
+ return size + (kAlignment - (size % kAlignment)) % kAlignment;
Aaron Boodman 2013/11/13 19:32:36 I think the "% kAlignment" at the end is unnecessa
abarth-chromium 2013/11/13 19:41:51 I haven't found any callers for this function, so
+}
+
+// Serialization --------------------------------------------------------------
+
+function encodePointer(memory, ptr, offsetPtr) {
Aaron Boodman 2013/11/13 19:32:36 Weird to use both 'ptr' and 'pointer'. Google styl
abarth-chromium 2013/11/13 19:41:51 Ok. I was thinking about switching to addr, but w
+ if (!ptr) {
+ store64(memory, offsetPtr, 0);
+ return;
+ }
+ var offset = ptr - offsetPtr;
+ store64(memory, offsetPtr, offset);
+}
+
+function decodePointer(memory, offsetPtr) {
+ var offset = load64(memory, offsetPtr);
+ if (!offset)
+ return 0;
+ return offsetPtr + offset;
+}
+
+function encodeHandle(memory, handlePtr, handles) {
+ handles.push(load32(memory, handlePtr));
+ store32(memory, handlePtr, handles.length - 1);
+}
+
+function decodeHandle(memory, handlePtr, handles) {
+ var index = load32(memory, handlePtr);
+ store32(memory, handlePtr, handles[index]);
+}
+
+// Record ---------------------------------------------------------------------
+
+function Record(memory, ptr) {
+ this.memory = memory;
+ this.base = ptr;
+ this.next = ptr;
+}
+
+Record.prototype.advance = function(offset) {
+ this.next += offset;
+}
+
+Record.prototype.readPtr = function() {
+ var ptr = decodePointer(this.memory, this.next);
+ this.next += 8;
+ return ptr;
+}
+
+Record.prototype.writePtr = function(ptr) {
+ encodePointer(this.memory, ptr, this.next);
+ this.next += 8;
+}
+
+Record.prototype.readRecord = function() {
+ return new Record(this.memory, this.readPtr());
+}
+
+Record.prototype.readString = function(len) {
+ // TODO(abarth): We should really support UTF-8. We might want to
+ // jump out of the VM to decode the string directly from the array
+ // buffer using v8::String::NewFromUtf8.
Aaron Boodman 2013/11/13 19:32:36 There are javascript implementations of utf8! I wr
abarth-chromium 2013/11/13 19:41:51 Link? :) I'd like to start with a pure JS implem
Aaron Boodman 2013/11/18 18:34:48 I believe that there is one I wrote internally as
+ var result = "";
+ var memory = this.memory;
+ var base = this.next;
+ for (var i = 0; i < len; ++i) {
+ result += String.fromCharCode(memory[base + i] & 0x7F);
+ }
+ this.next += len;
+ return result;
+}
+
+Record.prototype.read8 = function() {
+ var result = load8(this.memory, this.next);
+ this.next += 1;
+ return result;
+}
+
+Record.prototype.read32 = function() {
+ var result = load32(this.memory, this.next);
+ this.next += 4;
+ return result;
+}
+
+Record.prototype.read64 = function() {
+ var result = load64(this.memory, this.next);
+ this.next += 8;
+ return result;
+}
+
+Record.prototype.write8 = function(val) {
+ store8(this.memory, this.next, val);
+ this.next += 1;
+}
+
+Record.prototype.write32 = function(val) {
+ var after = this.next + 4;
+ store32(this.memory, this.next, val);
+ this.next += 4;
+};
+
+Record.prototype.write64 = function(val) {
+ store64(this.memory, this.next, val);
+ this.next += 8;
+};
+
+// Buffer ---------------------------------------------------------------------
+
+function Buffer(size) {
+ this.memory = new Uint8Array(size);
+ this.nextAllocation = 0;
+}
+
+Buffer.prototype.alloc = function(size) {
+ var ptr = this.nextAllocation;
+ this.nextAllocation += size;
+ if (this.nextAllocation > this.memory.length)
+ throw "Buffer full.";
+ return new Record(this.memory, ptr);
+};
+
+// Fields ---------------------------------------------------------------------
+
+var kArrayHeaderSize = 8;
+var kStructHeaderSize = 8;
+
+function encodeArray(record, class, val) {
+ var numberOfElements = val.length;
+ record.write32(kArrayHeaderSize + class.encodedSize * numberOfElements);
+ record.write32(numberOfElements);
+ for (var i = 0; i < numberOfElements; ++i) {
+ class.encode(record, val[i]);
+ }
+ // TODO(abarth): We should sanity check that everthing fits.
+}
+
+function decodeArray(record, class) {
+ var numberOfBytes = record.read32();
+ var numberOfElements = record.read32();
+ var val = [];
+ for (var i = 0; i < numberOfElements; ++i) {
+ val.push(class.decode(record));
+ }
+ // TODO(abarth): We should sanity check that everthing fits.
+ return val;
+}
+
+function decodeString(record) {
+ var numberOfBytes = record.read32();
+ var numberOfElements = record.read32();
+ return record.readString(numberOfElements);
+}
+
+// Message --------------------------------------------------------------------
+
+var kMessageHeaderSize = 8;
+
+function Message() {
+ this.memory = null;
+ this.handles = [];
+}
+
+Message.prototype.dispose = function() {
+ var len = this.handles.length;
+ for (var i = 0; i < len; ++i) {
+ mojo.core.close(this.handles[i]);
+ this.handles[i] = mojo.core.HANDLE_INVALID;
+ }
+};
+
+// MessageBuilder -------------------------------------------------------------
+
+function MessageBuilder(messageName, payloadSize) {
+ var buffer = new Buffer(kMessageHeaderSize + payloadSize);
+ var header = buffer.alloc(kMessageHeaderSize);
+ header.write32(buffer.length);
+ header.write32(messageName);
+
+ this.buffer = buffer;
+}
+
+MessageBuilder.prototype.takeBuffer = function() {
+ var buffer = this.buffer;
+ this.buffer = null;
+ return buffer;
+};
+
+// Basic types ----------------------------------------------------------------
+
+function Uint8() {
+}
+
+Uint8.encodedSize = 1;
+
+Uint8.decode = function(record) {
+ return record.read8();
+};
+
+Uint8.encode = function(record, val) {
+ record.write8(val);
+};
+
+function Ptr(class) {
+ this.class = class;
+};
+
+Ptr.prototype.encodedSize = 8;
+
+Ptr.prototype.decode = function(record) {
+ return class.decode(record.readRecord());
+};
+
+Ptr.prototype.encode = function(record, val) {
+ // TODO(abarth): Where does |buffer| come from?
+ objectRecord = buffer.alloc(class.encodedSize);
+ class.encode(objectRecord, val);
+ record.writePtr(objectRecord.base);
+};
+
+function Handle() {
+}
+
+// TOOD(abarth): Implement handles.
+
+// "Generated" code ===========================================================
+
+function Bar() {
+ this.alpha = 0;
+ this.beta = 0;
+ this.gamma = 0;
+}
+
+Bar.encodedSize = kStructHeaderSize + 8;
+
+Bar.decode = function(record) {
+ var val = new Bar();
+ // TODO(abarth): We need to support optional fields.
+ record.advance(kStructHeaderSize);
+ val.alpha = record.read8();
+ val.beta = record.read8();
+ val.gamma = record.read8();
+ record.advance(5);
+ return val;
+};
+
+Bar.encode = function(record, val) {
+ record.write32(Bar.encodedSize);
+ record.write32(3);
+ record.write8(val.alpha);
+ record.write8(val.beta);
+ record.write8(val.gamma);
+ record.advance(5);
+};
+
+ // int32_t x_;
+ // int32_t y_;
+ // uint8_t a_ : 1;
+ // uint8_t b_ : 1;
+ // uint8_t c_ : 1;
+ // uint8_t _pad0_[7];
+ // mojo::internal::StructPointer<Bar> bar_;
+ // mojo::internal::ArrayPointer<uint8_t> data_;
+ // mojo::internal::ArrayPointer<Bar*> extra_bars_;
+ // mojo::internal::StringPointer name_;
+ // mojo::internal::ArrayPointer<mojo::Handle> files_;
+
+function Foo() {
+ this.x = 0;
+ this.y = 0;
+ this.a = 0;
+ this.b = 0;
+ this.c = 0;
+ this.bar = null;
+ this.data = null;
+ this.extra_bars = null;
+ this.name = null;
+ this.files = null;
+}
+
+Foo.encodedSize = 64;
+
+Foo.decode = function(record) {
+ var val = new Foo();
+ // TODO(abarth): We need to support optional fields.
+ record.advance(kStructHeaderSize);
+ val.x = record.read32();
+ val.y = record.read32();
+ var packed = record.read8();
+ val.a = (packed >> 0) & 1;
+ val.b = (packed >> 1) & 1;
+ val.c = (packed >> 2) & 1;
+ record.advance(7);
+ val.bar = Bar.decode(record.readRecord());
+ val.data = decodeArray(record.readRecord(), Uint8);
+ val.extra_bars = decodeArray(record.readRecord(), new Ptr(Bar));
+ val.name = decodeString(record.readRecord());
+ val.files = decodeArray(record.readRecord(), Handle);
+}
+
+Foo.encode = function(record, val) {
+ record.write32(Foo.encodedSize);
+ record.write32(10);
+ record.write32(val.x);
+ record.write32(val.y);
+ var packed = (val.a & 1) << 0 |
+ (val.b & 1) << 1 |
+ (val.c & 1) << 2;
+ record.write8(packed);
+ record.advance(7);
+
+ // TODO(abarth): Where does buffer come from?
+ var barRecord = buffer.alloc(Bar.encodedSize);
+ Bar.encode(barRecord, val.bar);
+ record.writePtr(barRecord.base);
+
+ var dataRecord = buffer.alloc(Uint8.encodedSize);
+ encodeArray(dataRecord, Uint8, this.data);
+ record.writePtr(dataRecord.base);
+
+ var extra_barsClass = new Ptr(Bar);
+ var extra_barsRecord = buffer.alloc(extra_barsClass.encodedSize);
+ encodeArray(dataRecord, extra_barsClass, this.data);
+ record.writePtr(extra_barsRecord.base);
+
+ // TODO(abarth): We'll need something fancier here to support UTF-8.
+ var nameLength = val.name.length;
+ nameRecord = buffer.alloc(nameLength);
+ encodeString(nameRecord, val.name);
+ record.writePtr(nameRecord.base);
+
+ // TODO(abarth): We need to be able to encode handles.
+};
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698