2011-02-17 Jeremy Orlow <jorlow@chromium.org>
authorjorlow@chromium.org <jorlow@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 17 Feb 2011 21:06:12 +0000 (21:06 +0000)
committerjorlow@chromium.org <jorlow@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 17 Feb 2011 21:06:12 +0000 (21:06 +0000)
        Reviewed by Nate Chapin.

        Throwing in an IndexedDB error or success event should lead to the transaction aborting
        https://bugs.webkit.org/show_bug.cgi?id=54249

        * storage/indexeddb/exception-in-event-aborts-expected.txt: Added.
        * storage/indexeddb/exception-in-event-aborts.html: Added.
        * storage/indexeddb/queued-commands-expected.txt:
        * storage/indexeddb/queued-commands.html:
        * storage/indexeddb/request-event-propagation-expected.txt:
        * storage/indexeddb/request-event-propagation.html:
        * storage/indexeddb/resources/shared.js:
        (unexpectedErrorCallback):
        * storage/indexeddb/transaction-event-propagation-expected.txt:
        * storage/indexeddb/transaction-event-propagation.html:
2011-02-17  Jeremy Orlow  <jorlow@chromium.org>

        Reviewed by Nate Chapin.

        Throwing in an IndexedDB error or success event should lead to the transaction aborting
        https://bugs.webkit.org/show_bug.cgi?id=54249

        When an exception is thrown but not handled  within an IDBRequests success/error event,
        we should abort the transaction.

        Test: storage/indexeddb/exception-in-event-aborts.html

        * bindings/js/JSEventListener.cpp:
        (WebCore::JSEventListener::handleEvent):
        * bindings/js/JSEventTarget.cpp:
        (WebCore::toJS):
        * bindings/v8/V8AbstractEventListener.cpp:
        (WebCore::V8AbstractEventListener::invokeEventHandler):
        * dom/EventTarget.cpp:
        (WebCore::EventTarget::uncaughtExceptionInEventHandler):
        * dom/EventTarget.h:
        * storage/IDBRequest.cpp:
        (WebCore::IDBRequest::uncaughtExceptionInEventHandler):
        * storage/IDBRequest.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@78908 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
LayoutTests/ChangeLog
LayoutTests/storage/indexeddb/exception-in-event-aborts-expected.txt [new file with mode: 0644]
LayoutTests/storage/indexeddb/exception-in-event-aborts.html [new file with mode: 0644]
LayoutTests/storage/indexeddb/queued-commands-expected.txt
LayoutTests/storage/indexeddb/queued-commands.html
LayoutTests/storage/indexeddb/request-event-propagation-expected.txt
LayoutTests/storage/indexeddb/request-event-propagation.html
LayoutTests/storage/indexeddb/resources/shared.js
LayoutTests/storage/indexeddb/transaction-event-propagation-expected.txt
LayoutTests/storage/indexeddb/transaction-event-propagation.html
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/JSEventListener.cpp
Source/WebCore/bindings/js/JSEventTarget.cpp
Source/WebCore/bindings/v8/V8AbstractEventListener.cpp
Source/WebCore/dom/EventTarget.cpp
Source/WebCore/dom/EventTarget.h
Source/WebCore/storage/IDBRequest.cpp
Source/WebCore/storage/IDBRequest.h

index 4487a42..471f19a 100644 (file)
@@ -1,3 +1,21 @@
+2011-02-17  Jeremy Orlow  <jorlow@chromium.org>
+
+        Reviewed by Nate Chapin.
+
+        Throwing in an IndexedDB error or success event should lead to the transaction aborting
+        https://bugs.webkit.org/show_bug.cgi?id=54249
+
+        * storage/indexeddb/exception-in-event-aborts-expected.txt: Added.
+        * storage/indexeddb/exception-in-event-aborts.html: Added.
+        * storage/indexeddb/queued-commands-expected.txt:
+        * storage/indexeddb/queued-commands.html:
+        * storage/indexeddb/request-event-propagation-expected.txt:
+        * storage/indexeddb/request-event-propagation.html:
+        * storage/indexeddb/resources/shared.js:
+        (unexpectedErrorCallback):
+        * storage/indexeddb/transaction-event-propagation-expected.txt:
+        * storage/indexeddb/transaction-event-propagation.html:
+
 2011-02-17  Andreas Kling  <kling@webkit.org>
 
         Reviewed by Dirk Schulze.
