зеркало из https://github.com/mozilla/gecko-dev.git
Bug 748630: Support IDBTransaction.error. r=bent
This commit is contained in:
Родитель
bb676c03b1
Коммит
67ae468771
|
@ -471,7 +471,7 @@ AsyncConnectionHelper::OnError()
|
|||
if (doDefault &&
|
||||
mTransaction &&
|
||||
mTransaction->IsOpen() &&
|
||||
NS_FAILED(mTransaction->Abort())) {
|
||||
NS_FAILED(mTransaction->Abort(mRequest))) {
|
||||
NS_WARNING("Failed to abort transaction!");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -274,8 +274,7 @@ IDBRequest::GetError(nsIDOMDOMError** aError)
|
|||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (!mHaveResultOrErrorCode) {
|
||||
// XXX Need a real error code here.
|
||||
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(*aError = mError);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "nsIAppShell.h"
|
||||
#include "nsIScriptContext.h"
|
||||
|
||||
#include "DOMError.h"
|
||||
#include "mozilla/storage.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
|
@ -529,12 +530,24 @@ IDBTransaction::AbortWithCode(nsresult aAbortCode)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
IDBTransaction::Abort(IDBRequest* aRequest)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
NS_ASSERTION(aRequest, "This is undesirable.");
|
||||
|
||||
aRequest->GetError(getter_AddRefs(mError));
|
||||
|
||||
return AbortWithCode(aRequest->GetErrorCode());
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(IDBTransaction)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBTransaction,
|
||||
IDBWrapperCache)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mDatabase,
|
||||
nsIDOMEventTarget)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mError);
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(error)
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(complete)
|
||||
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(abort)
|
||||
|
@ -548,6 +561,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBTransaction, IDBWrapperCache)
|
||||
// Don't unlink mDatabase!
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mError);
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(error)
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(complete)
|
||||
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(abort)
|
||||
|
@ -605,6 +619,19 @@ IDBTransaction::GetMode(nsAString& aMode)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IDBTransaction::GetError(nsIDOMDOMError** aError)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (IsOpen()) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(*aError = mError);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IDBTransaction::GetObjectStoreNames(nsIDOMDOMStringList** aObjectStores)
|
||||
{
|
||||
|
@ -777,6 +804,14 @@ CommitHelper::Run()
|
|||
|
||||
event = CreateGenericEvent(NS_LITERAL_STRING(ABORT_EVT_STR),
|
||||
eDoesBubble, eNotCancelable);
|
||||
|
||||
// The transaction may already have an error object (e.g. if one of the
|
||||
// requests failed). If it doesn't, and it wasn't aborted
|
||||
// programmatically, create one now.
|
||||
if (!mTransaction->mError &&
|
||||
mAbortCode != NS_ERROR_DOM_INDEXEDDB_ABORT_ERR) {
|
||||
mTransaction->mError = DOMError::CreateForNSResult(mAbortCode);
|
||||
}
|
||||
}
|
||||
else {
|
||||
event = CreateGenericEvent(NS_LITERAL_STRING(COMPLETE_EVT_STR),
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "mozIStorageStatement.h"
|
||||
#include "mozIStorageFunction.h"
|
||||
#include "nsIIDBTransaction.h"
|
||||
#include "nsIDOMDOMError.h"
|
||||
#include "nsIRunnable.h"
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
|
@ -30,6 +31,7 @@ BEGIN_INDEXEDDB_NAMESPACE
|
|||
|
||||
class AsyncConnectionHelper;
|
||||
class CommitHelper;
|
||||
class IDBRequest;
|
||||
class IndexedDBDatabaseChild;
|
||||
class IndexedDBTransactionChild;
|
||||
class IndexedDBTransactionParent;
|
||||
|
@ -185,6 +187,9 @@ public:
|
|||
nsresult
|
||||
AbortWithCode(nsresult aAbortCode);
|
||||
|
||||
nsresult
|
||||
Abort(IDBRequest* aRequest);
|
||||
|
||||
nsresult
|
||||
GetAbortCode() const
|
||||
{
|
||||
|
@ -207,6 +212,7 @@ private:
|
|||
|
||||
nsRefPtr<IDBDatabase> mDatabase;
|
||||
nsRefPtr<DatabaseInfo> mDatabaseInfo;
|
||||
nsCOMPtr<nsIDOMDOMError> mError;
|
||||
nsTArray<nsString> mObjectStoreNames;
|
||||
ReadyState mReadyState;
|
||||
Mode mMode;
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIDOMDOMError.idl"
|
||||
|
||||
interface nsIDOMDOMError;
|
||||
interface nsIDOMEventListener;
|
||||
interface nsIIDBTransaction;
|
||||
|
||||
/**
|
||||
* IDBReqeust interface. See
|
||||
* IDBRequest interface. See
|
||||
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBRequest for more
|
||||
* information.
|
||||
*/
|
||||
|
|
|
@ -11,13 +11,14 @@ interface nsIIDBObjectStore;
|
|||
interface nsIIDBRequest;
|
||||
interface nsIIDBDatabase;
|
||||
interface nsIDOMDOMStringList;
|
||||
interface nsIDOMDOMError;
|
||||
|
||||
/**
|
||||
* IDBDTransaction interface. See
|
||||
* http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBTransaction
|
||||
* for more information.
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(e4927c76-4f1f-4d7d-80ad-8186e1677da6)]
|
||||
[scriptable, builtinclass, uuid(79f73099-02ff-416d-9754-5a315e29ee4f)]
|
||||
interface nsIIDBTransaction : nsISupports
|
||||
{
|
||||
readonly attribute nsIIDBDatabase db;
|
||||
|
@ -25,6 +26,8 @@ interface nsIIDBTransaction : nsISupports
|
|||
// "readonly", "readwrite" or "versionchange"
|
||||
readonly attribute DOMString mode;
|
||||
|
||||
readonly attribute nsIDOMDOMError error;
|
||||
|
||||
readonly attribute nsIDOMDOMStringList objectStoreNames;
|
||||
|
||||
nsIIDBObjectStore
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
setTimeout(testFinishedCallback, 0, "complete");
|
||||
}
|
||||
transaction.onabort = function(event) {
|
||||
setTimeout(testFinishedCallback, 0, "abort");
|
||||
setTimeout(testFinishedCallback, 0, "abort " + event.target.error.name);
|
||||
}
|
||||
|
||||
let objectStore = transaction.objectStore("foo");
|
||||
|
|
|
@ -37,7 +37,7 @@ function test1()
|
|||
is(result, "complete", "Got 'complete' result");
|
||||
}
|
||||
else {
|
||||
is(result, "abort", "Got 'abort' result");
|
||||
is(result, "abort UnknownError", "Got 'abort' result");
|
||||
}
|
||||
|
||||
if (addMoreTest1Count >= seenPopupCount + 5) {
|
||||
|
@ -108,7 +108,7 @@ function test2()
|
|||
if (addMoreCount > addMoreTest1Count + 5) {
|
||||
setFinishedCallback(function(result) {
|
||||
is(result, "finished", "Got 'finished' result");
|
||||
is(lastResult, "abort", "Aborted as expected");
|
||||
is(lastResult, "abort UnknownError", "Aborted as expected");
|
||||
ok(!seenPopup, "No popup");
|
||||
is(getPermission(testPageURL, "indexedDB-unlimited"),
|
||||
Components.interfaces.nsIPermissionManager.DENY_ACTION,
|
||||
|
|
|
@ -61,8 +61,10 @@
|
|||
is(db.version, 1, "Correct version");
|
||||
is(db.objectStoreNames.length, 0, "Correct objectStoreNames length");
|
||||
|
||||
event.target.transaction.oncomplete = unexpectedSuccessHandler;
|
||||
event.target.transaction.onabort = grabEventAndContinueHandler;
|
||||
let trans = event.target.transaction;
|
||||
|
||||
trans.oncomplete = unexpectedSuccessHandler;
|
||||
trans.onabort = grabEventAndContinueHandler;
|
||||
|
||||
let objectStore = db.createObjectStore("foo");
|
||||
|
||||
|
@ -84,10 +86,12 @@
|
|||
is(event.type, "abort", "Got a transaction abort event");
|
||||
is(db.version, 1, "Correct version");
|
||||
is(db.objectStoreNames.length, 1, "Correct objectStoreNames length");
|
||||
is(trans.error.name, "ConstraintError", "Right error");
|
||||
ok(trans.error === request.error, "Object identity holds");
|
||||
|
||||
event = yield;
|
||||
is(event.type, "error", "Got request error event");
|
||||
is(event.target.error.name, "AbortError", "Right error");
|
||||
is(event.target.error.name, "ConstraintError", "Right error");
|
||||
|
||||
let request = mozIndexedDB.open(window.location.pathname, 1);
|
||||
request.onerror = errorHandler;
|
||||
|
|
|
@ -96,11 +96,13 @@
|
|||
event = yield;
|
||||
|
||||
is(event.type, "abort", "Got transaction abort event");
|
||||
is(event.target.error, null, "Got null error object");
|
||||
|
||||
event = yield;
|
||||
|
||||
is(event.type, "error", "Got IDBOpenDBRequest error event");
|
||||
is(event.target, openrequest, "Right event target");
|
||||
is(event.target.error.name, "AbortError", "Right error name");
|
||||
|
||||
finishTest();
|
||||
yield;
|
||||
|
|
|
@ -112,17 +112,20 @@ function unexpectedSuccessHandler()
|
|||
finishTest();
|
||||
}
|
||||
|
||||
function ExpectError(name)
|
||||
function ExpectError(name, preventDefault)
|
||||
{
|
||||
this._name = name;
|
||||
this._preventDefault = preventDefault;
|
||||
}
|
||||
ExpectError.prototype = {
|
||||
handleEvent: function(event)
|
||||
{
|
||||
is(event.type, "error", "Got an error event");
|
||||
is(event.target.error.name, this._name, "Expected error was thrown.");
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (this._preventDefault) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
grabEventAndContinueHandler(event);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -225,26 +225,26 @@
|
|||
trans.objectStore("store2").add({ unique: 1, id: "unique" });
|
||||
|
||||
trans.objectStore("store1").add({ error: 1, unique: 1 }).onerror =
|
||||
new ExpectError("ConstraintError");
|
||||
new ExpectError("ConstraintError", true);
|
||||
trans.objectStore("store1").add({ error: 2 }).onsuccess =
|
||||
genCheck(c1++, { error: 2 }, "first" + test);
|
||||
yield; yield;
|
||||
|
||||
trans.objectStore("store2").add({ error: 3, unique: 1 }).onerror =
|
||||
new ExpectError("ConstraintError");
|
||||
new ExpectError("ConstraintError", true);
|
||||
trans.objectStore("store2").add({ error: 4 }).onsuccess =
|
||||
genCheck(c2, { error: 4, id: c2 }, "second" + test);
|
||||
c2++;
|
||||
yield; yield;
|
||||
|
||||
trans.objectStore("store1").add({ error: 5, unique: 1 }, 100000).onerror =
|
||||
new ExpectError("ConstraintError");
|
||||
new ExpectError("ConstraintError", true);
|
||||
trans.objectStore("store1").add({ error: 6 }).onsuccess =
|
||||
genCheck(c1++, { error: 6 }, "third" + test);
|
||||
yield; yield;
|
||||
|
||||
trans.objectStore("store2").add({ error: 7, unique: 1, id: 100000 }).onerror =
|
||||
new ExpectError("ConstraintError");
|
||||
new ExpectError("ConstraintError", true);
|
||||
trans.objectStore("store2").add({ error: 8 }).onsuccess =
|
||||
genCheck(c2, { error: 8, id: c2 }, "fourth" + test);
|
||||
c2++;
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
request = objectStore.put({ id: 5, index: 6 });
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
request.onerror = new ExpectError("ConstraintError");
|
||||
request.onerror = new ExpectError("ConstraintError", true);
|
||||
event = yield;
|
||||
|
||||
event.preventDefault();
|
||||
|
@ -58,7 +58,7 @@
|
|||
|
||||
request = cursor.update(cursor.value);
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
request.onerror = new ExpectError("ConstraintError");
|
||||
request.onerror = new ExpectError("ConstraintError", true);
|
||||
};
|
||||
|
||||
yield;
|
||||
|
|
|
@ -30,7 +30,7 @@ function testSteps()
|
|||
is(request.result, key, "Correct key");
|
||||
|
||||
request = objectStore.add({}, key);
|
||||
request.onerror = new ExpectError("ConstraintError");
|
||||
request.onerror = new ExpectError("ConstraintError", true);
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
yield;
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ function testSteps()
|
|||
is(event.target.result, "foopy", "Got correct result");
|
||||
|
||||
let request = objectStore.add("foopy", 5);
|
||||
request.onerror = new ExpectError("ConstraintError");
|
||||
request.onerror = new ExpectError("ConstraintError", true);
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
|
||||
trans.oncomplete = grabEventAndContinueHandler;
|
||||
|
|
|
@ -189,7 +189,7 @@ function testSteps()
|
|||
.objectStore(objectStoreName);
|
||||
request = objectStore.add({ name: "Bob", height: 62, weight: 170 },
|
||||
"237-23-7738");
|
||||
request.onerror = new ExpectError("ConstraintError");
|
||||
request.onerror = new ExpectError("ConstraintError", true);
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
event = yield;
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ function testSteps()
|
|||
is(event.target.result, key1, "put gave back the same key");
|
||||
|
||||
request = objectStore.add({id:10});
|
||||
request.onerror = new ExpectError("ConstraintError");
|
||||
request.onerror = new ExpectError("ConstraintError", true);
|
||||
request.onsuccess = unexpectedSuccessHandler;
|
||||
event = yield;
|
||||
|
||||
|
|
|
@ -176,14 +176,14 @@ function testSteps()
|
|||
if (keyI === 0) {
|
||||
doCompare(-0);
|
||||
let req = store.add(i, -0);
|
||||
req.onerror = new ExpectError("ConstraintError");
|
||||
req.onerror = new ExpectError("ConstraintError", true);
|
||||
req.onsuccess = unexpectedSuccessHandler;
|
||||
yield;
|
||||
}
|
||||
else if (Array.isArray(keyI) && keyI.length === 1 && keyI[0] === 0) {
|
||||
doCompare([-0]);
|
||||
let req = store.add(i, [-0]);
|
||||
req.onerror = new ExpectError("ConstraintError");
|
||||
req.onerror = new ExpectError("ConstraintError", true);
|
||||
req.onsuccess = unexpectedSuccessHandler;
|
||||
yield;
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ function testSteps()
|
|||
is(event.target, requests[2], "fired at the right request");
|
||||
event.target.result.close();
|
||||
|
||||
requests[3].onerror = new ExpectError("VersionError");
|
||||
requests[3].onerror = new ExpectError("VersionError", true);
|
||||
|
||||
event = yield;
|
||||
|
||||
|
|
|
@ -7,17 +7,19 @@ var testGenerator = testSteps();
|
|||
|
||||
var abortFired = false;
|
||||
|
||||
function abortListener() { abortFired = true; }
|
||||
function abortListener(evt)
|
||||
{
|
||||
abortFired = true;
|
||||
is(evt.target.error, null, "Expect a null error for an aborted transaction");
|
||||
}
|
||||
|
||||
function testSteps()
|
||||
{
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
const name = this.window ? window.location.pathname : "Splendid Test";
|
||||
const description = "My Test Database";
|
||||
|
||||
|
||||
let request = mozIndexedDB.open(name, 1, description);
|
||||
let request = mozIndexedDB.open(name, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
@ -31,6 +33,15 @@ function testSteps()
|
|||
let index;
|
||||
|
||||
transaction = event.target.transaction;
|
||||
|
||||
try {
|
||||
let error = transaction.error;
|
||||
ok(false, "Expect an exception");
|
||||
} catch(e) {
|
||||
ok(true, "Got an exception.");
|
||||
is(e.name, "InvalidStateError", "Got the right exception");
|
||||
}
|
||||
|
||||
objectStore = db.createObjectStore("foo", { autoIncrement: true });
|
||||
index = objectStore.createIndex("fooindex", "indexKey", { unique: true });
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче