Merge mozilla-central to mozilla-inbound
authorEd Morley <emorley@mozilla.com>
Tue, 26 Jun 2012 12:12:52 +0100
changeset 100377 551e7fe3f2ac295a73c4ad77b6746868555126c4
parent 100376 224e353a3e404709a5ef02cf1792fa0b12e4f7ea (current diff)
parent 100355 74e503bfa5755aa239dbaf2ba34fbd2e097fef21 (diff)
child 100378 e4f3532ec56c272f341f8ffae1979f1feb63fb73
child 100404 cad3e0609835dc8ec093b8a5ebf4f97d0a705d72
push idunknown
push userunknown
push dateunknown
milestone16.0a1
Merge mozilla-central to mozilla-inbound
layout/svg/base/src/nsSVGUtils.cpp
--- 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;
@@ -817,22 +852,28 @@ CommitHelper::Run()
     }
 
     if (!mAbortCode && NS_FAILED(WriteAutoIncrementCounts())) {
       mAbortCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
 
     if (!mAbortCode) {
       NS_NAMED_LITERAL_CSTRING(release, "COMMIT TRANSACTION");
-      if (NS_SUCCEEDED(mConnection->ExecuteSimpleSQL(release))) {
+      nsresult rv = mConnection->ExecuteSimpleSQL(release);
+      if (NS_SUCCEEDED(rv)) {
         if (mUpdateFileRefcountFunction) {
           mUpdateFileRefcountFunction->UpdateFileInfos();
         }
         CommitAutoIncrementCounts();
       }
+      else if (rv == NS_ERROR_FILE_NO_DEVICE_SPACE) {
+        // mozstorage translates SQLITE_FULL to NS_ERROR_FILE_NO_DEVICE_SPACE,
+        // which we know better as NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR.
+        mAbortCode = NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR;
+      }
       else {
         mAbortCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
       }
     }
 
     if (mAbortCode) {
       RevertAutoIncrementCounts();
       NS_NAMED_LITERAL_CSTRING(rollback, "ROLLBACK TRANSACTION");
--- 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 QuotaExceededError", "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 QuotaExceededError", "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");
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -7575,17 +7575,18 @@ DoApplyRenderingChangeToTree(nsIFrame* a
     // descendants of the transformed frame.
     UpdateViewsForTree(aFrame, aFrameManager,
                        nsChangeHint(aChange & (nsChangeHint_RepaintFrame |
                                                nsChangeHint_SyncFrameView |
                                                nsChangeHint_UpdateOpacityLayer)));
 
     // if frame has view, will already be invalidated
     if (aChange & nsChangeHint_RepaintFrame) {
-      if (aFrame->IsFrameOfType(nsIFrame::eSVG)) {
+      if (aFrame->IsFrameOfType(nsIFrame::eSVG) &&
+          !(aFrame->GetStateBits() & NS_STATE_IS_OUTER_SVG)) {
         if (aChange & nsChangeHint_UpdateEffects) {
           // Invalidate and update our area:
           nsSVGUtils::InvalidateAndScheduleBoundsUpdate(aFrame);
         } else {
           // Just invalidate our area:
           nsSVGUtils::InvalidateBounds(aFrame);
         }
       } else {
--- a/layout/svg/base/src/nsSVGUtils.cpp
+++ b/layout/svg/base/src/nsSVGUtils.cpp
@@ -600,17 +600,18 @@ nsSVGUtils::OuterSVGIsCallingUpdateBound
 {
   return nsSVGUtils::GetOuterSVGFrame(aFrame)->IsCallingUpdateBounds();
 }
 
 void
 nsSVGUtils::InvalidateBounds(nsIFrame *aFrame, bool aDuringUpdate,
                              const nsRect *aBoundsSubArea, PRUint32 aFlags)
 {
-  NS_ABORT_IF_FALSE(aFrame->IsFrameOfType(nsIFrame::eSVG),
+  NS_ABORT_IF_FALSE(aFrame->IsFrameOfType(nsIFrame::eSVG) &&
+                    !(aFrame->GetStateBits() & NS_STATE_IS_OUTER_SVG),
                     "Passed bad frame!");
 
   NS_ASSERTION(aDuringUpdate == OuterSVGIsCallingUpdateBounds(aFrame),
                "aDuringUpdate lies!");
 
   // Rendering observers must be notified about changes to the frames that they
   // are observing _before_ UpdateBounds is called on the SVG frame tree, so we
   // only need to notify observers if we're not under an UpdateBounds call.