<!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>[191722] 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/191722">191722</a></dd>
<dt>Author</dt> <dd>beidson@apple.com</dd>
<dt>Date</dt> <dd>2015-10-28 23:16:01 -0700 (Wed, 28 Oct 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Modern IDB: Support IDBDatabase.transaction() (and transaction scheduling in general).
https://bugs.webkit.org/show_bug.cgi?id=150614

Reviewed by Alex Christensen.

LayoutTests/imported/w3c:

* indexeddb/idbdatabase_transaction5-expected.txt: Progression!

Source/WebCore:

Tests: storage/indexeddb/modern/idbdatabase-transaction-failures.html
       storage/indexeddb/modern/transaction-scheduler-1.html
       storage/indexeddb/modern/transaction-scheduler-2.html
       storage/indexeddb/modern/transaction-scheduler-3.html
       storage/indexeddb/modern/transaction-scheduler-4.html
       storage/indexeddb/modern/transaction-scheduler-5.html
       storage/indexeddb/modern/transaction-scheduler-6.html

* Modules/indexeddb/IDBDatabase.idl:

* Modules/indexeddb/IndexedDB.h:

* Modules/indexeddb/client/IDBConnectionToServer.cpp:
(WebCore::IDBClient::IDBConnectionToServer::establishTransaction):
(WebCore::IDBClient::IDBConnectionToServer::didStartTransaction):
(WebCore::IDBClient::IDBConnectionToServer::hasRecordOfTransaction):
* Modules/indexeddb/client/IDBConnectionToServer.h:
* Modules/indexeddb/client/IDBConnectionToServerDelegate.h:

* Modules/indexeddb/client/IDBDatabaseImpl.cpp:
(WebCore::IDBClient::IDBDatabase::transaction):
(WebCore::IDBClient::IDBDatabase::didStartTransaction):
* Modules/indexeddb/client/IDBDatabaseImpl.h:

* Modules/indexeddb/client/IDBTransactionImpl.cpp:
(WebCore::IDBClient::IDBTransaction::IDBTransaction):
(WebCore::IDBClient::IDBTransaction::operationTimerFired):
(WebCore::IDBClient::IDBTransaction::didStart):
(WebCore::IDBClient::IDBTransaction::establishOnServer):
(WebCore::IDBClient::IDBTransaction::activate):
(WebCore::IDBClient::IDBTransaction::deactivate):
* Modules/indexeddb/client/IDBTransactionImpl.h:

* Modules/indexeddb/server/IDBConnectionToClient.cpp:
(WebCore::IDBServer::IDBConnectionToClient::didStartTransaction):
* Modules/indexeddb/server/IDBConnectionToClient.h:
* Modules/indexeddb/server/IDBConnectionToClientDelegate.h:

* Modules/indexeddb/server/IDBServer.cpp:
(WebCore::IDBServer::IDBServer::establishTransaction):
* Modules/indexeddb/server/IDBServer.h:

* Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
(WebCore::IDBServer::MemoryIDBBackingStore::beginTransaction):
(WebCore::IDBServer::MemoryIDBBackingStore::createObjectStore):
(WebCore::IDBServer::MemoryIDBBackingStore::removeObjectStoreForVersionChangeAbort):
(WebCore::IDBServer::MemoryIDBBackingStore::keyExistsInObjectStore):
(WebCore::IDBServer::MemoryIDBBackingStore::deleteRecord):
(WebCore::IDBServer::MemoryIDBBackingStore::putRecord):
(WebCore::IDBServer::MemoryIDBBackingStore::getRecord):
(WebCore::IDBServer::MemoryIDBBackingStore::registerObjectStore):
(WebCore::IDBServer::MemoryIDBBackingStore::unregisterObjectStore):
* Modules/indexeddb/server/MemoryIDBBackingStore.h:

* Modules/indexeddb/server/UniqueIDBDatabase.cpp:
(WebCore::IDBServer::UniqueIDBDatabase::startVersionChangeTransaction):
(WebCore::IDBServer::UniqueIDBDatabase::performCommitTransaction):
(WebCore::IDBServer::UniqueIDBDatabase::didPerformCommitTransaction):
(WebCore::IDBServer::UniqueIDBDatabase::didPerformAbortTransaction):
(WebCore::IDBServer::UniqueIDBDatabase::enqueueTransaction):
(WebCore::IDBServer::UniqueIDBDatabase::transactionSchedulingTimerFired):
(WebCore::IDBServer::UniqueIDBDatabase::activateTransactionInBackingStore):
(WebCore::IDBServer::UniqueIDBDatabase::performActivateTransactionInBackingStore):
(WebCore::IDBServer::UniqueIDBDatabase::didPerformActivateTransactionInBackingStore):
(WebCore::IDBServer::scopesOverlap):
(WebCore::IDBServer::UniqueIDBDatabase::takeNextRunnableTransaction):
(WebCore::IDBServer::UniqueIDBDatabase::inProgressTransactionCompleted):
* Modules/indexeddb/server/UniqueIDBDatabase.h:

* Modules/indexeddb/server/UniqueIDBDatabaseConnection.cpp:
(WebCore::IDBServer::UniqueIDBDatabaseConnection::establishTransaction):
* Modules/indexeddb/server/UniqueIDBDatabaseConnection.h:

* Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp:
(WebCore::IDBServer::UniqueIDBDatabaseTransaction::create):
(WebCore::IDBServer::UniqueIDBDatabaseTransaction::UniqueIDBDatabaseTransaction):
(WebCore::IDBServer::UniqueIDBDatabaseTransaction::objectStoreIdentifiers):
(WebCore::IDBServer::UniqueIDBDatabaseTransaction::didActivateInBackingStore):
* Modules/indexeddb/server/UniqueIDBDatabaseTransaction.h:

* Modules/indexeddb/shared/IDBTransactionInfo.cpp:
(WebCore::IDBTransactionInfo::clientTransaction):
(WebCore::IDBTransactionInfo::isolatedCopy):
* Modules/indexeddb/shared/IDBTransactionInfo.h:

* Modules/indexeddb/shared/InProcessIDBServer.cpp:
(WebCore::InProcessIDBServer::establishTransaction):
(WebCore::InProcessIDBServer::didStartTransaction):
* Modules/indexeddb/shared/InProcessIDBServer.h:

* bindings/js/IDBBindingUtilities.cpp:
(WebCore::deserializeIDBValueData):

* bindings/js/JSIDBDatabaseCustom.cpp:
(WebCore::JSIDBDatabase::transaction):

* bindings/js/ScriptState.cpp:
(WebCore::execStateFromPage):

LayoutTests:

* storage/indexeddb/modern/idbdatabase-transaction-failures-expected.txt: Added.
* storage/indexeddb/modern/idbdatabase-transaction-failures.html: Added.
* storage/indexeddb/modern/transaction-scheduler-1-expected.txt: Added.
* storage/indexeddb/modern/transaction-scheduler-1.html: Added.
* storage/indexeddb/modern/transaction-scheduler-2-expected.txt: Added.
* storage/indexeddb/modern/transaction-scheduler-2.html: Added.
* storage/indexeddb/modern/transaction-scheduler-3-expected.txt: Added.
* storage/indexeddb/modern/transaction-scheduler-3.html: Added.
* storage/indexeddb/modern/transaction-scheduler-4-expected.txt: Added.
* storage/indexeddb/modern/transaction-scheduler-4.html: Added.
* storage/indexeddb/modern/transaction-scheduler-5-expected.txt: Added.
* storage/indexeddb/modern/transaction-scheduler-5.html: Added.
* storage/indexeddb/modern/transaction-scheduler-6-expected.txt: Added.
* storage/indexeddb/modern/transaction-scheduler-6.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsimportedw3cChangeLog">trunk/LayoutTests/imported/w3c/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsimportedw3cindexeddbidbdatabase_transaction5expectedtxt">trunk/LayoutTests/imported/w3c/indexeddb/idbdatabase_transaction5-expected.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbIDBDatabaseidl">trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.idl</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbIndexedDBh">trunk/Source/WebCore/Modules/indexeddb/IndexedDB.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbclientIDBConnectionToServercpp">trunk/Source/WebCore/Modules/indexeddb/client/IDBConnectionToServer.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbclientIDBConnectionToServerh">trunk/Source/WebCore/Modules/indexeddb/client/IDBConnectionToServer.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbclientIDBConnectionToServerDelegateh">trunk/Source/WebCore/Modules/indexeddb/client/IDBConnectionToServerDelegate.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbclientIDBDatabaseImplcpp">trunk/Source/WebCore/Modules/indexeddb/client/IDBDatabaseImpl.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbclientIDBDatabaseImplh">trunk/Source/WebCore/Modules/indexeddb/client/IDBDatabaseImpl.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbclientIDBTransactionImplcpp">trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbclientIDBTransactionImplh">trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverIDBConnectionToClientcpp">trunk/Source/WebCore/Modules/indexeddb/server/IDBConnectionToClient.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverIDBConnectionToClienth">trunk/Source/WebCore/Modules/indexeddb/server/IDBConnectionToClient.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverIDBConnectionToClientDelegateh">trunk/Source/WebCore/Modules/indexeddb/server/IDBConnectionToClientDelegate.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverIDBServercpp">trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverIDBServerh">trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverMemoryIDBBackingStorecpp">trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverMemoryIDBBackingStoreh">trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverUniqueIDBDatabasecpp">trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverUniqueIDBDatabaseh">trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverUniqueIDBDatabaseConnectioncpp">trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseConnection.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverUniqueIDBDatabaseConnectionh">trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseConnection.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverUniqueIDBDatabaseTransactioncpp">trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverUniqueIDBDatabaseTransactionh">trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbsharedIDBTransactionInfocpp">trunk/Source/WebCore/Modules/indexeddb/shared/IDBTransactionInfo.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbsharedIDBTransactionInfoh">trunk/Source/WebCore/Modules/indexeddb/shared/IDBTransactionInfo.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbsharedInProcessIDBServercpp">trunk/Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbsharedInProcessIDBServerh">trunk/Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.h</a></li>
<li><a href="#trunkSourceWebCorebindingsjsIDBBindingUtilitiescpp">trunk/Source/WebCore/bindings/js/IDBBindingUtilities.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSIDBDatabaseCustomcpp">trunk/Source/WebCore/bindings/js/JSIDBDatabaseCustom.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsScriptStatecpp">trunk/Source/WebCore/bindings/js/ScriptState.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsstorageindexeddbmodernidbdatabasetransactionfailuresexpectedtxt">trunk/LayoutTests/storage/indexeddb/modern/idbdatabase-transaction-failures-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmodernidbdatabasetransactionfailureshtml">trunk/LayoutTests/storage/indexeddb/modern/idbdatabase-transaction-failures.html</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderntransactionscheduler1expectedtxt">trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-1-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderntransactionscheduler1html">trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-1.html</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderntransactionscheduler2expectedtxt">trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-2-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderntransactionscheduler2html">trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-2.html</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderntransactionscheduler3expectedtxt">trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-3-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderntransactionscheduler3html">trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-3.html</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderntransactionscheduler4expectedtxt">trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-4-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderntransactionscheduler4html">trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-4.html</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderntransactionscheduler5expectedtxt">trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-5-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderntransactionscheduler5html">trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-5.html</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderntransactionscheduler6expectedtxt">trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-6-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderntransactionscheduler6html">trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-6.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/LayoutTests/ChangeLog        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -1,3 +1,25 @@
</span><ins>+2015-10-28  Brady Eidson  &lt;beidson@apple.com&gt;
+
+        Modern IDB: Support IDBDatabase.transaction() (and transaction scheduling in general).
+        https://bugs.webkit.org/show_bug.cgi?id=150614
+
+        Reviewed by Alex Christensen.
+
+        * storage/indexeddb/modern/idbdatabase-transaction-failures-expected.txt: Added.
+        * storage/indexeddb/modern/idbdatabase-transaction-failures.html: Added.
+        * storage/indexeddb/modern/transaction-scheduler-1-expected.txt: Added.
+        * storage/indexeddb/modern/transaction-scheduler-1.html: Added.
+        * storage/indexeddb/modern/transaction-scheduler-2-expected.txt: Added.
+        * storage/indexeddb/modern/transaction-scheduler-2.html: Added.
+        * storage/indexeddb/modern/transaction-scheduler-3-expected.txt: Added.
+        * storage/indexeddb/modern/transaction-scheduler-3.html: Added.
+        * storage/indexeddb/modern/transaction-scheduler-4-expected.txt: Added.
+        * storage/indexeddb/modern/transaction-scheduler-4.html: Added.
+        * storage/indexeddb/modern/transaction-scheduler-5-expected.txt: Added.
+        * storage/indexeddb/modern/transaction-scheduler-5.html: Added.
+        * storage/indexeddb/modern/transaction-scheduler-6-expected.txt: Added.
+        * storage/indexeddb/modern/transaction-scheduler-6.html: Added.
+
</ins><span class="cx"> 2015-10-28  Andy Estes  &lt;aestes@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Content Filtering] Crash when allowing a 0-byte resource to load
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/ChangeLog (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/ChangeLog        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/LayoutTests/imported/w3c/ChangeLog        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -1,3 +1,12 @@
</span><ins>+2015-10-28  Brady Eidson  &lt;beidson@apple.com&gt;
+
+        Modern IDB: Support IDBDatabase.transaction() (and transaction scheduling in general).
+        https://bugs.webkit.org/show_bug.cgi?id=150614
+
+        Reviewed by Alex Christensen.
+
+        * indexeddb/idbdatabase_transaction5-expected.txt: Progression!
+
</ins><span class="cx"> 2015-10-26  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Indexing an object with an integer that is not a supported property index should not call the named property getter
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cindexeddbidbdatabase_transaction5expectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/indexeddb/idbdatabase_transaction5-expected.txt (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/indexeddb/idbdatabase_transaction5-expected.txt        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/LayoutTests/imported/w3c/indexeddb/idbdatabase_transaction5-expected.txt        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -1,3 +1,3 @@
</span><span class="cx"> 
</span><del>-FAIL IDBDatabase.transaction() - If storeNames is an empty list, the implementation must throw a DOMException of type InvalidAccessError assert_throws: function &quot;function () { db.transaction([]); }&quot; threw object &quot;Error: NotFoundError: DOM IDBDatabase Exception 8&quot; that is not a DOMException InvalidAccessError: property &quot;code&quot; is equal to 8, expected 15
</del><ins>+PASS IDBDatabase.transaction() - If storeNames is an empty list, the implementation must throw a DOMException of type InvalidAccessError 
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmodernidbdatabasetransactionfailuresexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/idbdatabase-transaction-failures-expected.txt (0 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/idbdatabase-transaction-failures-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/idbdatabase-transaction-failures-expected.txt        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+ALERT: Upgrade needed: Old version - 0 New version - 1
+ALERT: Failed to start a transaction while a versionChange transaction was in progress - Error: InvalidStateError: DOM Exception 11
+ALERT: versionchange transaction completed
+ALERT: Failed to start a transaction with an empty set of object stores - Error: InvalidAccessError: DOM Exception 15
+ALERT: Failed to start a transaction to a nonexistent object store - Error: NotFoundError: DOM Exception 8
+ALERT: Failed to start a transaction with an invalid mode - TypeError: Type error
+ALERT: Failed to explicitly start a versionchange transaction - TypeError: Type error
+ALERT: Failed to explicitly start a transaction with the close pending flag set - Error: InvalidStateError: DOM Exception 11
+ALERT: Done
+This tests some obvious failures that can happen while calling IDBDatabase.transaction()
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmodernidbdatabasetransactionfailureshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/idbdatabase-transaction-failures.html (0 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/idbdatabase-transaction-failures.html                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/idbdatabase-transaction-failures.html        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -0,0 +1,90 @@
</span><ins>+This tests some obvious failures that can happen while calling IDBDatabase.transaction()
+&lt;script&gt;
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function done()
+{
+    alert(&quot;Done&quot;);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+var createRequest = window.indexedDB.open(&quot;IDBDatabaseTransactionFailuresDatabase&quot;);
+var database;
+
+createRequest.onupgradeneeded = function(event) {
+    alert(&quot;Upgrade needed: Old version - &quot; + event.oldVersion + &quot; New version - &quot; + event.newVersion);
+
+    var versionTransaction = createRequest.transaction;
+    database = event.target.result;
+    var objectStore = database.createObjectStore(&quot;TestObjectStore&quot;);
+    var request = objectStore.put(&quot;foo&quot;, &quot;bar&quot;);
+
+    request.onerror = function(event) {
+        alert(&quot;put FAILED - &quot; + event);
+        done();
+    }
+    
+    try {
+        database.transaction(&quot;TestObjectStore&quot;, &quot;readonly&quot;);
+    } catch(e) {
+        alert(&quot;Failed to start a transaction while a versionChange transaction was in progress - &quot; + e);
+    }
+
+    versionTransaction.onabort = function(event) {
+        alert(&quot;versionchange transaction aborted&quot;);
+        done();
+    }
+
+    versionTransaction.oncomplete = function(event) {
+        alert(&quot;versionchange transaction completed&quot;);
+        continueTest();
+    }
+
+    versionTransaction.onerror = function(event) {
+        alert(&quot;versionchange transaction error'ed - &quot; + event);
+        done();
+    }
+}
+
+function continueTest()
+{
+    try {
+        database.transaction([], &quot;readonly&quot;);
+    } catch(e) {
+        alert(&quot;Failed to start a transaction with an empty set of object stores - &quot; + e);
+    }
+
+    try {
+        database.transaction(&quot;NonexistentObjectStore&quot;, &quot;readonly&quot;);
+    } catch(e) {
+        alert(&quot;Failed to start a transaction to a nonexistent object store - &quot; + e);
+    }
+
+    try {
+        database.transaction(&quot;TestObjectStore&quot;, &quot;blahblah&quot;);
+    } catch(e) {
+        alert(&quot;Failed to start a transaction with an invalid mode - &quot; + e);
+    }
+
+    try {
+        database.transaction(&quot;TestObjectStore&quot;, &quot;versionchange&quot;);
+    } catch(e) {
+        alert(&quot;Failed to explicitly start a versionchange transaction - &quot; + e);
+    }
+    
+    try {
+        database.close();
+        database.transaction(&quot;TestObjectStore&quot;, &quot;readonly&quot;);
+    } catch(e) {
+        alert(&quot;Failed to explicitly start a transaction with the close pending flag set - &quot; + e);
+    }
+    
+    done();
+}
+
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderntransactionscheduler1expectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-1-expected.txt (0 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-1-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-1-expected.txt        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+ALERT: Upgrade needed: Old version - 0 New version - 1
+ALERT: versionchange transaction completed
+ALERT: Success opening database connection - request 1
+ALERT: Success opening database connection - request 2
+ALERT: Two transactions open at once. Yay.
+ALERT: Done
+This test makes sure that two read-only transactions to an object store are active at the same time.
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderntransactionscheduler1html"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-1.html (0 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-1.html                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-1.html        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -0,0 +1,120 @@
</span><ins>+This test makes sure that two read-only transactions to an object store are active at the same time.
+&lt;script&gt;
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function done()
+{
+    alert(&quot;Done&quot;);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+var createRequest = window.indexedDB.open(&quot;TransactionScheduler1Database&quot;);
+
+createRequest.onupgradeneeded = function(event) {
+    alert(&quot;Upgrade needed: Old version - &quot; + event.oldVersion + &quot; New version - &quot; + event.newVersion);
+
+    var versionTransaction = createRequest.transaction;
+    var database = event.target.result;
+    var objectStore = database.createObjectStore(&quot;TestObjectStore&quot;);
+    var request = objectStore.put(&quot;foo&quot;, &quot;bar&quot;);
+
+    request.onerror = function(event) {
+        alert(&quot;put FAILED - &quot; + event);
+        done();
+    }
+    
+    versionTransaction.onabort = function(event) {
+        alert(&quot;versionchange transaction aborted&quot;);
+        done();
+    }
+
+    versionTransaction.oncomplete = function(event) {
+        alert(&quot;versionchange transaction completed&quot;);
+        continueTest();
+        database.close();
+    }
+
+    versionTransaction.onerror = function(event) {
+        alert(&quot;versionchange transaction error'ed - &quot; + event);
+        done();
+    }
+}
+
+function continueTest()
+{
+    var request1 = window.indexedDB.open(&quot;TransactionScheduler1Database&quot;, 1);
+    var request2 = window.indexedDB.open(&quot;TransactionScheduler1Database&quot;, 1);
+
+    setupRequest(request1, &quot;request 1&quot;);
+    setupRequest(request2, &quot;request 2&quot;);
+}
+
+function setupRequest(request, reqName)
+{
+    request.onsuccess = function(event) {
+        alert(&quot;Success opening database connection - &quot; + reqName);
+        var database = event.target.result;
+    
+        startTransactionLoop(event.target.result.transaction(&quot;TestObjectStore&quot;, &quot;readonly&quot;), true);
+    }
+    request.onerror = function(event) {
+        alert(&quot;Unexpected error - &quot; + reqName + &quot; - &quot; + event);
+        done();
+    }
+    request.onblocked = function(event) {
+        alert(&quot;Unexpected blocked - &quot; + reqName + &quot; - &quot; + event);
+        done();
+    }
+    request.onupgradeneeded = function(event) {
+        alert(&quot;Unexpected upgradeneeded - &quot; + reqName + &quot; - &quot; + event);
+        done();
+    } 
+}
+
+var numberOfOpenTransactions = 0;
+
+function startTransactionLoop(transaction, isFirstTime)
+{
+    var objectStore = transaction.objectStore(&quot;TestObjectStore&quot;);
+    var request = objectStore.get(&quot;bar&quot;);
+    
+    request.onsuccess = function(event) {
+        if (isFirstTime)
+            numberOfOpenTransactions++;
+        
+        if (numberOfOpenTransactions == 2) {
+            alert(&quot;Two transactions open at once. Yay.&quot;);
+            done();
+        }
+        startTransactionLoop(event.target.transaction, false);
+    }
+
+    request.onerror = function(event) {
+        alert(&quot;Unexpected request error - &quot; + event);
+        done();
+    }
+
+    transaction.onerror = function(event) {
+        alert(&quot;Unexpected transaction error - &quot; + event);
+        done();
+    }
+
+    transaction.onabort = function(event) {
+        --numberOfOpenTransactions;
+        alert(&quot;Unexpected transaction abort - &quot; + event);
+        done();
+    }
+
+    transaction.oncomplete = function(event) {
+        --numberOfOpenTransactions;
+        alert(&quot;Unexpected transaction complete - &quot; + event);
+        done();
+    }
+}
+
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderntransactionscheduler2expectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-2-expected.txt (0 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-2-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-2-expected.txt        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+ALERT: Upgrade needed: Old version - 0 New version - 1
+ALERT: versionchange transaction completed
+ALERT: Success opening database connection - Starting transaction to ObjectStore OS1
+ALERT: Success opening database connection - Starting transaction to ObjectStore OS2
+ALERT: Two transactions open at once. Yay.
+ALERT: Done
+This test makes sure that two read-only transactions to two different object stores are active at the same time.
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderntransactionscheduler2html"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-2.html (0 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-2.html                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-2.html        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -0,0 +1,126 @@
</span><ins>+This test makes sure that two read-only transactions to two different object stores are active at the same time.
+&lt;script&gt;
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function done()
+{
+    alert(&quot;Done&quot;);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+var createRequest = window.indexedDB.open(&quot;TransactionScheduler2Database&quot;);
+
+createRequest.onupgradeneeded = function(event) {
+    alert(&quot;Upgrade needed: Old version - &quot; + event.oldVersion + &quot; New version - &quot; + event.newVersion);
+
+    var versionTransaction = createRequest.transaction;
+    var database = event.target.result;
+    var objectStore = database.createObjectStore(&quot;OS1&quot;);
+    var request = objectStore.put(&quot;foo1&quot;, &quot;bar1&quot;);
+
+    request.onerror = function(event) {
+        alert(&quot;put1 FAILED - &quot; + event);
+        done();
+    }
+    
+    objectStore = database.createObjectStore(&quot;OS2&quot;);
+    request = objectStore.put(&quot;foo2&quot;, &quot;bar2&quot;);
+
+    request.onerror = function(event) {
+        alert(&quot;put2 FAILED - &quot; + event);
+        done();
+    }
+
+    versionTransaction.onabort = function(event) {
+        alert(&quot;versionchange transaction aborted&quot;);
+        done();
+    }
+
+    versionTransaction.oncomplete = function(event) {
+        alert(&quot;versionchange transaction completed&quot;);
+        continueTest();
+        database.close();
+    }
+
+    versionTransaction.onerror = function(event) {
+        alert(&quot;versionchange transaction error'ed - &quot; + event);
+        done();
+    }
+}
+
+function continueTest()
+{
+    var request1 = window.indexedDB.open(&quot;TransactionScheduler2Database&quot;, 1);
+    var request2 = window.indexedDB.open(&quot;TransactionScheduler2Database&quot;, 1);
+
+    setupRequest(request1, &quot;OS1&quot;);
+    setupRequest(request2, &quot;OS2&quot;);
+}
+
+function setupRequest(request, osname)
+{
+    request.onsuccess = function(event) {
+        alert(&quot;Success opening database connection - Starting transaction to ObjectStore &quot; + osname);
+        startTransactionLoop(event.target.result.transaction(osname, &quot;readonly&quot;), osname, true);
+    }
+    request.onerror = function(event) {
+        alert(&quot;Unexpected error - &quot; + osname + &quot; - &quot; + event);
+        done();
+    }
+    request.onblocked = function(event) {
+        alert(&quot;Unexpected blocked - &quot; + osname + &quot; - &quot; + event);
+        done();
+    }
+    request.onupgradeneeded = function(event) {
+        alert(&quot;Unexpected upgradeneeded - &quot; + osname + &quot; - &quot; + event);
+        done();
+    } 
+}
+
+var numberOfOpenTransactions = 0;
+
+function startTransactionLoop(transaction, osname, isFirstTime)
+{
+    var objectStore = transaction.objectStore(osname);
+    var request = objectStore.get(&quot;bar&quot;);
+    
+    request.onsuccess = function(event) {
+        if (isFirstTime)
+            numberOfOpenTransactions++;
+        
+        if (numberOfOpenTransactions == 2) {
+            alert(&quot;Two transactions open at once. Yay.&quot;);
+            done();
+        }
+        startTransactionLoop(event.target.transaction, osname, false);
+    }
+
+    request.onerror = function(event) {
+        alert(&quot;Unexpected request error - &quot; + event);
+        done();
+    }
+
+    transaction.onerror = function(event) {
+        alert(&quot;Unexpected transaction error - &quot; + event);
+        done();
+    }
+
+    transaction.onabort = function(event) {
+        --numberOfOpenTransactions;
+        alert(&quot;Unexpected transaction abort - &quot; + event);
+        done();
+    }
+
+    transaction.oncomplete = function(event) {
+        --numberOfOpenTransactions;
+        alert(&quot;Unexpected transaction complete - &quot; + event);
+        done();
+    }
+}
+
+&lt;/script&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderntransactionscheduler3expectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-3-expected.txt (0 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-3-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-3-expected.txt        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+ALERT: Upgrade needed: Old version - 0 New version - 1
+ALERT: versionchange transaction completed
+ALERT: Success opening database connection - Starting readonly transaction
+ALERT: Creating write transaction
+ALERT: Read transaction complete - [object Event]
+ALERT: Write transaction put success
+ALERT: Write transaction complete - [object Event]
+ALERT: Done
+This test makes sure that a write transaction is blocked by a read transaction with overlapping scope.
+It also makes sure the write transaction starts after the read transaction completes.
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderntransactionscheduler3html"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-3.html (0 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-3.html                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-3.html        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -0,0 +1,142 @@
</span><ins>+This test makes sure that a write transaction is blocked by a read transaction with overlapping scope.&lt;br&gt;
+It also makes sure the write transaction starts after the read transaction completes.&lt;br&gt;
+&lt;script&gt;
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function done()
+{
+    alert(&quot;Done&quot;);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+var createRequest = window.indexedDB.open(&quot;TransactionScheduler3Database&quot;);
+
+createRequest.onupgradeneeded = function(event) {
+    alert(&quot;Upgrade needed: Old version - &quot; + event.oldVersion + &quot; New version - &quot; + event.newVersion);
+
+    var versionTransaction = createRequest.transaction;
+    var database = event.target.result;
+    var objectStore = database.createObjectStore(&quot;OS&quot;);
+    var request = objectStore.put(&quot;bar&quot;, &quot;foo&quot;);
+
+    request.onerror = function(event) {
+        alert(&quot;put FAILED - &quot; + event);
+        done();
+    }
+
+    versionTransaction.onabort = function(event) {
+        alert(&quot;versionchange transaction aborted&quot;);
+        done();
+    }
+
+    versionTransaction.oncomplete = function(event) {
+        alert(&quot;versionchange transaction completed&quot;);
+        continueTest();
+        database.close();
+    }
+
+    versionTransaction.onerror = function(event) {
+        alert(&quot;versionchange transaction error'ed - &quot; + event);
+        done();
+    }
+}
+
+var secondDatabaseConnection;
+function continueTest()
+{
+    var longRunningReadRequest = window.indexedDB.open(&quot;TransactionScheduler3Database&quot;, 1);
+    longRunningReadRequest.onsuccess = function(event) {
+        alert(&quot;Success opening database connection - Starting readonly transaction&quot;);
+        secondDatabaseConnection = event.target.result;
+        readTransactionLoop(secondDatabaseConnection.transaction(&quot;OS&quot;, &quot;readonly&quot;), true);
+    }
+    longRunningReadRequest.onerror = function(event) {
+        alert(&quot;Long running read request unexpected error - &quot; + event);
+        done();
+    }
+    longRunningReadRequest.onblocked = function(event) {
+        alert(&quot;Long running read request unexpected blocked - &quot; + event);
+        done();
+    }
+    longRunningReadRequest.onupgradeneeded = function(event) {
+        alert(&quot;Long running read request unexpected upgradeneeded - &quot; + event);
+        done();
+    } 
+}
+
+var shouldEndReadTransaction = false;
+
+function readTransactionLoop(transaction, isFirstTime)
+{
+    var objectStore = transaction.objectStore(&quot;OS&quot;);
+    var request = objectStore.get(&quot;foo&quot;);
+    
+    request.onsuccess = function(event) {
+        if (!shouldEndReadTransaction)
+            readTransactionLoop(event.target.transaction, false);
+        
+        // Now that the read transaction is open, the write transaction can be started, but it will be blocked to start with.
+        if (isFirstTime)
+             startWriteTransaction()
+    }
+
+    request.onerror = function(event) {
+        alert(&quot;Unexpected request error - &quot; + event);
+        done();
+    }
+
+    transaction.onerror = function(event) {
+        alert(&quot;Unexpected transaction error - &quot; + event);
+        done();
+    }
+
+    transaction.onabort = function(event) {
+        alert(&quot;Unexpected transaction abort - &quot; + event);
+        done();
+    }
+
+    transaction.oncomplete = function(event) {
+        alert(&quot;Read transaction complete - &quot; + event);
+    }
+}
+
+function startWriteTransaction()
+{
+    alert(&quot;Creating write transaction&quot;);
+    var transaction = secondDatabaseConnection.transaction(&quot;OS&quot;, &quot;readwrite&quot;);
+    var objectStore = transaction.objectStore(&quot;OS&quot;);
+    var request = objectStore.put(&quot;baz&quot;, &quot;foo&quot;);
+
+    setTimeout(&quot;shouldEndReadTransaction = true;&quot;, 0);
+
+    request.onsuccess = function(event) {
+        alert(&quot;Write transaction put success&quot;);
+    }
+
+    request.onerror = function(event) {
+        alert(&quot;Write transaction put unexpected error - &quot; + event);
+        done();
+    }
+
+    transaction.onerror = function(event) {
+        alert(&quot;Write transaction unexpected error - &quot; + event);
+        done();
+    }
+
+    transaction.onabort = function(event) {
+        alert(&quot;Write transaction unexpected abort - &quot; + event);
+        done();
+    }
+
+    transaction.oncomplete = function(event) {
+        alert(&quot;Write transaction complete - &quot; + event);
+        done();
+    }
+}
+
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderntransactionscheduler4expectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-4-expected.txt (0 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-4-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-4-expected.txt        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -0,0 +1,20 @@
</span><ins>+ALERT: Upgrade needed: Old version - 0 New version - 1
+ALERT: versionchange transaction completed
+ALERT: Success opening database connection - Starting readonly transaction
+ALERT: Other objectstore read transaction get success - [object Event]
+ALERT: Other objectstore read transaction complete - [object Event]
+ALERT: Read transaction complete - [object Event]
+ALERT: Write transaction first put success
+ALERT: Second read-only transaction get success - [object Event]
+ALERT: Write transaction complete - [object Event]
+ALERT: Second read-only transaction complete - [object Event]
+ALERT: Done
+This test opens a long running read-only transaction to an object store, and then a read-write transaction to the same object store.
+The read-write transaction should be blocked while the long running read-only transaction is in progress.
+It also queues up a second read-only transaction to that same object store behind the blocked read-write transaction.
+Even though that second read-only transaction could start while the first is in progress and the read-write transaction is blocked,
+it should *not* start because doing so would risk continuing to block the read-write transaction.
+It also queues up a read-only to a different object store behind those first three transactions.
+That last read-only transaction *should* start while the read-write transaction is still blocked,
+as doing so won't risk blocking the read-write transaction further.
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderntransactionscheduler4html"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-4.html (0 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-4.html                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-4.html        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -0,0 +1,233 @@
</span><ins>+This test opens a long running read-only transaction to an object store, and then a read-write transaction to the same object store.&lt;br&gt;
+The read-write transaction should be blocked while the long running read-only transaction is in progress.&lt;br&gt;
+It also queues up a second read-only transaction to that same object store behind the blocked read-write transaction.&lt;br&gt;
+Even though that second read-only transaction could start while the first is in progress and the read-write transaction is blocked,&lt;br&gt;
+it should *not* start because doing so would risk continuing to block the read-write transaction.&lt;br&gt;
+It also queues up a read-only to a different object store behind those first three transactions.&lt;br&gt;
+That last read-only transaction *should* start while the read-write transaction is still blocked,&lt;br&gt;
+as doing so won't risk blocking the read-write transaction further.&lt;br&gt;
+&lt;script&gt;
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function done()
+{
+    alert(&quot;Done&quot;);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+var createRequest = window.indexedDB.open(&quot;TransactionScheduler4Database&quot;);
+
+createRequest.onupgradeneeded = function(event) {
+    alert(&quot;Upgrade needed: Old version - &quot; + event.oldVersion + &quot; New version - &quot; + event.newVersion);
+
+    var versionTransaction = createRequest.transaction;
+    var database = event.target.result;
+    var objectStore = database.createObjectStore(&quot;OS&quot;);
+    var request = objectStore.put(&quot;bar&quot;, &quot;foo&quot;);
+
+    request.onerror = function(event) {
+        alert(&quot;first put FAILED - &quot; + event);
+        done();
+    }
+
+    objectStore = database.createObjectStore(&quot;OtherOS&quot;);
+    request = objectStore.put(&quot;bar&quot;, &quot;foo&quot;);
+    
+    request.onerror = function(event) {
+        alert(&quot;second put FAILED - &quot; + event);
+        done();
+    }
+    
+    versionTransaction.onabort = function(event) {
+        alert(&quot;versionchange transaction aborted&quot;);
+        done();
+    }
+
+    versionTransaction.oncomplete = function(event) {
+        alert(&quot;versionchange transaction completed&quot;);
+        continueTest();
+        database.close();
+    }
+
+    versionTransaction.onerror = function(event) {
+        alert(&quot;versionchange transaction error'ed - &quot; + event);
+        done();
+    }
+}
+
+var secondDatabaseConnection;
+function continueTest()
+{
+    var longRunningReadRequest = window.indexedDB.open(&quot;TransactionScheduler4Database&quot;, 1);
+    longRunningReadRequest.onsuccess = function(event) {
+        alert(&quot;Success opening database connection - Starting readonly transaction&quot;);
+        secondDatabaseConnection = event.target.result;
+        
+        var transaction = secondDatabaseConnection.transaction(&quot;OS&quot;, &quot;readonly&quot;);
+        
+        transaction.onerror = function(event) {
+            alert(&quot;Unexpected transaction error - &quot; + event);
+            done();
+        }
+
+        transaction.onabort = function(event) {
+            alert(&quot;Unexpected transaction abort - &quot; + event);
+            done();
+        }
+
+        transaction.oncomplete = function(event) {
+            alert(&quot;Read transaction complete - &quot; + event);
+        }
+        
+        firstReadTransactionLoop(transaction, true);
+    }
+    longRunningReadRequest.onerror = function(event) {
+        alert(&quot;Long running read request unexpected error - &quot; + event);
+        done();
+    }
+    longRunningReadRequest.onblocked = function(event) {
+        alert(&quot;Long running read request unexpected blocked - &quot; + event);
+        done();
+    }
+    longRunningReadRequest.onupgradeneeded = function(event) {
+        alert(&quot;Long running read request unexpected upgradeneeded - &quot; + event);
+        done();
+    } 
+}
+
+var shouldEndReadTransaction = false;
+
+function firstReadTransactionLoop(transaction, isFirstTime)
+{
+    var objectStore = transaction.objectStore(&quot;OS&quot;);
+    var request = objectStore.get(&quot;foo&quot;);
+    
+    request.onsuccess = function(event) {
+        if (shouldEndReadTransaction)
+            return;
+            
+        firstReadTransactionLoop(event.target.transaction, false);
+        
+        // Now that the read transaction is open, the other transactions can be queued up.
+        if (isFirstTime)
+             startOtherTransactions()
+    }
+
+    request.onerror = function(event) {
+        alert(&quot;Unexpected request error - &quot; + event);
+        done();
+    }
+}
+
+var shouldEndReadTransaction = false;
+var loggedWritePutSuccessOnce = false;
+function writeTransactionLoop(transaction)
+{
+    var objectStore = transaction.objectStore(&quot;OS&quot;);
+    var request = objectStore.put(&quot;baz&quot;, &quot;foo&quot;);
+
+    request.onsuccess = function(event) {
+        if (!loggedWritePutSuccessOnce) {
+            alert(&quot;Write transaction first put success&quot;);
+            loggedWritePutSuccessOnce = true;
+        }
+        if (shouldEndReadTransaction)
+            return;
+        
+        writeTransactionLoop(transaction);
+    }
+    
+    request.onerror = function(event) {
+        alert(&quot;Write transaction put unexpected error - &quot; + event);
+        done();
+    }
+}
+
+function startOtherTransactions()
+{
+    var transaction = secondDatabaseConnection.transaction(&quot;OS&quot;, &quot;readwrite&quot;);
+
+    transaction.onerror = function(event) {
+        alert(&quot;Write transaction unexpected error - &quot; + event);
+        done();
+    }
+
+    transaction.onabort = function(event) {
+        alert(&quot;Write transaction unexpected abort - &quot; + event);
+        done();
+    }
+
+    transaction.oncomplete = function(event) {
+        alert(&quot;Write transaction complete - &quot; + event);
+    }
+    
+    writeTransactionLoop(transaction);
+
+    // This read-only transaction should be blocked behind the read-write transaction above, 
+    // and should not start until it finishes.
+    transaction = secondDatabaseConnection.transaction(&quot;OS&quot;, &quot;readonly&quot;);
+    transaction.onerror = function(event) {
+        alert(&quot;Second read-only transaction unexpected error - &quot; + event);
+        done();
+    }
+
+    transaction.onabort = function(event) {
+        alert(&quot;Second read-only transaction unexpected abort - &quot; + event);
+        done();
+    }
+
+    transaction.oncomplete = function(event) {
+        alert(&quot;Second read-only transaction complete - &quot; + event);
+        done();
+    }
+    
+    var objectStore = transaction.objectStore(&quot;OS&quot;);
+    var request = objectStore.get(&quot;foo&quot;);
+
+    request.onsuccess = function(event) {
+        alert(&quot;Second read-only transaction get success - &quot; + event);
+    }
+    
+    request.onerror = function(event) {
+        alert(&quot;Second read-only transaction put unexpected error - &quot; + event);
+        done();
+    }
+
+    // This read-only transaction is queued behind the 3 previous transactions, but should not
+    // be blocked because its scope doesn't overlap the read-write transaction.
+    transaction = secondDatabaseConnection.transaction(&quot;OtherOS&quot;, &quot;readonly&quot;);
+
+    transaction.onerror = function(event) {
+        alert(&quot;Other objectstore read transaction unexpected error - &quot; + event);
+        done();
+    }
+
+    transaction.onabort = function(event) {
+        alert(&quot;Other objectstore read transaction unexpected abort - &quot; + event);
+        done();
+    }
+
+    transaction.oncomplete = function(event) {
+        alert(&quot;Other objectstore read transaction complete - &quot; + event);
+        shouldEndReadTransaction = true;
+    }
+
+    objectStore = transaction.objectStore(&quot;OtherOS&quot;);
+    request = objectStore.get(&quot;foo&quot;);
+
+    request.onsuccess = function(event) {
+        alert(&quot;Other objectstore read transaction get success - &quot; + event);
+    }
+    
+    request.onerror = function(event) {
+        alert(&quot;Other objectstore read transaction get unexpected error - &quot; + event);
+        done();
+    }
+}
+
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderntransactionscheduler5expectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-5-expected.txt (0 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-5-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-5-expected.txt        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -0,0 +1,14 @@
</span><ins>+ALERT: Upgrade needed: Old version - 0 New version - 1
+ALERT: versionchange transaction completed
+ALERT: Success opening database connection - Starting transactions
+ALERT: Starting write transaction
+ALERT: Read transaction complete - [object Event]
+ALERT: Read transaction complete - [object Event]
+ALERT: Write to OS1 successful
+ALERT: Write to OS2 successful
+ALERT: Done
+This test creates two object stores.
+It then opens two long running read-only transactions, one per object store.
+It then opens a read-write transaction to both object stores.
+The read-only transactions both need to finish before the read-write transaction starts.
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderntransactionscheduler5html"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-5.html (0 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-5.html                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-5.html        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -0,0 +1,166 @@
</span><ins>+This test creates two object stores.&lt;br&gt;
+It then opens two long running read-only transactions, one per object store.&lt;br&gt;
+It then opens a read-write transaction to both object stores.&lt;br&gt;
+The read-only transactions both need to finish before the read-write transaction starts.&lt;br&gt;
+&lt;script&gt;
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function done()
+{
+    alert(&quot;Done&quot;);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+var createRequest = window.indexedDB.open(&quot;TransactionScheduler5Database&quot;);
+
+createRequest.onupgradeneeded = function(event) {
+    alert(&quot;Upgrade needed: Old version - &quot; + event.oldVersion + &quot; New version - &quot; + event.newVersion);
+
+    var versionTransaction = createRequest.transaction;
+    var database = event.target.result;
+    var objectStore = database.createObjectStore(&quot;OS1&quot;);
+    var request = objectStore.put(&quot;bar&quot;, &quot;foo&quot;);
+
+    request.onerror = function(event) {
+        alert(&quot;first put FAILED - &quot; + event);
+        done();
+    }
+
+    objectStore = database.createObjectStore(&quot;OS2&quot;);
+    request = objectStore.put(&quot;bar&quot;, &quot;foo&quot;);
+    
+    request.onerror = function(event) {
+        alert(&quot;second put FAILED - &quot; + event);
+        done();
+    }
+    
+    versionTransaction.onabort = function(event) {
+        alert(&quot;versionchange transaction aborted&quot;);
+        done();
+    }
+
+    versionTransaction.oncomplete = function(event) {
+        alert(&quot;versionchange transaction completed&quot;);
+        continueTest();
+        database.close();
+    }
+
+    versionTransaction.onerror = function(event) {
+        alert(&quot;versionchange transaction error'ed - &quot; + event);
+        done();
+    }
+}
+
+var secondDatabaseConnection;
+var readWriteTransaction;
+
+function setupReadTransactionCallbacks(transaction)
+{
+    transaction.onerror = function(event) {
+        alert(&quot;Unexpected transaction error - &quot; + event);
+        done();
+    }
+
+    transaction.onabort = function(event) {
+        alert(&quot;Unexpected transaction abort - &quot; + event);
+        done();
+    }
+
+    transaction.oncomplete = function(event) {
+        alert(&quot;Read transaction complete - &quot; + event);
+    }
+
+    transaction.hasDoneFirstRead = false;
+}
+
+function continueTest()
+{
+    var openDBRequest = window.indexedDB.open(&quot;TransactionScheduler5Database&quot;, 1);
+    openDBRequest.onsuccess = function(event) {
+        alert(&quot;Success opening database connection - Starting transactions&quot;);
+        secondDatabaseConnection = event.target.result;
+        
+        var transaction1 = secondDatabaseConnection.transaction(&quot;OS1&quot;, &quot;readonly&quot;);
+        setupReadTransactionCallbacks(transaction1);
+        var transaction2 = secondDatabaseConnection.transaction(&quot;OS2&quot;, &quot;readonly&quot;);
+        setupReadTransactionCallbacks(transaction2);
+
+        readTransactionLoop(transaction1, &quot;OS1&quot;, false);
+        readTransactionLoop(transaction2, &quot;OS2&quot;, true);
+    }
+    openDBRequest.onerror = function(event) {
+        alert(&quot;Long running read request unexpected error - &quot; + event);
+        done();
+    }
+    openDBRequest.onblocked = function(event) {
+        alert(&quot;Long running read request unexpected blocked - &quot; + event);
+        done();
+    }
+    openDBRequest.onupgradeneeded = function(event) {
+        alert(&quot;Long running read request unexpected upgradeneeded - &quot; + event);
+        done();
+    } 
+}
+
+var shouldEndReadTransaction = false;
+
+function readTransactionLoop(transaction, osname, shouldStartWrite)
+{
+    var objectStore = transaction.objectStore(osname);
+    var request = objectStore.get(&quot;foo&quot;);
+    
+    request.onsuccess = function(event) {
+        if (shouldEndReadTransaction &amp;&amp; transaction.hasDoneFirstRead)
+            return;
+
+        transaction.hasDoneFirstRead = true;
+        readTransactionLoop(event.target.transaction, osname, false);
+        
+        if (shouldStartWrite)
+             startWriteTransaction();
+    }
+
+    request.onerror = function(event) {
+        alert(&quot;Unexpected request error - &quot; + event);
+        done();
+    }
+}
+
+function startWriteTransaction()
+{
+    alert(&quot;Starting write transaction&quot;);
+    var transaction = secondDatabaseConnection.transaction([&quot;OS1&quot;, &quot;OS2&quot;], &quot;readwrite&quot;);
+    var objectStore = transaction.objectStore(&quot;OS1&quot;);
+    var request = objectStore.put(&quot;baz&quot;, &quot;foo&quot;);
+
+    shouldEndReadTransaction = true;
+
+    request.onsuccess = function(event) {
+        alert(&quot;Write to OS1 successful&quot;);
+    }
+    
+    request.onerror = function(event) {
+        alert(&quot;Write transaction put unexpected error - &quot; + event);
+        done();
+    }
+
+    objectStore = transaction.objectStore(&quot;OS2&quot;);
+    request = objectStore.put(&quot;baz&quot;, &quot;foo&quot;);
+
+    request.onsuccess = function(event) {
+        alert(&quot;Write to OS2 successful&quot;);
+        done();
+    }
+    
+    request.onerror = function(event) {
+        alert(&quot;Write transaction put unexpected error - &quot; + event);
+        done();
+    }
+}
+
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderntransactionscheduler6expectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-6-expected.txt (0 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-6-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-6-expected.txt        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+ALERT: Upgrade needed: Old version - 0 New version - 1
+ALERT: versionchange transaction completed
+ALERT: Starting a readonly transaction
+ALERT: Starting a readonly transaction
+ALERT: readonly transaction completed
+ALERT: readonly transaction completed
+ALERT: Write in readwrite transaction succeeded
+ALERT: readwrite transaction completed
+ALERT: Done
+This test starts two read-only transactions to an object store followed by a read-write transaction.
+It verifies that the read-write doesn't start until both read-onlys have finished.
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderntransactionscheduler6html"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-6.html (0 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-6.html                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/transaction-scheduler-6.html        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -0,0 +1,124 @@
</span><ins>+This test starts two read-only transactions to an object store followed by a read-write transaction.&lt;br&gt;
+It verifies that the read-write doesn't start until both read-onlys have finished.&lt;br&gt;
+&lt;script&gt;
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function done()
+{
+    alert(&quot;Done&quot;);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+var createRequest = window.indexedDB.open(&quot;TransactionScheduler6Database&quot;);
+var database;
+
+createRequest.onupgradeneeded = function(event) {
+    alert(&quot;Upgrade needed: Old version - &quot; + event.oldVersion + &quot; New version - &quot; + event.newVersion);
+
+    var versionTransaction = createRequest.transaction;
+    database = event.target.result;
+    var objectStore = database.createObjectStore(&quot;TestObjectStore&quot;);
+    var request = objectStore.put(&quot;foo&quot;, &quot;bar&quot;);
+
+    request.onerror = function(event) {
+        alert(&quot;put FAILED - &quot; + event);
+        done();
+    }
+    
+    versionTransaction.onabort = function(event) {
+        alert(&quot;versionchange transaction aborted&quot;);
+        done();
+    }
+
+    versionTransaction.oncomplete = function(event) {
+        alert(&quot;versionchange transaction completed&quot;);
+        continueTest();
+    }
+
+    versionTransaction.onerror = function(event) {
+        alert(&quot;versionchange transaction error'ed - &quot; + event);
+        done();
+    }
+}
+
+function continueTest()
+{
+    startTransactionLoop(database.transaction(&quot;TestObjectStore&quot;, &quot;readonly&quot;), true);
+    startTransactionLoop(database.transaction(&quot;TestObjectStore&quot;, &quot;readonly&quot;), true);
+    
+    var transaction = database.transaction(&quot;TestObjectStore&quot;, &quot;readwrite&quot;);
+    var objectStore = transaction.objectStore(&quot;TestObjectStore&quot;);
+    var request = objectStore.put(&quot;baz&quot;, &quot;foo&quot;);
+
+    request.onsuccess = function(event) {
+        alert(&quot;Write in readwrite transaction succeeded&quot;);
+    }
+    
+    request.onerror = function(event) {
+        alert(&quot;Write in readwrite transaction unexpectedly failed&quot;);
+        done();
+    }
+    
+    transaction.onabort = function(event) {
+        alert(&quot;readwrite transaction expectedly aborted&quot;);
+        done();
+    }
+
+    transaction.oncomplete = function(event) {
+        alert(&quot;readwrite transaction completed&quot;);
+        done();
+    }
+
+    transaction.onerror = function(event) {
+        alert(&quot;readwrite transaction error'ed - &quot; + event);
+        done();
+    }
+}
+
+var numberOfOpenTransactions = 0;
+
+function startTransactionLoop(transaction, isFirstTime)
+{
+    var objectStore = transaction.objectStore(&quot;TestObjectStore&quot;);
+    var request = objectStore.get(&quot;bar&quot;);
+    
+    request.onsuccess = function(event) {
+        if (isFirstTime) {
+            alert(&quot;Starting a readonly transaction&quot;);
+            numberOfOpenTransactions++;
+        }
+        
+        if (numberOfOpenTransactions == 2)
+            return;
+
+        startTransactionLoop(event.target.transaction, false);
+    }
+
+    request.onerror = function(event) {
+        alert(&quot;Unexpected request error - &quot; + event);
+        done();
+    }
+
+    transaction.onerror = function(event) {
+        alert(&quot;Unexpected transaction error - &quot; + event);
+        done();
+    }
+
+    transaction.onabort = function(event) {
+        --numberOfOpenTransactions;
+        alert(&quot;Unexpected transaction abort - &quot; + event);
+        done();
+    }
+
+    transaction.oncomplete = function(event) {
+        --numberOfOpenTransactions;
+        alert(&quot;readonly transaction completed&quot;);
+    }
+}
+
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/ChangeLog        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -1,3 +1,109 @@
</span><ins>+2015-10-28  Brady Eidson  &lt;beidson@apple.com&gt;
+
+        Modern IDB: Support IDBDatabase.transaction() (and transaction scheduling in general).
+        https://bugs.webkit.org/show_bug.cgi?id=150614
+
+        Reviewed by Alex Christensen.
+
+        Tests: storage/indexeddb/modern/idbdatabase-transaction-failures.html
+               storage/indexeddb/modern/transaction-scheduler-1.html
+               storage/indexeddb/modern/transaction-scheduler-2.html
+               storage/indexeddb/modern/transaction-scheduler-3.html
+               storage/indexeddb/modern/transaction-scheduler-4.html
+               storage/indexeddb/modern/transaction-scheduler-5.html
+               storage/indexeddb/modern/transaction-scheduler-6.html
+
+        * Modules/indexeddb/IDBDatabase.idl:
+
+        * Modules/indexeddb/IndexedDB.h:
+
+        * Modules/indexeddb/client/IDBConnectionToServer.cpp:
+        (WebCore::IDBClient::IDBConnectionToServer::establishTransaction):
+        (WebCore::IDBClient::IDBConnectionToServer::didStartTransaction):
+        (WebCore::IDBClient::IDBConnectionToServer::hasRecordOfTransaction):
+        * Modules/indexeddb/client/IDBConnectionToServer.h:
+        * Modules/indexeddb/client/IDBConnectionToServerDelegate.h:
+
+        * Modules/indexeddb/client/IDBDatabaseImpl.cpp:
+        (WebCore::IDBClient::IDBDatabase::transaction):
+        (WebCore::IDBClient::IDBDatabase::didStartTransaction):
+        * Modules/indexeddb/client/IDBDatabaseImpl.h:
+
+        * Modules/indexeddb/client/IDBTransactionImpl.cpp:
+        (WebCore::IDBClient::IDBTransaction::IDBTransaction):
+        (WebCore::IDBClient::IDBTransaction::operationTimerFired):
+        (WebCore::IDBClient::IDBTransaction::didStart):
+        (WebCore::IDBClient::IDBTransaction::establishOnServer):
+        (WebCore::IDBClient::IDBTransaction::activate):
+        (WebCore::IDBClient::IDBTransaction::deactivate):
+        * Modules/indexeddb/client/IDBTransactionImpl.h:
+
+        * Modules/indexeddb/server/IDBConnectionToClient.cpp:
+        (WebCore::IDBServer::IDBConnectionToClient::didStartTransaction):
+        * Modules/indexeddb/server/IDBConnectionToClient.h:
+        * Modules/indexeddb/server/IDBConnectionToClientDelegate.h:
+
+        * Modules/indexeddb/server/IDBServer.cpp:
+        (WebCore::IDBServer::IDBServer::establishTransaction):
+        * Modules/indexeddb/server/IDBServer.h:
+
+        * Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
+        (WebCore::IDBServer::MemoryIDBBackingStore::beginTransaction):
+        (WebCore::IDBServer::MemoryIDBBackingStore::createObjectStore):
+        (WebCore::IDBServer::MemoryIDBBackingStore::removeObjectStoreForVersionChangeAbort):
+        (WebCore::IDBServer::MemoryIDBBackingStore::keyExistsInObjectStore):
+        (WebCore::IDBServer::MemoryIDBBackingStore::deleteRecord):
+        (WebCore::IDBServer::MemoryIDBBackingStore::putRecord):
+        (WebCore::IDBServer::MemoryIDBBackingStore::getRecord):
+        (WebCore::IDBServer::MemoryIDBBackingStore::registerObjectStore):
+        (WebCore::IDBServer::MemoryIDBBackingStore::unregisterObjectStore):
+        * Modules/indexeddb/server/MemoryIDBBackingStore.h:
+
+        * Modules/indexeddb/server/UniqueIDBDatabase.cpp:
+        (WebCore::IDBServer::UniqueIDBDatabase::startVersionChangeTransaction):
+        (WebCore::IDBServer::UniqueIDBDatabase::performCommitTransaction):
+        (WebCore::IDBServer::UniqueIDBDatabase::didPerformCommitTransaction):
+        (WebCore::IDBServer::UniqueIDBDatabase::didPerformAbortTransaction):
+        (WebCore::IDBServer::UniqueIDBDatabase::enqueueTransaction):
+        (WebCore::IDBServer::UniqueIDBDatabase::transactionSchedulingTimerFired):
+        (WebCore::IDBServer::UniqueIDBDatabase::activateTransactionInBackingStore):
+        (WebCore::IDBServer::UniqueIDBDatabase::performActivateTransactionInBackingStore):
+        (WebCore::IDBServer::UniqueIDBDatabase::didPerformActivateTransactionInBackingStore):
+        (WebCore::IDBServer::scopesOverlap):
+        (WebCore::IDBServer::UniqueIDBDatabase::takeNextRunnableTransaction):
+        (WebCore::IDBServer::UniqueIDBDatabase::inProgressTransactionCompleted):
+        * Modules/indexeddb/server/UniqueIDBDatabase.h:
+
+        * Modules/indexeddb/server/UniqueIDBDatabaseConnection.cpp:
+        (WebCore::IDBServer::UniqueIDBDatabaseConnection::establishTransaction):
+        * Modules/indexeddb/server/UniqueIDBDatabaseConnection.h:
+
+        * Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp:
+        (WebCore::IDBServer::UniqueIDBDatabaseTransaction::create):
+        (WebCore::IDBServer::UniqueIDBDatabaseTransaction::UniqueIDBDatabaseTransaction):
+        (WebCore::IDBServer::UniqueIDBDatabaseTransaction::objectStoreIdentifiers):
+        (WebCore::IDBServer::UniqueIDBDatabaseTransaction::didActivateInBackingStore):
+        * Modules/indexeddb/server/UniqueIDBDatabaseTransaction.h:
+        
+        * Modules/indexeddb/shared/IDBTransactionInfo.cpp:
+        (WebCore::IDBTransactionInfo::clientTransaction):
+        (WebCore::IDBTransactionInfo::isolatedCopy):
+        * Modules/indexeddb/shared/IDBTransactionInfo.h:
+        
+        * Modules/indexeddb/shared/InProcessIDBServer.cpp:
+        (WebCore::InProcessIDBServer::establishTransaction):
+        (WebCore::InProcessIDBServer::didStartTransaction):
+        * Modules/indexeddb/shared/InProcessIDBServer.h:
+        
+        * bindings/js/IDBBindingUtilities.cpp:
+        (WebCore::deserializeIDBValueData):
+        
+        * bindings/js/JSIDBDatabaseCustom.cpp:
+        (WebCore::JSIDBDatabase::transaction):
+        
+        * bindings/js/ScriptState.cpp:
+        (WebCore::execStateFromPage):
+
</ins><span class="cx"> 2015-10-28  Eric Carlson  &lt;eric.carlson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [MediaStream] Play MediaStream through media element and rendered to canvas
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbIDBDatabaseidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.idl (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.idl        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.idl        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -39,13 +39,12 @@
</span><span class="cx"> 
</span><span class="cx">     [Custom, RaisesException] IDBObjectStore createObjectStore(DOMString name, optional Dictionary options);
</span><span class="cx">     [RaisesException] void deleteObjectStore(DOMString name);
</span><del>-    [CallWith=ScriptExecutionContext, RaisesException] IDBTransaction transaction(DOMString storeName, [Default=NullString] optional DOMString mode);
-    [CallWith=ScriptExecutionContext, RaisesException] IDBTransaction transaction(sequence&lt;DOMString&gt; storeNames, [Default=NullString] optional DOMString mode);
</del><ins>+    [Custom, CallWith=ScriptExecutionContext, RaisesException] IDBTransaction transaction(DOMString storeName, [Default=NullString] optional DOMString mode);
+    [Custom, CallWith=ScriptExecutionContext, RaisesException] IDBTransaction transaction(sequence&lt;DOMString&gt; storeNames, [Default=NullString] optional DOMString mode);
</ins><span class="cx">     void close();
</span><span class="cx"> 
</span><span class="cx">     attribute EventHandler onabort;
</span><span class="cx">     attribute EventHandler onerror;
</span><span class="cx">     attribute EventHandler onversionchange;
</span><del>-
</del><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbIndexedDBh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/IndexedDB.h (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/IndexedDB.h        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/IndexedDB.h        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -40,7 +40,6 @@
</span><span class="cx"> const unsigned TransactionModeMaximum = 2;
</span><span class="cx"> 
</span><span class="cx"> enum class TransactionState {
</span><del>-    Unstarted,
</del><span class="cx">     Active,
</span><span class="cx">     Inactive,
</span><span class="cx">     Committing,
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbclientIDBConnectionToServercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/client/IDBConnectionToServer.cpp (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/client/IDBConnectionToServer.cpp        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/client/IDBConnectionToServer.cpp        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -139,6 +139,16 @@
</span><span class="cx">     completeOperation(resultData);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void IDBConnectionToServer::establishTransaction(IDBTransaction&amp; transaction)
+{
+    LOG(IndexedDB, &quot;IDBConnectionToServer::establishTransaction&quot;);
+
+    ASSERT(!hasRecordOfTransaction(transaction));
+    m_pendingTransactions.set(transaction.info().identifier(), &amp;transaction);
+
+    m_delegate-&gt;establishTransaction(transaction.database().databaseConnectionIdentifier(), transaction.info());
+}
+
</ins><span class="cx"> void IDBConnectionToServer::commitTransaction(IDBTransaction&amp; transaction)
</span><span class="cx"> {
</span><span class="cx">     LOG(IndexedDB, &quot;IDBConnectionToServer::commitTransaction&quot;);
</span><span class="lines">@@ -190,6 +200,16 @@
</span><span class="cx">     connection-&gt;fireVersionChangeEvent(requestedVersion);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void IDBConnectionToServer::didStartTransaction(const IDBResourceIdentifier&amp; transactionIdentifier, const IDBError&amp; error)
+{
+    LOG(IndexedDB, &quot;IDBConnectionToServer::didStartTransaction&quot;);
+
+    auto transaction = m_pendingTransactions.take(transactionIdentifier);
+    ASSERT(transaction);
+
+    transaction-&gt;didStart(error);
+}
+
</ins><span class="cx"> void IDBConnectionToServer::databaseConnectionClosed(IDBDatabase&amp; database)
</span><span class="cx"> {
</span><span class="cx">     LOG(IndexedDB, &quot;IDBConnectionToServer::databaseConnectionClosed&quot;);
</span><span class="lines">@@ -224,6 +244,12 @@
</span><span class="cx">     operation-&gt;completed(resultData);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool IDBConnectionToServer::hasRecordOfTransaction(const IDBTransaction&amp; transaction) const
+{
+    auto identifier = transaction.info().identifier();
+    return m_pendingTransactions.contains(identifier) || m_committingTransactions.contains(identifier) || m_abortingTransactions.contains(identifier);
+}
+
</ins><span class="cx"> } // namespace IDBClient
</span><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbclientIDBConnectionToServerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/client/IDBConnectionToServer.h (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/client/IDBConnectionToServer.h        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/client/IDBConnectionToServer.h        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -77,7 +77,10 @@
</span><span class="cx">     void didAbortTransaction(const IDBResourceIdentifier&amp; transactionIdentifier, const IDBError&amp;);
</span><span class="cx"> 
</span><span class="cx">     void fireVersionChangeEvent(uint64_t databaseConnectionIdentifier, uint64_t requestedVersion);
</span><ins>+    void didStartTransaction(const IDBResourceIdentifier&amp; transactionIdentifier, const IDBError&amp;);
</ins><span class="cx"> 
</span><ins>+    void establishTransaction(IDBTransaction&amp;);
+
</ins><span class="cx">     void databaseConnectionClosed(IDBDatabase&amp;);
</span><span class="cx">     void registerDatabaseConnection(IDBDatabase&amp;);
</span><span class="cx">     void unregisterDatabaseConnection(IDBDatabase&amp;);
</span><span class="lines">@@ -88,10 +91,13 @@
</span><span class="cx">     void saveOperation(TransactionOperation&amp;);
</span><span class="cx">     void completeOperation(const IDBResultData&amp;);
</span><span class="cx"> 
</span><ins>+    bool hasRecordOfTransaction(const IDBTransaction&amp;) const;
+
</ins><span class="cx">     Ref&lt;IDBConnectionToServerDelegate&gt; m_delegate;
</span><span class="cx"> 
</span><span class="cx">     HashMap&lt;IDBResourceIdentifier, RefPtr&lt;IDBClient::IDBOpenDBRequest&gt;&gt; m_openDBRequestMap;
</span><span class="cx">     HashMap&lt;uint64_t, IDBDatabase*&gt; m_databaseConnectionMap;
</span><ins>+    HashMap&lt;IDBResourceIdentifier, RefPtr&lt;IDBTransaction&gt;&gt; m_pendingTransactions;
</ins><span class="cx">     HashMap&lt;IDBResourceIdentifier, RefPtr&lt;IDBTransaction&gt;&gt; m_committingTransactions;
</span><span class="cx">     HashMap&lt;IDBResourceIdentifier, RefPtr&lt;IDBTransaction&gt;&gt; m_abortingTransactions;
</span><span class="cx">     HashMap&lt;IDBResourceIdentifier, RefPtr&lt;TransactionOperation&gt;&gt; m_activeOperations;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbclientIDBConnectionToServerDelegateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/client/IDBConnectionToServerDelegate.h (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/client/IDBConnectionToServerDelegate.h        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/client/IDBConnectionToServerDelegate.h        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -34,6 +34,7 @@
</span><span class="cx"> class IDBObjectStoreInfo;
</span><span class="cx"> class IDBRequestData;
</span><span class="cx"> class IDBResourceIdentifier;
</span><ins>+class IDBTransactionInfo;
</ins><span class="cx"> class SerializedScriptValue;
</span><span class="cx"> 
</span><span class="cx"> namespace IndexedDB {
</span><span class="lines">@@ -54,6 +55,7 @@
</span><span class="cx">     virtual void createObjectStore(const IDBRequestData&amp;, const IDBObjectStoreInfo&amp;) = 0;
</span><span class="cx">     virtual void putOrAdd(const IDBRequestData&amp;, IDBKey*, SerializedScriptValue&amp;, const IndexedDB::ObjectStoreOverwriteMode) = 0;
</span><span class="cx">     virtual void getRecord(const IDBRequestData&amp;, IDBKey*) = 0;
</span><ins>+    virtual void establishTransaction(uint64_t databaseConnectionIdentifier, const IDBTransactionInfo&amp;) = 0;
</ins><span class="cx"> 
</span><span class="cx">     virtual void databaseConnectionClosed(uint64_t databaseConnectionIdentifier) = 0;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbclientIDBDatabaseImplcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/client/IDBDatabaseImpl.cpp (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/client/IDBDatabaseImpl.cpp        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/client/IDBDatabaseImpl.cpp        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -128,16 +128,54 @@
</span><span class="cx">     return adoptRef(&amp;objectStore.leakRef());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr&lt;WebCore::IDBTransaction&gt; IDBDatabase::transaction(ScriptExecutionContext*, const Vector&lt;String&gt;&amp;, const String&amp;, ExceptionCode&amp;)
</del><ins>+RefPtr&lt;WebCore::IDBTransaction&gt; IDBDatabase::transaction(ScriptExecutionContext*, const Vector&lt;String&gt;&amp; objectStores, const String&amp; modeString, ExceptionCode&amp; ec)
</ins><span class="cx"> {
</span><del>-    ASSERT_NOT_REACHED();
-    return nullptr;
</del><ins>+    LOG(IndexedDB, &quot;IDBDatabase::transaction&quot;);
+
+    if (m_closePending) {
+        ec = INVALID_STATE_ERR;
+        return nullptr;
+    }
+
+    if (objectStores.isEmpty()) {
+        ec = INVALID_ACCESS_ERR;
+        return nullptr;
+    }
+
+    IndexedDB::TransactionMode mode = IDBTransaction::stringToMode(modeString, ec);
+    if (ec)
+        return nullptr;
+
+    if (mode != IndexedDB::TransactionMode::ReadOnly &amp;&amp; mode != IndexedDB::TransactionMode::ReadWrite) {
+        ec = TypeError;
+        return nullptr;
+    }
+
+    if (m_versionChangeTransaction) {
+        ec = INVALID_STATE_ERR;
+        return nullptr;
+    }
+
+    for (auto&amp; objectStoreName : objectStores) {
+        if (m_info.hasObjectStore(objectStoreName))
+            continue;
+        ec = NOT_FOUND_ERR;
+        return nullptr;
+    }
+
+    auto info = IDBTransactionInfo::clientTransaction(m_serverConnection.get(), objectStores, mode);
+    auto transaction = IDBTransaction::create(*this, info);
+
+    m_activeTransactions.set(info.identifier(), &amp;transaction.get());
+
+    return adoptRef(&amp;transaction.leakRef());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr&lt;WebCore::IDBTransaction&gt; IDBDatabase::transaction(ScriptExecutionContext*, const String&amp;, const String&amp;, ExceptionCode&amp;)
</del><ins>+RefPtr&lt;WebCore::IDBTransaction&gt; IDBDatabase::transaction(ScriptExecutionContext* context, const String&amp; objectStore, const String&amp; mode, ExceptionCode&amp; ec)
</ins><span class="cx"> {
</span><del>-    ASSERT_NOT_REACHED();
-    return nullptr;
</del><ins>+    Vector&lt;String&gt; objectStores(1);
+    objectStores[0] = objectStore;
+    return transaction(context, objectStores, mode, ec);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void IDBDatabase::deleteObjectStore(const String&amp;, ExceptionCode&amp;)
</span><span class="lines">@@ -193,6 +231,14 @@
</span><span class="cx">     return WTF::move(transaction);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void IDBDatabase::didStartTransaction(IDBTransaction&amp; transaction)
+{
+    LOG(IndexedDB, &quot;IDBDatabase::didStartTransaction&quot;);
+    ASSERT(!m_versionChangeTransaction);
+
+    m_activeTransactions.set(transaction.info().identifier(), &amp;transaction);
+}
+
</ins><span class="cx"> void IDBDatabase::commitTransaction(IDBTransaction&amp; transaction)
</span><span class="cx"> {
</span><span class="cx">     LOG(IndexedDB, &quot;IDBDatabase::commitTransaction&quot;);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbclientIDBDatabaseImplh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/client/IDBDatabaseImpl.h (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/client/IDBDatabaseImpl.h        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/client/IDBDatabaseImpl.h        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -73,6 +73,8 @@
</span><span class="cx">     uint64_t databaseConnectionIdentifier() const { return m_databaseConnectionIdentifier; }
</span><span class="cx"> 
</span><span class="cx">     Ref&lt;IDBTransaction&gt; startVersionChangeTransaction(const IDBTransactionInfo&amp;);
</span><ins>+    void didStartTransaction(IDBTransaction&amp;);
+
</ins><span class="cx">     void commitTransaction(IDBTransaction&amp;);
</span><span class="cx">     void didCommitTransaction(IDBTransaction&amp;);
</span><span class="cx">     void abortTransaction(IDBTransaction&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbclientIDBTransactionImplcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.cpp (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.cpp        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.cpp        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -55,14 +55,18 @@
</span><span class="cx">     , m_operationTimer(*this, &amp;IDBTransaction::operationTimerFired)
</span><span class="cx"> 
</span><span class="cx"> {
</span><del>-    m_activationTimer = std::make_unique&lt;Timer&gt;(*this, &amp;IDBTransaction::activationTimerFired);
-    m_activationTimer-&gt;startOneShot(0);
</del><ins>+    relaxAdoptionRequirement();
</ins><span class="cx"> 
</span><del>-    if (m_info.mode() == IndexedDB::TransactionMode::VersionChange)
</del><ins>+    if (m_info.mode() == IndexedDB::TransactionMode::VersionChange) {
+        m_activationTimer = std::make_unique&lt;Timer&gt;(*this, &amp;IDBTransaction::activationTimerFired);
+        m_activationTimer-&gt;startOneShot(0);
</ins><span class="cx">         m_originalDatabaseInfo = std::make_unique&lt;IDBDatabaseInfo&gt;(m_database-&gt;info());
</span><ins>+        m_state = IndexedDB::TransactionState::Inactive;
+        m_startedOnServer = true;
+    } else
+        establishOnServer();
</ins><span class="cx"> 
</span><span class="cx">     suspendIfNeeded();
</span><del>-    m_state = IndexedDB::TransactionState::Inactive;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> IDBTransaction::~IDBTransaction()
</span><span class="lines">@@ -213,7 +217,7 @@
</span><span class="cx"> {
</span><span class="cx">     LOG(IndexedDB, &quot;IDBTransaction::operationTimerFired&quot;);
</span><span class="cx"> 
</span><del>-    if (m_state == IndexedDB::TransactionState::Unstarted)
</del><ins>+    if (!m_startedOnServer)
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     if (!m_transactionOperationQueue.isEmpty()) {
</span><span class="lines">@@ -247,6 +251,24 @@
</span><span class="cx">     m_originalDatabaseInfo = nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void IDBTransaction::didStart(const IDBError&amp; error)
+{
+    LOG(IndexedDB, &quot;IDBTransaction::didStart&quot;);
+
+    m_database-&gt;didStartTransaction(*this);
+
+    m_startedOnServer = true;
+
+    // It's possible the transaction failed to start on the server.
+    // That equates to an abort.
+    if (!error.isNull()) {
+        didAbort(error);
+        return;
+    }
+
+    scheduleOperationTimer();
+}
+
</ins><span class="cx"> void IDBTransaction::didAbort(const IDBError&amp; error)
</span><span class="cx"> {
</span><span class="cx">     LOG(IndexedDB, &quot;IDBTransaction::didAbort&quot;);
</span><span class="lines">@@ -416,15 +438,22 @@
</span><span class="cx">     request.requestCompleted(resultData);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void IDBTransaction::establishOnServer()
+{
+    LOG(IndexedDB, &quot;IDBTransaction::establishOnServer&quot;);
+
+    serverConnection().establishTransaction(*this);
+}
+
</ins><span class="cx"> void IDBTransaction::activate()
</span><span class="cx"> {
</span><del>-    ASSERT(m_state == IndexedDB::TransactionState::Unstarted || m_state == IndexedDB::TransactionState::Inactive);
</del><ins>+    ASSERT(!isFinishedOrFinishing());
</ins><span class="cx">     m_state = IndexedDB::TransactionState::Active;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void IDBTransaction::deactivate()
</span><span class="cx"> {
</span><del>-    if (m_state == IndexedDB::TransactionState::Unstarted || m_state == IndexedDB::TransactionState::Active)
</del><ins>+    if (m_state == IndexedDB::TransactionState::Active)
</ins><span class="cx">         m_state = IndexedDB::TransactionState::Inactive;
</span><span class="cx"> 
</span><span class="cx">     scheduleOperationTimer();
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbclientIDBTransactionImplh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.h (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.h        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.h        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -77,6 +77,7 @@
</span><span class="cx">     const IDBDatabase&amp; database() const { return m_database.get(); }
</span><span class="cx">     IDBDatabaseInfo* originalDatabaseInfo() const { return m_originalDatabaseInfo.get(); }
</span><span class="cx"> 
</span><ins>+    void didStart(const IDBError&amp;);
</ins><span class="cx">     void didAbort(const IDBError&amp;);
</span><span class="cx">     void didCommit(const IDBError&amp;);
</span><span class="cx"> 
</span><span class="lines">@@ -121,11 +122,15 @@
</span><span class="cx">     void getRecordOnServer(TransactionOperation&amp;, RefPtr&lt;IDBKey&gt;);
</span><span class="cx">     void didGetRecordOnServer(IDBRequest&amp;, const IDBResultData&amp;);
</span><span class="cx"> 
</span><ins>+    void establishOnServer();
+
</ins><span class="cx">     Ref&lt;IDBDatabase&gt; m_database;
</span><span class="cx">     IDBTransactionInfo m_info;
</span><span class="cx">     std::unique_ptr&lt;IDBDatabaseInfo&gt; m_originalDatabaseInfo;
</span><span class="cx"> 
</span><del>-    IndexedDB::TransactionState m_state { IndexedDB::TransactionState::Unstarted };
</del><ins>+    IndexedDB::TransactionState m_state { IndexedDB::TransactionState::Active };
+    bool m_startedOnServer { false };
+
</ins><span class="cx">     IDBError m_idbError;
</span><span class="cx"> 
</span><span class="cx">     Timer m_operationTimer;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverIDBConnectionToClientcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/IDBConnectionToClient.cpp (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/IDBConnectionToClient.cpp        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/server/IDBConnectionToClient.cpp        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -88,6 +88,11 @@
</span><span class="cx">     m_delegate-&gt;fireVersionChangeEvent(connection, requestedVersion);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void IDBConnectionToClient::didStartTransaction(const IDBResourceIdentifier&amp; transactionIdentifier, const IDBError&amp; error)
+{
+    m_delegate-&gt;didStartTransaction(transactionIdentifier, error);
+}
+
</ins><span class="cx"> } // namespace IDBServer
</span><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverIDBConnectionToClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/IDBConnectionToClient.h (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/IDBConnectionToClient.h        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/server/IDBConnectionToClient.h        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -57,6 +57,7 @@
</span><span class="cx">     void didGetRecord(const IDBResultData&amp;);
</span><span class="cx"> 
</span><span class="cx">     void fireVersionChangeEvent(UniqueIDBDatabaseConnection&amp;, uint64_t requestedVersion);
</span><ins>+    void didStartTransaction(const IDBResourceIdentifier&amp; transactionIdentifier, const IDBError&amp;);
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     IDBConnectionToClient(IDBConnectionToClientDelegate&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverIDBConnectionToClientDelegateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/IDBConnectionToClientDelegate.h (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/IDBConnectionToClientDelegate.h        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/server/IDBConnectionToClientDelegate.h        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -53,6 +53,7 @@
</span><span class="cx">     virtual void didGetRecord(const IDBResultData&amp;) = 0;
</span><span class="cx"> 
</span><span class="cx">     virtual void fireVersionChangeEvent(UniqueIDBDatabaseConnection&amp;, uint64_t requestedVersion) = 0;
</span><ins>+    virtual void didStartTransaction(const IDBResourceIdentifier&amp; transactionIdentifier, const IDBError&amp;) = 0;
</ins><span class="cx"> 
</span><span class="cx">     virtual void ref() = 0;
</span><span class="cx">     virtual void deref() = 0;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverIDBServercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -190,6 +190,17 @@
</span><span class="cx">     transaction-&gt;getRecord(requestData, keyData);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void IDBServer::establishTransaction(uint64_t databaseConnectionIdentifier, const IDBTransactionInfo&amp; info)
+{
+    LOG(IndexedDB, &quot;IDBServer::establishTransaction&quot;);
+
+    auto databaseConnection = m_databaseConnections.get(databaseConnectionIdentifier);
+    if (!databaseConnection)
+        return;
+
+    databaseConnection-&gt;establishTransaction(info);
+}
+
</ins><span class="cx"> void IDBServer::commitTransaction(const IDBResourceIdentifier&amp; transactionIdentifier)
</span><span class="cx"> {
</span><span class="cx">     LOG(IndexedDB, &quot;IDBServer::commitTransaction&quot;);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverIDBServerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.h (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.h        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.h        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -62,6 +62,7 @@
</span><span class="cx">     void createObjectStore(const IDBRequestData&amp;, const IDBObjectStoreInfo&amp;);
</span><span class="cx">     void putOrAdd(const IDBRequestData&amp;, const IDBKeyData&amp;, const ThreadSafeDataBuffer&amp; valueData, IndexedDB::ObjectStoreOverwriteMode);
</span><span class="cx">     void getRecord(const IDBRequestData&amp;, const IDBKeyData&amp;);
</span><ins>+    void establishTransaction(uint64_t databaseConnectionIdentifier, const IDBTransactionInfo&amp;);
</ins><span class="cx">     void databaseConnectionClosed(uint64_t databaseConnectionIdentifier);
</span><span class="cx"> 
</span><span class="cx">     void postDatabaseTask(std::unique_ptr&lt;CrossThreadTask&gt;&amp;&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryIDBBackingStorecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -75,8 +75,13 @@
</span><span class="cx"> 
</span><span class="cx">     // VersionChange transactions are scoped to &quot;every object store&quot;.
</span><span class="cx">     if (transaction-&gt;isVersionChange()) {
</span><del>-        for (auto&amp; objectStore : m_objectStores.values())
</del><ins>+        for (auto&amp; objectStore : m_objectStoresByIdentifier.values())
</ins><span class="cx">             transaction-&gt;addExistingObjectStore(*objectStore);
</span><ins>+    } else if (transaction-&gt;isWriting()) {
+        for (auto&amp; iterator : m_objectStoresByName) {
+            if (info.objectStores().contains(iterator.key))
+                transaction-&gt;addExistingObjectStore(*iterator.value);
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     m_transactions.set(info.identifier(), WTF::move(transaction));
</span><span class="lines">@@ -118,7 +123,7 @@
</span><span class="cx">     if (m_databaseInfo-&gt;hasObjectStore(info.name()))
</span><span class="cx">         return IDBError(IDBExceptionCode::ConstraintError);
</span><span class="cx"> 
</span><del>-    ASSERT(!m_objectStores.contains(info.identifier()));
</del><ins>+    ASSERT(!m_objectStoresByIdentifier.contains(info.identifier()));
</ins><span class="cx">     auto objectStore = MemoryObjectStore::create(info);
</span><span class="cx"> 
</span><span class="cx">     m_databaseInfo-&gt;addExistingObjectStore(info);
</span><span class="lines">@@ -128,7 +133,7 @@
</span><span class="cx">     ASSERT(rawTransaction-&gt;isVersionChange());
</span><span class="cx"> 
</span><span class="cx">     rawTransaction-&gt;addNewObjectStore(*objectStore);
</span><del>-    m_objectStores.set(info.identifier(), WTF::move(objectStore));
</del><ins>+    registerObjectStore(WTF::move(objectStore));
</ins><span class="cx"> 
</span><span class="cx">     return IDBError();
</span><span class="cx"> }
</span><span class="lines">@@ -137,20 +142,19 @@
</span><span class="cx"> {
</span><span class="cx">     LOG(IndexedDB, &quot;MemoryIDBBackingStore::removeObjectStoreForVersionChangeAbort&quot;);
</span><span class="cx"> 
</span><del>-    ASSERT(m_objectStores.contains(objectStore.info().identifier()));
-    ASSERT(m_objectStores.get(objectStore.info().identifier()) == &amp;objectStore);
</del><ins>+    ASSERT(m_objectStoresByIdentifier.contains(objectStore.info().identifier()));
+    ASSERT(m_objectStoresByIdentifier.get(objectStore.info().identifier()) == &amp;objectStore);
</ins><span class="cx"> 
</span><del>-    m_objectStores.remove(objectStore.info().identifier());
</del><ins>+    unregisterObjectStore(objectStore);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-
</del><span class="cx"> IDBError MemoryIDBBackingStore::keyExistsInObjectStore(const IDBResourceIdentifier&amp;, uint64_t objectStoreIdentifier, const IDBKeyData&amp; keyData, bool&amp; keyExists)
</span><span class="cx"> {
</span><span class="cx">     LOG(IndexedDB, &quot;MemoryIDBBackingStore::keyExistsInObjectStore&quot;);
</span><span class="cx"> 
</span><span class="cx">     ASSERT(objectStoreIdentifier);
</span><span class="cx"> 
</span><del>-    MemoryObjectStore* objectStore = m_objectStores.get(objectStoreIdentifier);
</del><ins>+    MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
</ins><span class="cx">     RELEASE_ASSERT(objectStore);
</span><span class="cx"> 
</span><span class="cx">     keyExists = objectStore-&gt;containsRecord(keyData);
</span><span class="lines">@@ -163,7 +167,7 @@
</span><span class="cx"> 
</span><span class="cx">     ASSERT(objectStoreIdentifier);
</span><span class="cx"> 
</span><del>-    MemoryObjectStore* objectStore = m_objectStores.get(objectStoreIdentifier);
</del><ins>+    MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
</ins><span class="cx">     RELEASE_ASSERT(objectStore);
</span><span class="cx">     RELEASE_ASSERT(m_transactions.contains(transactionIdentifier));
</span><span class="cx"> 
</span><span class="lines">@@ -181,7 +185,7 @@
</span><span class="cx">     if (!transaction)
</span><span class="cx">         return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral(&quot;No backing store transaction found to get record&quot;));
</span><span class="cx"> 
</span><del>-    MemoryObjectStore* objectStore = m_objectStores.get(objectStoreIdentifier);
</del><ins>+    MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
</ins><span class="cx">     if (!objectStore)
</span><span class="cx">         return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral(&quot;No backing store object store found to put record&quot;));
</span><span class="cx"> 
</span><span class="lines">@@ -198,7 +202,7 @@
</span><span class="cx">     if (!m_transactions.contains(transactionIdentifier))
</span><span class="cx">         return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral(&quot;No backing store transaction found to get record&quot;));
</span><span class="cx"> 
</span><del>-    MemoryObjectStore* objectStore = m_objectStores.get(objectStoreIdentifier);
</del><ins>+    MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
</ins><span class="cx">     if (!objectStore)
</span><span class="cx">         return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral(&quot;No backing store object store found&quot;));
</span><span class="cx"> 
</span><span class="lines">@@ -206,6 +210,25 @@
</span><span class="cx">     return IDBError();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MemoryIDBBackingStore::registerObjectStore(std::unique_ptr&lt;MemoryObjectStore&gt;&amp;&amp; objectStore)
+{
+    ASSERT(objectStore);
+    ASSERT(!m_objectStoresByIdentifier.contains(objectStore-&gt;info().identifier()));
+    ASSERT(!m_objectStoresByName.contains(objectStore-&gt;info().name()));
+
+    m_objectStoresByName.set(objectStore-&gt;info().name(), objectStore.get());
+    m_objectStoresByIdentifier.set(objectStore-&gt;info().identifier(), WTF::move(objectStore));
+}
+
+void MemoryIDBBackingStore::unregisterObjectStore(MemoryObjectStore&amp; objectStore)
+{
+    ASSERT(m_objectStoresByIdentifier.contains(objectStore.info().identifier()));
+    ASSERT(m_objectStoresByName.contains(objectStore.info().name()));
+
+    m_objectStoresByName.remove(objectStore.info().name());
+    m_objectStoresByIdentifier.remove(objectStore.info().identifier());
+}
+
</ins><span class="cx"> } // namespace IDBServer
</span><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryIDBBackingStoreh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.h (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.h        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.h        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -67,7 +67,11 @@
</span><span class="cx">     std::unique_ptr&lt;IDBDatabaseInfo&gt; m_databaseInfo;
</span><span class="cx"> 
</span><span class="cx">     HashMap&lt;IDBResourceIdentifier, std::unique_ptr&lt;MemoryBackingStoreTransaction&gt;&gt; m_transactions;
</span><del>-    HashMap&lt;uint64_t, std::unique_ptr&lt;MemoryObjectStore&gt;&gt; m_objectStores;
</del><ins>+
+    void registerObjectStore(std::unique_ptr&lt;MemoryObjectStore&gt;&amp;&amp;);
+    void unregisterObjectStore(MemoryObjectStore&amp;);
+    HashMap&lt;uint64_t, std::unique_ptr&lt;MemoryObjectStore&gt;&gt; m_objectStoresByIdentifier;
+    HashMap&lt;String, MemoryObjectStore*&gt; m_objectStoresByName;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace IDBServer
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverUniqueIDBDatabasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -171,6 +171,7 @@
</span><span class="cx">     addOpenDatabaseConnection(*m_versionChangeDatabaseConnection);
</span><span class="cx"> 
</span><span class="cx">     m_versionChangeTransaction = &amp;m_versionChangeDatabaseConnection-&gt;createVersionChangeTransaction(requestedVersion);
</span><ins>+    m_inProgressTransactions.set(m_versionChangeTransaction-&gt;info().identifier(), m_versionChangeTransaction);
</ins><span class="cx">     m_server.postDatabaseTask(createCrossThreadTask(*this, &amp;UniqueIDBDatabase::beginTransactionInBackingStore, m_versionChangeTransaction-&gt;info()));
</span><span class="cx"> 
</span><span class="cx">     auto result = IDBResultData::openDatabaseUpgradeNeeded(operation-&gt;requestData().requestIdentifier(), *m_versionChangeTransaction);
</span><span class="lines">@@ -391,16 +392,15 @@
</span><span class="cx">     LOG(IndexedDB, &quot;(db) UniqueIDBDatabase::performCommitTransaction&quot;);
</span><span class="cx"> 
</span><span class="cx">     IDBError error = m_backingStore-&gt;commitTransaction(transactionIdentifier);
</span><del>-    m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &amp;UniqueIDBDatabase::didPerformCommitTransaction, callbackIdentifier, error));
</del><ins>+    m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &amp;UniqueIDBDatabase::didPerformCommitTransaction, callbackIdentifier, error, transactionIdentifier));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void UniqueIDBDatabase::didPerformCommitTransaction(uint64_t callbackIdentifier, const IDBError&amp; error)
</del><ins>+void UniqueIDBDatabase::didPerformCommitTransaction(uint64_t callbackIdentifier, const IDBError&amp; error, const IDBResourceIdentifier&amp; transactionIdentifier)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(isMainThread());
</span><span class="cx">     LOG(IndexedDB, &quot;(main) UniqueIDBDatabase::didPerformCommitTransaction&quot;);
</span><span class="cx"> 
</span><del>-    // Previously blocked transactions might now be unblocked.
-    invokeTransactionScheduler();
</del><ins>+    inProgressTransactionCompleted(transactionIdentifier);
</ins><span class="cx"> 
</span><span class="cx">     performErrorCallback(callbackIdentifier, error);
</span><span class="cx"> }
</span><span class="lines">@@ -430,7 +430,7 @@
</span><span class="cx">     ASSERT(isMainThread());
</span><span class="cx">     LOG(IndexedDB, &quot;(main) UniqueIDBDatabase::didPerformAbortTransaction&quot;);
</span><span class="cx"> 
</span><del>-    if (m_versionChangeTransaction || m_versionChangeTransaction-&gt;info().identifier() == transactionIdentifier) {
</del><ins>+    if (m_versionChangeTransaction &amp;&amp; m_versionChangeTransaction-&gt;info().identifier() == transactionIdentifier) {
</ins><span class="cx">         ASSERT(&amp;m_versionChangeTransaction-&gt;databaseConnection() == m_versionChangeDatabaseConnection);
</span><span class="cx">         ASSERT(m_versionChangeTransaction-&gt;originalDatabaseInfo());
</span><span class="cx">         m_databaseInfo = std::make_unique&lt;IDBDatabaseInfo&gt;(*m_versionChangeTransaction-&gt;originalDatabaseInfo());
</span><span class="lines">@@ -439,8 +439,7 @@
</span><span class="cx">         m_versionChangeDatabaseConnection = nullptr;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // Previously blocked transactions might now be unblocked.
-    invokeTransactionScheduler();
</del><ins>+    inProgressTransactionCompleted(transactionIdentifier);
</ins><span class="cx"> 
</span><span class="cx">     performErrorCallback(callbackIdentifier, error);
</span><span class="cx"> }
</span><span class="lines">@@ -471,6 +470,17 @@
</span><span class="cx">     invokeTransactionScheduler();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void UniqueIDBDatabase::enqueueTransaction(Ref&lt;UniqueIDBDatabaseTransaction&gt;&amp;&amp; transaction)
+{
+    LOG(IndexedDB, &quot;UniqueIDBDatabase::enqueueTransaction&quot;);
+
+    ASSERT(transaction-&gt;info().mode() != IndexedDB::TransactionMode::VersionChange);
+
+    m_pendingTransactions.append(WTF::move(transaction));
+
+    invokeTransactionScheduler();
+}
+
</ins><span class="cx"> void UniqueIDBDatabase::invokeTransactionScheduler()
</span><span class="cx"> {
</span><span class="cx">     if (!m_transactionSchedulingTimer.isActive())
</span><span class="lines">@@ -481,14 +491,132 @@
</span><span class="cx"> {
</span><span class="cx">     LOG(IndexedDB, &quot;(main) UniqueIDBDatabase::transactionSchedulingTimerFired&quot;);
</span><span class="cx"> 
</span><del>-    if (!hasAnyOpenConnections() &amp;&amp; m_versionChangeOperation) {
-        startVersionChangeTransaction();
-        return;
</del><ins>+    if (m_pendingTransactions.isEmpty()) {
+        if (!hasAnyOpenConnections() &amp;&amp; m_versionChangeOperation) {
+            startVersionChangeTransaction();
+            return;
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // FIXME: Handle starting other pending transactions here.
</del><ins>+    bool hadDeferredTransactions = false;
+    auto transaction = takeNextRunnableTransaction(hadDeferredTransactions);
+
+    if (transaction) {
+        m_inProgressTransactions.set(transaction-&gt;info().identifier(), transaction);
+        for (auto objectStore : transaction-&gt;objectStoreIdentifiers())
+            m_objectStoreTransactionCounts.add(objectStore);
+
+        activateTransactionInBackingStore(*transaction);
+
+        // If no transactions were deferred, it's possible we can start another transaction right now.
+        if (!hadDeferredTransactions)
+            invokeTransactionScheduler();
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void UniqueIDBDatabase::activateTransactionInBackingStore(UniqueIDBDatabaseTransaction&amp; transaction)
+{
+    LOG(IndexedDB, &quot;(main) UniqueIDBDatabase::activateTransactionInBackingStore&quot;);
+
+    RefPtr&lt;UniqueIDBDatabase&gt; self(this);
+    RefPtr&lt;UniqueIDBDatabaseTransaction&gt; refTransaction(&amp;transaction);
+
+    auto callback = [this, self, refTransaction](const IDBError&amp; error) {
+        refTransaction-&gt;didActivateInBackingStore(error);
+    };
+
+    uint64_t callbackID = storeCallback(callback);
+    m_server.postDatabaseTask(createCrossThreadTask(*this, &amp;UniqueIDBDatabase::performActivateTransactionInBackingStore, callbackID, transaction.info()));
+}
+
+void UniqueIDBDatabase::performActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBTransactionInfo&amp; info)
+{
+    LOG(IndexedDB, &quot;(db) UniqueIDBDatabase::performActivateTransactionInBackingStore&quot;);
+
+    IDBError error = m_backingStore-&gt;beginTransaction(info);
+    m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &amp;UniqueIDBDatabase::didPerformActivateTransactionInBackingStore, callbackIdentifier, error));
+}
+
+void UniqueIDBDatabase::didPerformActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBError&amp; error)
+{
+    LOG(IndexedDB, &quot;(main) UniqueIDBDatabase::didPerformActivateTransactionInBackingStore&quot;);
+
+    invokeTransactionScheduler();
+
+    performErrorCallback(callbackIdentifier, error);
+}
+
+template&lt;typename T&gt; bool scopesOverlap(const T&amp; aScopes, const Vector&lt;uint64_t&gt;&amp; bScopes)
+{
+    for (auto scope : bScopes) {
+        if (aScopes.contains(scope))
+            return true;
+    }
+
+    return false;
+}
+
+RefPtr&lt;UniqueIDBDatabaseTransaction&gt; UniqueIDBDatabase::takeNextRunnableTransaction(bool&amp; hadDeferredTransactions)
+{
+    Deque&lt;RefPtr&lt;UniqueIDBDatabaseTransaction&gt;&gt; deferredTransactions;
+    RefPtr&lt;UniqueIDBDatabaseTransaction&gt; currentTransaction;
+
+    while (!m_pendingTransactions.isEmpty()) {
+        currentTransaction = m_pendingTransactions.takeFirst();
+
+        switch (currentTransaction-&gt;info().mode()) {
+        case IndexedDB::TransactionMode::ReadOnly:
+            // If there are any deferred transactions, the first one is a read-write transaction we need to unblock.
+            // Therefore, skip this read-only transaction if its scope overlaps with that read-write transaction.
+            if (!deferredTransactions.isEmpty()) {
+                ASSERT(deferredTransactions.first()-&gt;info().mode() == IndexedDB::TransactionMode::ReadWrite);
+                if (scopesOverlap(deferredTransactions.first()-&gt;objectStoreIdentifiers(), currentTransaction-&gt;objectStoreIdentifiers()))
+                    deferredTransactions.append(WTF::move(currentTransaction));
+            }
+
+            break;
+        case IndexedDB::TransactionMode::ReadWrite:
+            // If this read-write transaction's scope overlaps with running transactions, it must be deferred.
+            if (scopesOverlap(m_objectStoreTransactionCounts, currentTransaction-&gt;objectStoreIdentifiers()))
+                deferredTransactions.append(WTF::move(currentTransaction));
+
+            break;
+        case IndexedDB::TransactionMode::VersionChange:
+            // Version change transactions should never be scheduled in the traditional manner.
+            RELEASE_ASSERT_NOT_REACHED();
+        }
+
+        // If we didn't defer the currentTransaction above, it can be run now.
+        if (currentTransaction)
+            break;
+    }
+
+    hadDeferredTransactions = !deferredTransactions.isEmpty();
+    if (!hadDeferredTransactions)
+        return WTF::move(currentTransaction);
+
+    // Prepend the deferred transactions back on the beginning of the deque for future scheduling passes.
+    while (!deferredTransactions.isEmpty())
+        m_pendingTransactions.prepend(deferredTransactions.takeLast());
+
+    return WTF::move(currentTransaction);
+}
+
+void UniqueIDBDatabase::inProgressTransactionCompleted(const IDBResourceIdentifier&amp; transactionIdentifier)
+{
+    auto transaction = m_inProgressTransactions.take(transactionIdentifier);
+    ASSERT(transaction);
+
+    if (m_versionChangeTransaction == transaction)
+        m_versionChangeTransaction = nullptr;
+
+    for (auto objectStore : transaction-&gt;objectStoreIdentifiers())
+        m_objectStoreTransactionCounts.remove(objectStore);
+
+    // Previously blocked transactions might now be unblocked.
+    invokeTransactionScheduler();
+}
+
</ins><span class="cx"> void UniqueIDBDatabase::performErrorCallback(uint64_t callbackIdentifier, const IDBError&amp; error)
</span><span class="cx"> {
</span><span class="cx">     auto callback = m_errorCallbacks.take(callbackIdentifier);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverUniqueIDBDatabaseh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -37,6 +37,7 @@
</span><span class="cx"> #include &quot;UniqueIDBDatabaseConnection.h&quot;
</span><span class="cx"> #include &quot;UniqueIDBDatabaseTransaction.h&quot;
</span><span class="cx"> #include &lt;wtf/Deque.h&gt;
</span><ins>+#include &lt;wtf/HashCountedSet.h&gt;
</ins><span class="cx"> #include &lt;wtf/HashSet.h&gt;
</span><span class="cx"> #include &lt;wtf/Ref.h&gt;
</span><span class="cx"> #include &lt;wtf/ThreadSafeRefCounted.h&gt;
</span><span class="lines">@@ -76,6 +77,8 @@
</span><span class="cx">     void transactionDestroyed(UniqueIDBDatabaseTransaction&amp;);
</span><span class="cx">     void connectionClosedFromClient(UniqueIDBDatabaseConnection&amp;);
</span><span class="cx"> 
</span><ins>+    void enqueueTransaction(Ref&lt;UniqueIDBDatabaseTransaction&gt;&amp;&amp;);
+
</ins><span class="cx"> private:
</span><span class="cx">     UniqueIDBDatabase(IDBServer&amp;, const IDBDatabaseIdentifier&amp;);
</span><span class="cx">     
</span><span class="lines">@@ -86,6 +89,9 @@
</span><span class="cx">     void startVersionChangeTransaction();
</span><span class="cx">     void notifyConnectionsOfVersionChange();
</span><span class="cx"> 
</span><ins>+    void activateTransactionInBackingStore(UniqueIDBDatabaseTransaction&amp;);
+    void inProgressTransactionCompleted(const IDBResourceIdentifier&amp;);
+
</ins><span class="cx">     // Database thread operations
</span><span class="cx">     void openBackingStore(const IDBDatabaseIdentifier&amp;);
</span><span class="cx">     void performCommitTransaction(uint64_t callbackIdentifier, const IDBResourceIdentifier&amp; transactionIdentifier);
</span><span class="lines">@@ -94,14 +100,16 @@
</span><span class="cx">     void performCreateObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier&amp; transactionIdentifier, const IDBObjectStoreInfo&amp;);
</span><span class="cx">     void performPutOrAdd(uint64_t callbackIdentifier, const IDBResourceIdentifier&amp; transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData&amp;, const ThreadSafeDataBuffer&amp; valueData, IndexedDB::ObjectStoreOverwriteMode);
</span><span class="cx">     void performGetRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier&amp; transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData&amp;);
</span><ins>+    void performActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBTransactionInfo&amp;);
</ins><span class="cx"> 
</span><span class="cx">     // Main thread callbacks
</span><span class="cx">     void didOpenBackingStore(const IDBDatabaseInfo&amp;);
</span><span class="cx">     void didPerformCreateObjectStore(uint64_t callbackIdentifier, const IDBError&amp;, const IDBObjectStoreInfo&amp;);
</span><span class="cx">     void didPerformPutOrAdd(uint64_t callbackIdentifier, const IDBError&amp;, const IDBKeyData&amp;);
</span><span class="cx">     void didPerformGetRecord(uint64_t callbackIdentifier, const IDBError&amp;, const ThreadSafeDataBuffer&amp;);
</span><del>-    void didPerformCommitTransaction(uint64_t callbackIdentifier, const IDBError&amp;);
</del><ins>+    void didPerformCommitTransaction(uint64_t callbackIdentifier, const IDBError&amp;, const IDBResourceIdentifier&amp; transactionIdentifier);
</ins><span class="cx">     void didPerformAbortTransaction(uint64_t callbackIdentifier, const IDBError&amp;, const IDBResourceIdentifier&amp; transactionIdentifier);
</span><ins>+    void didPerformActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBError&amp;);
</ins><span class="cx"> 
</span><span class="cx">     uint64_t storeCallback(ErrorCallback);
</span><span class="cx">     uint64_t storeCallback(KeyDataCallback);
</span><span class="lines">@@ -113,6 +121,7 @@
</span><span class="cx"> 
</span><span class="cx">     void invokeTransactionScheduler();
</span><span class="cx">     void transactionSchedulingTimerFired();
</span><ins>+    RefPtr&lt;UniqueIDBDatabaseTransaction&gt; takeNextRunnableTransaction(bool&amp; hadDeferredTransactions);
</ins><span class="cx"> 
</span><span class="cx">     IDBServer&amp; m_server;
</span><span class="cx">     IDBDatabaseIdentifier m_identifier;
</span><span class="lines">@@ -134,6 +143,15 @@
</span><span class="cx">     HashMap&lt;uint64_t, ValueDataCallback&gt; m_valueDataCallbacks;
</span><span class="cx"> 
</span><span class="cx">     Timer m_transactionSchedulingTimer;
</span><ins>+
+    Deque&lt;RefPtr&lt;UniqueIDBDatabaseTransaction&gt;&gt; m_pendingTransactions;
+    HashMap&lt;IDBResourceIdentifier, RefPtr&lt;UniqueIDBDatabaseTransaction&gt;&gt; m_inProgressTransactions;
+
+    // The key into this set is the object store ID.
+    // The set counts how many transactions are open to the given object store.
+    // This helps make sure opening narrowly scoped transactions (one or two object stores)
+    // doesn't continuously block widely scoped write transactions.
+    HashCountedSet&lt;uint64_t&gt; m_objectStoreTransactionCounts;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace IDBServer
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverUniqueIDBDatabaseConnectioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseConnection.cpp (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseConnection.cpp        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseConnection.cpp        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -93,6 +93,21 @@
</span><span class="cx">     return transaction.get();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void UniqueIDBDatabaseConnection::establishTransaction(const IDBTransactionInfo&amp; info)
+{
+    LOG(IndexedDB, &quot;UniqueIDBDatabaseConnection::establishTransaction&quot;);
+
+    ASSERT(info.mode() != IndexedDB::TransactionMode::VersionChange);
+
+    // No transactions should ever come from the client after the client has already told us
+    // the connection is closing.
+    ASSERT(!m_closePending);
+
+    Ref&lt;UniqueIDBDatabaseTransaction&gt; transaction = UniqueIDBDatabaseTransaction::create(*this, info);
+    m_transactionMap.set(transaction-&gt;info().identifier(), &amp;transaction.get());
+    m_database.enqueueTransaction(WTF::move(transaction));
+}
+
</ins><span class="cx"> void UniqueIDBDatabaseConnection::didAbortTransaction(UniqueIDBDatabaseTransaction&amp; transaction, const IDBError&amp; error)
</span><span class="cx"> {
</span><span class="cx">     LOG(IndexedDB, &quot;UniqueIDBDatabaseConnection::didAbortTransaction&quot;);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverUniqueIDBDatabaseConnectionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseConnection.h (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseConnection.h        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseConnection.h        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -63,6 +63,7 @@
</span><span class="cx">     void fireVersionChangeEvent(uint64_t requestedVersion);
</span><span class="cx">     UniqueIDBDatabaseTransaction&amp; createVersionChangeTransaction(uint64_t newVersion);
</span><span class="cx"> 
</span><ins>+    void establishTransaction(const IDBTransactionInfo&amp;);
</ins><span class="cx">     void didAbortTransaction(UniqueIDBDatabaseTransaction&amp;, const IDBError&amp;);
</span><span class="cx">     void didCommitTransaction(UniqueIDBDatabaseTransaction&amp;, const IDBError&amp;);
</span><span class="cx">     void didCreateObjectStore(const IDBResultData&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverUniqueIDBDatabaseTransactioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -37,12 +37,12 @@
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> namespace IDBServer {
</span><span class="cx"> 
</span><del>-Ref&lt;UniqueIDBDatabaseTransaction&gt; UniqueIDBDatabaseTransaction::create(UniqueIDBDatabaseConnection&amp; connection, IDBTransactionInfo&amp; info)
</del><ins>+Ref&lt;UniqueIDBDatabaseTransaction&gt; UniqueIDBDatabaseTransaction::create(UniqueIDBDatabaseConnection&amp; connection, const IDBTransactionInfo&amp; info)
</ins><span class="cx"> {
</span><span class="cx">     return adoptRef(*new UniqueIDBDatabaseTransaction(connection, info));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-UniqueIDBDatabaseTransaction::UniqueIDBDatabaseTransaction(UniqueIDBDatabaseConnection&amp; connection, IDBTransactionInfo&amp; info)
</del><ins>+UniqueIDBDatabaseTransaction::UniqueIDBDatabaseTransaction(UniqueIDBDatabaseConnection&amp; connection, const IDBTransactionInfo&amp; info)
</ins><span class="cx">     : m_databaseConnection(connection)
</span><span class="cx">     , m_transactionInfo(info)
</span><span class="cx"> {
</span><span class="lines">@@ -148,6 +148,32 @@
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+const Vector&lt;uint64_t&gt;&amp; UniqueIDBDatabaseTransaction::objectStoreIdentifiers()
+{
+    if (!m_objectStoreIdentifiers.isEmpty())
+        return m_objectStoreIdentifiers;
+
+    auto&amp; info = m_databaseConnection-&gt;database().info();
+    for (auto objectStoreName : info.objectStoreNames()) {
+        auto objectStoreInfo = info.infoForExistingObjectStore(objectStoreName);
+        ASSERT(objectStoreInfo);
+        if (!objectStoreInfo)
+            continue;
+
+        if (m_transactionInfo.objectStores().contains(objectStoreName))
+            m_objectStoreIdentifiers.append(objectStoreInfo-&gt;identifier());
+    }
+
+    return m_objectStoreIdentifiers;
+}
+
+void UniqueIDBDatabaseTransaction::didActivateInBackingStore(const IDBError&amp; error)
+{
+    LOG(IndexedDB, &quot;UniqueIDBDatabaseTransaction::didActivateInBackingStore&quot;);
+
+    m_databaseConnection-&gt;connectionToClient().didStartTransaction(m_transactionInfo.identifier(), error);
+}
+
</ins><span class="cx"> } // namespace IDBServer
</span><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverUniqueIDBDatabaseTransactionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.h (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.h        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.h        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> class IDBDatabaseInfo;
</span><ins>+class IDBError;
</ins><span class="cx"> class IDBKeyData;
</span><span class="cx"> class IDBObjectStoreInfo;
</span><span class="cx"> class IDBRequestData;
</span><span class="lines">@@ -47,7 +48,7 @@
</span><span class="cx"> 
</span><span class="cx"> class UniqueIDBDatabaseTransaction : public RefCounted&lt;UniqueIDBDatabaseTransaction&gt; {
</span><span class="cx"> public:
</span><del>-    static Ref&lt;UniqueIDBDatabaseTransaction&gt; create(UniqueIDBDatabaseConnection&amp;, IDBTransactionInfo&amp;);
</del><ins>+    static Ref&lt;UniqueIDBDatabaseTransaction&gt; create(UniqueIDBDatabaseConnection&amp;, const IDBTransactionInfo&amp;);
</ins><span class="cx"> 
</span><span class="cx">     ~UniqueIDBDatabaseTransaction();
</span><span class="cx"> 
</span><span class="lines">@@ -65,13 +66,19 @@
</span><span class="cx">     void putOrAdd(const IDBRequestData&amp;, const IDBKeyData&amp;, const ThreadSafeDataBuffer&amp; valueData, IndexedDB::ObjectStoreOverwriteMode);
</span><span class="cx">     void getRecord(const IDBRequestData&amp;, const IDBKeyData&amp;);
</span><span class="cx"> 
</span><ins>+    void didActivateInBackingStore(const IDBError&amp;);
+
+    const Vector&lt;uint64_t&gt;&amp; objectStoreIdentifiers();
+
</ins><span class="cx"> private:
</span><del>-    UniqueIDBDatabaseTransaction(UniqueIDBDatabaseConnection&amp;, IDBTransactionInfo&amp;);
</del><ins>+    UniqueIDBDatabaseTransaction(UniqueIDBDatabaseConnection&amp;, const IDBTransactionInfo&amp;);
</ins><span class="cx"> 
</span><span class="cx">     Ref&lt;UniqueIDBDatabaseConnection&gt; m_databaseConnection;
</span><span class="cx">     IDBTransactionInfo m_transactionInfo;
</span><span class="cx"> 
</span><span class="cx">     std::unique_ptr&lt;IDBDatabaseInfo&gt; m_originalDatabaseInfo;
</span><ins>+
+    Vector&lt;uint64_t&gt; m_objectStoreIdentifiers;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace IDBServer
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbsharedIDBTransactionInfocpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/shared/IDBTransactionInfo.cpp (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/shared/IDBTransactionInfo.cpp        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/shared/IDBTransactionInfo.cpp        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -35,6 +35,15 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+IDBTransactionInfo IDBTransactionInfo::clientTransaction(const IDBClient::IDBConnectionToServer&amp; connection, const Vector&lt;String&gt;&amp; objectStores, IndexedDB::TransactionMode mode)
+{
+    IDBTransactionInfo result((IDBResourceIdentifier(connection)));
+    result.m_mode = mode;
+    result.m_objectStores = objectStores;
+
+    return result;
+}
+
</ins><span class="cx"> IDBTransactionInfo IDBTransactionInfo::versionChange(const IDBServer::IDBConnectionToClient&amp; connection, uint64_t newVersion)
</span><span class="cx"> {
</span><span class="cx">     IDBTransactionInfo result((IDBResourceIdentifier(connection)));
</span><span class="lines">@@ -50,6 +59,10 @@
</span><span class="cx">     result.m_mode = m_mode;
</span><span class="cx">     result.m_newVersion = m_newVersion;
</span><span class="cx"> 
</span><ins>+    result.m_objectStores.reserveCapacity(m_objectStores.size());
+    for (auto&amp; objectStore : m_objectStores)
+        result.m_objectStores.uncheckedAppend(objectStore.isolatedCopy());
+
</ins><span class="cx">     return WTF::move(result);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbsharedIDBTransactionInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/shared/IDBTransactionInfo.h (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/shared/IDBTransactionInfo.h        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/shared/IDBTransactionInfo.h        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -33,12 +33,18 @@
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><ins>+
+namespace IDBClient {
+class IDBConnectionToServer;
+}
+
</ins><span class="cx"> namespace IDBServer {
</span><span class="cx"> class IDBConnectionToClient;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> class IDBTransactionInfo {
</span><span class="cx"> public:
</span><ins>+    static IDBTransactionInfo clientTransaction(const IDBClient::IDBConnectionToServer&amp;, const Vector&lt;String&gt;&amp; objectStores, IndexedDB::TransactionMode);
</ins><span class="cx">     static IDBTransactionInfo versionChange(const IDBServer::IDBConnectionToClient&amp;, uint64_t newVersion);
</span><span class="cx"> 
</span><span class="cx">     IDBTransactionInfo isolatedCopy() const;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbsharedInProcessIDBServercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.cpp (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.cpp        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.cpp        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -188,6 +188,15 @@
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void InProcessIDBServer::establishTransaction(uint64_t databaseConnectionIdentifier, const IDBTransactionInfo&amp; info)
+{
+    RefPtr&lt;InProcessIDBServer&gt; self(this);
+
+    RunLoop::current().dispatch([this, self, databaseConnectionIdentifier, info] {
+        m_server-&gt;establishTransaction(databaseConnectionIdentifier, info);
+    });
+}
+
</ins><span class="cx"> void InProcessIDBServer::fireVersionChangeEvent(IDBServer::UniqueIDBDatabaseConnection&amp; connection, uint64_t requestedVersion)
</span><span class="cx"> {
</span><span class="cx">     RefPtr&lt;InProcessIDBServer&gt; self(this);
</span><span class="lines">@@ -197,6 +206,14 @@
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void InProcessIDBServer::didStartTransaction(const IDBResourceIdentifier&amp; transactionIdentifier, const IDBError&amp; error)
+{
+    RefPtr&lt;InProcessIDBServer&gt; self(this);
+    RunLoop::current().dispatch([this, self, transactionIdentifier, error] {
+        m_connectionToServer-&gt;didStartTransaction(transactionIdentifier, error);
+    });
+}
+
</ins><span class="cx"> void InProcessIDBServer::databaseConnectionClosed(uint64_t databaseConnectionIdentifier)
</span><span class="cx"> {
</span><span class="cx">     RefPtr&lt;InProcessIDBServer&gt; self(this);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbsharedInProcessIDBServerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.h (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.h        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.h        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -61,6 +61,7 @@
</span><span class="cx">     virtual void createObjectStore(const IDBRequestData&amp;, const IDBObjectStoreInfo&amp;) override final;
</span><span class="cx">     virtual void putOrAdd(const IDBRequestData&amp;, IDBKey*, SerializedScriptValue&amp;, const IndexedDB::ObjectStoreOverwriteMode) override final;
</span><span class="cx">     virtual void getRecord(const IDBRequestData&amp;, IDBKey*) override final;
</span><ins>+    virtual void establishTransaction(uint64_t databaseConnectionIdentifier, const IDBTransactionInfo&amp;) override final;
</ins><span class="cx">     virtual void databaseConnectionClosed(uint64_t databaseConnectionIdentifier) override final;
</span><span class="cx"> 
</span><span class="cx">     // IDBConnectionToClient
</span><span class="lines">@@ -73,6 +74,7 @@
</span><span class="cx">     virtual void didPutOrAdd(const IDBResultData&amp;) override final;
</span><span class="cx">     virtual void didGetRecord(const IDBResultData&amp;) override final;
</span><span class="cx">     virtual void fireVersionChangeEvent(IDBServer::UniqueIDBDatabaseConnection&amp;, uint64_t requestedVersion) override final;
</span><ins>+    virtual void didStartTransaction(const IDBResourceIdentifier&amp; transactionIdentifier, const IDBError&amp;) override final;
</ins><span class="cx"> 
</span><span class="cx">     virtual void ref() override { RefCounted&lt;InProcessIDBServer&gt;::ref(); }
</span><span class="cx">     virtual void deref() override { RefCounted&lt;InProcessIDBServer&gt;::deref(); }
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsIDBBindingUtilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/IDBBindingUtilities.cpp (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/IDBBindingUtilities.cpp        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/bindings/js/IDBBindingUtilities.cpp        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -346,6 +346,9 @@
</span><span class="cx">     DOMRequestState state(&amp;context);
</span><span class="cx">     auto* execState = state.exec();
</span><span class="cx"> 
</span><ins>+    if (!execState)
+        return Deprecated::ScriptValue();
+
</ins><span class="cx">     if (!valueData.data())
</span><span class="cx">         return Deprecated::ScriptValue(execState-&gt;vm(), jsUndefined());
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSIDBDatabaseCustomcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSIDBDatabaseCustom.cpp (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSIDBDatabaseCustom.cpp        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/bindings/js/JSIDBDatabaseCustom.cpp        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -81,6 +81,43 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JSValue JSIDBDatabase::transaction(ExecState&amp; exec)
+{
+    size_t argsCount = std::min&lt;size_t&gt;(2, exec.argumentCount());
+    if (argsCount &lt; 1)
+        return exec.vm().throwException(&amp;exec, createNotEnoughArgumentsError(&amp;exec));
+
+    auto* scriptContext = jsCast&lt;JSDOMGlobalObject*&gt;(exec.lexicalGlobalObject())-&gt;scriptExecutionContext();
+    if (!scriptContext)
+        return jsUndefined();
+
+    Vector&lt;String&gt; scope;
+    JSValue scopeArg(exec.argument(0));
+    if (scopeArg.isObject() &amp;&amp; isJSArray(scopeArg)) {
+        scope = toNativeArray&lt;String&gt;(&amp;exec, scopeArg);
+        if (exec.hadException())
+            return jsUndefined();
+    } else {
+        scope.append(scopeArg.toString(&amp;exec)-&gt;value(&amp;exec));
+        if (exec.hadException())
+            return jsUndefined();
+    }
+
+    String mode;
+    if (argsCount == 2) {
+        JSValue modeArg(exec.argument(1));
+        mode = modeArg.toString(&amp;exec)-&gt;value(&amp;exec);
+
+        if (exec.hadException())
+            return jsUndefined();
+    }
+
+    ExceptionCode ec = 0;
+    JSValue result = toJS(&amp;exec, globalObject(), impl().transaction(scriptContext, scope, mode, ec).get());
+    setDOMException(&amp;exec, ec);
+    return result;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+}
+
</ins><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsScriptStatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/ScriptState.cpp (191721 => 191722)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/ScriptState.cpp        2015-10-29 05:30:40 UTC (rev 191721)
+++ trunk/Source/WebCore/bindings/js/ScriptState.cpp        2015-10-29 06:16:01 UTC (rev 191722)
</span><span class="lines">@@ -92,7 +92,7 @@
</span><span class="cx"> 
</span><span class="cx"> JSC::ExecState* execStateFromPage(DOMWrapperWorld&amp; world, Page* page)
</span><span class="cx"> {
</span><del>-    return page-&gt;mainFrame().script().globalObject(world)-&gt;globalExec();
</del><ins>+    return page ? page-&gt;mainFrame().script().globalObject(world)-&gt;globalExec() : nullptr;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> JSC::ExecState* execStateFromWorkerGlobalScope(WorkerGlobalScope* workerGlobalScope)
</span></span></pre>
</div>
</div>

</body>
</html>