Bug 748630: Support IDBTransaction.error. r=bent
authorKyle Huey <khuey@kylehuey.com>
Mon, 25 Jun 2012 12:15:17 -0700
changeset 112752 e4e2536462b424ad65d4b6038c2d5c920ed5a781
parent 112751 5238faf97c3c92d125eb2303d91f8d5ee0c6079f
child 112753 6e4fca267ad8034431b54317d283ddaa3d4073e7
push id1708
push userakeybl@mozilla.com
push dateMon, 19 Nov 2012 21:10:21 +0000
treeherdermozilla-beta@27b14fe50103 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent
bugs748630
milestone16.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 748630: Support IDBTransaction.error. r=bent
content/base/src/nsINode.cpp
dom/indexedDB/AsyncConnectionHelper.cpp
dom/indexedDB/IDBRequest.cpp
dom/indexedDB/IDBTransaction.cpp
dom/indexedDB/IDBTransaction.h
dom/indexedDB/nsIIDBRequest.idl
dom/indexedDB/nsIIDBTransaction.idl
dom/indexedDB/test/browser_quotaPrompt.html
dom/indexedDB/test/browser_quotaPromptDeny.js
dom/indexedDB/test/error_events_abort_transactions_iframe.html
dom/indexedDB/test/exceptions_in_success_events_iframe.html
dom/indexedDB/test/helpers.js
dom/indexedDB/test/test_autoIncrement.html
dom/indexedDB/test/test_unique_index_update.html
dom/indexedDB/test/unit/test_add_twice_failure.js
dom/indexedDB/test/unit/test_index_empty_keyPath.js
dom/indexedDB/test/unit/test_indexes.js
dom/indexedDB/test/unit/test_key_requirements.js
dom/indexedDB/test/unit/test_keys.js
dom/indexedDB/test/unit/test_traffic_jam.js
dom/indexedDB/test/unit/test_transaction_abort.js
--- a/dom/indexedDB/AsyncConnectionHelper.cpp
+++ b/dom/indexedDB/AsyncConnectionHelper.cpp
@@ -466,17 +466,17 @@ AsyncConnectionHelper::OnError()
     NS_ASSERTION(!mTransaction ||
                  mTransaction->IsOpen() ||
                  mTransaction->IsAborted(),
                  "How else can this be closed?!");
 
     if (doDefault &&
         mTransaction &&
         mTransaction->IsOpen() &&
-        NS_FAILED(mTransaction->Abort())) {
+        NS_FAILED(mTransaction->Abort(mRequest))) {
       NS_WARNING("Failed to abort transaction!");
     }
   }
   else {
     NS_WARNING("DispatchEvent failed!");
   }
 }
 
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -269,18 +269,17 @@ IDBRequest::GetResult(jsval* aResult)
 }
 
 NS_IMETHODIMP
 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);
   return NS_OK;
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(IDBRequest)
 
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -6,16 +6,17 @@
 
 #include "base/basictypes.h"
 
 #include "IDBTransaction.h"
 
 #include "nsIAppShell.h"
 #include "nsIScriptContext.h"
 
+#include "DOMError.h"
 #include "mozilla/storage.h"
 #include "nsContentUtils.h"
 #include "nsDOMClassInfoID.h"
 #include "nsDOMLists.h"
 #include "nsEventDispatcher.h"
 #include "nsPIDOMWindow.h"
 #include "nsProxyRelease.h"
 #include "nsThreadUtils.h"
@@ -524,35 +525,48 @@ IDBTransaction::AbortWithCode(nsresult a
   // abort event will be fired when all outstanding requests finish.
   if (needToCommitOrRollback) {
     return CommitOrRollback();
   }
 
   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)
 
   for (PRUint32 i = 0; i < tmp->mCreatedObjectStores.Length(); i++) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCreatedObjectStores[i]");
     cb.NoteXPCOMChild(static_cast<nsIIDBObjectStore*>(
                       tmp->mCreatedObjectStores[i].get()));
   }
 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)
 
   tmp->mCreatedObjectStores.Clear();
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
@@ -601,16 +615,29 @@ IDBTransaction::GetMode(nsAString& aMode
       NS_NOTREACHED("Bad mode value!");
       return NS_ERROR_UNEXPECTED;
   }
 
   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)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   nsRefPtr<nsDOMStringList> list(new nsDOMStringList());
 
   nsAutoTArray<nsString, 10> stackArray;
   nsTArray<nsString>* arrayOfNames;
@@ -772,16 +799,24 @@ CommitHelper::Run()
         // This will make the database take a snapshot of it's DatabaseInfo
         mTransaction->Database()->Close();
         // Then remove the info from the hash as it contains invalid data.
         DatabaseInfo::Remove(mTransaction->Database()->Id());
       }
 
       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),
                                  eDoesNotBubble, eNotCancelable);
     }
     NS_ENSURE_TRUE(event, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
     bool dummy;
--- a/dom/indexedDB/IDBTransaction.h
+++ b/dom/indexedDB/IDBTransaction.h
@@ -8,16 +8,17 @@
 #define mozilla_dom_indexeddb_idbtransaction_h__
 
 #include "mozilla/dom/indexedDB/IndexedDatabase.h"
 
 #include "mozIStorageConnection.h"
 #include "mozIStorageStatement.h"
 #include "mozIStorageFunction.h"
 #include "nsIIDBTransaction.h"
+#include "nsIDOMDOMError.h"
 #include "nsIRunnable.h"
 
 #include "nsAutoPtr.h"
 #include "nsClassHashtable.h"
 #include "nsHashKeys.h"
 #include "nsInterfaceHashtable.h"
 
 #include "mozilla/dom/indexedDB/IDBDatabase.h"
@@ -25,16 +26,17 @@
 #include "mozilla/dom/indexedDB/FileInfo.h"
 
 class nsIThread;
 
 BEGIN_INDEXEDDB_NAMESPACE
 
 class AsyncConnectionHelper;
 class CommitHelper;
+class IDBRequest;
 class IndexedDBDatabaseChild;
 class IndexedDBTransactionChild;
 class IndexedDBTransactionParent;
 struct ObjectStoreInfo;
 class TransactionThreadPool;
 class UpdateRefcountFunction;
 
 class IDBTransactionListener
@@ -181,16 +183,19 @@ public:
   nsresult
   ObjectStoreInternal(const nsAString& aName,
                       IDBObjectStore** _retval);
 
   nsresult
   AbortWithCode(nsresult aAbortCode);
 
   nsresult
+  Abort(IDBRequest* aRequest);
+
+  nsresult
   GetAbortCode() const
   {
     return mAbortCode;
   }
 
 private:
   // Should only be called directly through IndexedDBDatabaseChild.
   static already_AddRefed<IDBTransaction>
@@ -202,16 +207,17 @@ private:
 
   IDBTransaction();
   ~IDBTransaction();
 
   nsresult CommitOrRollback();
 
   nsRefPtr<IDBDatabase> mDatabase;
   nsRefPtr<DatabaseInfo> mDatabaseInfo;
+  nsCOMPtr<nsIDOMDOMError> mError;
   nsTArray<nsString> mObjectStoreNames;
   ReadyState mReadyState;
   Mode mMode;
   PRUint32 mPendingRequests;
 
   // Only touched on the main thread.
   NS_DECL_EVENT_HANDLER(error)
   NS_DECL_EVENT_HANDLER(complete)
--- a/dom/indexedDB/nsIIDBRequest.idl
+++ b/dom/indexedDB/nsIIDBRequest.idl
@@ -1,22 +1,22 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #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.
  */
 [scriptable, builtinclass, uuid(4b9d901b-14a4-430c-b41b-5ecb238f4184)]
 interface nsIIDBRequest : nsISupports
 {
   readonly attribute jsval result;
 
--- a/dom/indexedDB/nsIIDBTransaction.idl
+++ b/dom/indexedDB/nsIIDBTransaction.idl
@@ -6,30 +6,33 @@
 
 #include "nsISupports.idl"
 
 interface nsIDOMEventListener;
 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;
 
   // "readonly", "readwrite" or "versionchange"
   readonly attribute DOMString mode;
 
+  readonly attribute nsIDOMDOMError error;
+
   readonly attribute nsIDOMDOMStringList objectStoreNames;
 
   nsIIDBObjectStore
   objectStore([Null(Stringify)] in DOMString name);
 
   // Don't commit the transaction.
   void abort();
 
--- a/dom/indexedDB/test/browser_quotaPrompt.html
+++ b/dom/indexedDB/test/browser_quotaPrompt.html
@@ -12,17 +12,17 @@
 
       function onAddMore() {
         let transaction = db.transaction("foo", "readwrite");
 
         transaction.oncomplete = function(event) {
           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");
         let obj = {
           foo: "                                                              ",
           bar: "                                                              ",
           baz: "                                                              "
         };
--- a/dom/indexedDB/test/browser_quotaPromptDeny.js
+++ b/dom/indexedDB/test/browser_quotaPromptDeny.js
@@ -32,17 +32,17 @@ function test1()
     setFinishedCallback(function(result) {
       is(result, "ready", "Got 'ready' result");
 
       setFinishedCallback(function(result) {
         if (!seenPopupCount) {
           is(result, "complete", "Got 'complete' result");
         }
         else {
-          is(result, "abort", "Got 'abort' result");
+          is(result, "abort UnknownError", "Got 'abort' result");
         }
 
         if (addMoreTest1Count >= seenPopupCount + 5) {
           setFinishedCallback(function(result) {
             is(result, "finished", "Got 'finished' result");
             is(getPermission(testPageURL, "indexedDB-unlimited"),
                Components.interfaces.nsIPermissionManager.DENY_ACTION,
                "Correct permission set");
@@ -103,17 +103,17 @@ function test2()
         ok(!seenPopup, "No popup");
         is(getPermission(testPageURL, "indexedDB-unlimited"),
            Components.interfaces.nsIPermissionManager.DENY_ACTION,
            "Correct permission set");
 
         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,
                "Correct permission set");
 
             gBrowser.removeCurrentTab();
             unregisterAllPopupEventHandlers();
             removePermission(testPageURL, "indexedDB");
--- a/dom/indexedDB/test/error_events_abort_transactions_iframe.html
+++ b/dom/indexedDB/test/error_events_abort_transactions_iframe.html
@@ -56,18 +56,20 @@
       request.onupgradeneeded = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
 
       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");
 
       is(db.objectStoreNames.length, 1, "Correct objectStoreNames length");
       ok(db.objectStoreNames.contains("foo"), "Has correct objectStore");
 
       request = objectStore.add({}, 1);
       request.onsuccess = grabEventAndContinueHandler;
@@ -79,20 +81,22 @@
       request.onerror = function(event) {
         // Don't do anything! We want this error.
       }
       event = yield;
 
       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;
       request.onupgradeneeded = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
 
--- a/dom/indexedDB/test/exceptions_in_success_events_iframe.html
+++ b/dom/indexedDB/test/exceptions_in_success_events_iframe.html
@@ -91,21 +91,23 @@
       request = objectStore.add({}, 1);
       request.onsuccess = function(event) {
         throw "foo";
       };
 
       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;
     }
   </script>
 
 </head>
 
--- a/dom/indexedDB/test/helpers.js
+++ b/dom/indexedDB/test/helpers.js
@@ -107,27 +107,30 @@ function browserErrorHandler(event)
 }
 
 function unexpectedSuccessHandler()
 {
   ok(false, "Got success, but did not expect it!");
   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);
   }
 };
 
 function compareKeys(k1, k2) {
   let t = typeof k1;
   if (t != typeof k2)
     return false;
--- a/dom/indexedDB/test/test_autoIncrement.html
+++ b/dom/indexedDB/test/test_autoIncrement.html
@@ -220,36 +220,36 @@
 
       // Test that error inserts doesn't increase generator
       test = " for test error inserts";
       trans = db.transaction(["store1", "store2"], RW);
       trans.objectStore("store1").add({ unique: 1 }, -1);
       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++;
       yield; yield;
 
       // Test that aborts doesn't increase generator
       test = " for test aborted transaction";
       trans = db.transaction(["store1", "store2"], RW);
--- a/dom/indexedDB/test/test_unique_index_update.html
+++ b/dom/indexedDB/test/test_unique_index_update.html
@@ -36,34 +36,34 @@
       is(event.type, "success", "expect a success event");
 
       for each (let autoIncrement in [false, true]) {
         objectStore = db.transaction(autoIncrement, IDBTransaction.READ_WRITE)
                         .objectStore(autoIncrement);
 
         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();
 
         let keyRange = IDBKeyRange.only(5);
 
         objectStore.index("").openCursor(keyRange).onsuccess = function(event) {
           let cursor = event.target.result;
           ok(cursor, "Must have a cursor here");
 
           is(cursor.value.index, 5, "Still have the right index value");
 
           cursor.value.index = 6;
 
           request = cursor.update(cursor.value);
           request.onsuccess = unexpectedSuccessHandler;
-          request.onerror = new ExpectError("ConstraintError");
+          request.onerror = new ExpectError("ConstraintError", true);
         };
 
         yield;
       }
 
       finishTest();
       yield;
     }
--- a/dom/indexedDB/test/unit/test_add_twice_failure.js
+++ b/dom/indexedDB/test/unit/test_add_twice_failure.js
@@ -25,16 +25,16 @@ function testSteps()
   request = objectStore.add({}, key);
   request.onerror = errorHandler;
   request.onsuccess = grabEventAndContinueHandler;
   event = yield;
 
   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;
 
   finishTest();
   yield;
 }
 
--- a/dom/indexedDB/test/unit/test_index_empty_keyPath.js
+++ b/dom/indexedDB/test/unit/test_index_empty_keyPath.js
@@ -65,17 +65,17 @@ function testSteps()
   request.onerror = errorHandler;
   request.onsuccess = grabEventAndContinueHandler;
   
   let event = yield;
 
   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;
 
   yield;
   yield;
 
   finishTest();
--- a/dom/indexedDB/test/unit/test_indexes.js
+++ b/dom/indexedDB/test/unit/test_indexes.js
@@ -184,17 +184,17 @@ function testSteps()
 
   is(keyIndex, objectStoreData.length - 1, "Saw all the expected keys");
 
   // Check that the name index enforces its unique constraint.
   objectStore = db.transaction(objectStoreName, "readwrite")
                   .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;
 
   ok(true, "Test group 3");
 
   keyIndex = objectStoreDataNameSort.length - 1;
 
   request = objectStore.index("name").openKeyCursor(null, "prev");
--- a/dom/indexedDB/test/unit/test_key_requirements.js
+++ b/dom/indexedDB/test/unit/test_key_requirements.js
@@ -173,17 +173,17 @@ function testSteps()
   request = objectStore.put({id:10});
   request.onerror = errorHandler;
   request.onsuccess = grabEventAndContinueHandler;
   event = yield;
 
   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;
 
   try {
     objectStore.add({}, null);
     ok(false, "add with null key should throw!");
   }
   catch (e) {
--- a/dom/indexedDB/test/unit/test_keys.js
+++ b/dom/indexedDB/test/unit/test_keys.js
@@ -171,24 +171,24 @@ function testSteps()
       ok(compareKeys(e.target.result, keyI),
          "Returned key should actually be equal");
     };
     
     // Test that -0 compares the same as 0
     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;
     }
   }
 
   store.openCursor().onsuccess = grabEventAndContinueHandler;
   for (i = 0; i < keys.length; ++i) {
     event = yield;
--- a/dom/indexedDB/test/unit/test_traffic_jam.js
+++ b/dom/indexedDB/test/unit/test_traffic_jam.js
@@ -64,17 +64,17 @@ function testSteps()
 
   requests[2].onsuccess = grabEventAndContinueHandler;
 
   event = yield;
   is(event.type, "success", "expect a success event");
   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;
 
   requests[4].onsuccess = grabEventAndContinueHandler;
 
   event = yield;
   is(event.type, "success", "expect a success event");
   is(event.target, requests[4], "fired at the right request");
--- a/dom/indexedDB/test/unit/test_transaction_abort.js
+++ b/dom/indexedDB/test/unit/test_transaction_abort.js
@@ -2,40 +2,51 @@
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 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;
   let event = yield;
 
   let db = event.target.result;
   db.onabort = abortListener;
 
   let transaction;
   let objectStore;
   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 });
 
   is(transaction.db, db, "Correct database");
   is(transaction.mode, "versionchange", "Correct mode");
   is(transaction.objectStoreNames.length, 1, "Correct names length");
   is(transaction.objectStoreNames.item(0), "foo", "Correct name");
   is(transaction.objectStore("foo"), objectStore, "Can get stores");