diff --git a/LayoutTests/storage/indexeddb/exception-in-event-aborts-expected.txt b/LayoutTests/storage/indexeddb/exception-in-event-aborts-expected.txt
new file mode 100644 (file)
index 0000000..2dd8279
--- /dev/null
@@ -0,0 +1,59 @@
+Test exceptions in IDBRequest handlers cause aborts.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+webkitIndexedDB.open('name')
+db = event.target.result
+db.setVersion('new version')
+setVersionSuccess():
+trans = event.target.result
+PASS trans !== null is true
+trans.oncomplete = startTest
+Deleted all object stores.
+store = db.createObjectStore('storeName', null)
+store.add({x: 'value', y: 'zzz'}, 'key')
+
+trans = db.transaction([], webkitIDBTransaction.READ_WRITE)
+trans.onabort = transactionAborted1
+trans.oncomplete = unexpectedCompleteCallback
+store = trans.objectStore('storeName')
+store.add({x: 'value2', y: 'zzz2'}, 'key2')
+
+event.preventDefault()
+Throwing
+
+PASS The transaction was aborted.
+trans = db.transaction([], webkitIDBTransaction.READ_WRITE)
+trans.onabort = transactionAborted2
+trans.oncomplete = unexpectedCompleteCallback
+store = trans.objectStore('storeName')
+store.add({x: 'value', y: 'zzz'}, 'key')
+
+event.preventDefault()
+Throwing
+
+PASS The transaction was aborted.
+trans = db.transaction([], webkitIDBTransaction.READ_WRITE)
+trans.onabort = unexpectedAbortCallback
+trans.oncomplete = transactionCompleted1
+store = trans.objectStore('storeName')
+store.add({x: 'value3', y: 'zzz3'}, 'key3')
+
+event.preventDefault()
+Throwing within a try block
+
+PASS The transaction completed.
+trans = db.transaction([], webkitIDBTransaction.READ_WRITE)
+trans.onabort = unexpectedAbortCallback
+trans.oncomplete = transactionCompleted2
+store = trans.objectStore('storeName')
+store.add({x: 'value4', y: 'zzz4'}, 'key4')
+FAIL Success function called unexpectedly.
+
+PASS The transaction completed.
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/storage/indexeddb/exception-in-event-aborts.html b/LayoutTests/storage/indexeddb/exception-in-event-aborts.html
new file mode 100644 (file)
index 0000000..3cac81d
--- /dev/null
@@ -0,0 +1,133 @@
+<html>
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+<script src="../../fast/js/resources/js-test-post-function.js"></script>
+<script src="resources/shared.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+
+description("Test exceptions in IDBRequest handlers cause aborts.");
+if (window.layoutTestController) 
+    layoutTestController.waitUntilDone();
+
+function test()
+{
+    request = evalAndLog("webkitIndexedDB.open('name')");
+    request.onsuccess = setVersion;
+    request.onerror = unexpectedErrorCallback;
+}
+
+function setVersion()
+{
+    db = evalAndLog("db = event.target.result");
+
+    request = evalAndLog("db.setVersion('new version')");
+    request.onsuccess = deleteExisting;
+    request.onerror = unexpectedErrorCallback;
+}
+
+function deleteExisting()
+{
+    debug("setVersionSuccess():");
+    window.trans = evalAndLog("trans = event.target.result");
+    shouldBeTrue("trans !== null");
+    trans.onabort = unexpectedAbortCallback;
+    evalAndLog("trans.oncomplete = startTest");
+
+    deleteAllObjectStores(db);
+
+    store = evalAndLog("store = db.createObjectStore('storeName', null)");
+    request = evalAndLog("store.add({x: 'value', y: 'zzz'}, 'key')");
+    request.onerror = unexpectedErrorCallback;
+}
+
+function startTest()
+{
+    debug("");
+    trans = evalAndLog("trans = db.transaction([], webkitIDBTransaction.READ_WRITE)");
+    evalAndLog("trans.onabort = transactionAborted1");
+    evalAndLog("trans.oncomplete = unexpectedCompleteCallback");
+    store = evalAndLog("store = trans.objectStore('storeName')");
+    request = evalAndLog("store.add({x: 'value2', y: 'zzz2'}, 'key2')");
+    trans.addEventListener('success', causeException, true);
+    request.onerror = unexpectedErrorCallback;
+}
+
+function causeException()
+{
+    debug("");
+    evalAndLog("event.preventDefault()");
+    debug("Throwing");
+    throw "OH NO!!!";
+}
+
+function transactionAborted1()
+{
+    debug("");
+    testPassed("The transaction was aborted.");
+    trans = evalAndLog("trans = db.transaction([], webkitIDBTransaction.READ_WRITE)");
+    evalAndLog("trans.onabort = transactionAborted2");
+    evalAndLog("trans.oncomplete = unexpectedCompleteCallback");
+    store = evalAndLog("store = trans.objectStore('storeName')");
+    request = evalAndLog("store.add({x: 'value', y: 'zzz'}, 'key')");
+    request.onsuccess = unexpectedSuccessCallback;
+    db.onerror = causeException;
+}
+
+function transactionAborted2()
+{
+    debug("");
+    testPassed("The transaction was aborted.");
+    trans = evalAndLog("trans = db.transaction([], webkitIDBTransaction.READ_WRITE)");
+    evalAndLog("trans.onabort = unexpectedAbortCallback");
+    evalAndLog("trans.oncomplete = transactionCompleted1");
+    store = evalAndLog("store = trans.objectStore('storeName')");
+    request = evalAndLog("store.add({x: 'value3', y: 'zzz3'}, 'key3')");
+    request.onsuccess = throwAndCatch;
+    request.onerror = unexpectedErrorCallback;
+    db.onerror = null;
+}
+
+function throwAndCatch()
+{
+    debug("");
+    evalAndLog("event.preventDefault()");
+    debug("Throwing within a try block");
+    try {
+        throw "AHHH";
+    } catch (e) {
+    }
+}
+
+function transactionCompleted1()
+{
+    debug("");
+    testPassed("The transaction completed.");
+    trans = evalAndLog("trans = db.transaction([], webkitIDBTransaction.READ_WRITE)");
+    evalAndLog("trans.onabort = unexpectedAbortCallback");
+    evalAndLog("trans.oncomplete = transactionCompleted2");
+    store = evalAndLog("store = trans.objectStore('storeName')");
+    request = evalAndLog("store.add({x: 'value4', y: 'zzz4'}, 'key4')");
+    request.onsuccess = unexpectedSuccessCallback;
+    request.onerror = throwAndCatch;
+}
+
+function transactionCompleted2()
+{
+    debug("");
+    testPassed("The transaction completed.");
+    debug("");
+    done();
+}
+
+test();
+
+var successfullyParsed = true;
+
+</script>
+</body>
+</html>
index f5a8234..264d7e7 100644 (file)
@@ -10,7 +10,7 @@ setVersionSuccess():
 trans = event.target.result
 PASS trans !== null is true
 Deleted all object stores.
