<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[209069] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/209069">209069</a></dd>
<dt>Author</dt> <dd>beidson@apple.com</dd>
<dt>Date</dt> <dd>2016-11-29 08:05:17 -0800 (Tue, 29 Nov 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>IndexedDB 2.0: Queue up completed requests in the client, handle them one by one.
https://bugs.webkit.org/show_bug.cgi?id=165000
Reviewed by Alex Christensen.
Source/WebCore:
No new tests (Covered extensively by every existing test).
Currently when a TransactionOperation completes on the server, it immediately completes
itself on the client side, including scheduling an event dispatch if necessary.
This patch changes it so that "server completed operations" instead queue up in the
IDBTransaction and are "client-side completed" asynchronously, 1-by-1.
Currently this is a "no behavior change" because only one operation is ever sent to
the server at a time.
But that will change with https://webkit.org/b/164932
And this patch is a pre-requisite for that.
* Modules/indexeddb/IDBRequest.cpp:
(WebCore::IDBRequest::dispatchEvent):
(WebCore::IDBRequest::didOpenOrIterateCursor):
(WebCore::IDBRequest::completeRequestAndDispatchEvent):
(WebCore::IDBRequest::requestCompleted): Deleted.
* Modules/indexeddb/IDBRequest.h:
* Modules/indexeddb/IDBTransaction.cpp:
(WebCore::IDBTransaction::IDBTransaction):
(WebCore::IDBTransaction::internalAbort):
(WebCore::IDBTransaction::abortOnServerAndCancelRequests):
(WebCore::IDBTransaction::scheduleOperation):
(WebCore::IDBTransaction::schedulePendingOperationTimer):
(WebCore::IDBTransaction::pendingOperationTimerFired):
(WebCore::IDBTransaction::operationCompletedOnServer):
(WebCore::IDBTransaction::scheduleCompletedOperationTimer):
(WebCore::IDBTransaction::completedOperationTimerFired):
(WebCore::IDBTransaction::completeNoncursorRequest):
(WebCore::IDBTransaction::completeCursorRequest):
(WebCore::IDBTransaction::finishedDispatchEventForRequest):
(WebCore::IDBTransaction::didStart):
(WebCore::IDBTransaction::didOpenCursorOnServer):
(WebCore::IDBTransaction::didIterateCursorOnServer):
(WebCore::IDBTransaction::didGetAllRecordsOnServer):
(WebCore::IDBTransaction::didGetRecordOnServer):
(WebCore::IDBTransaction::didGetCountOnServer):
(WebCore::IDBTransaction::didDeleteRecordOnServer):
(WebCore::IDBTransaction::didClearObjectStoreOnServer):
(WebCore::IDBTransaction::putOrAddOnServer):
(WebCore::IDBTransaction::didPutOrAddOnServer):
(WebCore::IDBTransaction::operationCompletedOnClient):
(WebCore::IDBTransaction::deactivate):
(WebCore::IDBTransaction::connectionClosedFromServer):
(WebCore::IDBTransaction::scheduleOperationTimer): Deleted.
(WebCore::IDBTransaction::operationTimerFired): Deleted.
(WebCore::IDBTransaction::operationDidComplete): Deleted.
* Modules/indexeddb/IDBTransaction.h:
* Modules/indexeddb/client/IDBConnectionProxy.cpp:
(WebCore::IDBClient::IDBConnectionProxy::completeOperation):
* Modules/indexeddb/client/TransactionOperation.cpp:
(WebCore::IDBClient::TransactionOperation::TransactionOperation):
* Modules/indexeddb/client/TransactionOperation.h:
(WebCore::IDBClient::TransactionOperation::transitionToCompleteOnThisThread):
(WebCore::IDBClient::TransactionOperation::transitionToComplete):
(WebCore::IDBClient::TransactionOperation::doComplete):
(WebCore::IDBClient::TransactionOperation::idbRequest):
(WebCore::IDBClient::TransactionOperation::performCompleteOnOriginThread): Deleted.
(WebCore::IDBClient::TransactionOperation::completed): Deleted.
LayoutTests:
* storage/indexeddb/modern/resources/transaction-scheduler-6.js: This test had a bug which was masked by previously
synchronous behavior. Fix that bug!</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmodernresourcestransactionscheduler6js">trunk/LayoutTests/storage/indexeddb/modern/resources/transaction-scheduler-6.js</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbIDBRequestcpp">trunk/Source/WebCore/Modules/indexeddb/IDBRequest.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbIDBRequesth">trunk/Source/WebCore/Modules/indexeddb/IDBRequest.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbIDBTransactioncpp">trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbIDBTransactionh">trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbclientIDBConnectionProxycpp">trunk/Source/WebCore/Modules/indexeddb/client/IDBConnectionProxy.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbclientTransactionOperationcpp">trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbclientTransactionOperationh">trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverSQLiteIDBBackingStorecpp">trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (209068 => 209069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-11-29 16:04:41 UTC (rev 209068)
+++ trunk/LayoutTests/ChangeLog        2016-11-29 16:05:17 UTC (rev 209069)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2016-11-29 Brady Eidson <beidson@apple.com>
+
+ IndexedDB 2.0: Queue up completed requests in the client, handle them one by one.
+ https://bugs.webkit.org/show_bug.cgi?id=165000
+
+ Reviewed by Alex Christensen.
+
+ * storage/indexeddb/modern/resources/transaction-scheduler-6.js: This test had a bug which was masked by previously
+ synchronous behavior. Fix that bug!
+
</ins><span class="cx"> 2016-11-29 Zalan Bujtas <zalan@apple.com>
</span><span class="cx">
</span><span class="cx"> Safari (WebKit) doesn't wrap element within flex when width comes below min-width
</span></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmodernresourcestransactionscheduler6js"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/storage/indexeddb/modern/resources/transaction-scheduler-6.js (209068 => 209069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/resources/transaction-scheduler-6.js        2016-11-29 16:04:41 UTC (rev 209068)
+++ trunk/LayoutTests/storage/indexeddb/modern/resources/transaction-scheduler-6.js        2016-11-29 16:05:17 UTC (rev 209069)
</span><span class="lines">@@ -3,6 +3,10 @@
</span><span class="cx">
</span><span class="cx"> indexedDBTest(prepareDatabase);
</span><span class="cx">
</span><ins>+function log(msg)
+{
+        debug(msg);
+}
</ins><span class="cx">
</span><span class="cx"> function done()
</span><span class="cx"> {
</span><span class="lines">@@ -13,7 +17,7 @@
</span><span class="cx">
</span><span class="cx"> function prepareDatabase(event)
</span><span class="cx"> {
</span><del>- debug("Upgrade needed: Old version - " + event.oldVersion + " New version - " + event.newVersion);
</del><ins>+ log("Upgrade needed: Old version - " + event.oldVersion + " New version - " + event.newVersion);
</ins><span class="cx">
</span><span class="cx"> var versionTransaction = event.target.transaction;
</span><span class="cx"> database = event.target.result;
</span><span class="lines">@@ -21,22 +25,22 @@
</span><span class="cx"> var request = objectStore.put("foo", "bar");
</span><span class="cx">
</span><span class="cx"> request.onerror = function(event) {
</span><del>- debug("put FAILED - " + event);
</del><ins>+ log("put FAILED - " + event);
</ins><span class="cx"> done();
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> versionTransaction.onabort = function(event) {
</span><del>- debug("versionchange transaction aborted");
</del><ins>+ log("versionchange transaction aborted");
</ins><span class="cx"> done();
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> versionTransaction.oncomplete = function(event) {
</span><del>- debug("versionchange transaction completed");
</del><ins>+ log("versionchange transaction completed");
</ins><span class="cx"> continueTest();
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> versionTransaction.onerror = function(event) {
</span><del>- debug("versionchange transaction error'ed - " + event);
</del><ins>+ log("versionchange transaction error'ed - " + event);
</ins><span class="cx"> done();
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="lines">@@ -51,26 +55,26 @@
</span><span class="cx"> var request = objectStore.put("baz", "foo");
</span><span class="cx">
</span><span class="cx"> request.onsuccess = function(event) {
</span><del>- debug("Write in readwrite transaction succeeded");
</del><ins>+ log("Write in readwrite transaction succeeded");
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> request.onerror = function(event) {
</span><del>- debug("Write in readwrite transaction unexpectedly failed");
</del><ins>+ log("Write in readwrite transaction unexpectedly failed");
</ins><span class="cx"> done();
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> transaction.onabort = function(event) {
</span><del>- debug("readwrite transaction expectedly aborted");
</del><ins>+ log("readwrite transaction expectedly aborted");
</ins><span class="cx"> done();
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> transaction.oncomplete = function(event) {
</span><del>- debug("readwrite transaction completed");
</del><ins>+ log("readwrite transaction completed");
</ins><span class="cx"> done();
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> transaction.onerror = function(event) {
</span><del>- debug("readwrite transaction error'ed - " + event);
</del><ins>+ log("readwrite transaction error'ed - " + event);
</ins><span class="cx"> done();
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="lines">@@ -84,7 +88,7 @@
</span><span class="cx">
</span><span class="cx"> request.onsuccess = function(event) {
</span><span class="cx"> if (isFirstTime) {
</span><del>- debug("Starting a readonly transaction");
</del><ins>+ log("Starting a readonly transaction");
</ins><span class="cx"> numberOfOpenTransactions++;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -95,24 +99,22 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> request.onerror = function(event) {
</span><del>- debug("Unexpected request error - " + event);
</del><ins>+ log("Unexpected request error - " + event);
</ins><span class="cx"> done();
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> transaction.onerror = function(event) {
</span><del>- debug("Unexpected transaction error - " + event);
</del><ins>+ log("Unexpected transaction error - " + event);
</ins><span class="cx"> done();
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> transaction.onabort = function(event) {
</span><del>- --numberOfOpenTransactions;
- debug("Unexpected transaction abort - " + event);
</del><ins>+ log("Unexpected transaction abort - " + event);
</ins><span class="cx"> done();
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> transaction.oncomplete = function(event) {
</span><del>- --numberOfOpenTransactions;
- debug("readonly transaction completed");
</del><ins>+ log("readonly transaction completed");
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (209068 => 209069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-11-29 16:04:41 UTC (rev 209068)
+++ trunk/Source/WebCore/ChangeLog        2016-11-29 16:05:17 UTC (rev 209069)
</span><span class="lines">@@ -1,3 +1,75 @@
</span><ins>+2016-11-29 Brady Eidson <beidson@apple.com>
+
+ IndexedDB 2.0: Queue up completed requests in the client, handle them one by one.
+ https://bugs.webkit.org/show_bug.cgi?id=165000
+
+ Reviewed by Alex Christensen.
+
+ No new tests (Covered extensively by every existing test).
+
+ Currently when a TransactionOperation completes on the server, it immediately completes
+ itself on the client side, including scheduling an event dispatch if necessary.
+
+ This patch changes it so that "server completed operations" instead queue up in the
+ IDBTransaction and are "client-side completed" asynchronously, 1-by-1.
+
+ Currently this is a "no behavior change" because only one operation is ever sent to
+ the server at a time.
+
+ But that will change with https://webkit.org/b/164932
+ And this patch is a pre-requisite for that.
+
+ * Modules/indexeddb/IDBRequest.cpp:
+ (WebCore::IDBRequest::dispatchEvent):
+ (WebCore::IDBRequest::didOpenOrIterateCursor):
+ (WebCore::IDBRequest::completeRequestAndDispatchEvent):
+ (WebCore::IDBRequest::requestCompleted): Deleted.
+ * Modules/indexeddb/IDBRequest.h:
+
+ * Modules/indexeddb/IDBTransaction.cpp:
+ (WebCore::IDBTransaction::IDBTransaction):
+ (WebCore::IDBTransaction::internalAbort):
+ (WebCore::IDBTransaction::abortOnServerAndCancelRequests):
+ (WebCore::IDBTransaction::scheduleOperation):
+ (WebCore::IDBTransaction::schedulePendingOperationTimer):
+ (WebCore::IDBTransaction::pendingOperationTimerFired):
+ (WebCore::IDBTransaction::operationCompletedOnServer):
+ (WebCore::IDBTransaction::scheduleCompletedOperationTimer):
+ (WebCore::IDBTransaction::completedOperationTimerFired):
+ (WebCore::IDBTransaction::completeNoncursorRequest):
+ (WebCore::IDBTransaction::completeCursorRequest):
+ (WebCore::IDBTransaction::finishedDispatchEventForRequest):
+ (WebCore::IDBTransaction::didStart):
+ (WebCore::IDBTransaction::didOpenCursorOnServer):
+ (WebCore::IDBTransaction::didIterateCursorOnServer):
+ (WebCore::IDBTransaction::didGetAllRecordsOnServer):
+ (WebCore::IDBTransaction::didGetRecordOnServer):
+ (WebCore::IDBTransaction::didGetCountOnServer):
+ (WebCore::IDBTransaction::didDeleteRecordOnServer):
+ (WebCore::IDBTransaction::didClearObjectStoreOnServer):
+ (WebCore::IDBTransaction::putOrAddOnServer):
+ (WebCore::IDBTransaction::didPutOrAddOnServer):
+ (WebCore::IDBTransaction::operationCompletedOnClient):
+ (WebCore::IDBTransaction::deactivate):
+ (WebCore::IDBTransaction::connectionClosedFromServer):
+ (WebCore::IDBTransaction::scheduleOperationTimer): Deleted.
+ (WebCore::IDBTransaction::operationTimerFired): Deleted.
+ (WebCore::IDBTransaction::operationDidComplete): Deleted.
+ * Modules/indexeddb/IDBTransaction.h:
+
+ * Modules/indexeddb/client/IDBConnectionProxy.cpp:
+ (WebCore::IDBClient::IDBConnectionProxy::completeOperation):
+
+ * Modules/indexeddb/client/TransactionOperation.cpp:
+ (WebCore::IDBClient::TransactionOperation::TransactionOperation):
+ * Modules/indexeddb/client/TransactionOperation.h:
+ (WebCore::IDBClient::TransactionOperation::transitionToCompleteOnThisThread):
+ (WebCore::IDBClient::TransactionOperation::transitionToComplete):
+ (WebCore::IDBClient::TransactionOperation::doComplete):
+ (WebCore::IDBClient::TransactionOperation::idbRequest):
+ (WebCore::IDBClient::TransactionOperation::performCompleteOnOriginThread): Deleted.
+ (WebCore::IDBClient::TransactionOperation::completed): Deleted.
+
</ins><span class="cx"> 2016-11-29 Zalan Bujtas <zalan@apple.com>
</span><span class="cx">
</span><span class="cx"> Safari (WebKit) doesn't wrap element within flex when width comes below min-width
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbIDBRequestcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/IDBRequest.cpp (209068 => 209069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/IDBRequest.cpp        2016-11-29 16:04:41 UTC (rev 209068)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBRequest.cpp        2016-11-29 16:05:17 UTC (rev 209069)
</span><span class="lines">@@ -304,6 +304,9 @@
</span><span class="cx"> m_transaction->abortDueToFailedRequest(*m_domError);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ if (m_transaction)
+ m_transaction->finishedDispatchEventForRequest(*this);
+
</ins><span class="cx"> return dontPreventDefault;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -465,10 +468,10 @@
</span><span class="cx"> m_cursorRequestNotifier = nullptr;
</span><span class="cx"> m_pendingCursor = nullptr;
</span><span class="cx">
</span><del>- requestCompleted(resultData);
</del><ins>+ completeRequestAndDispatchEvent(resultData);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void IDBRequest::requestCompleted(const IDBResultData& resultData)
</del><ins>+void IDBRequest::completeRequestAndDispatchEvent(const IDBResultData& resultData)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(currentThread() == originThreadID());
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbIDBRequesth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/IDBRequest.h (209068 => 209069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/IDBRequest.h        2016-11-29 16:04:41 UTC (rev 209068)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBRequest.h        2016-11-29 16:05:17 UTC (rev 209069)
</span><span class="lines">@@ -87,7 +87,7 @@
</span><span class="cx"> using RefCounted::ref;
</span><span class="cx"> using RefCounted::deref;
</span><span class="cx">
</span><del>- void requestCompleted(const IDBResultData&);
</del><ins>+ void completeRequestAndDispatchEvent(const IDBResultData&);
</ins><span class="cx">
</span><span class="cx"> void setResult(const IDBKeyData&);
</span><span class="cx"> void setResult(const Vector<IDBKeyData>&);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbIDBTransactioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp (209068 => 209069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp        2016-11-29 16:04:41 UTC (rev 209068)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp        2016-11-29 16:05:17 UTC (rev 209069)
</span><span class="lines">@@ -74,8 +74,10 @@
</span><span class="cx"> : IDBActiveDOMObject(database.scriptExecutionContext())
</span><span class="cx"> , m_database(database)
</span><span class="cx"> , m_info(info)
</span><del>- , m_operationTimer(*this, &IDBTransaction::operationTimerFired)
</del><ins>+ , m_pendingOperationTimer(*this, &IDBTransaction::pendingOperationTimerFired)
+ , m_completedOperationTimer(*this, &IDBTransaction::completedOperationTimerFired)
</ins><span class="cx"> , m_openDBRequest(request)
</span><ins>+ , m_currentlyCompletingRequest(request)
</ins><span class="cx">
</span><span class="cx"> {
</span><span class="cx"> LOG(IndexedDB, "IDBTransaction::IDBTransaction - %s", m_info.loggingString().utf8().data());
</span><span class="lines">@@ -244,7 +246,7 @@
</span><span class="cx">
</span><span class="cx"> transitionedToFinishing(IndexedDB::TransactionState::Aborting);
</span><span class="cx">
</span><del>- m_abortQueue.swap(m_transactionOperationQueue);
</del><ins>+ m_abortQueue.swap(m_pendingTransactionOperationQueue);
</ins><span class="cx">
</span><span class="cx"> scheduleOperation(IDBClient::createTransactionOperation(*this, nullptr, &IDBTransaction::abortOnServerAndCancelRequests));
</span><span class="cx"> }
</span><span class="lines">@@ -253,7 +255,7 @@
</span><span class="cx"> {
</span><span class="cx"> LOG(IndexedDB, "IDBTransaction::abortOnServerAndCancelRequests");
</span><span class="cx"> ASSERT(currentThread() == m_database->originThreadID());
</span><del>- ASSERT(m_transactionOperationQueue.isEmpty());
</del><ins>+ ASSERT(m_pendingTransactionOperationQueue.isEmpty());
</ins><span class="cx">
</span><span class="cx"> m_database->connectionProxy().abortTransaction(*this);
</span><span class="cx">
</span><span class="lines">@@ -260,12 +262,16 @@
</span><span class="cx"> ASSERT(m_transactionOperationMap.contains(operation.identifier()));
</span><span class="cx"> m_transactionOperationMap.remove(operation.identifier());
</span><span class="cx">
</span><ins>+ m_currentlyCompletingRequest = nullptr;
+
</ins><span class="cx"> IDBError error(IDBDatabaseException::AbortError);
</span><del>- for (auto& operation : m_abortQueue)
- operation->completed(IDBResultData::error(operation->identifier(), error));
</del><ins>+ for (auto& operation : m_abortQueue) {
+ m_currentlyCompletingRequest = nullptr;
+ operation->doComplete(IDBResultData::error(operation->identifier(), error));
+ }
</ins><span class="cx">
</span><span class="cx"> // Since we're aborting, it should be impossible to have queued any further operations.
</span><del>- ASSERT(m_transactionOperationQueue.isEmpty());
</del><ins>+ ASSERT(m_pendingTransactionOperationQueue.isEmpty());
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> const char* IDBTransaction::activeDOMObjectName() const
</span><span class="lines">@@ -339,30 +345,30 @@
</span><span class="cx"> ASSERT(!m_transactionOperationMap.contains(operation->identifier()));
</span><span class="cx"> ASSERT(currentThread() == m_database->originThreadID());
</span><span class="cx">
</span><del>- m_transactionOperationQueue.append(operation);
</del><ins>+ m_pendingTransactionOperationQueue.append(operation);
</ins><span class="cx"> m_transactionOperationMap.set(operation->identifier(), WTFMove(operation));
</span><span class="cx">
</span><del>- scheduleOperationTimer();
</del><ins>+ schedulePendingOperationTimer();
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void IDBTransaction::scheduleOperationTimer()
</del><ins>+void IDBTransaction::schedulePendingOperationTimer()
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(currentThread() == m_database->originThreadID());
</span><span class="cx">
</span><del>- if (!m_operationTimer.isActive())
- m_operationTimer.startOneShot(0);
</del><ins>+ if (!m_pendingOperationTimer.isActive())
+ m_pendingOperationTimer.startOneShot(0);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void IDBTransaction::operationTimerFired()
</del><ins>+void IDBTransaction::pendingOperationTimerFired()
</ins><span class="cx"> {
</span><del>- LOG(IndexedDB, "IDBTransaction::operationTimerFired (%p)", this);
</del><ins>+ LOG(IndexedDB, "IDBTransaction::pendingOperationTimerFired (%p)", this);
</ins><span class="cx"> ASSERT(currentThread() == m_database->originThreadID());
</span><span class="cx">
</span><span class="cx"> if (!m_startedOnServer)
</span><span class="cx"> return;
</span><span class="cx">
</span><del>- if (!m_transactionOperationQueue.isEmpty()) {
- auto operation = m_transactionOperationQueue.takeFirst();
</del><ins>+ if (!m_pendingTransactionOperationQueue.isEmpty()) {
+ auto operation = m_pendingTransactionOperationQueue.takeFirst();
</ins><span class="cx"> operation->perform();
</span><span class="cx">
</span><span class="cx"> return;
</span><span class="lines">@@ -375,6 +381,67 @@
</span><span class="cx"> commit();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void IDBTransaction::operationCompletedOnServer(const IDBResultData& data, IDBClient::TransactionOperation& operation)
+{
+ ASSERT(currentThread() == m_database->originThreadID());
+ ASSERT(currentThread() == operation.originThreadID());
+
+ m_completedOnServerQueue.append({ &operation, data });
+ scheduleCompletedOperationTimer();
+}
+
+void IDBTransaction::scheduleCompletedOperationTimer()
+{
+ ASSERT(currentThread() == m_database->originThreadID());
+
+ if (!m_completedOperationTimer.isActive())
+ m_completedOperationTimer.startOneShot(0);
+}
+
+void IDBTransaction::completedOperationTimerFired()
+{
+ LOG(IndexedDB, "IDBTransaction::completedOperationTimerFired (%p)", this);
+ ASSERT(currentThread() == m_database->originThreadID());
+
+ if (m_completedOnServerQueue.isEmpty() || m_currentlyCompletingRequest)
+ return;
+
+ auto iterator = m_completedOnServerQueue.takeFirst();
+ iterator.first->doComplete(iterator.second);
+
+ if (!m_completedOnServerQueue.isEmpty() && !m_currentlyCompletingRequest)
+ scheduleCompletedOperationTimer();
+}
+
+void IDBTransaction::completeNoncursorRequest(IDBRequest& request, const IDBResultData& result)
+{
+ ASSERT(!m_currentlyCompletingRequest);
+
+ request.completeRequestAndDispatchEvent(result);
+
+ m_currentlyCompletingRequest = &request;
+}
+
+void IDBTransaction::completeCursorRequest(IDBRequest& request, const IDBResultData& result)
+{
+ ASSERT(!m_currentlyCompletingRequest);
+
+ request.didOpenOrIterateCursor(result);
+
+ m_currentlyCompletingRequest = &request;
+}
+
+void IDBTransaction::finishedDispatchEventForRequest(IDBRequest& request)
+{
+ if (isFinishedOrFinishing())
+ return;
+
+ ASSERT_UNUSED(request, !m_currentlyCompletingRequest || m_currentlyCompletingRequest == &request);
+
+ m_currentlyCompletingRequest = nullptr;
+ scheduleCompletedOperationTimer();
+}
+
</ins><span class="cx"> void IDBTransaction::commit()
</span><span class="cx"> {
</span><span class="cx"> LOG(IndexedDB, "IDBTransaction::commit");
</span><span class="lines">@@ -422,7 +489,7 @@
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- scheduleOperationTimer();
</del><ins>+ schedulePendingOperationTimer();
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void IDBTransaction::notifyDidAbort(const IDBError& error)
</span><span class="lines">@@ -724,7 +791,7 @@
</span><span class="cx"> LOG(IndexedDB, "IDBTransaction::didOpenCursorOnServer");
</span><span class="cx"> ASSERT(currentThread() == m_database->originThreadID());
</span><span class="cx">
</span><del>- request.didOpenOrIterateCursor(resultData);
</del><ins>+ completeCursorRequest(request, resultData);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void IDBTransaction::iterateCursor(IDBCursor& cursor, const IDBIterateCursorData& data)
</span><span class="lines">@@ -753,7 +820,7 @@
</span><span class="cx"> LOG(IndexedDB, "IDBTransaction::didIterateCursorOnServer");
</span><span class="cx"> ASSERT(currentThread() == m_database->originThreadID());
</span><span class="cx">
</span><del>- request.didOpenOrIterateCursor(resultData);
</del><ins>+ completeCursorRequest(request, resultData);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> Ref<IDBRequest> IDBTransaction::requestGetAllObjectStoreRecords(JSC::ExecState& state, IDBObjectStore& objectStore, const IDBKeyRangeData& keyRangeData, IndexedDB::GetAllType getAllType, std::optional<uint32_t> count)
</span><span class="lines">@@ -806,7 +873,7 @@
</span><span class="cx"> ASSERT(currentThread() == m_database->originThreadID());
</span><span class="cx">
</span><span class="cx"> if (resultData.type() == IDBResultType::Error) {
</span><del>- request.requestCompleted(resultData);
</del><ins>+ completeNoncursorRequest(request, resultData);
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -822,7 +889,7 @@
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- request.requestCompleted(resultData);
</del><ins>+ completeNoncursorRequest(request, resultData);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> Ref<IDBRequest> IDBTransaction::requestGetRecord(ExecState& state, IDBObjectStore& objectStore, const IDBGetRecordData& getRecordData)
</span><span class="lines">@@ -890,7 +957,7 @@
</span><span class="cx"> ASSERT(currentThread() == m_database->originThreadID());
</span><span class="cx">
</span><span class="cx"> if (resultData.type() == IDBResultType::Error) {
</span><del>- request.requestCompleted(resultData);
</del><ins>+ completeNoncursorRequest(request, resultData);
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -910,7 +977,7 @@
</span><span class="cx"> request.setResultToUndefined();
</span><span class="cx"> }
</span><span class="cx">
</span><del>- request.requestCompleted(resultData);
</del><ins>+ completeNoncursorRequest(request, resultData);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> Ref<IDBRequest> IDBTransaction::requestCount(ExecState& state, IDBObjectStore& objectStore, const IDBKeyRangeData& range)
</span><span class="lines">@@ -961,7 +1028,7 @@
</span><span class="cx"> ASSERT(currentThread() == m_database->originThreadID());
</span><span class="cx">
</span><span class="cx"> request.setResult(resultData.resultInteger());
</span><del>- request.requestCompleted(resultData);
</del><ins>+ completeNoncursorRequest(request, resultData);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> Ref<IDBRequest> IDBTransaction::requestDeleteRecord(ExecState& state, IDBObjectStore& objectStore, const IDBKeyRangeData& range)
</span><span class="lines">@@ -994,7 +1061,7 @@
</span><span class="cx"> ASSERT(currentThread() == m_database->originThreadID());
</span><span class="cx">
</span><span class="cx"> request.setResultToUndefined();
</span><del>- request.requestCompleted(resultData);
</del><ins>+ completeNoncursorRequest(request, resultData);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> Ref<IDBRequest> IDBTransaction::requestClearObjectStore(ExecState& state, IDBObjectStore& objectStore)
</span><span class="lines">@@ -1028,7 +1095,7 @@
</span><span class="cx"> ASSERT(currentThread() == m_database->originThreadID());
</span><span class="cx">
</span><span class="cx"> request.setResultToUndefined();
</span><del>- request.requestCompleted(resultData);
</del><ins>+ completeNoncursorRequest(request, resultData);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> Ref<IDBRequest> IDBTransaction::requestPutOrAdd(ExecState& state, IDBObjectStore& objectStore, IDBKey* key, SerializedScriptValue& value, IndexedDB::ObjectStoreOverwriteMode overwriteMode)
</span><span class="lines">@@ -1074,7 +1141,7 @@
</span><span class="cx"> RefPtr<IDBClient::TransactionOperation> protectedOperation(&operation);
</span><span class="cx"> auto result = IDBResultData::error(operation.identifier(), { IDBDatabaseException::UnknownError, ASCIILiteral("Error preparing Blob/File data to be stored in object store") });
</span><span class="cx"> scriptExecutionContext()->postTask([protectedOperation = WTFMove(protectedOperation), result = WTFMove(result)](ScriptExecutionContext&) {
</span><del>- protectedOperation->completed(result);
</del><ins>+ protectedOperation->doComplete(result);
</ins><span class="cx"> });
</span><span class="cx"> }
</span><span class="cx"> return;
</span><span class="lines">@@ -1092,7 +1159,7 @@
</span><span class="cx"> // In that case, we cannot successfully store this record, so we callback with an error.
</span><span class="cx"> auto result = IDBResultData::error(protectedOperation->identifier(), { IDBDatabaseException::UnknownError, ASCIILiteral("Error preparing Blob/File data to be stored in object store") });
</span><span class="cx"> callOnMainThread([protectedThis = WTFMove(protectedThis), protectedOperation = WTFMove(protectedOperation), result = WTFMove(result)]() mutable {
</span><del>- protectedOperation->completed(result);
</del><ins>+ protectedOperation->doComplete(result);
</ins><span class="cx"> });
</span><span class="cx"> });
</span><span class="cx"> }
</span><span class="lines">@@ -1106,7 +1173,7 @@
</span><span class="cx"> request.setResult(*result);
</span><span class="cx"> else
</span><span class="cx"> request.setResultToUndefined();
</span><del>- request.requestCompleted(resultData);
</del><ins>+ completeNoncursorRequest(request, resultData);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void IDBTransaction::deleteObjectStore(const String& objectStoreName)
</span><span class="lines">@@ -1167,8 +1234,10 @@
</span><span class="cx"> ASSERT_UNUSED(resultData, resultData.type() == IDBResultType::DeleteIndexSuccess || resultData.type() == IDBResultType::Error);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void IDBTransaction::operationDidComplete(IDBClient::TransactionOperation& operation)
</del><ins>+void IDBTransaction::operationCompletedOnClient(IDBClient::TransactionOperation& operation)
</ins><span class="cx"> {
</span><ins>+ LOG(IndexedDB, "IDBTransaction::operationCompletedOnClient");
+
</ins><span class="cx"> ASSERT(m_transactionOperationMap.get(operation.identifier()) == &operation);
</span><span class="cx"> ASSERT(currentThread() == m_database->originThreadID());
</span><span class="cx"> ASSERT(currentThread() == operation.originThreadID());
</span><span class="lines">@@ -1175,7 +1244,7 @@
</span><span class="cx">
</span><span class="cx"> m_transactionOperationMap.remove(operation.identifier());
</span><span class="cx">
</span><del>- scheduleOperationTimer();
</del><ins>+ schedulePendingOperationTimer();
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void IDBTransaction::establishOnServer()
</span><span class="lines">@@ -1203,7 +1272,7 @@
</span><span class="cx"> if (m_state == IndexedDB::TransactionState::Active)
</span><span class="cx"> m_state = IndexedDB::TransactionState::Inactive;
</span><span class="cx">
</span><del>- scheduleOperationTimer();
</del><ins>+ schedulePendingOperationTimer();
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void IDBTransaction::connectionClosedFromServer(const IDBError& error)
</span><span class="lines">@@ -1215,12 +1284,14 @@
</span><span class="cx"> Vector<RefPtr<IDBClient::TransactionOperation>> operations;
</span><span class="cx"> copyValuesToVector(m_transactionOperationMap, operations);
</span><span class="cx">
</span><del>- for (auto& operation : operations)
- operation->completed(IDBResultData::error(operation->identifier(), error));
</del><ins>+ for (auto& operation : operations) {
+ m_currentlyCompletingRequest = nullptr;
+ operation->doComplete(IDBResultData::error(operation->identifier(), error));
+ }
</ins><span class="cx">
</span><span class="cx"> connectionProxy().forgetActiveOperations(operations);
</span><span class="cx">
</span><del>- m_transactionOperationQueue.clear();
</del><ins>+ m_pendingTransactionOperationQueue.clear();
</ins><span class="cx"> m_abortQueue.clear();
</span><span class="cx"> m_transactionOperationMap.clear();
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbIDBTransactionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.h (209068 => 209069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.h        2016-11-29 16:04:41 UTC (rev 209068)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.h        2016-11-29 16:05:17 UTC (rev 209069)
</span><span class="lines">@@ -138,8 +138,11 @@
</span><span class="cx"> void activate();
</span><span class="cx"> void deactivate();
</span><span class="cx">
</span><del>- void operationDidComplete(IDBClient::TransactionOperation&);
</del><ins>+ void operationCompletedOnServer(const IDBResultData&, IDBClient::TransactionOperation&);
+ void operationCompletedOnClient(IDBClient::TransactionOperation&);
</ins><span class="cx">
</span><ins>+ void finishedDispatchEventForRequest(IDBRequest&);
+
</ins><span class="cx"> bool isFinishedOrFinishing() const;
</span><span class="cx"> bool isFinished() const { return m_state == IndexedDB::TransactionState::Finished; }
</span><span class="cx">
</span><span class="lines">@@ -159,7 +162,8 @@
</span><span class="cx"> void finishAbortOrCommit();
</span><span class="cx">
</span><span class="cx"> void scheduleOperation(RefPtr<IDBClient::TransactionOperation>&&);
</span><del>- void operationTimerFired();
</del><ins>+ void pendingOperationTimerFired();
+ void completedOperationTimerFired();
</ins><span class="cx">
</span><span class="cx"> void fireOnComplete();
</span><span class="cx"> void fireOnAbort();
</span><span class="lines">@@ -217,8 +221,12 @@
</span><span class="cx">
</span><span class="cx"> void establishOnServer();
</span><span class="cx">
</span><del>- void scheduleOperationTimer();
</del><ins>+ void completeNoncursorRequest(IDBRequest&, const IDBResultData&);
+ void completeCursorRequest(IDBRequest&, const IDBResultData&);
</ins><span class="cx">
</span><ins>+ void schedulePendingOperationTimer();
+ void scheduleCompletedOperationTimer();
+
</ins><span class="cx"> Ref<IDBDatabase> m_database;
</span><span class="cx"> IDBTransactionInfo m_info;
</span><span class="cx">
</span><span class="lines">@@ -228,12 +236,14 @@
</span><span class="cx"> IDBError m_idbError;
</span><span class="cx"> RefPtr<DOMError> m_domError;
</span><span class="cx">
</span><del>- Timer m_operationTimer;
</del><ins>+ Timer m_pendingOperationTimer;
+ Timer m_completedOperationTimer;
</ins><span class="cx"> std::unique_ptr<Timer> m_activationTimer;
</span><span class="cx">
</span><span class="cx"> RefPtr<IDBOpenDBRequest> m_openDBRequest;
</span><span class="cx">
</span><del>- Deque<RefPtr<IDBClient::TransactionOperation>> m_transactionOperationQueue;
</del><ins>+ Deque<RefPtr<IDBClient::TransactionOperation>> m_pendingTransactionOperationQueue;
+ Deque<std::pair<RefPtr<IDBClient::TransactionOperation>, IDBResultData>> m_completedOnServerQueue;
</ins><span class="cx"> Deque<RefPtr<IDBClient::TransactionOperation>> m_abortQueue;
</span><span class="cx"> HashMap<IDBResourceIdentifier, RefPtr<IDBClient::TransactionOperation>> m_transactionOperationMap;
</span><span class="cx">
</span><span class="lines">@@ -242,6 +252,7 @@
</span><span class="cx"> HashMap<uint64_t, std::unique_ptr<IDBObjectStore>> m_deletedObjectStores;
</span><span class="cx">
</span><span class="cx"> HashSet<RefPtr<IDBRequest>> m_openRequests;
</span><ins>+ RefPtr<IDBRequest> m_currentlyCompletingRequest;
</ins><span class="cx">
</span><span class="cx"> bool m_contextStopped { false };
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbclientIDBConnectionProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/client/IDBConnectionProxy.cpp (209068 => 209069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/client/IDBConnectionProxy.cpp        2016-11-29 16:04:41 UTC (rev 209068)
+++ trunk/Source/WebCore/Modules/indexeddb/client/IDBConnectionProxy.cpp        2016-11-29 16:05:17 UTC (rev 209069)
</span><span class="lines">@@ -249,7 +249,7 @@
</span><span class="cx"> if (!operation)
</span><span class="cx"> return;
</span><span class="cx">
</span><del>- operation->performCompleteOnOriginThread(resultData, WTFMove(operation));
</del><ins>+ operation->transitionToComplete(resultData, WTFMove(operation));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void IDBConnectionProxy::abortOpenAndUpgradeNeeded(uint64_t databaseConnectionIdentifier, const IDBResourceIdentifier& transactionIdentifier)
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbclientTransactionOperationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.cpp (209068 => 209069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.cpp        2016-11-29 16:04:41 UTC (rev 209068)
+++ trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.cpp        2016-11-29 16:05:17 UTC (rev 209069)
</span><span class="lines">@@ -43,6 +43,8 @@
</span><span class="cx"> m_indexRecordType = request.requestedIndexRecordType();
</span><span class="cx"> if (auto* cursor = request.pendingCursor())
</span><span class="cx"> m_cursorIdentifier = std::make_unique<IDBResourceIdentifier>(cursor->info().identifier());
</span><ins>+
+ m_idbRequest = &request;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> } // namespace IDBClient
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbclientTransactionOperationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.h (209068 => 209069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.h        2016-11-29 16:04:41 UTC (rev 209068)
+++ trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.h        2016-11-29 16:05:17 UTC (rev 209069)
</span><span class="lines">@@ -61,25 +61,31 @@
</span><span class="cx"> m_performFunction = { };
</span><span class="cx"> }
</span><span class="cx">
</span><del>- void performCompleteOnOriginThread(const IDBResultData& data, RefPtr<TransactionOperation>&& lastRef)
</del><ins>+ void transitionToCompleteOnThisThread(const IDBResultData& data)
</ins><span class="cx"> {
</span><ins>+ ASSERT(m_originThreadID == currentThread());
+ m_transaction->operationCompletedOnServer(data, *this);
+ }
+
+ void transitionToComplete(const IDBResultData& data, RefPtr<TransactionOperation>&& lastRef)
+ {
</ins><span class="cx"> ASSERT(isMainThread());
</span><span class="cx">
</span><span class="cx"> if (m_originThreadID == currentThread())
</span><del>- completed(data);
</del><ins>+ transitionToCompleteOnThisThread(data);
</ins><span class="cx"> else {
</span><del>- m_transaction->performCallbackOnOriginThread(*this, &TransactionOperation::completed, data);
</del><ins>+ m_transaction->performCallbackOnOriginThread(*this, &TransactionOperation::transitionToCompleteOnThisThread, data);
</ins><span class="cx"> m_transaction->callFunctionOnOriginThread([lastRef = WTFMove(lastRef)]() {
</span><span class="cx"> });
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>- void completed(const IDBResultData& data)
</del><ins>+ void doComplete(const IDBResultData& data)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(m_originThreadID == currentThread());
</span><span class="cx"> ASSERT(m_completeFunction);
</span><span class="cx"> m_completeFunction(data);
</span><del>- m_transaction->operationDidComplete(*this);
</del><ins>+ m_transaction->operationCompletedOnClient(*this);
</ins><span class="cx">
</span><span class="cx"> // m_completeFunction might be holding the last ref to this TransactionOperation,
</span><span class="cx"> // so we need to do this trick to null it out without first destroying it.
</span><span class="lines">@@ -91,6 +97,8 @@
</span><span class="cx">
</span><span class="cx"> ThreadIdentifier originThreadID() const { return m_originThreadID; }
</span><span class="cx">
</span><ins>+ IDBRequest* idbRequest() { return m_idbRequest.get(); }
+
</ins><span class="cx"> protected:
</span><span class="cx"> TransactionOperation(IDBTransaction& transaction)
</span><span class="cx"> : m_transaction(transaction)
</span><span class="lines">@@ -118,6 +126,7 @@
</span><span class="cx"> IndexedDB::IndexRecordType indexRecordType() const { return m_indexRecordType; }
</span><span class="cx">
</span><span class="cx"> ThreadIdentifier m_originThreadID { currentThread() };
</span><ins>+ RefPtr<IDBRequest> m_idbRequest;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> template <typename... Arguments>
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverSQLiteIDBBackingStorecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp (209068 => 209069)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp        2016-11-29 16:04:41 UTC (rev 209068)
+++ trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp        2016-11-29 16:05:17 UTC (rev 209069)
</span><span class="lines">@@ -807,11 +807,8 @@
</span><span class="cx"> return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to abort a transaction that hasn't been established") };
</span><span class="cx"> }
</span><span class="cx">
</span><del>-
- if (transaction->mode() == IDBTransactionMode::Versionchange) {
- ASSERT(m_originalDatabaseInfoBeforeVersionChange);
</del><ins>+ if (transaction->mode() == IDBTransactionMode::Versionchange && m_originalDatabaseInfoBeforeVersionChange)
</ins><span class="cx"> m_databaseInfo = WTFMove(m_originalDatabaseInfoBeforeVersionChange);
</span><del>- }
</del><span class="cx">
</span><span class="cx"> return transaction->abort();
</span><span class="cx"> }
</span></span></pre>
</div>
</div>
</body>
</html>