Bug 1248447 - Stop grafting prototypes in storage.js::patchMetadataMapsAndProtos() r?pbrosset
MozReview-Commit-ID: 2mQERql1pOj
--- a/devtools/server/actors/storage.js
+++ b/devtools/server/actors/storage.js
@@ -1451,17 +1451,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.
@@ -1724,32 +1724,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});
@@ -1844,31 +1844,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) {