-db.createObjectStore('storeName', null)
+db.createObjectStore('storeName')
 store.createIndex('indexName', 'x')
 store.add({x: 'value', y: 'zzz'}, 'key')
 store.add({x: 'value2', y: 'zzz2'}, 'key2')
index 635140b..46eaa49 100644 (file)
@@ -39,7 +39,7 @@ function deleteExisting()
 
     deleteAllObjectStores(db);
 
-    window.store = evalAndLog("db.createObjectStore('storeName', null)");
+    window.store = evalAndLog("db.createObjectStore('storeName')");
     window.indexObject = evalAndLog("store.createIndex('indexName', 'x')");
 
     request = evalAndLog("store.add({x: 'value', y: 'zzz'}, 'key')");
index 70aca36..ba180b2 100644 (file)
@@ -45,6 +45,8 @@ PASS captureFired is false
 PASS requestFired is false
 PASS bubbleFired is false
 PASS dbBubbleFired is false
+PASS event.target is request
+PASS event.currentTarget is db
 
 In IDBTransaction error capture
 PASS dbCaptureFired is true
@@ -52,6 +54,8 @@ PASS captureFired is false
 PASS requestFired is false
 PASS bubbleFired is false
 PASS dbBubbleFired is false
+PASS event.target is request
+PASS event.currentTarget is trans
 
 In IDBRequest handler
 PASS dbCaptureFired is true
@@ -59,6 +63,8 @@ PASS captureFired is true
 PASS requestFired is false
 PASS bubbleFired is false
 PASS dbBubbleFired is false
