Bug 1248447 - Stop grafting prototypes in storage.js::patchMetadataMapsAndProtos() r=pbro
authorMichael Ratcliffe <mratcliffe@mozilla.com>
Thu, 17 Mar 2016 15:42:43 +0000
changeset 289642 4fba702c0a2202bafca77a99616b37361e49d4e4
parent 289641 bc7572388c5a057baa743635a596ed1fa43f1543
child 289643 6eadbc6c9876326c3814ccc8c089c13de88eeeec
push id30108
push usercbook@mozilla.com
push dateTue, 22 Mar 2016 11:14:31 +0000
treeherdermozilla-central@ea6298e1b4f7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspbro
bugs1248447
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1248447 - Stop grafting prototypes in storage.js::patchMetadataMapsAndProtos() r=pbro MozReview-Commit-ID: 2mQERql1pOj
devtools/server/actors/storage.js
--- a/devtools/server/actors/storage.js
+++ b/devtools/server/actors/storage.js
@@ -1279,17 +1279,17 @@ StorageActors.createActor({
 
   populateStoresForHost: Task.async(function*(host) {
     let storeMap = new Map();
     let {names} = yield this.getDBNamesForHost(host);
 
     for (let name of names) {
       let metadata = yield this.getDBMetaData(host, name);
 
-      indexedDBHelpers.patchMetadataMapsAndProtos(metadata);
+      metadata = indexedDBHelpers.patchMetadataMapsAndProtos(metadata);
       storeMap.set(name, metadata);
     }
 
     this.hostVsStores.set(host, storeMap);
   }),
 
   /**
    * Returns the over-the-wire implementation of the indexed db entity.
@@ -1552,32 +1552,32 @@ var indexedDBHelpers = {
   Task.async(function*(host, name = "null", options, hostVsStores) {
     name = JSON.parse(name);
     if (!name || !name.length) {
       // This means that details about the db in this particular host are
       // requested.
       let dbs = [];
       if (hostVsStores.has(host)) {
         for (let [, db] of hostVsStores.get(host)) {
-          indexedDBHelpers.patchMetadataMapsAndProtos(db);
+          db = indexedDBHelpers.patchMetadataMapsAndProtos(db);
           dbs.push(db.toObject());
         }
       }
       return this.backToChild("getValuesForHost", {dbs: dbs});
     }
 
     let [db2, objectStore, id] = name;
     if (!objectStore) {
       // This means that details about all the object stores in this db are
       // requested.
       let objectStores = [];
       if (hostVsStores.has(host) && hostVsStores.get(host).has(db2)) {
         let db = hostVsStores.get(host).get(db2);
 
-        indexedDBHelpers.patchMetadataMapsAndProtos(db);
+        db = indexedDBHelpers.patchMetadataMapsAndProtos(db);
 
         let objectStores2 = db.objectStores;
 
         for (let objectStore2 of objectStores2) {
           objectStores.push(objectStore2[1].toObject());
         }
       }
       return this.backToChild("getValuesForHost", {objectStores: objectStores});
@@ -1672,31 +1672,46 @@ var indexedDBHelpers = {
     };
     request.onerror = () => {
       db.close();
       success.resolve([]);
     };
     return success.promise;
   },
 
+  /**
+   * When indexedDB metadata is parsed to and from JSON then the object's
+   * prototype is dropped and any Maps are changed to arrays of arrays. This
+   * method is used to repair the prototypes and fix any broken Maps.
+   */
   patchMetadataMapsAndProtos: function(metadata) {
-    for (let [, store] of metadata._objectStores) {
-      store.__proto__ = ObjectStoreMetadata.prototype;
+    let md = Object.create(DatabaseMetadata.prototype);
+    Object.assign(md, metadata);
+
+    md._objectStores = new Map(metadata._objectStores);
+
+    for (let [name, store] of md._objectStores) {
+      let obj = Object.create(ObjectStoreMetadata.prototype);
+      Object.assign(obj, store);
+
+      md._objectStores.set(name, obj);
 
       if (typeof store._indexes.length !== "undefined") {
-        store._indexes = new Map(store._indexes);
+        obj._indexes = new Map(store._indexes);
       }
 
-      for (let [, value] of store._indexes) {
-        value.__proto__ = IndexMetadata.prototype;
+      for (let [name2, value] of obj._indexes) {
+        let obj2 = Object.create(IndexMetadata.prototype);
+        Object.assign(obj2, value);
+
+        obj._indexes.set(name2, obj2);
       }
     }
 
-    metadata._objectStores = new Map(metadata._objectStores);
-    metadata.__proto__ = DatabaseMetadata.prototype;
+    return md;
   },
 
   handleChildRequest: function(msg) {
     let host;
     let name;
     let args = msg.data.args;
 
     switch (msg.json.method) {