mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 871445 - patch 7 - DataStore: WebIDL porting
This commit is contained in:
parent
de02341250
commit
5b41735aeb
@ -32,11 +32,311 @@ XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
||||
"@mozilla.org/childprocessmessagemanager;1",
|
||||
"nsIMessageSender");
|
||||
|
||||
/* Helper function */
|
||||
/* Helper functions */
|
||||
function createDOMError(aWindow, aEvent) {
|
||||
return new aWindow.DOMError(aEvent.target.error.name);
|
||||
}
|
||||
|
||||
function throwInvalidArg(aWindow) {
|
||||
return aWindow.Promise.reject(
|
||||
new aWindow.DOMError("SyntaxError", "Non-numeric or invalid id"));
|
||||
}
|
||||
|
||||
function throwReadOnly(aWindow) {
|
||||
return aWindow.Promise.reject(
|
||||
new aWindow.DOMError("ReadOnlyError", "DataStore in readonly mode"));
|
||||
}
|
||||
|
||||
function parseIds(aId) {
|
||||
function parseId(aId) {
|
||||
aId = parseInt(aId);
|
||||
return (isNaN(aId) || aId <= 0) ? null : aId;
|
||||
}
|
||||
|
||||
if (!Array.isArray(aId)) {
|
||||
return parseId(aId);
|
||||
}
|
||||
|
||||
for (let i = 0; i < aId.length; ++i) {
|
||||
aId[i] = parseId(aId[i]);
|
||||
if (aId[i] === null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return aId;
|
||||
}
|
||||
|
||||
/* Exposed DataStore object */
|
||||
function ExposedDataStore(aWindow, aDataStore, aReadOnly) {
|
||||
debug("ExposedDataStore created");
|
||||
this.init(aWindow, aDataStore, aReadOnly);
|
||||
}
|
||||
|
||||
ExposedDataStore.prototype = {
|
||||
classDescription: "DataStore XPCOM Component",
|
||||
classID: Components.ID("{db5c9602-030f-4bff-a3de-881a8de370f2}"),
|
||||
contractID: "@mozilla.org/dom/datastore;1",
|
||||
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsISupports]),
|
||||
|
||||
callbacks: [],
|
||||
|
||||
init: function(aWindow, aDataStore, aReadOnly) {
|
||||
debug("ExposedDataStore init");
|
||||
|
||||
this.window = aWindow;
|
||||
this.dataStore = aDataStore;
|
||||
this.isReadOnly = aReadOnly;
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
debug("receiveMessage");
|
||||
|
||||
if (aMessage.name != "DataStore:Changed:Return:OK") {
|
||||
debug("Wrong message: " + aMessage.name);
|
||||
return;
|
||||
}
|
||||
|
||||
let self = this;
|
||||
|
||||
this.dataStore.retrieveRevisionId(
|
||||
function() {
|
||||
let event = new self.window.DataStoreChangeEvent('change', aMessage.data);
|
||||
self.__DOM_IMPL__.dispatchEvent(event);
|
||||
},
|
||||
// Forcing the reading of the revisionId
|
||||
true
|
||||
);
|
||||
},
|
||||
|
||||
// Public interface :
|
||||
|
||||
get name() {
|
||||
return this.dataStore.name;
|
||||
},
|
||||
|
||||
get owner() {
|
||||
return this.dataStore.owner;
|
||||
},
|
||||
|
||||
get readOnly() {
|
||||
return this.isReadOnly;
|
||||
},
|
||||
|
||||
get: function(aId) {
|
||||
aId = parseIds(aId);
|
||||
if (aId === null) {
|
||||
return throwInvalidArg(this.window);
|
||||
}
|
||||
|
||||
let self = this;
|
||||
|
||||
// Promise<Object>
|
||||
return this.dataStore.newDBPromise(this.window, "readonly",
|
||||
function(aResolve, aReject, aTxn, aStore, aRevisionStore) {
|
||||
self.dataStore.getInternal(aStore,
|
||||
Array.isArray(aId) ? aId : [ aId ],
|
||||
function(aResults) {
|
||||
aResolve(Array.isArray(aId) ? aResults : aResults[0]);
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
update: function(aId, aObj) {
|
||||
aId = parseInt(aId);
|
||||
if (isNaN(aId) || aId <= 0) {
|
||||
return throwInvalidArg(this.window);
|
||||
}
|
||||
|
||||
if (this.isReadOnly) {
|
||||
return throwReadOnly(this.window);
|
||||
}
|
||||
|
||||
let self = this;
|
||||
|
||||
// Promise<void>
|
||||
return this.dataStore.newDBPromise(this.window, "readwrite",
|
||||
function(aResolve, aReject, aTxn, aStore, aRevisionStore) {
|
||||
self.dataStore.updateInternal(aResolve, aStore, aRevisionStore, aId, aObj);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
add: function(aObj) {
|
||||
if (this.isReadOnly) {
|
||||
return throwReadOnly(this.window);
|
||||
}
|
||||
|
||||
let self = this;
|
||||
|
||||
// Promise<int>
|
||||
return this.dataStore.newDBPromise(this.window, "readwrite",
|
||||
function(aResolve, aReject, aTxn, aStore, aRevisionStore) {
|
||||
self.dataStore.addInternal(aResolve, aStore, aRevisionStore, aObj);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
remove: function(aId) {
|
||||
aId = parseInt(aId);
|
||||
if (isNaN(aId) || aId <= 0) {
|
||||
return throwInvalidArg(this.window);
|
||||
}
|
||||
|
||||
if (this.isReadOnly) {
|
||||
return throwReadOnly(this.window);
|
||||
}
|
||||
|
||||
let self = this;
|
||||
|
||||
// Promise<void>
|
||||
return this.dataStore.newDBPromise(this.window, "readwrite",
|
||||
function(aResolve, aReject, aTxn, aStore, aRevisionStore) {
|
||||
self.dataStore.removeInternal(aResolve, aStore, aRevisionStore, aId);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
clear: function() {
|
||||
if (this.isReadOnly) {
|
||||
return throwReadOnly(this.window);
|
||||
}
|
||||
|
||||
let self = this;
|
||||
|
||||
// Promise<void>
|
||||
return this.dataStore.newDBPromise(this.window, "readwrite",
|
||||
function(aResolve, aReject, aTxn, aStore, aRevisionStore) {
|
||||
self.dataStore.clearInternal(aResolve, aStore, aRevisionStore);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
get revisionId() {
|
||||
return this.dataStore.revisionId;
|
||||
},
|
||||
|
||||
getChanges: function(aRevisionId) {
|
||||
debug("GetChanges: " + aRevisionId);
|
||||
|
||||
if (aRevisionId === null || aRevisionId === undefined) {
|
||||
return this.window.Promise.reject(
|
||||
new this.window.DOMError("SyntaxError", "Invalid revisionId"));
|
||||
}
|
||||
|
||||
let self = this;
|
||||
|
||||
// Promise<DataStoreChanges>
|
||||
return new this.window.Promise(function(aResolve, aReject) {
|
||||
debug("GetChanges promise started");
|
||||
self.dataStore.db.revisionTxn(
|
||||
'readonly',
|
||||
function(aTxn, aStore) {
|
||||
debug("GetChanges transaction success");
|
||||
|
||||
let request = self.dataStore.db.getInternalRevisionId(
|
||||
aRevisionId,
|
||||
aStore,
|
||||
function(aInternalRevisionId) {
|
||||
if (aInternalRevisionId == undefined) {
|
||||
aResolve(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
// This object is the return value of this promise.
|
||||
// Initially we use maps, and then we convert them in array.
|
||||
let changes = {
|
||||
revisionId: '',
|
||||
addedIds: {},
|
||||
updatedIds: {},
|
||||
removedIds: {}
|
||||
};
|
||||
|
||||
let request = aStore.mozGetAll(self.window.IDBKeyRange.lowerBound(aInternalRevisionId, true));
|
||||
request.onsuccess = function(aEvent) {
|
||||
for (let i = 0; i < aEvent.target.result.length; ++i) {
|
||||
let data = aEvent.target.result[i];
|
||||
|
||||
switch (data.operation) {
|
||||
case REVISION_ADDED:
|
||||
changes.addedIds[data.objectId] = true;
|
||||
break;
|
||||
|
||||
case REVISION_UPDATED:
|
||||
// We don't consider an update if this object has been added
|
||||
// or if it has been already modified by a previous
|
||||
// operation.
|
||||
if (!(data.objectId in changes.addedIds) &&
|
||||
!(data.objectId in changes.updatedIds)) {
|
||||
changes.updatedIds[data.objectId] = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case REVISION_REMOVED:
|
||||
let id = data.objectId;
|
||||
|
||||
// If the object has been added in this range of revisions
|
||||
// we can ignore it and remove it from the list.
|
||||
if (id in changes.addedIds) {
|
||||
delete changes.addedIds[id];
|
||||
} else {
|
||||
changes.removedIds[id] = true;
|
||||
}
|
||||
|
||||
if (id in changes.updatedIds) {
|
||||
delete changes.updatedIds[id];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// The last revisionId.
|
||||
if (aEvent.target.result.length) {
|
||||
changes.revisionId = aEvent.target.result[aEvent.target.result.length - 1].revisionId;
|
||||
}
|
||||
|
||||
// From maps to arrays.
|
||||
changes.addedIds = Object.keys(changes.addedIds).map(function(aKey) { return parseInt(aKey, 10); });
|
||||
changes.updatedIds = Object.keys(changes.updatedIds).map(function(aKey) { return parseInt(aKey, 10); });
|
||||
changes.removedIds = Object.keys(changes.removedIds).map(function(aKey) { return parseInt(aKey, 10); });
|
||||
|
||||
let wrappedObject = ObjectWrapper.wrap(changes, self.window);
|
||||
aResolve(wrappedObject);
|
||||
};
|
||||
}
|
||||
);
|
||||
},
|
||||
function(aEvent) {
|
||||
debug("GetChanges transaction failed");
|
||||
aReject(createDOMError(self.window, aEvent));
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
getLength: function() {
|
||||
let self = this;
|
||||
|
||||
// Promise<int>
|
||||
return this.dataStore.newDBPromise(this.window, "readonly",
|
||||
function(aResolve, aReject, aTxn, aStore, aRevisionStore) {
|
||||
self.dataStore.getLengthInternal(aResolve, aStore);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
set onchange(aCallback) {
|
||||
debug("Set OnChange");
|
||||
this.__DOM_IMPL__.setEventHandler("onchange", aCallback);
|
||||
},
|
||||
|
||||
get onchange() {
|
||||
debug("Get OnChange");
|
||||
return this.__DOM_IMPL__.getEventHandler("onchange");
|
||||
}
|
||||
};
|
||||
|
||||
/* DataStore object */
|
||||
|
||||
function DataStore(aAppId, aName, aOwner, aReadOnly, aGlobalScope) {
|
||||
@ -249,336 +549,23 @@ DataStore.prototype = {
|
||||
},
|
||||
|
||||
exposeObject: function(aWindow, aReadOnly) {
|
||||
let self = this;
|
||||
let object = {
|
||||
callbacks: [],
|
||||
debug("Exposing Object");
|
||||
|
||||
// Public interface :
|
||||
|
||||
get name() {
|
||||
return self.name;
|
||||
},
|
||||
|
||||
get owner() {
|
||||
return self.owner;
|
||||
},
|
||||
|
||||
get readOnly() {
|
||||
return aReadOnly;
|
||||
},
|
||||
|
||||
get: function DS_get(aId) {
|
||||
aId = this.parseIds(aId);
|
||||
if (aId === null) {
|
||||
return this.throwInvalidArg(aWindow);
|
||||
}
|
||||
|
||||
// Promise<Object>
|
||||
return self.newDBPromise(aWindow, "readonly",
|
||||
function(aResolve, aReject, aTxn, aStore, aRevisionStore) {
|
||||
self.getInternal(aStore, Array.isArray(aId) ? aId : [ aId ],
|
||||
function(aResults) {
|
||||
aResolve(Array.isArray(aId) ? aResults : aResults[0]);
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
update: function DS_update(aId, aObj) {
|
||||
aId = parseInt(aId);
|
||||
if (isNaN(aId) || aId <= 0) {
|
||||
return this.throwInvalidArg(aWindow);
|
||||
}
|
||||
|
||||
if (aReadOnly) {
|
||||
return this.throwReadOnly(aWindow);
|
||||
}
|
||||
|
||||
// Promise<void>
|
||||
return self.newDBPromise(aWindow, "readwrite",
|
||||
function(aResolve, aReject, aTxn, aStore, aRevisionStore) {
|
||||
self.updateInternal(aResolve, aStore, aRevisionStore, aId, aObj);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
add: function DS_add(aObj) {
|
||||
if (aReadOnly) {
|
||||
return this.throwReadOnly(aWindow);
|
||||
}
|
||||
|
||||
// Promise<int>
|
||||
return self.newDBPromise(aWindow, "readwrite",
|
||||
function(aResolve, aReject, aTxn, aStore, aRevisionStore) {
|
||||
self.addInternal(aResolve, aStore, aRevisionStore, aObj);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
remove: function DS_remove(aId) {
|
||||
aId = parseInt(aId);
|
||||
if (isNaN(aId) || aId <= 0) {
|
||||
return this.throwInvalidArg(aWindow);
|
||||
}
|
||||
|
||||
if (aReadOnly) {
|
||||
return this.throwReadOnly(aWindow);
|
||||
}
|
||||
|
||||
// Promise<void>
|
||||
return self.newDBPromise(aWindow, "readwrite",
|
||||
function(aResolve, aReject, aTxn, aStore, aRevisionStore) {
|
||||
self.removeInternal(aResolve, aStore, aRevisionStore, aId);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
clear: function DS_clear() {
|
||||
if (aReadOnly) {
|
||||
return this.throwReadOnly(aWindow);
|
||||
}
|
||||
|
||||
// Promise<void>
|
||||
return self.newDBPromise(aWindow, "readwrite",
|
||||
function(aResolve, aReject, aTxn, aStore, aRevisionStore) {
|
||||
self.clearInternal(aResolve, aStore, aRevisionStore);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
get revisionId() {
|
||||
return self.revisionId;
|
||||
},
|
||||
|
||||
getChanges: function(aRevisionId) {
|
||||
debug("GetChanges: " + aRevisionId);
|
||||
|
||||
if (aRevisionId === null || aRevisionId === undefined) {
|
||||
return aWindow.Promise.reject(
|
||||
new aWindow.DOMError("SyntaxError", "Invalid revisionId"));
|
||||
}
|
||||
|
||||
// Promise<DataStoreChanges>
|
||||
return new aWindow.Promise(function(aResolve, aReject) {
|
||||
debug("GetChanges promise started");
|
||||
self.db.revisionTxn(
|
||||
'readonly',
|
||||
function(aTxn, aStore) {
|
||||
debug("GetChanges transaction success");
|
||||
|
||||
let request = self.db.getInternalRevisionId(
|
||||
aRevisionId,
|
||||
aStore,
|
||||
function(aInternalRevisionId) {
|
||||
if (aInternalRevisionId == undefined) {
|
||||
aResolve(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
// This object is the return value of this promise.
|
||||
// Initially we use maps, and then we convert them in array.
|
||||
let changes = {
|
||||
revisionId: '',
|
||||
addedIds: {},
|
||||
updatedIds: {},
|
||||
removedIds: {}
|
||||
};
|
||||
|
||||
let request = aStore.mozGetAll(aWindow.IDBKeyRange.lowerBound(aInternalRevisionId, true));
|
||||
request.onsuccess = function(aEvent) {
|
||||
for (let i = 0; i < aEvent.target.result.length; ++i) {
|
||||
let data = aEvent.target.result[i];
|
||||
|
||||
switch (data.operation) {
|
||||
case REVISION_ADDED:
|
||||
changes.addedIds[data.objectId] = true;
|
||||
break;
|
||||
|
||||
case REVISION_UPDATED:
|
||||
// We don't consider an update if this object has been added
|
||||
// or if it has been already modified by a previous
|
||||
// operation.
|
||||
if (!(data.objectId in changes.addedIds) &&
|
||||
!(data.objectId in changes.updatedIds)) {
|
||||
changes.updatedIds[data.objectId] = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case REVISION_REMOVED:
|
||||
let id = data.objectId;
|
||||
|
||||
// If the object has been added in this range of revisions
|
||||
// we can ignore it and remove it from the list.
|
||||
if (id in changes.addedIds) {
|
||||
delete changes.addedIds[id];
|
||||
} else {
|
||||
changes.removedIds[id] = true;
|
||||
}
|
||||
|
||||
if (id in changes.updatedIds) {
|
||||
delete changes.updatedIds[id];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// The last revisionId.
|
||||
if (aEvent.target.result.length) {
|
||||
changes.revisionId = aEvent.target.result[aEvent.target.result.length - 1].revisionId;
|
||||
}
|
||||
|
||||
// From maps to arrays.
|
||||
changes.addedIds = Object.keys(changes.addedIds).map(function(aKey) { return parseInt(aKey, 10); });
|
||||
changes.updatedIds = Object.keys(changes.updatedIds).map(function(aKey) { return parseInt(aKey, 10); });
|
||||
changes.removedIds = Object.keys(changes.removedIds).map(function(aKey) { return parseInt(aKey, 10); });
|
||||
|
||||
let wrappedObject = ObjectWrapper.wrap(changes, aWindow);
|
||||
aResolve(wrappedObject);
|
||||
};
|
||||
}
|
||||
);
|
||||
},
|
||||
function(aEvent) {
|
||||
debug("GetChanges transaction failed");
|
||||
aReject(createDOMError(aWindow, aEvent));
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
getLength: function DS_getLength() {
|
||||
// Promise<int>
|
||||
return self.newDBPromise(aWindow, "readonly",
|
||||
function(aResolve, aReject, aTxn, aStore, aRevisionStore) {
|
||||
self.getLengthInternal(aResolve, aStore);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
set onchange(aCallback) {
|
||||
debug("Set OnChange");
|
||||
this.onchangeCb = aCallback;
|
||||
},
|
||||
|
||||
get onchange() {
|
||||
debug("Get OnChange");
|
||||
return this.onchangeCb;
|
||||
},
|
||||
|
||||
addEventListener: function(aName, aCallback) {
|
||||
debug("addEventListener:" + aName);
|
||||
if (aName != 'change') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.callbacks.push(aCallback);
|
||||
},
|
||||
|
||||
removeEventListener: function(aName, aCallback) {
|
||||
debug('removeEventListener');
|
||||
let pos = this.callbacks.indexOf(aCallback);
|
||||
if (pos != -1) {
|
||||
this.callbacks.splice(pos, 1);
|
||||
}
|
||||
},
|
||||
|
||||
__exposedProps__: {
|
||||
name: 'r',
|
||||
owner: 'r',
|
||||
readOnly: 'r',
|
||||
get: 'r',
|
||||
update: 'r',
|
||||
add: 'r',
|
||||
remove: 'r',
|
||||
clear: 'r',
|
||||
revisionId: 'r',
|
||||
getChanges: 'r',
|
||||
getLength: 'r',
|
||||
onchange: 'rw',
|
||||
addEventListener: 'r',
|
||||
removeEventListener: 'r'
|
||||
},
|
||||
|
||||
throwInvalidArg: function(aWindow) {
|
||||
return aWindow.Promise.reject(
|
||||
new aWindow.DOMError("SyntaxError", "Non-numeric or invalid id"));
|
||||
},
|
||||
|
||||
throwReadOnly: function(aWindow) {
|
||||
return aWindow.Promise.reject(
|
||||
new aWindow.DOMError("ReadOnlyError", "DataStore in readonly mode"));
|
||||
},
|
||||
|
||||
parseIds: function(aId) {
|
||||
function parseId(aId) {
|
||||
aId = parseInt(aId);
|
||||
return (isNaN(aId) || aId <= 0) ? null : aId;
|
||||
}
|
||||
|
||||
if (!Array.isArray(aId)) {
|
||||
return parseId(aId);
|
||||
}
|
||||
|
||||
for (let i = 0; i < aId.length; ++i) {
|
||||
aId[i] = parseId(aId[i]);
|
||||
if (aId[i] === null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return aId;
|
||||
},
|
||||
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
debug("receiveMessage");
|
||||
|
||||
if (aMessage.name != "DataStore:Changed:Return:OK") {
|
||||
debug("Wrong message: " + aMessage.name);
|
||||
return;
|
||||
}
|
||||
|
||||
self.retrieveRevisionId(
|
||||
function() {
|
||||
if (object.onchangeCb || object.callbacks.length) {
|
||||
let wrappedData = ObjectWrapper.wrap(aMessage.data, aWindow);
|
||||
|
||||
// This array is used to avoid that a callback adds/removes
|
||||
// another eventListener.
|
||||
var cbs = [];
|
||||
if (object.onchangeCb) {
|
||||
cbs.push(object.onchangeCb);
|
||||
}
|
||||
|
||||
for (let i = 0; i < object.callbacks.length; ++i) {
|
||||
cbs.push(object.callbacks[i]);
|
||||
}
|
||||
|
||||
for (let i = 0; i < cbs.length; ++i) {
|
||||
try {
|
||||
cbs[i](wrappedData);
|
||||
} catch(e) {}
|
||||
}
|
||||
}
|
||||
},
|
||||
// Forcing the reading of the revisionId
|
||||
true
|
||||
);
|
||||
}
|
||||
};
|
||||
let exposedObject = new ExposedDataStore(aWindow, this, aReadOnly);
|
||||
let object = aWindow.DataStore._create(aWindow, exposedObject);
|
||||
|
||||
Services.obs.addObserver(function(aSubject, aTopic, aData) {
|
||||
let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
if (wId == object.innerWindowID) {
|
||||
cpmm.removeMessageListener("DataStore:Changed:Return:OK", object);
|
||||
if (wId == exposedObject.innerWindowID) {
|
||||
cpmm.removeMessageListener("DataStore:Changed:Return:OK", exposedObject);
|
||||
}
|
||||
}, "inner-window-destroyed", false);
|
||||
|
||||
let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
object.innerWindowID = util.currentInnerWindowID;
|
||||
exposedObject.innerWindowID = util.currentInnerWindowID;
|
||||
|
||||
cpmm.addMessageListener("DataStore:Changed:Return:OK", object);
|
||||
cpmm.addMessageListener("DataStore:Changed:Return:OK", exposedObject);
|
||||
cpmm.sendAsyncMessage("DataStore:RegisterForMessages",
|
||||
{ store: this.name, owner: this.owner });
|
||||
|
||||
@ -610,4 +597,3 @@ function DataStoreAccess(aAppId, aName, aOrigin, aReadOnly) {
|
||||
}
|
||||
|
||||
DataStoreAccess.prototype = {};
|
||||
|
||||
|
@ -45,36 +45,6 @@
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreErrorGet(id) {
|
||||
gStore.get(id).then(function(what) {
|
||||
ok(false, "store.get(" + id + ") retrieves data");
|
||||
}, function(error) {
|
||||
ok(true, "store.get() failed properly because the id is non-valid");
|
||||
ok(error instanceof DOMError, "error is a DOMError");
|
||||
is(error.name, "SyntaxError", "Error is a syntax error");
|
||||
}).then(runTest, cbError);
|
||||
}
|
||||
|
||||
function testStoreErrorUpdate(id) {
|
||||
gStore.update(id, "foo").then(function(what) {
|
||||
ok(false, "store.update(" + id + ") retrieves data");
|
||||
}, function(error) {
|
||||
ok(true, "store.update() failed properly because the id is non-valid");
|
||||
ok(error instanceof DOMError, "error is a DOMError");
|
||||
is(error.name, "SyntaxError", "Error is a syntax error");
|
||||
}).then(runTest, cbError);
|
||||
}
|
||||
|
||||
function testStoreErrorRemove(id) {
|
||||
gStore.remove(id).then(function(what) {
|
||||
ok(false, "store.remove(" + id + ") retrieves data");
|
||||
}, function(error) {
|
||||
ok(true, "store.remove() failed properly because the id is non-valid");
|
||||
ok(error instanceof DOMError, "error is a DOMError");
|
||||
is(error.name, "SyntaxError", "Error is a syntax error");
|
||||
}).then(runTest, cbError);
|
||||
}
|
||||
|
||||
function testStoreGet(id, value) {
|
||||
gStore.get(id).then(function(what) {
|
||||
ok(true, "store.get() retrieves data");
|
||||
@ -120,11 +90,6 @@
|
||||
// Test for GetDataStore
|
||||
testGetDataStores,
|
||||
|
||||
// Broken ID
|
||||
function() { testStoreErrorGet('hello world'); },
|
||||
function() { testStoreErrorGet(true); },
|
||||
function() { testStoreErrorGet(null); },
|
||||
|
||||
// Unknown ID
|
||||
function() { testStoreGet(42, undefined); },
|
||||
function() { testStoreGet(42, undefined); }, // twice
|
||||
@ -145,11 +110,6 @@
|
||||
gId = id; runTest(); }, cbError); },
|
||||
function() { testStoreGet(gId, "hello world"); },
|
||||
|
||||
// Broken update
|
||||
function() { testStoreErrorUpdate('hello world'); },
|
||||
function() { testStoreErrorUpdate(true); },
|
||||
function() { testStoreErrorUpdate(null); },
|
||||
|
||||
// Update + Get - string
|
||||
function() { testStoreUpdate(gId, "hello world 2").then(function() {
|
||||
runTest(); }, cbError); },
|
||||
@ -158,11 +118,6 @@
|
||||
// getLength
|
||||
function() { testStoreGetLength(3).then(function() { runTest(); }, cbError); },
|
||||
|
||||
// Broken remove
|
||||
function() { testStoreErrorRemove('hello world'); },
|
||||
function() { testStoreErrorRemove(true); },
|
||||
function() { testStoreErrorRemove(null); },
|
||||
|
||||
// Remove
|
||||
function() { testStoreRemove(gId).then(function(what) {
|
||||
runTest(); }, cbError); },
|
||||
|
@ -61,10 +61,11 @@
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function eventListener(obj) {
|
||||
ok(obj, "OnChangeListener is called with data");
|
||||
is(obj.id, gChangeId, "OnChangeListener is called with the right ID: " + obj.id);
|
||||
is(obj.operation, gChangeOperation, "OnChangeListener is called with the right operation:" + obj.operation + " " + gChangeOperation);
|
||||
function eventListener(evt) {
|
||||
ok(evt, "OnChangeListener is called with data");
|
||||
is(/[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}/.test(evt.revisionId), true, "event.revisionId returns something");
|
||||
is(evt.id, gChangeId, "OnChangeListener is called with the right ID: " + evt.id);
|
||||
is(evt.operation, gChangeOperation, "OnChangeListener is called with the right operation:" + evt.operation + " " + gChangeOperation);
|
||||
runTest();
|
||||
}
|
||||
|
||||
@ -75,6 +76,7 @@
|
||||
// Add onchange = function
|
||||
function() {
|
||||
gStore.onchange = eventListener;
|
||||
is(gStore.onchange, eventListener, "onChange is set");
|
||||
runTest();
|
||||
},
|
||||
|
||||
|
54
dom/webidl/DataStore.webidl
Normal file
54
dom/webidl/DataStore.webidl
Normal file
@ -0,0 +1,54 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
[Pref="dom.datastore.enabled",
|
||||
JSImplementation="@mozilla.org/dom/datastore;1"]
|
||||
interface DataStore : EventTarget {
|
||||
// Returns the label of the DataSource.
|
||||
readonly attribute DOMString name;
|
||||
|
||||
// Returns the origin of the DataSource (e.g., 'facebook.com').
|
||||
// This value is the manifest URL of the owner app.
|
||||
readonly attribute DOMString owner;
|
||||
|
||||
// is readOnly a F(current_app, datastore) function? yes
|
||||
readonly attribute boolean readOnly;
|
||||
|
||||
// Promise<any>
|
||||
Promise get(unsigned long id);
|
||||
|
||||
// Promise<any>
|
||||
Promise get(sequence<unsigned long> id);
|
||||
|
||||
// Promise<void>
|
||||
Promise update(unsigned long id, any obj);
|
||||
|
||||
// Promise<unsigned long>
|
||||
Promise add(any obj);
|
||||
|
||||
// Promise<boolean>
|
||||
Promise remove(unsigned long id);
|
||||
|
||||
// Promise<void>
|
||||
Promise clear();
|
||||
|
||||
readonly attribute DOMString revisionId;
|
||||
|
||||
attribute EventHandler onchange;
|
||||
|
||||
// Promise<DataStoreChanges>
|
||||
Promise getChanges(DOMString revisionId);
|
||||
|
||||
// Promise<unsigned long>
|
||||
Promise getLength();
|
||||
};
|
||||
|
||||
dictionary DataStoreChanges {
|
||||
DOMString revisionId;
|
||||
sequence<unsigned long> addedIds;
|
||||
sequence<unsigned long> updatedIds;
|
||||
sequence<unsigned long> removedIds;
|
||||
};
|
19
dom/webidl/DataStoreChangeEvent.webidl
Normal file
19
dom/webidl/DataStoreChangeEvent.webidl
Normal file
@ -0,0 +1,19 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
dictionary DataStoreChangeEventInit : EventInit {
|
||||
DOMString revisionId = "";
|
||||
unsigned long id = 0;
|
||||
DOMString operation = "";
|
||||
};
|
||||
|
||||
[Pref="dom.datastore.enabled",
|
||||
Constructor(DOMString type, optional DataStoreChangeEventInit eventInitDict)]
|
||||
interface DataStoreChangeEvent : Event {
|
||||
readonly attribute DOMString revisionId;
|
||||
readonly attribute unsigned long id;
|
||||
readonly attribute DOMString operation;
|
||||
};
|
@ -73,6 +73,7 @@ WEBIDL_FILES = [
|
||||
'DOMTokenList.webidl',
|
||||
'DOMTransaction.webidl',
|
||||
'DataContainerEvent.webidl',
|
||||
'DataStore.webidl',
|
||||
'DelayNode.webidl',
|
||||
'DesktopNotification.webidl',
|
||||
'DeviceMotionEvent.webidl',
|
||||
@ -535,6 +536,7 @@ if CONFIG['ENABLE_TESTS']:
|
||||
|
||||
GENERATED_EVENTS_WEBIDL_FILES = [
|
||||
'BlobEvent.webidl',
|
||||
'DataStoreChangeEvent.webidl',
|
||||
'DeviceLightEvent.webidl',
|
||||
'DeviceProximityEvent.webidl',
|
||||
'MediaStreamEvent.webidl',
|
||||
|
Loading…
Reference in New Issue
Block a user