+PASS event.target is request
+PASS event.currentTarget is request
 
 In IDBTransaction error bubble
 PASS dbCaptureFired is true
@@ -66,6 +72,8 @@ PASS captureFired is true
 PASS requestFired is true
 PASS bubbleFired is false
 PASS dbBubbleFired is false
+PASS event.target is request
+PASS event.currentTarget is trans
 
 In IDBDatabase error bubble
 PASS dbCaptureFired is true
@@ -73,6 +81,8 @@ PASS captureFired is true
 PASS requestFired is true
 PASS bubbleFired is true
 PASS dbBubbleFired is false
+PASS event.target is request
+PASS event.currentTarget is db
 
 Transaction aborted
 PASS dbCaptureFired is true
@@ -106,6 +116,8 @@ PASS captureFired is false
 PASS requestFired is false
 PASS bubbleFired is false
 PASS dbBubbleFired is false
+PASS event.target is request
+PASS event.currentTarget is db
 
 In IDBTransaction success capture
 PASS dbCaptureFired is true
@@ -113,6 +125,8 @@ PASS captureFired is false
 PASS requestFired is false
 PASS bubbleFired is false
 PASS dbBubbleFired is false
+PASS event.target is request
+PASS event.currentTarget is trans
 
 In IDBRequest handler
 PASS dbCaptureFired is true
@@ -120,6 +134,8 @@ PASS captureFired is true
 PASS requestFired is false
 PASS bubbleFired is false
 PASS dbBubbleFired is false
+PASS event.target is request
+PASS event.currentTarget is request
 
 Transaction completed
 PASS dbCaptureFired is true
index a91d8c3..60dadb2 100644 (file)
@@ -101,6 +101,8 @@ function dbErrorCaptureCallback()
     shouldBeFalse("requestFired");
     shouldBeFalse("bubbleFired");
     shouldBeFalse("dbBubbleFired");
+    shouldBe("event.target", "request");
+    shouldBe("event.currentTarget", "db");
     dbCaptureFired = true;
 }
 
@@ -113,6 +115,8 @@ function errorCaptureCallback()
     shouldBeFalse("requestFired");
     shouldBeFalse("bubbleFired");
     shouldBeFalse("dbBubbleFired");
+    shouldBe("event.target", "request");
+    shouldBe("event.currentTarget", "trans");
     captureFired = true;
 }
 
@@ -125,6 +129,8 @@ function errorFiredCallback()
     shouldBeFalse("requestFired");
     shouldBeFalse("bubbleFired");
     shouldBeFalse("dbBubbleFired");
+    shouldBe("event.target", "request");
+    shouldBe("event.currentTarget", "request");
     requestFired = true;
 }
 
@@ -137,6 +143,8 @@ function errorBubbleCallback()
     shouldBeTrue("requestFired");
     shouldBeFalse("bubbleFired");
     shouldBeFalse("dbBubbleFired");
+    shouldBe("event.target", "request");
+    shouldBe("event.currentTarget", "trans");
     bubbleFired = true;
 }
 
@@ -149,6 +157,8 @@ function dbErrorBubbleCallback()
     shouldBeTrue("requestFired");
     shouldBeTrue("bubbleFired");
     shouldBeFalse("dbBubbleFired");
+    shouldBe("event.target", "request");
+    shouldBe("event.currentTarget", "db");
     dbBubbleFired = true;
 }
 
@@ -198,6 +208,8 @@ function dbSuccessCaptureCallback()
     shouldBeFalse("requestFired");
     shouldBeFalse("bubbleFired");
     shouldBeFalse("dbBubbleFired");
+    shouldBe("event.target", "request");
+    shouldBe("event.currentTarget", "db");
     dbCaptureFired = true;
 }
 
@@ -210,6 +222,8 @@ function successCaptureCallback()
     shouldBeFalse("requestFired");
     shouldBeFalse("bubbleFired");
     shouldBeFalse("dbBubbleFired");
+    shouldBe("event.target", "request");
+    shouldBe("event.currentTarget", "trans");
     captureFired = true;
 }
 
@@ -222,6 +236,8 @@ function successFiredCallback()
     shouldBeFalse("requestFired");
     shouldBeFalse("bubbleFired");
     shouldBeFalse("dbBubbleFired");
+    shouldBe("event.target", "request");
+    shouldBe("event.currentTarget", "request");
     requestFired = true;
 }
 
