Bug 748630: Support IDBTransaction.error. r=bent

--HG--
extra : rebase_source : 4f832cefc08e6c55a7dded3a26baeb1678479387
This commit is contained in:
Kyle Huey 2012-06-25 12:15:17 -07:00
parent a19e2ef687
commit 3c9664b712
20 changed files with 95 additions and 32 deletions

View File

@ -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!");
}
}

View File

@ -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);

View File

@ -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),

View File

@ -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;

View File

@ -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.
*/

View File

@ -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

View File

@ -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");

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
};

View File

@ -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++;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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 });