diff --git a/js/map.js b/js/map.js
new file mode 100644
index 0000000..2fb1483
--- /dev/null
+++ b/js/map.js
@@ -0,0 +1,542 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+goog.provide('jspb.Map');
+
+goog.require('goog.asserts');
+
+goog.forwardDeclare('jspb.BinaryReader');
+goog.forwardDeclare('jspb.BinaryWriter');
+
+
+
+/**
+ * Constructs a new Map. A Map is a container that is used to implement map
+ * fields on message objects. It closely follows the ES6 Map API; however,
+ * it is distinct because we do not want to depend on external polyfills or
+ * on ES6 itself.
+ *
+ * This constructor should only be called from generated message code. It is not
+ * intended for general use by library consumers.
+ *
+ * @template K, V
+ *
+ * @param {!Array<!Array<?>>} arr
+ *
+ * @param {?function(new:V, ?=)=} opt_valueCtor
+ *    The constructor for type V, if type V is a message type.
+ *
+ * @constructor
+ * @struct
+ */
+jspb.Map = function(arr, opt_valueCtor) {
+  /** @const @private */
+  this.arr_ = arr;
+  /** @const @private */
+  this.valueCtor_ = opt_valueCtor;
+
+  /** @type {!Object<string, !jspb.Map.Entry_<K,V>>} @private */
+  this.map_ = {};
+
+  /**
+   * Is `this.arr_ updated with respect to `this.map_`?
+   * @type {boolean}
+   */
+  this.arrClean = true;
+
+  if (this.arr_.length > 0) {
+    this.loadFromArray_();
+  }
+};
+
+
+/**
+ * Load initial content from underlying array.
+ * @private
+ */
+jspb.Map.prototype.loadFromArray_ = function() {
+  for (var i = 0; i < this.arr_.length; i++) {
+    var record = this.arr_[i];
+    var key = record[0];
+    var value = record[1];
+    this.map_[key.toString()] = new jspb.Map.Entry_(key, value);
+  }
+  this.arrClean = true;
+};
+
+
+/**
+ * Synchronize content to underlying array, if needed, and return it.
+ * @return {!Array<!Array<!Object>>}
+ */
+jspb.Map.prototype.toArray = function() {
+  if (this.arrClean) {
+    if (this.valueCtor_) {
+      // We need to recursively sync maps in submessages to their arrays.
+      var m = this.map_;
+      for (var p in m) {
+        if (Object.prototype.hasOwnProperty.call(m, p)) {
+          var valueWrapper = /** @type {?jspb.Message} */ (m[p].valueWrapper);
+          if (valueWrapper) {
+            valueWrapper.toArray();
+          }
+        }
+      }
+    }
+  } else {
+    // Delete all elements.
+    this.arr_.length = 0;
+    var strKeys = this.stringKeys_();
+    // Output keys in deterministic (sorted) order.
+    strKeys.sort();
+    for (var i = 0; i < strKeys.length; i++) {
+      var entry = this.map_[strKeys[i]];
+      var valueWrapper = /** @type {?jspb.Message} */ (entry.valueWrapper);
+      if (valueWrapper) {
+        valueWrapper.toArray();
+      }
+      this.arr_.push([entry.key, entry.value]);
+    }
+    this.arrClean = true;
+  }
+  return this.arr_;
+};
+
+
+/**
+ * Returns the map formatted as an array of key-value pairs, suitable for the
+ * toObject() form of a message.
+ *
+ * @param {boolean=} includeInstance Whether to include the JSPB instance for
+ *    transitional soy proto support: http://goto/soy-param-migration
+ * @param {!function((boolean|undefined),V):!Object=} valueToObject
+ *    The static toObject() method, if V is a message type.
+ * @return {!Array<!Array<!Object>>}
+ */
+jspb.Map.prototype.toObject = function(includeInstance, valueToObject) {
+  var rawArray = this.toArray();
+  var entries = [];
+  for (var i = 0; i < rawArray.length; i++) {
+    var entry = this.map_[rawArray[i][0].toString()];
+    this.wrapEntry_(entry);
+    var valueWrapper = /** @type {V|undefined} */ (entry.valueWrapper);
+    if (valueWrapper) {
+      goog.asserts.assert(valueToObject);
+      entries.push([entry.key, valueToObject(includeInstance, valueWrapper)]);
+    } else {
+      entries.push([entry.key, entry.value]);
+    }
+  }
+  return entries;
+};
+
+
+/**
+ * Returns a Map from the given array of key-value pairs when the values are of
+ * message type. The values in the array must match the format returned by their
+ * message type's toObject() method.
+ *
+ * @template K, V
+ * @param {!Array<!Array<!Object>>} entries
+ * @param {!function(new:V,?=)} valueCtor
+ *    The constructor for type V.
+ * @param {!function(!Object):V} valueFromObject
+ *    The fromObject function for type V.
+ * @return {!jspb.Map<K, V>}
+ */
+jspb.Map.fromObject = function(entries, valueCtor, valueFromObject) {
+  var result = new jspb.Map([], valueCtor);
+  for (var i = 0; i < entries.length; i++) {
+    var key = entries[i][0];
+    var value = valueFromObject(entries[i][1]);
+    result.set(key, value);
+  }
+  return result;
+};
+
+
+/**
+ * Helper: an IteratorIterable over an array.
+ * @template T
+ * @param {!Array<T>} arr the array
+ * @implements {IteratorIterable<T>}
+ * @constructor @struct
+ * @private
+ */
+jspb.Map.ArrayIteratorIterable_ = function(arr) {
+  /** @type {number} @private */
+  this.idx_ = 0;
+
+  /** @const @private */
+  this.arr_ = arr;
+};
+
+
+/** @override @final */
+jspb.Map.ArrayIteratorIterable_.prototype.next = function() {
+  if (this.idx_ < this.arr_.length) {
+    return {done: false, value: this.arr_[this.idx_++]};
+  } else {
+    return {done: true, value: undefined};
+  }
+};
+
+if (typeof(Symbol) != 'undefined') {
+  /** @override */
+  jspb.Map.ArrayIteratorIterable_.prototype[Symbol.iterator] = function() {
+    return this;
+  };
+}
+
+
+/**
+ * Returns the map's length (number of key/value pairs).
+ * @return {number}
+ */
+jspb.Map.prototype.getLength = function() {
+  return this.stringKeys_().length;
+};
+
+
+/**
+ * Clears the map.
+ */
+jspb.Map.prototype.clear = function() {
+  this.map_ = {};
+  this.arrClean = false;
+};
+
+
+/**
+ * Deletes a particular key from the map.
+ * N.B.: differs in name from ES6 Map's `delete` because IE8 does not support
+ * reserved words as property names.
+ * @this {jspb.Map}
+ * @param {K} key
+ * @return {boolean} Whether any entry with this key was deleted.
+ */
+jspb.Map.prototype.del = function(key) {
+  var keyValue = key.toString();
+  var hadKey = this.map_.hasOwnProperty(keyValue);
+  delete this.map_[keyValue];
+  this.arrClean = false;
+  return hadKey;
+};
+
+
+/**
+ * Returns an array of [key, value] pairs in the map.
+ *
+ * This is redundant compared to the plain entries() method, but we provide this
+ * to help out Angular 1.x users.  Still evaluating whether this is the best
+ * option.
+ *
+ * @return {!Array<!Array<K|V>>}
+ */
+jspb.Map.prototype.getEntryList = function() {
+  var entries = [];
+  var strKeys = this.stringKeys_();
+  strKeys.sort();
+  for (var i = 0; i < strKeys.length; i++) {
+    var entry = this.map_[strKeys[i]];
+    entries.push([entry.key, entry.value]);
+  }
+  return entries;
+};
+
+
+/**
+ * Returns an iterator-iterable over [key, value] pairs in the map.
+ * Closure compiler sadly doesn't support tuples, ie. Iterator<[K,V]>.
+ * @return {!IteratorIterable<!Array<K|V>>} The iterator-iterable.
+ */
+jspb.Map.prototype.entries = function() {
+  var entries = [];
+  var strKeys = this.stringKeys_();
+  strKeys.sort();
+  for (var i = 0; i < strKeys.length; i++) {
+    var entry = this.map_[strKeys[i]];
+    entries.push([entry.key, this.wrapEntry_(entry)]);
+  }
+  return new jspb.Map.ArrayIteratorIterable_(entries);
+};
+
+
+/**
+ * Returns an iterator-iterable over keys in the map.
+ * @return {!IteratorIterable<K>} The iterator-iterable.
+ */
+jspb.Map.prototype.keys = function() {
+  var keys = [];
+  var strKeys = this.stringKeys_();
+  strKeys.sort();
+  for (var i = 0; i < strKeys.length; i++) {
+    var entry = this.map_[strKeys[i]];
+    keys.push(entry.key);
+  }
+  return new jspb.Map.ArrayIteratorIterable_(keys);
+};
+
+
+/**
+ * Returns an iterator-iterable over values in the map.
+ * @return {!IteratorIterable<V>} The iterator-iterable.
+ */
+jspb.Map.prototype.values = function() {
+  var values = [];
+  var strKeys = this.stringKeys_();
+  strKeys.sort();
+  for (var i = 0; i < strKeys.length; i++) {
+    var entry = this.map_[strKeys[i]];
+    values.push(this.wrapEntry_(entry));
+  }
+  return new jspb.Map.ArrayIteratorIterable_(values);
+};
+
+
+/**
+ * Iterates over entries in the map, calling a function on each.
+ * @template T
+ * @param {function(this:T, V, K, ?jspb.Map<K, V>)} cb
+ * @param {T=} opt_thisArg
+ */
+jspb.Map.prototype.forEach = function(cb, opt_thisArg) {
+  var strKeys = this.stringKeys_();
+  strKeys.sort();
+  for (var i = 0; i < strKeys.length; i++) {
+    var entry = this.map_[strKeys[i]];
+    cb.call(opt_thisArg, this.wrapEntry_(entry), entry.key, this);
+  }
+};
+
+
+/**
+ * Sets a key in the map to the given value.
+ * @param {K} key The key
+ * @param {V} value The value
+ * @return {!jspb.Map<K,V>}
+ */
+jspb.Map.prototype.set = function(key, value) {
+  var entry = new jspb.Map.Entry_(key);
+  if (this.valueCtor_) {
+    entry.valueWrapper = value;
+    // .toArray() on a message returns a reference to the underlying array
+    // rather than a copy.
+    entry.value = value.toArray();
+  } else {
+    entry.value = value;
+  }
+  this.map_[key.toString()] = entry;
+  this.arrClean = false;
+  return this;
+};
+
+
+/**
+ * Helper: lazily construct a wrapper around an entry, if needed, and return the
+ * user-visible type.
+ * @param {!jspb.Map.Entry_<K,V>} entry
+ * @return {V}
+ * @private
+ */
+jspb.Map.prototype.wrapEntry_ = function(entry) {
+  if (this.valueCtor_) {
+    if (!entry.valueWrapper) {
+      entry.valueWrapper = new this.valueCtor_(entry.value);
+    }
+    return /** @type {V} */ (entry.valueWrapper);
+  } else {
+    return entry.value;
+  }
+};
+
+
+/**
+ * Gets the value corresponding to a key in the map.
+ * @param {K} key
+ * @return {V|undefined} The value, or `undefined` if key not present
+ */
+jspb.Map.prototype.get = function(key) {
+  var keyValue = key.toString();
+  var entry = this.map_[keyValue];
+  if (entry) {
+    return this.wrapEntry_(entry);
+  } else {
+    return undefined;
+  }
+};
+
+
+/**
+ * Determines whether the given key is present in the map.
+ * @param {K} key
+ * @return {boolean} `true` if the key is present
+ */
+jspb.Map.prototype.has = function(key) {
+  var keyValue = key.toString();
+  return (keyValue in this.map_);
+};
+
+
+/**
+ * Write this Map field in wire format to a BinaryWriter, using the given field
+ * number.
+ * @param {number} fieldNumber
+ * @param {!jspb.BinaryWriter} writer
+ * @param {!function(this:jspb.BinaryWriter,number,K)} keyWriterFn
+ *     The method on BinaryWriter that writes type K to the stream.
+ * @param {!function(this:jspb.BinaryWriter,number,V,?=)|
+ *          function(this:jspb.BinaryWriter,number,V,?)} valueWriterFn
+ *     The method on BinaryWriter that writes type V to the stream.  May be
+ *     writeMessage, in which case the second callback arg form is used.
+ * @param {function(V,!jspb.BinaryWriter)=} opt_valueWriterCallback
+ *    The BinaryWriter serialization callback for type V, if V is a message
+ *    type.
+ */
+jspb.Map.prototype.serializeBinary = function(
+    fieldNumber, writer, keyWriterFn, valueWriterFn, opt_valueWriterCallback) {
+  var strKeys = this.stringKeys_();
+  strKeys.sort();
+  for (var i = 0; i < strKeys.length; i++) {
+    var entry = this.map_[strKeys[i]];
+    writer.beginSubMessage(fieldNumber);
+    keyWriterFn.call(writer, 1, entry.key);
+    if (this.valueCtor_) {
+      valueWriterFn.call(writer, 2, this.wrapEntry_(entry),
+                         opt_valueWriterCallback);
+    } else {
+      /** @type {function(this:jspb.BinaryWriter,number,?)} */ (valueWriterFn)
+          .call(writer, 2, entry.value);
+    }
+    writer.endSubMessage();
+  }
+};
+
+
+/**
+ * Read one key/value message from the given BinaryReader. Compatible as the
+ * `reader` callback parameter to jspb.BinaryReader.readMessage, to be called
+ * when a key/value pair submessage is encountered. If the Key is undefined,
+ * we should default it to 0.
+ * @template K, V
+ * @param {!jspb.Map} map
+ * @param {!jspb.BinaryReader} reader
+ * @param {!function(this:jspb.BinaryReader):K} keyReaderFn
+ *     The method on BinaryReader that reads type K from the stream.
+ *
+ * @param {!function(this:jspb.BinaryReader):V|
+ *          function(this:jspb.BinaryReader,V,
+ *                  function(V,!jspb.BinaryReader))} valueReaderFn
+ *    The method on BinaryReader that reads type V from the stream. May be
+ *    readMessage, in which case the second callback arg form is used.
+ *
+ * @param {?function(V,!jspb.BinaryReader)=} opt_valueReaderCallback
+ *    The BinaryReader parsing callback for type V, if V is a message type
+ *
+ * @param {K=} opt_defaultKey
+ *    The default value for the type of map keys. Accepting map
+ *    entries with unset keys is required for maps to be backwards compatible
+ *    with the repeated message representation described here: goo.gl/zuoLAC
+ *
+ */
+jspb.Map.deserializeBinary = function(map, reader, keyReaderFn, valueReaderFn,
+                                      opt_valueReaderCallback, opt_defaultKey) {
+  var key = opt_defaultKey;
+  var value = undefined;
+
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+
+    if (field == 1) {
+      // Key.
+      key = keyReaderFn.call(reader);
+    } else if (field == 2) {
+      // Value.
+      if (map.valueCtor_) {
+        goog.asserts.assert(opt_valueReaderCallback);
+        value = new map.valueCtor_();
+        valueReaderFn.call(reader, value, opt_valueReaderCallback);
+      } else {
+        value =
+            (/** @type {function(this:jspb.BinaryReader):?} */ (valueReaderFn))
+                .call(reader);
+      }
+    }
+  }
+
+  goog.asserts.assert(key != undefined);
+  goog.asserts.assert(value != undefined);
+  map.set(key, value);
+};
+
+
+/**
+ * Helper: compute the list of all stringified keys in the underlying Object
+ * map.
+ * @return {!Array<string>}
+ * @private
+ */
+jspb.Map.prototype.stringKeys_ = function() {
+  var m = this.map_;
+  var ret = [];
+  for (var p in m) {
+    if (Object.prototype.hasOwnProperty.call(m, p)) {
+      ret.push(p);
+    }
+  }
+  return ret;
+};
+
+
+
+/**
+ * @param {K} key The entry's key.
+ * @param {V=} opt_value The entry's value wrapper.
+ * @constructor
+ * @struct
+ * @template K, V
+ * @private
+ */
+jspb.Map.Entry_ = function(key, opt_value) {
+  /** @const {K} */
+  this.key = key;
+
+  // The JSPB-serializable value.  For primitive types this will be of type V.
+  // For message types it will be an array.
+  /** @type {V} */
+  this.value = opt_value;
+
+  // Only used for submessage values.
+  /** @type {V} */
+  this.valueWrapper = undefined;
+};