index ebd58c8..9b23cb8 100644 (file)
@@ -12,7 +12,7 @@ function unexpectedSuccessCallback()
 
 function unexpectedErrorCallback()
 {
-    testFailed("Error function called unexpectedly: (" + event.target.code + ") " + event.target.message);
+    testFailed("Error function called unexpectedly: (" + event.target.errorCode + ") " + event.target.webkitErrorMessage);
 }
 
 function unexpectedAbortCallback()
index dba4e07..ee30e13 100644 (file)
@@ -27,16 +27,22 @@ In IDBDatabase abort capture
 PASS dbCaptureFired is false
 PASS abortFired is false
 PASS dbBubbleFired1 is false
+PASS event.target is trans
+PASS event.currentTarget is db
 
 In abort handler
 PASS dbCaptureFired is true
 PASS abortFired is false
 PASS dbBubbleFired1 is false
+PASS event.target is trans
+PASS event.currentTarget is trans
 
 In IDBDatabase error bubble
 PASS dbCaptureFired is true
 PASS abortFired is true
 PASS dbBubbleFired1 is false
+PASS event.target is trans
+PASS event.currentTarget is db
 
 Verifing success.
 trans = db.transaction([], webkitIDBTransaction.READ_WRITE)
@@ -57,11 +63,15 @@ In IDBDatabase complete capture
 PASS dbCaptureFired is false
 PASS completeFired is false
 PASS dbBubbleFired2 is false
+PASS event.target is trans
+PASS event.currentTarget is db
 
 In IDBRequest handler
 PASS dbCaptureFired is true
 PASS completeFired is false
 PASS dbBubbleFired2 is false
+PASS event.target is trans
+PASS event.currentTarget is trans
 
 PASS successfullyParsed is true
 
index 4d15cf5..276b52f 100644 (file)
@@ -68,6 +68,8 @@ function dbAbortCaptureCallback()
     shouldBeFalse("dbCaptureFired");
     shouldBeFalse("abortFired");
     shouldBeFalse("dbBubbleFired1");
+    shouldBe("event.target", "trans");
+    shouldBe("event.currentTarget", "db");
     dbCaptureFired = true;
 }
 
@@ -78,6 +80,8 @@ function abortFiredCallback()
     shouldBeTrue("dbCaptureFired");
     shouldBeFalse("abortFired");
     shouldBeFalse("dbBubbleFired1");
+    shouldBe("event.target", "trans");
+    shouldBe("event.currentTarget", "trans");
     abortFired = true;
 }
 
@@ -88,6 +92,8 @@ function dbAbortBubbleCallback()
     shouldBeTrue("dbCaptureFired");
     shouldBeTrue("abortFired");
     shouldBeFalse("dbBubbleFired1");
+    shouldBe("event.target", "trans");
+    shouldBe("event.currentTarget", "db");
     dbBubbleFired1 = true;
     debug("");
     debug("Verifing success.");
@@ -116,6 +122,8 @@ function dbCompleteCaptureCallback()
     shouldBeFalse("dbCaptureFired");
     shouldBeFalse("completeFired");
     shouldBeFalse("dbBubbleFired2");
+    shouldBe("event.target", "trans");
+    shouldBe("event.currentTarget", "db");
     dbCaptureFired = true;
 }
 
@@ -126,6 +134,8 @@ function completeFiredCallback()
     shouldBeTrue("dbCaptureFired");
     shouldBeFalse("completeFired");
     shouldBeFalse("dbBubbleFired2");
+    shouldBe("event.target", "trans");
+    shouldBe("event.currentTarget", "trans");
     completeFired = true;
     debug("");
     done();
index 089e137..c7cd37e 100644 (file)
@@ -1,3 +1,28 @@
+2011-02-17  Jeremy Orlow  <jorlow@chromium.org>
+
+        Reviewed by Nate Chapin.
+
+        Throwing in an IndexedDB error or success event should lead to the transaction aborting
+        https://bugs.webkit.org/show_bug.cgi?id=54249
+
+        When an exception is thrown but not handled  within an IDBRequests success/error event,
+        we should abort the transaction.
+
+        Test: storage/indexeddb/exception-in-event-aborts.html
+
+        * bindings/js/JSEventListener.cpp:
+        (WebCore::JSEventListener::handleEvent):
+        * bindings/js/JSEventTarget.cpp:
+        (WebCore::toJS):
+        * bindings/v8/V8AbstractEventListener.cpp:
+        (WebCore::V8AbstractEventListener::invokeEventHandler):
+        * dom/EventTarget.cpp:
+        (WebCore::EventTarget::uncaughtExceptionInEventHandler):
+        * dom/EventTarget.h:
+        * storage/IDBRequest.cpp:
+        (WebCore::IDBRequest::uncaughtExceptionInEventHandler):
+        * storage/IDBRequest.h:
+
 2011-02-17  Sam Weinig  <sam@webkit.org>
 
         Reviewed by Maciej Stachowiak.
index 825a4ad..90a164b 100644 (file)
@@ -126,9 +126,10 @@ void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext
 
         globalObject->setCurrentEvent(savedEvent);
 
-        if (exec->hadException())
+        if (exec->hadException()) {
+            event->target()->uncaughtExceptionInEventHandler();
             reportCurrentException(exec);
-        else {
+        else {
             if (!retval.isUndefinedOrNull() && event->storesResultAsString())
                 event->storeResult(ustringToString(retval.toString(exec)));
             if (m_isAttribute) {
index 04be175..e4d6724 100644 (file)
@@ -160,8 +160,14 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, EventTarget* targ
 #endif
 
 #if ENABLE(INDEXED_DATABASE)
+    if (IDBDatabase* idbDatabase = target->toIDBDatabase())
+        return toJS(exec, idbDatabase);
+
     if (IDBRequest* idbRequest = target->toIDBRequest())
         return toJS(exec, idbRequest);
+
+    if (IDBTransaction* idbTransaction = target->toIDBTransaction())
+        return toJS(exec, idbTransaction);
 #endif
 
 #if ENABLE(WEB_AUDIO)
index bda4345..6dc49fa 100644 (file)
@@ -147,12 +147,11 @@ void V8AbstractEventListener::invokeEventHandler(ScriptExecutionContext* context
         v8Context->Global()->SetHiddenValue(eventSymbol, jsEvent);
         tryCatch.Reset();
 
-        // Call the event handler.
         returnValue = callListenerFunction(context, jsEvent, event);
+        if (tryCatch.HasCaught())
+            event->target()->uncaughtExceptionInEventHandler();
         if (!tryCatch.CanContinue())
             return;
-
-        // If an error occurs while handling the event, it should be reported in a regular way.
         tryCatch.Reset();
 
         // Restore the old event. This must be done for all exit paths through this method.
index 0cb425e..7bd5cd6 100644 (file)
@@ -305,6 +305,10 @@ bool EventTarget::dispatchEvent(PassRefPtr<Event> event)
     return fireEventListeners(event.get());
 }
 
+void EventTarget::uncaughtExceptionInEventHandler()
+{
+}
+
 bool EventTarget::fireEventListeners(Event* event)
 {
     ASSERT(!eventDispatchForbidden());
index 1e26642..31644b7 100644 (file)
@@ -153,6 +153,7 @@ namespace WebCore {
         virtual void removeAllEventListeners();
         virtual bool dispatchEvent(PassRefPtr<Event>);
         bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&); // DOM API
+        virtual void uncaughtExceptionInEventHandler();
 
         // Used for legacy "onEvent" attribute APIs.
         bool setAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener>);
index a3e5eaa..6cffab8 100644 (file)
@@ -253,6 +253,12 @@ bool IDBRequest::dispatchEvent(PassRefPtr<Event> event)
     return dontPreventDefault;
 }
 
+void IDBRequest::uncaughtExceptionInEventHandler()
+{
+    if (m_transaction)
+        m_transaction->backend()->abort();
+}
+
 void IDBRequest::enqueueEvent(PassRefPtr<Event> event)
 {
     ASSERT(!m_finished);
index e40f1b1..5f2469d 100644 (file)
@@ -87,6 +87,7 @@ public:
     virtual ScriptExecutionContext* scriptExecutionContext() const;
     virtual bool dispatchEvent(PassRefPtr<Event>);
     bool dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec) { return EventTarget::dispatchEvent(event, ec); }
+    virtual void uncaughtExceptionInEventHandler();
 
     using ThreadSafeShared<IDBCallbacks>::ref;
     using ThreadSafeShared<IDBCallbacks>::deref;