<!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>[192490] 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/192490">192490</a></dd>
<dt>Author</dt> <dd>beidson@apple.com</dd>
<dt>Date</dt> <dd>2015-11-16 15:17:46 -0800 (Mon, 16 Nov 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Modern IDB:Make in-memory ObjectStore cursors work.
https://bugs.webkit.org/show_bug.cgi?id=151196

Reviewed by Darin Adler.

Source/WebCore:

Tests: storage/indexeddb/modern/cursor-2.html
       storage/indexeddb/modern/cursor-3.html
       storage/indexeddb/modern/cursor-4.html
       storage/indexeddb/modern/cursor-5.html
       storage/indexeddb/modern/cursor-6.html
       storage/indexeddb/modern/cursor-7.html
       storage/indexeddb/modern/cursor-8.html
       storage/indexeddb/modern/objectstore-cursor-advance-failures.html
       storage/indexeddb/modern/objectstore-cursor-continue-failures.html

Object store cursors directly hold on to a std::set&lt;&gt;::iterator to act as the cursor.

The object store tells all of its cursors when it is cleared or records are deleted
so the cursors can invalidate their iterators as needed.

In case of such invalidation, the cursor hangs on to the current key value so it can
pick up where it left off in case it is iterated.

* CMakeLists.txt:
* WebCore.xcodeproj/project.pbxproj:

* Modules/indexeddb/IDBGetResult.h:
(WebCore::IDBGetResult::isolatedCopy):

* Modules/indexeddb/IDBKeyRangeData.cpp:
(WebCore::IDBKeyRangeData::containsKey):
(WebCore::IDBKeyRangeData::loggingString):
* Modules/indexeddb/IDBKeyRangeData.h:

* Modules/indexeddb/client/IDBAnyImpl.cpp:
(WebCore::IDBClient::IDBAny::modernIDBCursor):

* Modules/indexeddb/client/IDBCursorImpl.cpp:
(WebCore::IDBClient::IDBCursor::update):
(WebCore::IDBClient::IDBCursor::advance):
(WebCore::IDBClient::IDBCursor::continueFunction):
(WebCore::IDBClient::IDBCursor::setGetResult):
* Modules/indexeddb/client/IDBCursorImpl.h:

* Modules/indexeddb/client/IDBRequestImpl.cpp:
(WebCore::IDBClient::IDBRequest::dispatchEvent):
(WebCore::IDBClient::IDBRequest::didOpenOrIterateCursor):
* Modules/indexeddb/client/IDBRequestImpl.h:
(WebCore::IDBClient::IDBRequest::pendingCursor):

* Modules/indexeddb/client/IDBTransactionImpl.cpp:
(WebCore::IDBClient::IDBTransaction::addRequest): Deleted.

* Modules/indexeddb/client/TransactionOperation.cpp:
(WebCore::IDBClient::TransactionOperation::TransactionOperation):
* Modules/indexeddb/client/TransactionOperation.h:
(WebCore::IDBClient::TransactionOperation::cursorIdentifier):

* Modules/indexeddb/server/IDBBackingStore.h:

* Modules/indexeddb/server/MemoryBackingStoreTransaction.cpp:
(WebCore::IDBServer::MemoryBackingStoreTransaction::objectStoreCleared):
(WebCore::IDBServer::MemoryBackingStoreTransaction::abort):
* Modules/indexeddb/server/MemoryBackingStoreTransaction.h:

* Modules/indexeddb/server/MemoryCursor.cpp: Added.
(WebCore::IDBServer::cursorMap):
(WebCore::IDBServer::MemoryCursor::MemoryCursor):
(WebCore::IDBServer::MemoryCursor::~MemoryCursor):
(WebCore::IDBServer::MemoryCursor::cursorForIdentifier):
* Modules/indexeddb/server/MemoryCursor.h: Added.

* Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
(WebCore::IDBServer::MemoryIDBBackingStore::openCursor):
(WebCore::IDBServer::MemoryIDBBackingStore::iterateCursor):
* Modules/indexeddb/server/MemoryIDBBackingStore.h:

* Modules/indexeddb/server/MemoryObjectStore.cpp:
(WebCore::IDBServer::MemoryObjectStore::clear):
(WebCore::IDBServer::MemoryObjectStore::replaceKeyValueStore):
(WebCore::IDBServer::MemoryObjectStore::deleteRecord):
(WebCore::IDBServer::MemoryObjectStore::addRecord):
(WebCore::IDBServer::MemoryObjectStore::updateCursorsForPutRecord):
(WebCore::IDBServer::MemoryObjectStore::updateCursorsForDeleteRecord):
(WebCore::IDBServer::MemoryObjectStore::maybeOpenCursor):
* Modules/indexeddb/server/MemoryObjectStore.h:
(WebCore::IDBServer::MemoryObjectStore::orderedKeys):

* Modules/indexeddb/server/MemoryObjectStoreCursor.cpp: Added.
(WebCore::IDBServer::MemoryObjectStoreCursor::create):
(WebCore::IDBServer::MemoryObjectStoreCursor::MemoryObjectStoreCursor):
(WebCore::IDBServer::MemoryObjectStoreCursor::objectStoreCleared):
(WebCore::IDBServer::MemoryObjectStoreCursor::keyDeleted):
(WebCore::IDBServer::MemoryObjectStoreCursor::keyAdded):
(WebCore::IDBServer::MemoryObjectStoreCursor::setFirstInRemainingRange):
(WebCore::IDBServer::MemoryObjectStoreCursor::firstForwardIteratorInRemainingRange):
(WebCore::IDBServer::MemoryObjectStoreCursor::firstReverseIteratorInRemainingRange):
(WebCore::IDBServer::MemoryObjectStoreCursor::currentData):
(WebCore::IDBServer::MemoryObjectStoreCursor::incrementForwardIterator):
(WebCore::IDBServer::MemoryObjectStoreCursor::incrementReverseIterator):
(WebCore::IDBServer::MemoryObjectStoreCursor::hasValidPosition):
(WebCore::IDBServer::MemoryObjectStoreCursor::iterate):
* Modules/indexeddb/server/MemoryObjectStoreCursor.h: Added.

* Modules/indexeddb/server/UniqueIDBDatabase.cpp:
(WebCore::IDBServer::UniqueIDBDatabase::iterateCursor):
(WebCore::IDBServer::UniqueIDBDatabase::performIterateCursor):
* Modules/indexeddb/server/UniqueIDBDatabase.h:

* Modules/indexeddb/shared/IDBCursorInfo.h:
(WebCore::IDBCursorInfo::range):

* Modules/indexeddb/shared/IDBRequestData.cpp:
(WebCore::IDBRequestData::IDBRequestData):
(WebCore::IDBRequestData::cursorIdentifier):
* Modules/indexeddb/shared/IDBRequestData.h:

LayoutTests:

* storage/indexeddb/modern/cursor-1-expected.txt:
* storage/indexeddb/modern/cursor-2-expected.txt: Added.
* storage/indexeddb/modern/cursor-2.html: Added.
* storage/indexeddb/modern/cursor-3-expected.txt: Added.
* storage/indexeddb/modern/cursor-3.html: Added.
* storage/indexeddb/modern/cursor-4-expected.txt: Added.
* storage/indexeddb/modern/cursor-4.html: Added.
* storage/indexeddb/modern/cursor-5-expected.txt: Added.
* storage/indexeddb/modern/cursor-5.html: Added.
* storage/indexeddb/modern/cursor-6-expected.txt: Added.
* storage/indexeddb/modern/cursor-6.html: Added.
* storage/indexeddb/modern/cursor-7-expected.txt: Added.
* storage/indexeddb/modern/cursor-7.html: Added.
* storage/indexeddb/modern/cursor-8-expected.txt: Added.
* storage/indexeddb/modern/cursor-8.html: Added.
* storage/indexeddb/modern/objectstore-cursor-advance-failures-expected.txt: Added.
* storage/indexeddb/modern/objectstore-cursor-advance-failures.html: Added.
* storage/indexeddb/modern/objectstore-cursor-continue-failures-expected.txt: Added.
* storage/indexeddb/modern/objectstore-cursor-continue-failures.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderncursor1expectedtxt">trunk/LayoutTests/storage/indexeddb/modern/cursor-1-expected.txt</a></li>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbIDBGetResulth">trunk/Source/WebCore/Modules/indexeddb/IDBGetResult.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbIDBKeyRangeDatacpp">trunk/Source/WebCore/Modules/indexeddb/IDBKeyRangeData.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbIDBKeyRangeDatah">trunk/Source/WebCore/Modules/indexeddb/IDBKeyRangeData.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbclientIDBAnyImplcpp">trunk/Source/WebCore/Modules/indexeddb/client/IDBAnyImpl.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbclientIDBCursorImplcpp">trunk/Source/WebCore/Modules/indexeddb/client/IDBCursorImpl.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbclientIDBCursorImplh">trunk/Source/WebCore/Modules/indexeddb/client/IDBCursorImpl.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbclientIDBRequestImplcpp">trunk/Source/WebCore/Modules/indexeddb/client/IDBRequestImpl.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbclientIDBRequestImplh">trunk/Source/WebCore/Modules/indexeddb/client/IDBRequestImpl.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbclientIDBTransactionImplcpp">trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbclientTransactionOperationcpp">trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbclientTransactionOperationh">trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverIDBBackingStoreh">trunk/Source/WebCore/Modules/indexeddb/server/IDBBackingStore.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverMemoryBackingStoreTransactioncpp">trunk/Source/WebCore/Modules/indexeddb/server/MemoryBackingStoreTransaction.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverMemoryBackingStoreTransactionh">trunk/Source/WebCore/Modules/indexeddb/server/MemoryBackingStoreTransaction.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="#trunkSourceWebCoreModulesindexeddbserverMemoryObjectStorecpp">trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverMemoryObjectStoreh">trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.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="#trunkSourceWebCoreModulesindexeddbsharedIDBCursorInfoh">trunk/Source/WebCore/Modules/indexeddb/shared/IDBCursorInfo.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbsharedIDBRequestDatacpp">trunk/Source/WebCore/Modules/indexeddb/shared/IDBRequestData.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbsharedIDBRequestDatah">trunk/Source/WebCore/Modules/indexeddb/shared/IDBRequestData.h</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderncursor2expectedtxt">trunk/LayoutTests/storage/indexeddb/modern/cursor-2-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderncursor2html">trunk/LayoutTests/storage/indexeddb/modern/cursor-2.html</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderncursor3expectedtxt">trunk/LayoutTests/storage/indexeddb/modern/cursor-3-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderncursor3html">trunk/LayoutTests/storage/indexeddb/modern/cursor-3.html</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderncursor4expectedtxt">trunk/LayoutTests/storage/indexeddb/modern/cursor-4-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderncursor4html">trunk/LayoutTests/storage/indexeddb/modern/cursor-4.html</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderncursor5expectedtxt">trunk/LayoutTests/storage/indexeddb/modern/cursor-5-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderncursor5html">trunk/LayoutTests/storage/indexeddb/modern/cursor-5.html</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderncursor6expectedtxt">trunk/LayoutTests/storage/indexeddb/modern/cursor-6-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderncursor6html">trunk/LayoutTests/storage/indexeddb/modern/cursor-6.html</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderncursor7expectedtxt">trunk/LayoutTests/storage/indexeddb/modern/cursor-7-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderncursor7html">trunk/LayoutTests/storage/indexeddb/modern/cursor-7.html</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderncursor8expectedtxt">trunk/LayoutTests/storage/indexeddb/modern/cursor-8-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmoderncursor8html">trunk/LayoutTests/storage/indexeddb/modern/cursor-8.html</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmodernobjectstorecursoradvancefailuresexpectedtxt">trunk/LayoutTests/storage/indexeddb/modern/objectstore-cursor-advance-failures-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmodernobjectstorecursoradvancefailureshtml">trunk/LayoutTests/storage/indexeddb/modern/objectstore-cursor-advance-failures.html</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmodernobjectstorecursorcontinuefailuresexpectedtxt">trunk/LayoutTests/storage/indexeddb/modern/objectstore-cursor-continue-failures-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmodernobjectstorecursorcontinuefailureshtml">trunk/LayoutTests/storage/indexeddb/modern/objectstore-cursor-continue-failures.html</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverMemoryCursorcpp">trunk/Source/WebCore/Modules/indexeddb/server/MemoryCursor.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverMemoryCursorh">trunk/Source/WebCore/Modules/indexeddb/server/MemoryCursor.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverMemoryObjectStoreCursorcpp">trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStoreCursor.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverMemoryObjectStoreCursorh">trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStoreCursor.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/LayoutTests/ChangeLog        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2015-11-16  Brady Eidson  &lt;beidson@apple.com&gt;
+
+        Modern IDB:Make in-memory ObjectStore cursors work.
+        https://bugs.webkit.org/show_bug.cgi?id=151196
+
+        Reviewed by Darin Adler.
+
+        * storage/indexeddb/modern/cursor-1-expected.txt:
+        * storage/indexeddb/modern/cursor-2-expected.txt: Added.
+        * storage/indexeddb/modern/cursor-2.html: Added.
+        * storage/indexeddb/modern/cursor-3-expected.txt: Added.
+        * storage/indexeddb/modern/cursor-3.html: Added.
+        * storage/indexeddb/modern/cursor-4-expected.txt: Added.
+        * storage/indexeddb/modern/cursor-4.html: Added.
+        * storage/indexeddb/modern/cursor-5-expected.txt: Added.
+        * storage/indexeddb/modern/cursor-5.html: Added.
+        * storage/indexeddb/modern/cursor-6-expected.txt: Added.
+        * storage/indexeddb/modern/cursor-6.html: Added.
+        * storage/indexeddb/modern/cursor-7-expected.txt: Added.
+        * storage/indexeddb/modern/cursor-7.html: Added.
+        * storage/indexeddb/modern/cursor-8-expected.txt: Added.
+        * storage/indexeddb/modern/cursor-8.html: Added.
+        * storage/indexeddb/modern/objectstore-cursor-advance-failures-expected.txt: Added.
+        * storage/indexeddb/modern/objectstore-cursor-advance-failures.html: Added.
+        * storage/indexeddb/modern/objectstore-cursor-continue-failures-expected.txt: Added.
+        * storage/indexeddb/modern/objectstore-cursor-continue-failures.html: Added.
+
</ins><span class="cx"> 2015-11-16  Ryan Haddad  &lt;ryanhaddad@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Removed Yosemite modifier for flaky test http/tests/media/video-preload.html
</span></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderncursor1expectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/storage/indexeddb/modern/cursor-1-expected.txt (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/cursor-1-expected.txt        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/LayoutTests/storage/indexeddb/modern/cursor-1-expected.txt        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -1,11 +1,11 @@
</span><span class="cx"> This tests basic IDBCursor functionality
</span><span class="cx"> Initial upgrade needed: Old version - 0 New version - 1
</span><del>-Error opening cursor (expected for now)
</del><ins>+Success opening cursor
</ins><span class="cx"> Cursor is: [object IDBCursorWithValue]
</span><span class="cx"> Cursor direction is: next
</span><span class="cx"> Cursor source is: [object IDBObjectStore] (TestObjectStore)
</span><del>-Cursor key is: null
-Cursor primary key is: null
</del><ins>+Cursor key is: 0
+Cursor primary key is: 0
</ins><span class="cx"> Error opening cursor (expected for now)
</span><span class="cx"> Cursor is: [object IDBCursorWithValue]
</span><span class="cx"> Cursor direction is: next
</span><span class="lines">@@ -18,12 +18,12 @@
</span><span class="cx"> Cursor source is: [object IDBIndex] (TestIndex1)
</span><span class="cx"> Cursor key is: null
</span><span class="cx"> Cursor primary key is: null
</span><del>-Error opening cursor (expected for now)
</del><ins>+Success opening cursor
</ins><span class="cx"> Cursor is: [object IDBCursorWithValue]
</span><span class="cx"> Cursor direction is: nextunique
</span><span class="cx"> Cursor source is: [object IDBObjectStore] (TestObjectStore)
</span><del>-Cursor key is: null
-Cursor primary key is: null
</del><ins>+Cursor key is: 0
+Cursor primary key is: 0
</ins><span class="cx"> Error opening cursor (expected for now)
</span><span class="cx"> Cursor is: [object IDBCursorWithValue]
</span><span class="cx"> Cursor direction is: nextunique
</span><span class="lines">@@ -36,12 +36,12 @@
</span><span class="cx"> Cursor source is: [object IDBIndex] (TestIndex1)
</span><span class="cx"> Cursor key is: null
</span><span class="cx"> Cursor primary key is: null
</span><del>-Error opening cursor (expected for now)
</del><ins>+Success opening cursor
</ins><span class="cx"> Cursor is: [object IDBCursorWithValue]
</span><span class="cx"> Cursor direction is: prev
</span><span class="cx"> Cursor source is: [object IDBObjectStore] (TestObjectStore)
</span><del>-Cursor key is: null
-Cursor primary key is: null
</del><ins>+Cursor key is: foo
+Cursor primary key is: foo
</ins><span class="cx"> Error opening cursor (expected for now)
</span><span class="cx"> Cursor is: [object IDBCursorWithValue]
</span><span class="cx"> Cursor direction is: prev
</span><span class="lines">@@ -54,12 +54,12 @@
</span><span class="cx"> Cursor source is: [object IDBIndex] (TestIndex1)
</span><span class="cx"> Cursor key is: null
</span><span class="cx"> Cursor primary key is: null
</span><del>-Error opening cursor (expected for now)
</del><ins>+Success opening cursor
</ins><span class="cx"> Cursor is: [object IDBCursorWithValue]
</span><span class="cx"> Cursor direction is: prevunique
</span><span class="cx"> Cursor source is: [object IDBObjectStore] (TestObjectStore)
</span><del>-Cursor key is: null
-Cursor primary key is: null
</del><ins>+Cursor key is: foo
+Cursor primary key is: foo
</ins><span class="cx"> Error opening cursor (expected for now)
</span><span class="cx"> Cursor is: [object IDBCursorWithValue]
</span><span class="cx"> Cursor direction is: prevunique
</span></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderncursor2expectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/cursor-2-expected.txt (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/cursor-2-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/cursor-2-expected.txt        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,173 @@
</span><ins>+This test checks basic functionality walking a &quot;next&quot; and &quot;prev&quot; cursor on an object store with some records.
+Initial upgrade needed: Old version - 0 New version - 1
+Success iterating next cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 0
+Cursor value is: Record 0
+Cursor primary key is: 0
+Success iterating next cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 1
+Cursor value is: Record 1
+Cursor primary key is: 1
+Success iterating next cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 2
+Cursor value is: Record 2
+Cursor primary key is: 2
+Success iterating next cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 3
+Cursor value is: Record 3
+Cursor primary key is: 3
+Success iterating next cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 4
+Cursor value is: Record 4
+Cursor primary key is: 4
+Success iterating next cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 5
+Cursor value is: Record 5
+Cursor primary key is: 5
+Success iterating next cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 6
+Cursor value is: Record 6
+Cursor primary key is: 6
+Success iterating next cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 7
+Cursor value is: Record 7
+Cursor primary key is: 7
+Success iterating next cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 8
+Cursor value is: Record 8
+Cursor primary key is: 8
+Success iterating next cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 9
+Cursor value is: Record 9
+Cursor primary key is: 9
+Success iterating next cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: foo
+Cursor value is: [object Object]
+Cursor primary key is: foo
+Success iterating next cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: undefined
+Cursor value is: undefined
+Cursor primary key is: undefined
+Success iterating prev cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: foo
+Cursor value is: [object Object]
+Cursor primary key is: foo
+Success iterating prev cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 9
+Cursor value is: Record 9
+Cursor primary key is: 9
+Success iterating prev cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 8
+Cursor value is: Record 8
+Cursor primary key is: 8
+Success iterating prev cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 7
+Cursor value is: Record 7
+Cursor primary key is: 7
+Success iterating prev cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 6
+Cursor value is: Record 6
+Cursor primary key is: 6
+Success iterating prev cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 5
+Cursor value is: Record 5
+Cursor primary key is: 5
+Success iterating prev cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 4
+Cursor value is: Record 4
+Cursor primary key is: 4
+Success iterating prev cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 3
+Cursor value is: Record 3
+Cursor primary key is: 3
+Success iterating prev cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 2
+Cursor value is: Record 2
+Cursor primary key is: 2
+Success iterating prev cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 1
+Cursor value is: Record 1
+Cursor primary key is: 1
+Success iterating prev cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 0
+Cursor value is: Record 0
+Cursor primary key is: 0
+Success iterating prev cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: undefined
+Cursor value is: undefined
+Cursor primary key is: undefined
+Initial upgrade versionchange transaction complete
+Done
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderncursor2html"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/cursor-2.html (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/cursor-2.html                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/cursor-2.html        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,84 @@
</span><ins>+This test checks basic functionality walking a &quot;next&quot; and &quot;prev&quot; cursor on an object store with some records.&lt;br&gt;
+&lt;div id=&quot;logger&quot;&gt;&lt;/div&gt;
+&lt;script&gt;
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function done()
+{
+    log(&quot;Done&quot;);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function log(message)
+{
+    document.getElementById(&quot;logger&quot;).innerHTML += message + &quot;&lt;br&gt;&quot;;
+}
+
+var createRequest = window.indexedDB.open(&quot;Cursor2Database&quot;, 1);
+
+function logCursor(cursor)
+{
+    log(&quot;Cursor is: &quot; + cursor);
+    log(&quot;Cursor direction is: &quot; + cursor.direction);
+    log(&quot;Cursor source is: &quot; + cursor.source + &quot; (&quot; + cursor.source.name + &quot;)&quot;);    
+    log(&quot;Cursor key is: &quot; + cursor.key);    
+    log(&quot;Cursor value is: &quot; + cursor.value);    
+    log(&quot;Cursor primary key is: &quot; + cursor.primaryKey);    
+}
+
+var objectStore;
+
+function setupRequest(request)
+{
+    request.onsuccess = function() {
+        log(&quot;Success iterating &quot; + request.result.direction + &quot; cursor&quot;);
+        logCursor(request.result);
+        if (request.result.key != undefined)
+            request.result.continue();
+        else if (request.result.direction == &quot;next&quot;)
+            setupRequest(objectStore.openCursor(IDBKeyRange.lowerBound(-Infinity), &quot;prev&quot;));
+        // else
+        //     log(&quot;OKAY how?&quot;);
+    }
+    request.onerror = function(e) {
+        log(&quot;Error iterating cursor&quot;);
+        done();
+    } 
+}
+
+createRequest.onupgradeneeded = function(event) {
+    log(&quot;Initial upgrade needed: Old version - &quot; + event.oldVersion + &quot; New version - &quot; + event.newVersion);
+
+    var versionTransaction = createRequest.transaction;
+    var database = event.target.result;
+    objectStore = database.createObjectStore(&quot;TestObjectStore&quot;);
+
+    for (var i = 0; i &lt; 10; ++i) {
+        objectStore.put(&quot;Record &quot; + i, i);
+    }
+    objectStore.put({ bar: &quot;Hello&quot; }, &quot;foo&quot;);
+    
+    setupRequest(objectStore.openCursor());
+      
+    versionTransaction.onabort = function(event) {
+        log(&quot;Initial upgrade versionchange transaction unexpected aborted&quot;);
+        done();
+    }
+
+    versionTransaction.oncomplete = function(event) {
+        log(&quot;Initial upgrade versionchange transaction complete&quot;);
+        done();
+    }
+
+    versionTransaction.onerror = function(event) {
+        log(&quot;Initial upgrade versionchange transaction unexpected error&quot; + event);
+        done();
+    }
+}
+
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderncursor3expectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/cursor-3-expected.txt (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/cursor-3-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/cursor-3-expected.txt        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,89 @@
</span><ins>+This test various uses of advance() and continue() on a &quot;next&quot; cursor&quot;.
+Initial upgrade needed: Old version - 0 New version - 1
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 0
+Cursor value is: Record 0
+Cursor primary key is: 0
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 2
+Cursor value is: Record 2
+Cursor primary key is: 2
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 4
+Cursor value is: Record 4
+Cursor primary key is: 4
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 6
+Cursor value is: Record 6
+Cursor primary key is: 6
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 8
+Cursor value is: Record 8
+Cursor primary key is: 8
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: foo
+Cursor value is: [object Object]
+Cursor primary key is: foo
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: undefined
+Cursor value is: undefined
+Cursor primary key is: undefined
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 0
+Cursor value is: Record 0
+Cursor primary key is: 0
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 3
+Cursor value is: Record 3
+Cursor primary key is: 3
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 6
+Cursor value is: Record 6
+Cursor primary key is: 6
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 9
+Cursor value is: Record 9
+Cursor primary key is: 9
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: next
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: undefined
+Cursor value is: undefined
+Cursor primary key is: undefined
+Initial upgrade versionchange transaction complete
+Done
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderncursor3html"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/cursor-3.html (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/cursor-3.html                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/cursor-3.html        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,96 @@
</span><ins>+This test various uses of advance() and continue() on a &quot;next&quot; cursor&quot;.&lt;br&gt;
+&lt;div id=&quot;logger&quot;&gt;&lt;/div&gt;
+&lt;script&gt;
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function done()
+{
+    log(&quot;Done&quot;);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function log(message)
+{
+    document.getElementById(&quot;logger&quot;).innerHTML += message + &quot;&lt;br&gt;&quot;;
+}
+
+var createRequest = window.indexedDB.open(&quot;Cursor3Database&quot;, 1);
+
+function logCursor(cursor)
+{
+    log(&quot;Cursor is: &quot; + cursor);
+    log(&quot;Cursor direction is: &quot; + cursor.direction);
+    log(&quot;Cursor source is: &quot; + cursor.source + &quot; (&quot; + cursor.source.name + &quot;)&quot;);    
+    log(&quot;Cursor key is: &quot; + cursor.key);    
+    log(&quot;Cursor value is: &quot; + cursor.value);    
+    log(&quot;Cursor primary key is: &quot; + cursor.primaryKey);    
+}
+
+var objectStore;
+
+function setupRequest1(request)
+{
+    request.onsuccess = function() {
+        log(&quot;Success iterating cursor&quot;);
+        logCursor(request.result);
+        if (request.result.key != undefined)
+            request.result.continue(request.result.key + 2);
+        else
+          setupRequest2(objectStore.openCursor());
+    }
+    request.onerror = function(e) {
+        log(&quot;Error iterating cursor&quot;);
+        done();
+    } 
+}
+
+function setupRequest2(request)
+{
+    request.onsuccess = function() {
+        log(&quot;Success iterating cursor&quot;);
+        logCursor(request.result);
+        if (request.result.key != undefined)
+            request.result.advance(3);        
+    }
+    request.onerror = function(e) {
+        log(&quot;Error iterating cursor&quot;);
+        done();
+    } 
+}
+
+createRequest.onupgradeneeded = function(event) {
+    log(&quot;Initial upgrade needed: Old version - &quot; + event.oldVersion + &quot; New version - &quot; + event.newVersion);
+
+    var versionTransaction = createRequest.transaction;
+    var database = event.target.result;
+    objectStore = database.createObjectStore(&quot;TestObjectStore&quot;);
+
+    for (var i = 0; i &lt; 10; ++i) {
+        objectStore.put(&quot;Record &quot; + i, i);
+    }
+    objectStore.put({ bar: &quot;Hello&quot; }, &quot;foo&quot;);
+    
+    setupRequest1(objectStore.openCursor());
+      
+    versionTransaction.onabort = function(event) {
+        log(&quot;Initial upgrade versionchange transaction unexpected aborted&quot;);
+        done();
+    }
+
+    versionTransaction.oncomplete = function(event) {
+        log(&quot;Initial upgrade versionchange transaction complete&quot;);
+        done();
+    }
+
+    versionTransaction.onerror = function(event) {
+        log(&quot;Initial upgrade versionchange transaction unexpected error&quot; + event);
+        done();
+    }
+}
+
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderncursor4expectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/cursor-4-expected.txt (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/cursor-4-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/cursor-4-expected.txt        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,82 @@
</span><ins>+This test various uses of advance() and continue() on a &quot;prev&quot; cursor&quot;.
+Initial upgrade needed: Old version - 0 New version - 1
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 9
+Cursor value is: Record 9
+Cursor primary key is: 9
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 7
+Cursor value is: Record 7
+Cursor primary key is: 7
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 5
+Cursor value is: Record 5
+Cursor primary key is: 5
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 3
+Cursor value is: Record 3
+Cursor primary key is: 3
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 1
+Cursor value is: Record 1
+Cursor primary key is: 1
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: undefined
+Cursor value is: undefined
+Cursor primary key is: undefined
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 9
+Cursor value is: Record 9
+Cursor primary key is: 9
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 6
+Cursor value is: Record 6
+Cursor primary key is: 6
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 3
+Cursor value is: Record 3
+Cursor primary key is: 3
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: 0
+Cursor value is: Record 0
+Cursor primary key is: 0
+Success iterating cursor
+Cursor is: [object IDBCursorWithValue]
+Cursor direction is: prev
+Cursor source is: [object IDBObjectStore] (TestObjectStore)
+Cursor key is: undefined
+Cursor value is: undefined
+Cursor primary key is: undefined
+Initial upgrade versionchange transaction complete
+Done
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderncursor4html"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/cursor-4.html (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/cursor-4.html                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/cursor-4.html        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,95 @@
</span><ins>+This test various uses of advance() and continue() on a &quot;prev&quot; cursor&quot;.&lt;br&gt;
+&lt;div id=&quot;logger&quot;&gt;&lt;/div&gt;
+&lt;script&gt;
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function done()
+{
+    log(&quot;Done&quot;);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function log(message)
+{
+    document.getElementById(&quot;logger&quot;).innerHTML += message + &quot;&lt;br&gt;&quot;;
+}
+
+var createRequest = window.indexedDB.open(&quot;Cursor4Database&quot;, 1);
+
+function logCursor(cursor)
+{
+    log(&quot;Cursor is: &quot; + cursor);
+    log(&quot;Cursor direction is: &quot; + cursor.direction);
+    log(&quot;Cursor source is: &quot; + cursor.source + &quot; (&quot; + cursor.source.name + &quot;)&quot;);    
+    log(&quot;Cursor key is: &quot; + cursor.key);    
+    log(&quot;Cursor value is: &quot; + cursor.value);    
+    log(&quot;Cursor primary key is: &quot; + cursor.primaryKey);    
+}
+
+var objectStore;
+
+function setupRequest1(request)
+{
+    request.onsuccess = function() {
+        log(&quot;Success iterating cursor&quot;);
+        logCursor(request.result);
+        if (request.result.key != undefined)
+            request.result.continue(request.result.key - 2);
+        else
+          setupRequest2(objectStore.openCursor(IDBKeyRange.lowerBound(-Infinity), &quot;prev&quot;));
+    }
+    request.onerror = function(e) {
+        log(&quot;Error iterating cursor&quot;);
+        done();
+    } 
+}
+
+function setupRequest2(request)
+{
+    request.onsuccess = function() {
+        log(&quot;Success iterating cursor&quot;);
+        logCursor(request.result);
+        if (request.result.key != undefined)
+            request.result.advance(3);        
+    }
+    request.onerror = function(e) {
+        log(&quot;Error iterating cursor&quot;);
+        done();
+    } 
+}
+
+createRequest.onupgradeneeded = function(event) {
+    log(&quot;Initial upgrade needed: Old version - &quot; + event.oldVersion + &quot; New version - &quot; + event.newVersion);
+
+    var versionTransaction = createRequest.transaction;
+    var database = event.target.result;
+    objectStore = database.createObjectStore(&quot;TestObjectStore&quot;);
+
+    for (var i = 0; i &lt; 10; ++i) {
+        objectStore.put(&quot;Record &quot; + i, i);
+    }
+        
+    setupRequest1(objectStore.openCursor(IDBKeyRange.lowerBound(-Infinity), &quot;prev&quot;));
+      
+    versionTransaction.onabort = function(event) {
+        log(&quot;Initial upgrade versionchange transaction unexpected aborted&quot;);
+        done();
+    }
+
+    versionTransaction.oncomplete = function(event) {
+        log(&quot;Initial upgrade versionchange transaction complete&quot;);
+        done();
+    }
+
+    versionTransaction.onerror = function(event) {
+        log(&quot;Initial upgrade versionchange transaction unexpected error&quot; + event);
+        done();
+    }
+}
+
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderncursor5expectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/cursor-5-expected.txt (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/cursor-5-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/cursor-5-expected.txt        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,9 @@
</span><ins>+This tests iterating a &quot;next&quot; cursor in a read-write transaction while changing records.
+Initial upgrade needed: Old version - 0 New version - 1
+Cursor open at key 0
+Record 0 deleted, even though that's where the cursor currently points.
+Cursor iterated to key 1
+Cursor iterated to key 2 with value 'Scary new actual record!'
+Initial upgrade versionchange transaction complete
+Done
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderncursor5html"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/cursor-5.html (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/cursor-5.html                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/cursor-5.html        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,77 @@
</span><ins>+This tests iterating a &quot;next&quot; cursor in a read-write transaction while changing records.&lt;br&gt;
+&lt;div id=&quot;logger&quot;&gt;&lt;/div&gt;
+&lt;script&gt;
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function done()
+{
+    log(&quot;Done&quot;);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function log(message)
+{
+    document.getElementById(&quot;logger&quot;).innerHTML += message + &quot;&lt;br&gt;&quot;;
+}
+
+var createRequest = window.indexedDB.open(&quot;Cursor5Database&quot;, 1);
+
+createRequest.onupgradeneeded = function(event) {
+    log(&quot;Initial 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;);
+
+    for (var i = 0; i &lt; 3; ++i)
+        objectStore.put(&quot;Record &quot; + i, i);
+    
+    var request = objectStore.openCursor();
+    request.onsuccess = function() {
+        log(&quot;Cursor open at key &quot; + request.result.key);
+
+        // This tests deleting the current record out of underneath the cursor.
+        // Its current key should be 0, after an iteration its next key should be 1.
+        objectStore.delete(0).onsuccess = function() {
+            log(&quot;Record 0 deleted, even though that's where the cursor currently points.&quot;);
+        }
+        
+        // Now that cursor iteration has begun, manually delete and then replace a record 
+        // that will eventually be iterated to, making sure the new value is picked up. 
+        objectStore.delete(2);
+        objectStore.put(&quot;Scary new actual record!&quot;, 2);
+    
+        request.onsuccess = function() {
+            log(&quot;Cursor iterated to key &quot; + request.result.key);
+            
+            request.onsuccess = function() {
+                log(&quot;Cursor iterated to key &quot; + request.result.key + &quot; with value '&quot; + request.result.value + &quot;'&quot;);
+            }
+            
+            request.result.continue();
+        }
+        request.result.continue();
+    }
+          
+    versionTransaction.onabort = function(event) {
+        log(&quot;Initial upgrade versionchange transaction unexpected aborted&quot;);
+        done();
+    }
+
+    versionTransaction.oncomplete = function(event) {
+        log(&quot;Initial upgrade versionchange transaction complete&quot;);
+        done();
+    }
+
+    versionTransaction.onerror = function(event) {
+        log(&quot;Initial upgrade versionchange transaction unexpected error&quot; + event);
+        done();
+    }
+}
+
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderncursor6expectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/cursor-6-expected.txt (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/cursor-6-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/cursor-6-expected.txt        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,9 @@
</span><ins>+This tests iterating a &quot;prev&quot; cursor in a read-write transaction while changing records.
+Initial upgrade needed: Old version - 0 New version - 1
+Cursor open at key 2
+Record 2 deleted, even though that's where the cursor currently points.
+Cursor iterated to key 1
+Cursor iterated to key 0 with value 'Scary new actual record!'
+Initial upgrade versionchange transaction complete
+Done
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderncursor6html"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/cursor-6.html (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/cursor-6.html                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/cursor-6.html        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,78 @@
</span><ins>+This tests iterating a &quot;prev&quot; cursor in a read-write transaction while changing records.&lt;br&gt;
+&lt;div id=&quot;logger&quot;&gt;&lt;/div&gt;
+&lt;script&gt;
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function done()
+{
+    log(&quot;Done&quot;);
+    
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function log(message)
+{
+    document.getElementById(&quot;logger&quot;).innerHTML += message + &quot;&lt;br&gt;&quot;;
+}
+
+var createRequest = window.indexedDB.open(&quot;Cursor6Database&quot;, 1);
+
+createRequest.onupgradeneeded = function(event) {
+    log(&quot;Initial 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;);
+
+    for (var i = 0; i &lt; 3; ++i)
+        objectStore.put(&quot;Record &quot; + i, i);
+    
+    var request = objectStore.openCursor(IDBKeyRange.lowerBound(-Infinity), &quot;prev&quot;);
+    request.onsuccess = function() {
+        log(&quot;Cursor open at key &quot; + request.result.key);
+
+        // This tests deleting the current record out of underneath the cursor.
+        // Its current key should be 2, after an iteration its next key should be 1.
+        objectStore.delete(2).onsuccess = function() {
+            log(&quot;Record 2 deleted, even though that's where the cursor currently points.&quot;);
+        }
+        
+        // Now that cursor iteration has begun, manually delete and then replace a record 
+        // that will eventually be iterated to, making sure the new value is picked up. 
+        objectStore.delete(0);
+        objectStore.put(&quot;Scary new actual record!&quot;, 0);
+    
+        request.onsuccess = function() {
+            log(&quot;Cursor iterated to key &quot; + request.result.key);
+            
+            request.onsuccess = function() {
+                log(&quot;Cursor iterated to key &quot; + request.result.key + &quot; with value '&quot; + request.result.value + &quot;'&quot;);
+            }
+            
+            request.result.continue();
+        }
+        request.result.continue();
+    }
+          
+    versionTransaction.onabort = function(event) {
+        log(&quot;Initial upgrade versionchange transaction unexpected aborted&quot;);
+        done();
+    }
+
+    versionTransaction.oncomplete = function(event) {
+        log(&quot;Initial upgrade versionchange transaction complete&quot;);
+        done();
+    }
+
+    versionTransaction.onerror = function(event) {
+        log(&quot;Initial upgrade versionchange transaction unexpected error&quot; + event);
+        done();
+    }
+}
+
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderncursor7expectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/cursor-7-expected.txt (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/cursor-7-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/cursor-7-expected.txt        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+This tests iterating a &quot;next&quot; cursor in a read-write transaction combined with clearing the object store.
+Initial upgrade needed: Old version - 0 New version - 1
+Cursor open at key 0
+Object store cleared.
+Cursor iterated to key 100
+Initial upgrade versionchange transaction complete
+Done
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderncursor7html"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/cursor-7.html (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/cursor-7.html                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/cursor-7.html        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,71 @@
</span><ins>+This tests iterating a &quot;next&quot; cursor in a read-write transaction combined with clearing the object store.&lt;br&gt;
+&lt;div id=&quot;logger&quot;&gt;&lt;/div&gt;
+&lt;script&gt;
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function done()
+{
+    log(&quot;Done&quot;);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function log(message)
+{
+    document.getElementById(&quot;logger&quot;).innerHTML += message + &quot;&lt;br&gt;&quot;;
+}
+
+var createRequest = window.indexedDB.open(&quot;Cursor7Database&quot;, 1);
+
+createRequest.onupgradeneeded = function(event) {
+    log(&quot;Initial 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;);
+
+    for (var i = 0; i &lt; 3; ++i)
+        objectStore.put(&quot;Record &quot; + i, i);
+    
+    var request = objectStore.openCursor();
+    request.onsuccess = function() {
+        log(&quot;Cursor open at key &quot; + request.result.key);
+
+        // This tests deleting the current record out of underneath the cursor.
+        // Its current key should be 0, after an iteration its next key should be 1.
+        objectStore.clear().onsuccess = function() {
+            log(&quot;Object store cleared.&quot;);
+        }
+        
+        // The cursor is currently on key 0, which no longer exists.
+        // It's next key would have been 1, but the object store has been cleared.
+        // Whatever key we put in the object store that is greater than 0 will be the actual next key.
+        objectStore.put(&quot;Record 100&quot;, 100);
+    
+        request.onsuccess = function() {
+            log(&quot;Cursor iterated to key &quot; + request.result.key);
+        }
+        request.result.continue();
+    }
+          
+    versionTransaction.onabort = function(event) {
+        log(&quot;Initial upgrade versionchange transaction unexpected aborted&quot;);
+        done();
+    }
+
+    versionTransaction.oncomplete = function(event) {
+        log(&quot;Initial upgrade versionchange transaction complete&quot;);
+        done();
+    }
+
+    versionTransaction.onerror = function(event) {
+        log(&quot;Initial upgrade versionchange transaction unexpected error&quot; + event);
+        done();
+    }
+}
+
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderncursor8expectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/cursor-8-expected.txt (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/cursor-8-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/cursor-8-expected.txt        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+This tests iterating a &quot;prev&quot; cursor in a read-write transaction while changing records.
+Initial upgrade needed: Old version - 0 New version - 1
+Cursor open at key 2
+Object store cleared.
+Cursor iterated to key -100
+Initial upgrade versionchange transaction complete
+Done
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmoderncursor8html"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/cursor-8.html (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/cursor-8.html                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/cursor-8.html        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,72 @@
</span><ins>+This tests iterating a &quot;prev&quot; cursor in a read-write transaction while changing records.&lt;br&gt;
+&lt;div id=&quot;logger&quot;&gt;&lt;/div&gt;
+&lt;script&gt;
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function done()
+{
+    log(&quot;Done&quot;);
+    
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function log(message)
+{
+    document.getElementById(&quot;logger&quot;).innerHTML += message + &quot;&lt;br&gt;&quot;;
+}
+
+var createRequest = window.indexedDB.open(&quot;Cursor8Database&quot;, 1);
+
+createRequest.onupgradeneeded = function(event) {
+    log(&quot;Initial 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;);
+
+    for (var i = 0; i &lt; 3; ++i)
+        objectStore.put(&quot;Record &quot; + i, i);
+    
+    var request = objectStore.openCursor(IDBKeyRange.lowerBound(-Infinity), &quot;prev&quot;);
+    request.onsuccess = function() {
+        log(&quot;Cursor open at key &quot; + request.result.key);
+
+        // This tests deleting the current record out of underneath the cursor.
+        // Its current key should be 0, after an iteration its next key should be 1.
+        objectStore.clear().onsuccess = function() {
+            log(&quot;Object store cleared.&quot;);
+        }
+        
+        // The cursor is currently on key 2, which no longer exists.
+        // It's next key would have been 1, but the object store has been cleared.
+        // Whatever key we put in the object store that is less than 2 will be the actual next key.
+        objectStore.put(&quot;Record -100&quot;, -100);
+    
+        request.onsuccess = function() {
+            log(&quot;Cursor iterated to key &quot; + request.result.key);
+        }
+        request.result.continue();
+    }
+          
+    versionTransaction.onabort = function(event) {
+        log(&quot;Initial upgrade versionchange transaction unexpected aborted&quot;);
+        done();
+    }
+
+    versionTransaction.oncomplete = function(event) {
+        log(&quot;Initial upgrade versionchange transaction complete&quot;);
+        done();
+    }
+
+    versionTransaction.onerror = function(event) {
+        log(&quot;Initial upgrade versionchange transaction unexpected error&quot; + event);
+        done();
+    }
+}
+
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmodernobjectstorecursoradvancefailuresexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/objectstore-cursor-advance-failures-expected.txt (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/objectstore-cursor-advance-failures-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/objectstore-cursor-advance-failures-expected.txt        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+This tests some obvious failures that can happen while calling IDBCursor.advance() on object store cursors.
+Initial upgrade needed: Old version - 0 New version - 1
+Failed to advance object store cursor with undefined count argument
+Failed to advance object store cursor with '0' count argument
+Failed to advance object store cursor with negative count argument
+Failed to advance object store cursor after deleting object store
+Failed to advance an object store cursor when it is already fetching the next record
+Initial upgrade versionchange transaction complete
+Failed to advance object store cursor while transaction inactive
+readonly transaction complete
+Done
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmodernobjectstorecursoradvancefailureshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/objectstore-cursor-advance-failures.html (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/objectstore-cursor-advance-failures.html                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/objectstore-cursor-advance-failures.html        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,144 @@
</span><ins>+This tests some obvious failures that can happen while calling IDBCursor.advance() on object store cursors.&lt;br&gt;
+&lt;div id=&quot;logger&quot;&gt;&lt;/div&gt;
+&lt;script&gt;
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function done()
+{
+    log(&quot;Done&quot;);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function log(message)
+{
+    document.getElementById(&quot;logger&quot;).innerHTML += message + &quot;&lt;br&gt;&quot;;
+}
+
+var createRequest = window.indexedDB.open(&quot;IDBAdvanceFailuresDatabase&quot;, 1);
+var database;
+
+createRequest.onupgradeneeded = function(event) {
+    log(&quot;Initial 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;);
+    for (var i = 0; i &lt; 10; ++i)
+        objectStore.put(&quot;Record &quot; + i, i);
+    
+    var request = objectStore.openCursor();
+    request.onsuccess = function() {
+        var cursor = request.result;
+
+        try {
+            cursor.advance();
+        } catch(e) {
+            log(&quot;Failed to advance object store cursor with undefined count argument&quot;);
+        }
+
+        try {
+            cursor.advance(0);
+        } catch(e) {
+            log(&quot;Failed to advance object store cursor with '0' count argument&quot;);
+        }
+
+        try {
+            cursor.advance(-1);
+        } catch(e) {
+            log(&quot;Failed to advance object store cursor with negative count argument&quot;);
+        }
+
+        database.deleteObjectStore(&quot;TestObjectStore&quot;);
+        try {
+            cursor.advance(1);
+        } catch(e) {
+            log(&quot;Failed to advance object store cursor after deleting object store&quot;);
+        }
+
+        // Recreate the object store for use in the next stage of testing
+        objectStore = database.createObjectStore(&quot;TestObjectStore&quot;);
+        for (var i = 0; i &lt; 10; ++i)
+            objectStore.put(&quot;Record &quot; + i, i);
+    }
+    
+    var os2 = database.createObjectStore(&quot;TestObjectStore2&quot;);
+    for (var i = 0; i &lt; 10; ++i)
+        os2.put(&quot;Record &quot; + i, i);
+        
+    var request2 = os2.openCursor();
+    request2.onsuccess = function() {
+        var cursor = request2.result;
+        cursor.continue();
+        try {
+            cursor.advance(1);
+        } catch(e) {
+            log(&quot;Failed to advance an object store cursor when it is already fetching the next record&quot;);
+        }
+        request2.onsuccess = undefined;
+    }
+
+    versionTransaction.onabort = function(event) {
+        log(&quot;Initial upgrade versionchange transaction unexpected aborted&quot;);
+        done();
+    }
+
+    versionTransaction.oncomplete = function(event) {
+        log(&quot;Initial upgrade versionchange transaction complete&quot;);
+        continueTest1();
+    }
+
+    versionTransaction.onerror = function(event) {
+        log(&quot;Initial upgrade versionchange transaction unexpected error&quot; + event);
+        done();
+    }
+}
+
+function continueTest1()
+{
+    var transaction = database.transaction(&quot;TestObjectStore&quot;, &quot;readonly&quot;);
+    var objectStore = transaction.objectStore(&quot;TestObjectStore&quot;);
+    var cursor = objectStore.openCursor();
+
+    // Spin the transaction with get requests to keep it alive long enough for the setTimeout to fire.
+    var canFinish = false;
+    var spinGet = function() { 
+        objectStore.get(&quot;foo&quot;).onsuccess = function() {
+            if (!canFinish)
+                spinGet();
+        }
+    }
+    spinGet();
+
+    var testWhileInactive = function() {
+        try {
+            cursor.advance(1);
+        } catch(e) {
+            log(&quot;Failed to advance object store cursor while transaction inactive&quot;);
+        }
+        canFinish = true;
+    }
+    
+    setTimeout(testWhileInactive, 0);
+    
+    transaction.onabort = function(event) {
+        log(&quot;readonly transaction unexpected abort&quot; + event);
+        done();
+    }
+
+    transaction.oncomplete = function(event) {
+        log(&quot;readonly transaction complete&quot;);
+        done();
+    }
+
+    transaction.onerror = function(event) {
+        log(&quot;readonly transaction unexpected error&quot; + event);
+        done();
+    }
+}
+
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmodernobjectstorecursorcontinuefailuresexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/objectstore-cursor-continue-failures-expected.txt (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/objectstore-cursor-continue-failures-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/objectstore-cursor-continue-failures-expected.txt        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+This tests some obvious failures that can happen while calling IDBCursor.continue() on object store cursors.
+Initial upgrade needed: Old version - 0 New version - 1
+Failed to continue a 'next' object store cursor to a key less than the current key
+Failed to continue object store cursor with invalid key
+Failed to continue object store cursor after deleting object store
+Failed to continue a 'prev' object store cursor to a key greater than the current key
+Failed to continue an object store cursor when it is already fetching the next record
+Initial upgrade versionchange transaction complete
+Failed to continue object store cursor while transaction inactive
+readonly transaction complete
+Done
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmodernobjectstorecursorcontinuefailureshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/objectstore-cursor-continue-failures.html (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/objectstore-cursor-continue-failures.html                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/objectstore-cursor-continue-failures.html        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,148 @@
</span><ins>+This tests some obvious failures that can happen while calling IDBCursor.continue() on object store cursors.&lt;br&gt;
+&lt;div id=&quot;logger&quot;&gt;&lt;/div&gt;
+&lt;script&gt;
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.dumpAsText();
+}
+
+function done()
+{
+    log(&quot;Done&quot;);
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function log(message)
+{
+    document.getElementById(&quot;logger&quot;).innerHTML += message + &quot;&lt;br&gt;&quot;;
+}
+
+var createRequest = window.indexedDB.open(&quot;IDBContinueFailuresDatabase&quot;, 1);
+var database;
+
+createRequest.onupgradeneeded = function(event) {
+    log(&quot;Initial 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;);
+    for (var i = 0; i &lt; 10; ++i)
+        objectStore.put(&quot;Record &quot; + i, i);
+    
+    var request = objectStore.openCursor();
+    request.onsuccess = function() {
+        var cursor = request.result;
+
+        try {
+            cursor.continue(-1);
+        } catch(e) {
+            log(&quot;Failed to continue a 'next' object store cursor to a key less than the current key&quot;);
+        }
+
+        try {
+            cursor.continue(NaN);
+        } catch(e) {
+            log(&quot;Failed to continue object store cursor with invalid key&quot;);
+        }
+
+        database.deleteObjectStore(&quot;TestObjectStore&quot;);
+        try {
+            cursor.continue();
+        } catch(e) {
+            log(&quot;Failed to continue object store cursor after deleting object store&quot;);
+        }
+
+        // Recreate the object store for use in the next stage of testing
+        objectStore = database.createObjectStore(&quot;TestObjectStore&quot;);
+        for (var i = 0; i &lt; 10; ++i)
+            objectStore.put(&quot;Record &quot; + i, i);
+    }
+    
+    var request2 = objectStore.openCursor(IDBKeyRange.lowerBound(-Infinity), &quot;prev&quot;);
+    request2.onsuccess = function() {
+        var cursor = request2.result;
+        try {
+            cursor.continue(100);
+        } catch(e) {
+            log(&quot;Failed to continue a 'prev' object store cursor to a key greater than the current key&quot;);
+        }
+    }
+
+    var os2 = database.createObjectStore(&quot;TestObjectStore2&quot;);
+    for (var i = 0; i &lt; 10; ++i)
+        os2.put(&quot;Record &quot; + i, i);
+        
+    var request3 = os2.openCursor();
+    request3.onsuccess = function() {
+        var cursor = request3.result;
+        cursor.continue();
+        try {
+            cursor.continue();
+        } catch(e) {
+            log(&quot;Failed to continue an object store cursor when it is already fetching the next record&quot;);
+        }
+        request3.onsuccess = undefined;
+    }
+
+    versionTransaction.onabort = function(event) {
+        log(&quot;Initial upgrade versionchange transaction unexpected aborted&quot;);
+        done();
+    }
+
+    versionTransaction.oncomplete = function(event) {
+        log(&quot;Initial upgrade versionchange transaction complete&quot;);
+        continueTest1();
+    }
+
+    versionTransaction.onerror = function(event) {
+        log(&quot;Initial upgrade versionchange transaction unexpected error&quot; + event);
+        done();
+    }
+}
+
+function continueTest1()
+{
+    var transaction = database.transaction(&quot;TestObjectStore&quot;, &quot;readonly&quot;);
+    var objectStore = transaction.objectStore(&quot;TestObjectStore&quot;);
+    var cursor = objectStore.openCursor();
+
+    // Spin the transaction with get requests to keep it alive long enough for the setTimeout to fire.
+    var canFinish = false;
+    var spinGet = function() { 
+        objectStore.get(&quot;foo&quot;).onsuccess = function() {
+            if (!canFinish)
+                spinGet();
+        }
+    }
+    spinGet();
+
+    var testWhileInactive = function() {
+        try {
+            cursor.continue();
+        } catch(e) {
+            log(&quot;Failed to continue object store cursor while transaction inactive&quot;);
+        }
+        canFinish = true;
+    }
+    
+    setTimeout(testWhileInactive, 0);
+    
+    transaction.onabort = function(event) {
+        log(&quot;readonly transaction unexpected abort&quot; + event);
+        done();
+    }
+
+    transaction.oncomplete = function(event) {
+        log(&quot;readonly transaction complete&quot;);
+        done();
+    }
+
+    transaction.onerror = function(event) {
+        log(&quot;readonly transaction unexpected error&quot; + event);
+        done();
+    }
+}
+
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/CMakeLists.txt        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/CMakeLists.txt        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -905,9 +905,11 @@
</span><span class="cx">     Modules/indexeddb/server/IndexValueEntry.cpp
</span><span class="cx">     Modules/indexeddb/server/IndexValueStore.cpp
</span><span class="cx">     Modules/indexeddb/server/MemoryBackingStoreTransaction.cpp
</span><ins>+    Modules/indexeddb/server/MemoryCursor.cpp
</ins><span class="cx">     Modules/indexeddb/server/MemoryIDBBackingStore.cpp
</span><span class="cx">     Modules/indexeddb/server/MemoryIndex.cpp
</span><span class="cx">     Modules/indexeddb/server/MemoryObjectStore.cpp
</span><ins>+    Modules/indexeddb/server/MemoryObjectStoreCursor.cpp
</ins><span class="cx">     Modules/indexeddb/server/UniqueIDBDatabase.cpp
</span><span class="cx">     Modules/indexeddb/server/UniqueIDBDatabaseConnection.cpp
</span><span class="cx">     Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/ChangeLog        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -1,3 +1,122 @@
</span><ins>+2015-11-16  Brady Eidson  &lt;beidson@apple.com&gt;
+
+        Modern IDB:Make in-memory ObjectStore cursors work.
+        https://bugs.webkit.org/show_bug.cgi?id=151196
+
+        Reviewed by Darin Adler.
+
+        Tests: storage/indexeddb/modern/cursor-2.html
+               storage/indexeddb/modern/cursor-3.html
+               storage/indexeddb/modern/cursor-4.html
+               storage/indexeddb/modern/cursor-5.html
+               storage/indexeddb/modern/cursor-6.html
+               storage/indexeddb/modern/cursor-7.html
+               storage/indexeddb/modern/cursor-8.html
+               storage/indexeddb/modern/objectstore-cursor-advance-failures.html
+               storage/indexeddb/modern/objectstore-cursor-continue-failures.html
+
+        Object store cursors directly hold on to a std::set&lt;&gt;::iterator to act as the cursor.
+        
+        The object store tells all of its cursors when it is cleared or records are deleted
+        so the cursors can invalidate their iterators as needed.
+        
+        In case of such invalidation, the cursor hangs on to the current key value so it can 
+        pick up where it left off in case it is iterated.
+
+        * CMakeLists.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+
+        * Modules/indexeddb/IDBGetResult.h:
+        (WebCore::IDBGetResult::isolatedCopy):
+        
+        * Modules/indexeddb/IDBKeyRangeData.cpp:
+        (WebCore::IDBKeyRangeData::containsKey):
+        (WebCore::IDBKeyRangeData::loggingString):
+        * Modules/indexeddb/IDBKeyRangeData.h:
+        
+        * Modules/indexeddb/client/IDBAnyImpl.cpp:
+        (WebCore::IDBClient::IDBAny::modernIDBCursor):
+        
+        * Modules/indexeddb/client/IDBCursorImpl.cpp:
+        (WebCore::IDBClient::IDBCursor::update):
+        (WebCore::IDBClient::IDBCursor::advance):
+        (WebCore::IDBClient::IDBCursor::continueFunction):
+        (WebCore::IDBClient::IDBCursor::setGetResult):
+        * Modules/indexeddb/client/IDBCursorImpl.h:
+        
+        * Modules/indexeddb/client/IDBRequestImpl.cpp:
+        (WebCore::IDBClient::IDBRequest::dispatchEvent):
+        (WebCore::IDBClient::IDBRequest::didOpenOrIterateCursor):
+        * Modules/indexeddb/client/IDBRequestImpl.h:
+        (WebCore::IDBClient::IDBRequest::pendingCursor):
+        
+        * Modules/indexeddb/client/IDBTransactionImpl.cpp:
+        (WebCore::IDBClient::IDBTransaction::addRequest): Deleted.
+        
+        * Modules/indexeddb/client/TransactionOperation.cpp:
+        (WebCore::IDBClient::TransactionOperation::TransactionOperation):
+        * Modules/indexeddb/client/TransactionOperation.h:
+        (WebCore::IDBClient::TransactionOperation::cursorIdentifier):
+        
+        * Modules/indexeddb/server/IDBBackingStore.h:
+        
+        * Modules/indexeddb/server/MemoryBackingStoreTransaction.cpp:
+        (WebCore::IDBServer::MemoryBackingStoreTransaction::objectStoreCleared):
+        (WebCore::IDBServer::MemoryBackingStoreTransaction::abort):
+        * Modules/indexeddb/server/MemoryBackingStoreTransaction.h:
+        
+        * Modules/indexeddb/server/MemoryCursor.cpp: Added.
+        (WebCore::IDBServer::cursorMap):
+        (WebCore::IDBServer::MemoryCursor::MemoryCursor):
+        (WebCore::IDBServer::MemoryCursor::~MemoryCursor):
+        (WebCore::IDBServer::MemoryCursor::cursorForIdentifier):
+        * Modules/indexeddb/server/MemoryCursor.h: Added.
+        
+        * Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
+        (WebCore::IDBServer::MemoryIDBBackingStore::openCursor):
+        (WebCore::IDBServer::MemoryIDBBackingStore::iterateCursor):
+        * Modules/indexeddb/server/MemoryIDBBackingStore.h:
+        
+        * Modules/indexeddb/server/MemoryObjectStore.cpp:
+        (WebCore::IDBServer::MemoryObjectStore::clear):
+        (WebCore::IDBServer::MemoryObjectStore::replaceKeyValueStore):
+        (WebCore::IDBServer::MemoryObjectStore::deleteRecord):
+        (WebCore::IDBServer::MemoryObjectStore::addRecord):
+        (WebCore::IDBServer::MemoryObjectStore::updateCursorsForPutRecord):
+        (WebCore::IDBServer::MemoryObjectStore::updateCursorsForDeleteRecord):
+        (WebCore::IDBServer::MemoryObjectStore::maybeOpenCursor):
+        * Modules/indexeddb/server/MemoryObjectStore.h:
+        (WebCore::IDBServer::MemoryObjectStore::orderedKeys):
+        
+        * Modules/indexeddb/server/MemoryObjectStoreCursor.cpp: Added.
+        (WebCore::IDBServer::MemoryObjectStoreCursor::create):
+        (WebCore::IDBServer::MemoryObjectStoreCursor::MemoryObjectStoreCursor):
+        (WebCore::IDBServer::MemoryObjectStoreCursor::objectStoreCleared):
+        (WebCore::IDBServer::MemoryObjectStoreCursor::keyDeleted):
+        (WebCore::IDBServer::MemoryObjectStoreCursor::keyAdded):
+        (WebCore::IDBServer::MemoryObjectStoreCursor::setFirstInRemainingRange):
+        (WebCore::IDBServer::MemoryObjectStoreCursor::firstForwardIteratorInRemainingRange):
+        (WebCore::IDBServer::MemoryObjectStoreCursor::firstReverseIteratorInRemainingRange):
+        (WebCore::IDBServer::MemoryObjectStoreCursor::currentData):
+        (WebCore::IDBServer::MemoryObjectStoreCursor::incrementForwardIterator):
+        (WebCore::IDBServer::MemoryObjectStoreCursor::incrementReverseIterator):
+        (WebCore::IDBServer::MemoryObjectStoreCursor::hasValidPosition):
+        (WebCore::IDBServer::MemoryObjectStoreCursor::iterate):
+        * Modules/indexeddb/server/MemoryObjectStoreCursor.h: Added.
+
+        * Modules/indexeddb/server/UniqueIDBDatabase.cpp:
+        (WebCore::IDBServer::UniqueIDBDatabase::iterateCursor):
+        (WebCore::IDBServer::UniqueIDBDatabase::performIterateCursor):
+        * Modules/indexeddb/server/UniqueIDBDatabase.h:
+
+        * Modules/indexeddb/shared/IDBCursorInfo.h:
+        (WebCore::IDBCursorInfo::range):
+
+        * Modules/indexeddb/shared/IDBRequestData.cpp:
+        (WebCore::IDBRequestData::IDBRequestData):
+        (WebCore::IDBRequestData::cursorIdentifier):
+        * Modules/indexeddb/shared/IDBRequestData.h:
+
</ins><span class="cx"> 2015-11-16  Anders Carlsson  &lt;andersca@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Add identifier strings for a bunch of context menu items
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbIDBGetResulth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/IDBGetResult.h (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/IDBGetResult.h        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBGetResult.h        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -83,6 +83,7 @@
</span><span class="cx">         IDBGetResult result;
</span><span class="cx">         result.valueBuffer = valueBuffer;
</span><span class="cx">         result.keyData = keyData.isolatedCopy();
</span><ins>+        result.primaryKeyData = primaryKeyData.isolatedCopy();
</ins><span class="cx">         result.keyPath = keyPath.isolatedCopy();
</span><span class="cx">         return result;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbIDBKeyRangeDatacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/IDBKeyRangeData.cpp (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/IDBKeyRangeData.cpp        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBKeyRangeData.cpp        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -79,6 +79,26 @@
</span><span class="cx">     return !lowerKey.compare(upperKey);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool IDBKeyRangeData::containsKey(const IDBKeyData&amp; key) const
+{
+    if (lowerKey.isValid()) {
+        auto compare = lowerKey.compare(key);
+        if (compare &gt; 0)
+            return false;
+        if (lowerOpen &amp;&amp; !compare)
+            return false;
+    }
+    if (upperKey.isValid()) {
+        auto compare = upperKey.compare(key);
+        if (compare &lt; 0)
+            return false;
+        if (upperOpen &amp;&amp; !compare)
+            return false;
+    }
+
+    return true;
+}
+
</ins><span class="cx"> bool IDBKeyRangeData::isValid() const
</span><span class="cx"> {
</span><span class="cx">     if (isNull)
</span><span class="lines">@@ -93,6 +113,13 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#ifndef NDEBUG
+String IDBKeyRangeData::loggingString() const
+{
+    return makeString(lowerOpen ? &quot;( &quot; : &quot;[ &quot;, lowerKey.loggingString(), &quot;, &quot;, upperKey.loggingString(), upperOpen ? &quot; )&quot; : &quot; ]&quot;);
+}
+#endif
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(INDEXED_DATABASE)
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbIDBKeyRangeDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/IDBKeyRangeData.h (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/IDBKeyRangeData.h        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBKeyRangeData.h        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -65,6 +65,7 @@
</span><span class="cx">     WEBCORE_EXPORT PassRefPtr&lt;IDBKeyRange&gt; maybeCreateIDBKeyRange() const;
</span><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT bool isExactlyOneKey() const;
</span><ins>+    bool containsKey(const IDBKeyData&amp;) const;
</ins><span class="cx">     bool isValid() const;
</span><span class="cx"> 
</span><span class="cx">     template&lt;class Encoder&gt; void encode(Encoder&amp;) const;
</span><span class="lines">@@ -77,6 +78,10 @@
</span><span class="cx"> 
</span><span class="cx">     bool lowerOpen;
</span><span class="cx">     bool upperOpen;
</span><ins>+
+#ifndef NDEBUG
+    String loggingString() const;
+#endif
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> template&lt;class Encoder&gt;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbclientIDBAnyImplcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/client/IDBAnyImpl.cpp (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/client/IDBAnyImpl.cpp        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/client/IDBAnyImpl.cpp        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -141,7 +141,9 @@
</span><span class="cx"> IDBCursor* IDBAny::modernIDBCursor()
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_type == IDBAny::Type::IDBCursor || m_type == IDBAny::Type::IDBCursorWithValue);
</span><del>-    return m_cursor.get();
</del><ins>+    if (m_type == IDBAny::Type::IDBCursor)
+        return m_cursor.get();
+    return m_cursorWithValue.get();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RefPtr&lt;WebCore::IDBTransaction&gt; IDBAny::idbTransaction()
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbclientIDBCursorImplcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/client/IDBCursorImpl.cpp (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/client/IDBCursorImpl.cpp        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/client/IDBCursorImpl.cpp        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -112,7 +112,7 @@
</span><span class="cx"> 
</span><span class="cx"> RefPtr&lt;WebCore::IDBRequest&gt; IDBCursor::update(JSC::ExecState&amp; exec, Deprecated::ScriptValue&amp; value, ExceptionCode&amp; ec)
</span><span class="cx"> {
</span><del>-    LOG(IndexedDB, &quot;IDBCursor::advance&quot;);
</del><ins>+    LOG(IndexedDB, &quot;IDBCursor::update&quot;);
</ins><span class="cx"> 
</span><span class="cx">     if (sourcesDeleted()) {
</span><span class="cx">         ec = IDBDatabaseException::InvalidStateError;
</span><span class="lines">@@ -171,6 +171,8 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    m_gotValue = false;
+
</ins><span class="cx">     uncheckedIteratorCursor(IDBKeyData(), count);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -220,21 +222,23 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (!key.isValid()) {
</del><ins>+    if (!key.isNull() &amp;&amp; !key.isValid()) {
</ins><span class="cx">         ec = IDBDatabaseException::DataError;
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (m_info.isDirectionForward()) {
</span><del>-        if (key.compare(m_currentPrimaryKeyData) &lt;= 0) {
</del><ins>+        if (!key.isNull() &amp;&amp; key.compare(m_currentPrimaryKeyData) &lt;= 0) {
</ins><span class="cx">             ec = IDBDatabaseException::DataError;
</span><span class="cx">             return;
</span><span class="cx">         }
</span><del>-    } else if (key.compare(m_currentPrimaryKeyData) &gt;= 0) {
</del><ins>+    } else if (!key.isNull() &amp;&amp; key.compare(m_currentPrimaryKeyData) &gt;= 0) {
</ins><span class="cx">         ec = IDBDatabaseException::DataError;
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    m_gotValue = false;
+
</ins><span class="cx">     uncheckedIteratorCursor(key, 0);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -276,12 +280,23 @@
</span><span class="cx">     return effectiveObjectStore().deleteFunction(context, m_deprecatedCurrentPrimaryKey.jsValue(), ec);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void IDBCursor::setGetResult(const IDBGetResult&amp;)
</del><ins>+void IDBCursor::setGetResult(IDBRequest&amp; request, const IDBGetResult&amp; getResult)
</ins><span class="cx"> {
</span><del>-    LOG(IndexedDB, &quot;IDBCursor::setGetResult&quot;);
</del><ins>+    LOG(IndexedDB, &quot;IDBCursor::setGetResult - current key %s&quot;, getResult.keyData.loggingString().utf8().data());
</ins><span class="cx"> 
</span><del>-    // FIXME: Implement.
</del><ins>+    auto* context = request.scriptExecutionContext();
+    if (!context)
+        return;
</ins><span class="cx"> 
</span><ins>+    m_deprecatedCurrentKey = idbKeyDataToScriptValue(context, getResult.keyData);
+    m_deprecatedCurrentPrimaryKey = idbKeyDataToScriptValue(context, getResult.primaryKeyData);
+    m_currentPrimaryKeyData = getResult.primaryKeyData;
+
+    if (isKeyCursor())
+        m_deprecatedCurrentValue = { };
+    else
+        m_deprecatedCurrentValue = deserializeIDBValueData(*context, getResult.valueBuffer);
+
</ins><span class="cx">     m_gotValue = true;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbclientIDBCursorImplh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/client/IDBCursorImpl.h (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/client/IDBCursorImpl.h        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/client/IDBCursorImpl.h        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -69,7 +69,7 @@
</span><span class="cx">     void clearRequest() { m_request = nullptr; }
</span><span class="cx">     IDBRequest* request() { return m_request; }
</span><span class="cx"> 
</span><del>-    void setGetResult(const IDBGetResult&amp;);
</del><ins>+    void setGetResult(IDBRequest&amp;, const IDBGetResult&amp;);
</ins><span class="cx"> 
</span><span class="cx">     virtual bool isKeyCursor() const override { return true; }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbclientIDBRequestImplcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/client/IDBRequestImpl.cpp (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/client/IDBRequestImpl.cpp        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/client/IDBRequestImpl.cpp        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -227,7 +227,7 @@
</span><span class="cx"> 
</span><span class="cx"> bool IDBRequest::dispatchEvent(Event&amp; event)
</span><span class="cx"> {
</span><del>-    LOG(IndexedDB, &quot;IDBRequest::dispatchEvent - %s&quot;, event.type().characters8());
</del><ins>+    LOG(IndexedDB, &quot;IDBRequest::dispatchEvent - %s (%p)&quot;, event.type().characters8(), this);
</ins><span class="cx"> 
</span><span class="cx">     if (event.type() != eventNames().blockedEvent)
</span><span class="cx">         m_readyState = IDBRequestReadyState::Done;
</span><span class="lines">@@ -246,11 +246,10 @@
</span><span class="cx">         dontPreventDefault = IDBEventDispatcher::dispatch(event, targets);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    m_hasPendingActivity = false;
-
-    // FIXME: When we implement reusable requests (for cursors) it will be incorrect to always remove the request from the transaction.
-    if (m_transaction)
</del><ins>+    if (m_transaction &amp;&amp; !m_pendingCursor) {
</ins><span class="cx">         m_transaction-&gt;removeRequest(*this);
</span><ins>+        m_hasPendingActivity = false;
+    }
</ins><span class="cx"> 
</span><span class="cx">     return dontPreventDefault;
</span><span class="cx"> }
</span><span class="lines">@@ -316,8 +315,8 @@
</span><span class="cx"> void IDBRequest::didOpenOrIterateCursor(const IDBResultData&amp; resultData)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_pendingCursor);
</span><del>-    if (resultData.type() == IDBResultType::IterateCursorSuccess)
-        m_pendingCursor-&gt;setGetResult(resultData.getResult());
</del><ins>+    if (resultData.type() == IDBResultType::IterateCursorSuccess || resultData.type() == IDBResultType::OpenCursorSuccess)
+        m_pendingCursor-&gt;setGetResult(*this, resultData.getResult());
</ins><span class="cx"> 
</span><span class="cx">     m_result = IDBAny::create(*m_pendingCursor);
</span><span class="cx">     m_pendingCursor = nullptr;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbclientIDBRequestImplh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/client/IDBRequestImpl.h (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/client/IDBRequestImpl.h        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/client/IDBRequestImpl.h        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -95,6 +95,8 @@
</span><span class="cx">     void willIterateCursor(IDBCursor&amp;);
</span><span class="cx">     void didOpenOrIterateCursor(const IDBResultData&amp;);
</span><span class="cx"> 
</span><ins>+    const IDBCursor* pendingCursor() const { return m_pendingCursor.get(); }
+
</ins><span class="cx"> protected:
</span><span class="cx">     IDBRequest(IDBConnectionToServer&amp;, ScriptExecutionContext*);
</span><span class="cx">     IDBRequest(ScriptExecutionContext&amp;, IDBObjectStore&amp;, IDBTransaction&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbclientIDBTransactionImplcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.cpp (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.cpp        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.cpp        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -211,7 +211,6 @@
</span><span class="cx"> 
</span><span class="cx"> void IDBTransaction::addRequest(IDBRequest&amp; request)
</span><span class="cx"> {
</span><del>-    ASSERT(!m_openRequests.contains(&amp;request));
</del><span class="cx">     m_openRequests.add(&amp;request);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -239,7 +238,7 @@
</span><span class="cx"> 
</span><span class="cx"> void IDBTransaction::operationTimerFired()
</span><span class="cx"> {
</span><del>-    LOG(IndexedDB, &quot;IDBTransaction::operationTimerFired&quot;);
</del><ins>+    LOG(IndexedDB, &quot;IDBTransaction::operationTimerFired (%p)&quot;, this);
</ins><span class="cx"> 
</span><span class="cx">     if (!m_startedOnServer)
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbclientTransactionOperationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.cpp (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.cpp        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.cpp        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -28,6 +28,8 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(INDEXED_DATABASE)
</span><span class="cx"> 
</span><ins>+#include &quot;IDBCursorImpl.h&quot;
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx"> namespace IDBClient {
</span><span class="cx"> 
</span><span class="lines">@@ -38,6 +40,8 @@
</span><span class="cx">     m_indexIdentifier = request.sourceIndexIdentifier();
</span><span class="cx">     if (m_indexIdentifier)
</span><span class="cx">         m_indexRecordType = request.requestedIndexRecordType();
</span><ins>+    if (auto* cursor = request.pendingCursor())
+        m_cursorIdentifier = std::make_unique&lt;IDBResourceIdentifier&gt;(cursor-&gt;info().identifier());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace IDBClient
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbclientTransactionOperationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.h (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.h        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.h        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -59,6 +59,7 @@
</span><span class="cx">     IDBResourceIdentifier transactionIdentifier() const { return m_transaction-&gt;info().identifier(); }
</span><span class="cx">     uint64_t objectStoreIdentifier() const { return m_objectStoreIdentifier; }
</span><span class="cx">     uint64_t indexIdentifier() const { return m_indexIdentifier; }
</span><ins>+    IDBResourceIdentifier* cursorIdentifier() const { return m_cursorIdentifier.get(); }
</ins><span class="cx">     IDBTransaction&amp; transaction() { return m_transaction.get(); }
</span><span class="cx">     IndexedDB::IndexRecordType indexRecordType() const { return m_indexRecordType; }
</span><span class="cx"> 
</span><span class="lines">@@ -75,6 +76,7 @@
</span><span class="cx">     IDBResourceIdentifier m_identifier;
</span><span class="cx">     uint64_t m_objectStoreIdentifier { 0 };
</span><span class="cx">     uint64_t m_indexIdentifier { 0 };
</span><ins>+    std::unique_ptr&lt;IDBResourceIdentifier&gt; m_cursorIdentifier;
</ins><span class="cx">     IndexedDB::IndexRecordType m_indexRecordType;
</span><span class="cx">     std::function&lt;void ()&gt; m_performFunction;
</span><span class="cx">     std::function&lt;void (const IDBResultData&amp;)&gt; m_completeFunction;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverIDBBackingStoreh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/IDBBackingStore.h (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/IDBBackingStore.h        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/server/IDBBackingStore.h        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -72,7 +72,7 @@
</span><span class="cx">     virtual IDBError getCount(const IDBResourceIdentifier&amp; transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData&amp;, uint64_t&amp; outCount) = 0;
</span><span class="cx">     virtual IDBError generateKeyNumber(const IDBResourceIdentifier&amp; transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t&amp; keyNumber) = 0;
</span><span class="cx">     virtual IDBError openCursor(const IDBResourceIdentifier&amp; transactionIdentifier, const IDBCursorInfo&amp;, IDBGetResult&amp; outResult) = 0;
</span><del>-    virtual IDBError iterateCursor(const IDBResourceIdentifier&amp; transactionIdentifier, const IDBKeyData&amp;, unsigned long count, IDBGetResult&amp; outResult) = 0;
</del><ins>+    virtual IDBError iterateCursor(const IDBResourceIdentifier&amp; transactionIdentifier, const IDBResourceIdentifier&amp; cursorIdentifier, const IDBKeyData&amp;, uint32_t count, IDBGetResult&amp; outResult) = 0;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace IDBServer
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryBackingStoreTransactioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryBackingStoreTransaction.cpp (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryBackingStoreTransaction.cpp        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryBackingStoreTransaction.cpp        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -111,7 +111,7 @@
</span><span class="cx">         addResult.iterator-&gt;value = WTF::move(objectStore);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MemoryBackingStoreTransaction::objectStoreCleared(MemoryObjectStore&amp; objectStore, std::unique_ptr&lt;KeyValueMap&gt;&amp;&amp; keyValueMap)
</del><ins>+void MemoryBackingStoreTransaction::objectStoreCleared(MemoryObjectStore&amp; objectStore, std::unique_ptr&lt;KeyValueMap&gt;&amp;&amp; keyValueMap, std::unique_ptr&lt;std::set&lt;IDBKeyData&gt;&gt;&amp;&amp; orderedKeys)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_objectStores.contains(&amp;objectStore));
</span><span class="cx"> 
</span><span class="lines">@@ -122,6 +122,9 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     addResult.iterator-&gt;value = WTF::move(keyValueMap);
</span><ins>+
+    ASSERT(!m_clearedOrderedKeys.contains(&amp;objectStore));
+    m_clearedOrderedKeys.add(&amp;objectStore, WTF::move(orderedKeys));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MemoryBackingStoreTransaction::indexCleared(MemoryIndex&amp; index, std::unique_ptr&lt;IndexValueStore&gt;&amp;&amp; valueStore)
</span><span class="lines">@@ -196,8 +199,10 @@
</span><span class="cx">         objectStore-&gt;setKeyGeneratorValue(m_originalKeyGenerators.get(objectStore));
</span><span class="cx"> 
</span><span class="cx">         auto clearedKeyValueMap = m_clearedKeyValueMaps.take(objectStore);
</span><del>-        if (clearedKeyValueMap)
-            objectStore-&gt;replaceKeyValueStore(WTF::move(clearedKeyValueMap));
</del><ins>+        if (clearedKeyValueMap) {
+            ASSERT(m_clearedOrderedKeys.contains(objectStore));
+            objectStore-&gt;replaceKeyValueStore(WTF::move(clearedKeyValueMap), m_clearedOrderedKeys.take(objectStore));
+        }
</ins><span class="cx"> 
</span><span class="cx">         auto keyValueMap = m_originalValues.take(objectStore);
</span><span class="cx">         if (!keyValueMap)
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryBackingStoreTransactionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryBackingStoreTransaction.h (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryBackingStoreTransaction.h        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryBackingStoreTransaction.h        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -63,7 +63,7 @@
</span><span class="cx">     
</span><span class="cx">     void recordValueChanged(MemoryObjectStore&amp;, const IDBKeyData&amp;, ThreadSafeDataBuffer*);
</span><span class="cx">     void objectStoreDeleted(std::unique_ptr&lt;MemoryObjectStore&gt;);
</span><del>-    void objectStoreCleared(MemoryObjectStore&amp;, std::unique_ptr&lt;KeyValueMap&gt;&amp;&amp;);
</del><ins>+    void objectStoreCleared(MemoryObjectStore&amp;, std::unique_ptr&lt;KeyValueMap&gt;&amp;&amp;, std::unique_ptr&lt;std::set&lt;IDBKeyData&gt;&gt;&amp;&amp;);
</ins><span class="cx">     void indexCleared(MemoryIndex&amp;, std::unique_ptr&lt;IndexValueStore&gt;&amp;&amp;);
</span><span class="cx"> 
</span><span class="cx">     void addNewIndex(MemoryIndex&amp;);
</span><span class="lines">@@ -95,6 +95,7 @@
</span><span class="cx">     HashMap&lt;String, std::unique_ptr&lt;MemoryIndex&gt;&gt; m_deletedIndexes;
</span><span class="cx">     HashMap&lt;MemoryObjectStore*, std::unique_ptr&lt;KeyValueMap&gt;&gt; m_originalValues;
</span><span class="cx">     HashMap&lt;MemoryObjectStore*, std::unique_ptr&lt;KeyValueMap&gt;&gt; m_clearedKeyValueMaps;
</span><ins>+    HashMap&lt;MemoryObjectStore*, std::unique_ptr&lt;std::set&lt;IDBKeyData&gt;&gt;&gt; m_clearedOrderedKeys;
</ins><span class="cx">     HashMap&lt;MemoryIndex*, std::unique_ptr&lt;IndexValueStore&gt;&gt; m_clearedIndexValueStores;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryCursorcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/indexeddb/server/MemoryCursor.cpp (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryCursor.cpp                                (rev 0)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryCursor.cpp        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,66 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;MemoryCursor.h&quot;
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include &quot;IDBResourceIdentifier.h&quot;
+#include &quot;MemoryIDBBackingStore.h&quot;
+#include &lt;wtf/HashMap.h&gt;
+#include &lt;wtf/NeverDestroyed.h&gt;
+
+namespace WebCore {
+namespace IDBServer {
+
+static HashMap&lt;IDBResourceIdentifier, MemoryCursor*&gt;&amp; cursorMap()
+{
+    static NeverDestroyed&lt;HashMap&lt;IDBResourceIdentifier, MemoryCursor*&gt;&gt; map;
+    return map;
+}
+
+MemoryCursor::MemoryCursor(const IDBCursorInfo&amp; info)
+    : m_info(info)
+{
+    ASSERT(!cursorMap().contains(m_info.identifier()));
+    cursorMap().set(m_info.identifier(), this);
+}
+
+MemoryCursor::~MemoryCursor()
+{
+    ASSERT(cursorMap().contains(m_info.identifier()));
+    cursorMap().remove(m_info.identifier());
+}
+
+MemoryCursor* MemoryCursor::cursorForIdentifier(const IDBResourceIdentifier&amp; identifier)
+{
+    return cursorMap().get(identifier);
+}
+
+} // namespace IDBServer
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryCursorh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/indexeddb/server/MemoryCursor.h (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryCursor.h                                (rev 0)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryCursor.h        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,61 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MemoryCursor_h
+#define MemoryCursor_h
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include &quot;IDBCursorInfo.h&quot;
+
+namespace WebCore {
+
+class IDBKeyData;
+class IDBResourceIdentifier;
+
+struct IDBGetResult;
+
+namespace IDBServer {
+
+class MemoryCursor {
+public:
+    virtual ~MemoryCursor();
+
+    virtual void currentData(IDBGetResult&amp;) = 0;
+    virtual void iterate(const IDBKeyData&amp;, uint32_t count, IDBGetResult&amp;) = 0;
+
+    static MemoryCursor* cursorForIdentifier(const IDBResourceIdentifier&amp;);
+
+protected:
+    MemoryCursor(const IDBCursorInfo&amp;);
+
+    IDBCursorInfo m_info;
+};
+
+} // namespace IDBServer
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
+#endif // MemoryCursor_h
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryIDBBackingStorecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -28,10 +28,12 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(INDEXED_DATABASE)
</span><span class="cx"> 
</span><ins>+#include &quot;IDBCursorInfo.h&quot;
</ins><span class="cx"> #include &quot;IDBIndexInfo.h&quot;
</span><span class="cx"> #include &quot;IDBKeyRangeData.h&quot;
</span><span class="cx"> #include &quot;Logging.h&quot;
</span><span class="cx"> #include &quot;MemoryObjectStore.h&quot;
</span><ins>+#include &quot;MemoryObjectStoreCursor.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> namespace IDBServer {
</span><span class="lines">@@ -234,11 +236,11 @@
</span><span class="cx">     ASSERT(objectStoreIdentifier);
</span><span class="cx"> 
</span><span class="cx">     if (!m_transactions.contains(transactionIdentifier))
</span><del>-        return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral(&quot;No backing store transaction found to delete from&quot;));
</del><ins>+        return IDBError(IDBExceptionCode::Unknown, ASCIILiteral(&quot;No backing store transaction found to delete from&quot;));
</ins><span class="cx"> 
</span><span class="cx">     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
</span><span class="cx">     if (!objectStore)
</span><del>-        return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral(&quot;No backing store object store found&quot;));
</del><ins>+        return IDBError(IDBExceptionCode::Unknown, ASCIILiteral(&quot;No backing store object store found&quot;));
</ins><span class="cx"> 
</span><span class="cx">     objectStore-&gt;deleteRange(range);
</span><span class="cx">     return IDBError();
</span><span class="lines">@@ -252,11 +254,11 @@
</span><span class="cx"> 
</span><span class="cx">     auto transaction = m_transactions.get(transactionIdentifier);
</span><span class="cx">     if (!transaction)
</span><del>-        return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral(&quot;No backing store transaction found to put record&quot;));
</del><ins>+        return IDBError(IDBExceptionCode::Unknown, ASCIILiteral(&quot;No backing store transaction found to put record&quot;));
</ins><span class="cx"> 
</span><span class="cx">     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
</span><span class="cx">     if (!objectStore)
</span><del>-        return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral(&quot;No backing store object store found to put record&quot;));
</del><ins>+        return IDBError(IDBExceptionCode::Unknown, ASCIILiteral(&quot;No backing store object store found to put record&quot;));
</ins><span class="cx"> 
</span><span class="cx">     return objectStore-&gt;addRecord(*transaction, keyData, value);
</span><span class="cx"> }
</span><span class="lines">@@ -268,11 +270,11 @@
</span><span class="cx">     ASSERT(objectStoreIdentifier);
</span><span class="cx"> 
</span><span class="cx">     if (!m_transactions.contains(transactionIdentifier))
</span><del>-        return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral(&quot;No backing store transaction found to get record&quot;));
</del><ins>+        return IDBError(IDBExceptionCode::Unknown, ASCIILiteral(&quot;No backing store transaction found to get record&quot;));
</ins><span class="cx"> 
</span><span class="cx">     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
</span><span class="cx">     if (!objectStore)
</span><del>-        return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral(&quot;No backing store object store found&quot;));
</del><ins>+        return IDBError(IDBExceptionCode::Unknown, ASCIILiteral(&quot;No backing store object store found&quot;));
</ins><span class="cx"> 
</span><span class="cx">     outValue = objectStore-&gt;valueForKeyRange(range);
</span><span class="cx">     return IDBError();
</span><span class="lines">@@ -285,11 +287,11 @@
</span><span class="cx">     ASSERT(objectStoreIdentifier);
</span><span class="cx"> 
</span><span class="cx">     if (!m_transactions.contains(transactionIdentifier))
</span><del>-        return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral(&quot;No backing store transaction found to get record&quot;));
</del><ins>+        return IDBError(IDBExceptionCode::Unknown, ASCIILiteral(&quot;No backing store transaction found to get record&quot;));
</ins><span class="cx"> 
</span><span class="cx">     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
</span><span class="cx">     if (!objectStore)
</span><del>-        return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral(&quot;No backing store object store found&quot;));
</del><ins>+        return IDBError(IDBExceptionCode::Unknown, ASCIILiteral(&quot;No backing store object store found&quot;));
</ins><span class="cx"> 
</span><span class="cx">     outValue = objectStore-&gt;indexValueForKeyRange(indexIdentifier, recordType, range);
</span><span class="cx">     return IDBError();
</span><span class="lines">@@ -302,11 +304,11 @@
</span><span class="cx">     ASSERT(objectStoreIdentifier);
</span><span class="cx"> 
</span><span class="cx">     if (!m_transactions.contains(transactionIdentifier))
</span><del>-        return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral(&quot;No backing store transaction found to get count&quot;));
</del><ins>+        return IDBError(IDBExceptionCode::Unknown, ASCIILiteral(&quot;No backing store transaction found to get count&quot;));
</ins><span class="cx"> 
</span><span class="cx">     MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
</span><span class="cx">     if (!objectStore)
</span><del>-        return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral(&quot;No backing store object store found&quot;));
</del><ins>+        return IDBError(IDBExceptionCode::Unknown, ASCIILiteral(&quot;No backing store object store found&quot;));
</ins><span class="cx"> 
</span><span class="cx">     outCount = objectStore-&gt;countForKeyRange(indexIdentifier, range);
</span><span class="cx"> 
</span><span class="lines">@@ -329,22 +331,49 @@
</span><span class="cx">     return IDBError();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-IDBError MemoryIDBBackingStore::openCursor(const IDBResourceIdentifier&amp;, const IDBCursorInfo&amp;, IDBGetResult&amp;)
</del><ins>+IDBError MemoryIDBBackingStore::openCursor(const IDBResourceIdentifier&amp; transactionIdentifier, const IDBCursorInfo&amp; info, IDBGetResult&amp; outData)
</ins><span class="cx"> {
</span><span class="cx">     LOG(IndexedDB, &quot;MemoryIDBBackingStore::openCursor&quot;);
</span><span class="cx"> 
</span><del>-    // FIXME: Implement.
</del><ins>+    ASSERT(!MemoryCursor::cursorForIdentifier(info.identifier()));
</ins><span class="cx"> 
</span><del>-    return { IDBExceptionCode::Unknown };
</del><ins>+    if (!m_transactions.contains(transactionIdentifier))
+        return IDBError(IDBExceptionCode::Unknown, ASCIILiteral(&quot;No backing store transaction found in which to open a cursor&quot;));
+
+    switch (info.cursorSource()) {
+    case IndexedDB::CursorSource::ObjectStore: {
+        auto* objectStore = m_objectStoresByIdentifier.get(info.sourceIdentifier());
+        if (!objectStore)
+            return IDBError(IDBExceptionCode::Unknown, ASCIILiteral(&quot;No backing store object store found&quot;));
+
+        MemoryCursor* cursor = objectStore-&gt;maybeOpenCursor(info);
+        if (!cursor)
+            return IDBError(IDBExceptionCode::Unknown, ASCIILiteral(&quot;Could not create object store cursor in backing store&quot;));
+
+        cursor-&gt;currentData(outData);
+        break;
+    }
+    case IndexedDB::CursorSource::Index:
+        return IDBError(IDBExceptionCode::Unknown, ASCIILiteral(&quot;Index cursors not yet supported&quot;));
+    }
+
+    return { };
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-IDBError MemoryIDBBackingStore::iterateCursor(const IDBResourceIdentifier&amp;, const IDBKeyData&amp;, unsigned long, IDBGetResult&amp;)
</del><ins>+IDBError MemoryIDBBackingStore::iterateCursor(const IDBResourceIdentifier&amp; transactionIdentifier, const IDBResourceIdentifier&amp; cursorIdentifier, const IDBKeyData&amp; key, uint32_t count, IDBGetResult&amp; outData)
</ins><span class="cx"> {
</span><span class="cx">     LOG(IndexedDB, &quot;MemoryIDBBackingStore::iterateCursor&quot;);
</span><span class="cx"> 
</span><del>-    // FIXME: Implement.
</del><ins>+    if (!m_transactions.contains(transactionIdentifier))
+        return IDBError(IDBExceptionCode::Unknown, ASCIILiteral(&quot;No backing store transaction found in which to iterate cursor&quot;));
</ins><span class="cx"> 
</span><del>-    return { IDBExceptionCode::Unknown };
</del><ins>+    auto* cursor = MemoryCursor::cursorForIdentifier(cursorIdentifier);
+    if (!cursor)
+        return IDBError(IDBExceptionCode::Unknown, ASCIILiteral(&quot;No backing store cursor found in which to iterate cursor&quot;));
+
+    cursor-&gt;iterate(key, count, outData);
+
+    return { };
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MemoryIDBBackingStore::registerObjectStore(std::unique_ptr&lt;MemoryObjectStore&gt;&amp;&amp; objectStore)
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryIDBBackingStoreh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.h (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.h        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.h        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -64,7 +64,7 @@
</span><span class="cx">     virtual IDBError getCount(const IDBResourceIdentifier&amp; transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData&amp;, uint64_t&amp; outCount) override final;
</span><span class="cx">     virtual IDBError generateKeyNumber(const IDBResourceIdentifier&amp; transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t&amp; keyNumber) override final;
</span><span class="cx">     virtual IDBError openCursor(const IDBResourceIdentifier&amp; transactionIdentifier, const IDBCursorInfo&amp;, IDBGetResult&amp; outResult) override final;
</span><del>-    virtual IDBError iterateCursor(const IDBResourceIdentifier&amp; transactionIdentifier, const IDBKeyData&amp;, unsigned long count, IDBGetResult&amp; outResult) override final;
</del><ins>+    virtual IDBError iterateCursor(const IDBResourceIdentifier&amp; transactionIdentifier, const IDBResourceIdentifier&amp; cursorIdentifier, const IDBKeyData&amp;, uint32_t count, IDBGetResult&amp; outResult) override final;
</ins><span class="cx"> 
</span><span class="cx">     void removeObjectStoreForVersionChangeAbort(MemoryObjectStore&amp;);
</span><span class="cx">     void restoreObjectStoreForVersionChangeAbort(std::unique_ptr&lt;MemoryObjectStore&gt;&amp;&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryObjectStorecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.cpp (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.cpp        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.cpp        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -105,17 +105,21 @@
</span><span class="cx">     LOG(IndexedDB, &quot;MemoryObjectStore::clear&quot;);
</span><span class="cx">     ASSERT(m_writeTransaction);
</span><span class="cx"> 
</span><del>-    m_writeTransaction-&gt;objectStoreCleared(*this, WTF::move(m_keyValueStore));
</del><ins>+    m_writeTransaction-&gt;objectStoreCleared(*this, WTF::move(m_keyValueStore), WTF::move(m_orderedKeys));
</ins><span class="cx">     for (auto&amp; index : m_indexesByIdentifier.values())
</span><span class="cx">         index-&gt;objectStoreCleared();
</span><ins>+
+    for (auto&amp; cursor : m_cursors.values())
+        cursor-&gt;objectStoreCleared();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MemoryObjectStore::replaceKeyValueStore(std::unique_ptr&lt;KeyValueMap&gt;&amp;&amp; store)
</del><ins>+void MemoryObjectStore::replaceKeyValueStore(std::unique_ptr&lt;KeyValueMap&gt;&amp;&amp; store, std::unique_ptr&lt;std::set&lt;IDBKeyData&gt;&gt;&amp;&amp; orderedKeys)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_writeTransaction);
</span><span class="cx">     ASSERT(m_writeTransaction-&gt;isAborting());
</span><span class="cx"> 
</span><span class="cx">     m_keyValueStore = WTF::move(store);
</span><ins>+    m_orderedKeys = WTF::move(orderedKeys);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MemoryObjectStore::deleteRecord(const IDBKeyData&amp; key)
</span><span class="lines">@@ -142,6 +146,7 @@
</span><span class="cx">     m_orderedKeys-&gt;erase(key);
</span><span class="cx"> 
</span><span class="cx">     updateIndexesForDeleteRecord(key);
</span><ins>+    updateCursorsForDeleteRecord(key);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MemoryObjectStore::deleteRange(const IDBKeyRangeData&amp; inputRange)
</span><span class="lines">@@ -193,7 +198,8 @@
</span><span class="cx">     if (!error.isNull()) {
</span><span class="cx">         m_keyValueStore-&gt;remove(mapResult.iterator);
</span><span class="cx">         m_orderedKeys-&gt;erase(listResult.first);
</span><del>-    }
</del><ins>+    } else
+        updateCursorsForPutRecord(listResult.first);
</ins><span class="cx"> 
</span><span class="cx">     return error;
</span><span class="cx"> }
</span><span class="lines">@@ -219,6 +225,18 @@
</span><span class="cx">     return *globalObject.get()-&gt;globalExec();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MemoryObjectStore::updateCursorsForPutRecord(std::set&lt;IDBKeyData&gt;::iterator iterator)
+{
+    for (auto&amp; cursor : m_cursors.values())
+        cursor-&gt;keyAdded(iterator);
+}
+
+void MemoryObjectStore::updateCursorsForDeleteRecord(const IDBKeyData&amp; key)
+{
+    for (auto&amp; cursor : m_cursors.values())
+        cursor-&gt;keyDeleted(key);
+}
+
</ins><span class="cx"> void MemoryObjectStore::updateIndexesForDeleteRecord(const IDBKeyData&amp; value)
</span><span class="cx"> {
</span><span class="cx">     for (auto* index : m_indexesByName.values())
</span><span class="lines">@@ -358,6 +376,16 @@
</span><span class="cx">     m_indexesByIdentifier.remove(index.info().identifier());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+MemoryObjectStoreCursor* MemoryObjectStore::maybeOpenCursor(const IDBCursorInfo&amp; info)
+{
+    auto result = m_cursors.add(info.identifier(), nullptr);
+    if (!result.isNewEntry)
+        return nullptr;
+
+    result.iterator-&gt;value = MemoryObjectStoreCursor::create(*this, info);
+    return result.iterator-&gt;value.get();
+}
+
</ins><span class="cx"> } // namespace IDBServer
</span><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryObjectStoreh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.h (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.h        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.h        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -31,12 +31,14 @@
</span><span class="cx"> #include &quot;IDBKeyData.h&quot;
</span><span class="cx"> #include &quot;IDBObjectStoreInfo.h&quot;
</span><span class="cx"> #include &quot;MemoryIndex.h&quot;
</span><ins>+#include &quot;MemoryObjectStoreCursor.h&quot;
</ins><span class="cx"> #include &quot;ThreadSafeDataBuffer.h&quot;
</span><span class="cx"> #include &lt;set&gt;
</span><span class="cx"> #include &lt;wtf/HashMap.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+class IDBCursorInfo;
</ins><span class="cx"> class IDBError;
</span><span class="cx"> class IDBKeyData;
</span><span class="cx"> 
</span><span class="lines">@@ -74,7 +76,7 @@
</span><span class="cx">     void setKeyGeneratorValue(uint64_t value) { m_keyGeneratorValue = value; }
</span><span class="cx"> 
</span><span class="cx">     void clear();
</span><del>-    void replaceKeyValueStore(std::unique_ptr&lt;KeyValueMap&gt;&amp;&amp;);
</del><ins>+    void replaceKeyValueStore(std::unique_ptr&lt;KeyValueMap&gt;&amp;&amp;, std::unique_ptr&lt;std::set&lt;IDBKeyData&gt;&gt;&amp;&amp;);
</ins><span class="cx"> 
</span><span class="cx">     ThreadSafeDataBuffer valueForKeyRange(const IDBKeyRangeData&amp;) const;
</span><span class="cx">     IDBGetResult indexValueForKeyRange(uint64_t indexIdentifier, IndexedDB::IndexRecordType, const IDBKeyRangeData&amp;) const;
</span><span class="lines">@@ -82,13 +84,20 @@
</span><span class="cx"> 
</span><span class="cx">     const IDBObjectStoreInfo&amp; info() const { return m_info; }
</span><span class="cx"> 
</span><ins>+    MemoryObjectStoreCursor* maybeOpenCursor(const IDBCursorInfo&amp;);
+
+    std::set&lt;IDBKeyData&gt;* orderedKeys() { return m_orderedKeys.get(); }
+
</ins><span class="cx"> private:
</span><span class="cx">     MemoryObjectStore(const IDBObjectStoreInfo&amp;);
</span><span class="cx"> 
</span><span class="cx">     IDBKeyData lowestKeyWithRecordInRange(const IDBKeyRangeData&amp;) const;
</span><ins>+    std::set&lt;IDBKeyData&gt;::iterator lowestIteratorInRange(const IDBKeyRangeData&amp;, bool reverse) const;
</ins><span class="cx"> 
</span><span class="cx">     IDBError updateIndexesForPutRecord(const IDBKeyData&amp;, const ThreadSafeDataBuffer&amp; value);
</span><span class="cx">     void updateIndexesForDeleteRecord(const IDBKeyData&amp; value);
</span><ins>+    void updateCursorsForPutRecord(std::set&lt;IDBKeyData&gt;::iterator);
+    void updateCursorsForDeleteRecord(const IDBKeyData&amp;);
</ins><span class="cx"> 
</span><span class="cx">     IDBObjectStoreInfo m_info;
</span><span class="cx"> 
</span><span class="lines">@@ -102,6 +111,7 @@
</span><span class="cx">     void unregisterIndex(MemoryIndex&amp;);
</span><span class="cx">     HashMap&lt;uint64_t, std::unique_ptr&lt;MemoryIndex&gt;&gt; m_indexesByIdentifier;
</span><span class="cx">     HashMap&lt;String, MemoryIndex*&gt; m_indexesByName;
</span><ins>+    HashMap&lt;IDBResourceIdentifier, std::unique_ptr&lt;MemoryObjectStoreCursor&gt;&gt; m_cursors;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace IDBServer
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryObjectStoreCursorcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStoreCursor.cpp (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStoreCursor.cpp                                (rev 0)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStoreCursor.cpp        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,376 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;MemoryObjectStoreCursor.h&quot;
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include &quot;Logging.h&quot;
+#include &quot;MemoryObjectStore.h&quot;
+
+namespace WebCore {
+namespace IDBServer {
+
+std::unique_ptr&lt;MemoryObjectStoreCursor&gt; MemoryObjectStoreCursor::create(MemoryObjectStore&amp; objectStore, const IDBCursorInfo&amp; info)
+{
+    return std::make_unique&lt;MemoryObjectStoreCursor&gt;(objectStore, info);
+}
+
+MemoryObjectStoreCursor::MemoryObjectStoreCursor(MemoryObjectStore&amp; objectStore, const IDBCursorInfo&amp; info)
+    : MemoryCursor(info)
+    , m_objectStore(objectStore)
+{
+    m_remainingRange = m_info.range();
+
+    auto* orderedKeys = objectStore.orderedKeys();
+    if (!orderedKeys)
+        return;
+
+    setFirstInRemainingRange(*orderedKeys);
+}
+
+void MemoryObjectStoreCursor::objectStoreCleared()
+{
+    clearIterators();
+}
+
+void MemoryObjectStoreCursor::keyDeleted(const IDBKeyData&amp; key)
+{
+    if (m_currentPositionKey != key)
+        return;
+
+    clearIterators();
+}
+
+void MemoryObjectStoreCursor::keyAdded(std::set&lt;IDBKeyData&gt;::iterator iterator)
+{
+    ASSERT(m_currentPositionKey.isValid());
+
+    if (hasIterators())
+        return;
+
+    if (*iterator != m_currentPositionKey)
+        return;
+
+    if (m_info.isDirectionForward())
+        m_forwardIterator = iterator;
+    else
+        m_reverseIterator = --std::set&lt;IDBKeyData&gt;::reverse_iterator(iterator);
+}
+
+void MemoryObjectStoreCursor::setFirstInRemainingRange(std::set&lt;IDBKeyData&gt;&amp; set)
+{
+    clearIterators();
+
+    if (m_info.isDirectionForward()) {
+        m_forwardIterator = firstForwardIteratorInRemainingRange(set);
+        if (*m_forwardIterator != set.end()) {
+            m_remainingRange.lowerKey = **m_forwardIterator;
+            m_remainingRange.lowerOpen = true;
+        }
+    } else {
+        m_reverseIterator = firstReverseIteratorInRemainingRange(set);
+        if (*m_reverseIterator != set.rend()) {
+            m_remainingRange.upperKey = **m_reverseIterator;
+            m_remainingRange.upperOpen = true;
+        }
+    }
+}
+
+std::set&lt;IDBKeyData&gt;::iterator MemoryObjectStoreCursor::firstForwardIteratorInRemainingRange(std::set&lt;IDBKeyData&gt;&amp; set)
+{
+    if (m_remainingRange.isExactlyOneKey())
+        return set.find(m_remainingRange.lowerKey);
+
+    auto lowest = set.lower_bound(m_remainingRange.lowerKey);
+    if (lowest == set.end())
+        return lowest;
+
+    if (m_remainingRange.lowerOpen &amp;&amp; *lowest == m_remainingRange.lowerKey) {
+        ++lowest;
+        if (lowest == set.end())
+            return lowest;
+    }
+
+    if (!m_remainingRange.upperKey.isNull()) {
+        if (lowest-&gt;compare(m_remainingRange.upperKey) &gt; 0)
+            return set.end();
+
+        if (m_remainingRange.upperOpen &amp;&amp; *lowest == m_remainingRange.upperKey)
+            return set.end();
+    }
+
+    return lowest;
+}
+
+std::set&lt;IDBKeyData&gt;::reverse_iterator MemoryObjectStoreCursor::firstReverseIteratorInRemainingRange(std::set&lt;IDBKeyData&gt;&amp; set)
+{
+    if (m_remainingRange.isExactlyOneKey()) {
+        auto iterator = set.find(m_remainingRange.lowerKey);
+        if (iterator == set.end())
+            return set.rend();
+
+        return --std::set&lt;IDBKeyData&gt;::reverse_iterator(iterator);
+    }
+
+    if (!m_remainingRange.upperKey.isValid())
+        return set.rbegin();
+
+    // This is one record past the actual key we're looking for.
+    auto highest = set.upper_bound(m_remainingRange.upperKey);
+
+    // This is one record before that, which *is* the key we're looking for.
+    auto reverse = std::set&lt;IDBKeyData&gt;::reverse_iterator(highest);
+    if (reverse == set.rend())
+        return reverse;
+
+    if (m_remainingRange.upperOpen &amp;&amp; *reverse == m_remainingRange.upperKey) {
+        ++reverse;
+        if (reverse == set.rend())
+            return reverse;
+    }
+
+    if (!m_remainingRange.lowerKey.isNull()) {
+        if (reverse-&gt;compare(m_remainingRange.lowerKey) &lt; 0)
+            return set.rend();
+
+        if (m_remainingRange.lowerOpen &amp;&amp; *reverse == m_remainingRange.lowerKey)
+            return set.rend();
+    }
+
+    return reverse;
+}
+
+void MemoryObjectStoreCursor::currentData(IDBGetResult&amp; data)
+{
+    if (!hasIterators()) {
+        m_currentPositionKey = { };
+        data = { };
+        return;
+    }
+
+    auto* set = m_objectStore.orderedKeys();
+    ASSERT(set);
+    if (m_info.isDirectionForward()) {
+        if (!m_forwardIterator || *m_forwardIterator == set-&gt;end()) {
+            data = { };
+            return;
+        }
+
+        m_currentPositionKey = **m_forwardIterator;
+        data.keyData = **m_forwardIterator;
+        data.primaryKeyData = **m_forwardIterator;
+        data.valueBuffer = m_objectStore.valueForKeyRange(**m_forwardIterator);
+    } else {
+        if (!m_reverseIterator || *m_reverseIterator == set-&gt;rend()) {
+            data = { };
+            return;
+        }
+
+        m_currentPositionKey = **m_reverseIterator;
+        data.keyData = **m_reverseIterator;
+        data.primaryKeyData = **m_reverseIterator;
+        data.valueBuffer = m_objectStore.valueForKeyRange(**m_reverseIterator);
+    }
+}
+
+void MemoryObjectStoreCursor::incrementForwardIterator(std::set&lt;IDBKeyData&gt;&amp; set, const IDBKeyData&amp; key, uint32_t count)
+{
+    // We might need to re-grab the current iterator.
+    // e.g. If the record it was pointed to had been deleted.
+    bool didResetIterator = false;
+    if (!hasIterators()) {
+        if (!m_currentPositionKey.isValid())
+            return;
+
+        m_remainingRange.lowerKey = m_currentPositionKey;
+        m_remainingRange.lowerOpen = false;
+        setFirstInRemainingRange(set);
+
+        didResetIterator = true;
+    }
+
+    if (*m_forwardIterator == set.end())
+        return;
+
+    if (key.isValid()) {
+        // If iterating to a key, the count passed in must be zero, as there is no way to iterate by both a count and to a key.
+        ASSERT(!count);
+
+        if (!m_info.range().containsKey(key))
+            return;
+
+        if ((*m_forwardIterator)-&gt;compare(key) &lt; 0) {
+            m_remainingRange.lowerKey = key;
+            m_remainingRange.lowerOpen = false;
+            setFirstInRemainingRange(set);
+        }
+
+        return;
+    }
+
+    if (!count)
+        count = 1;
+
+    // If the forwardIterator was reset because it's previous record had been deleted,
+    // we might have already advanced past the current position, eating one one of the iteration counts.
+    if (didResetIterator &amp;&amp; (*m_forwardIterator)-&gt;compare(m_currentPositionKey) &gt; 0)
+        --count;
+
+    while (count) {
+        --count;
+
+        ++*m_forwardIterator;
+
+        if (*m_forwardIterator == set.end())
+            return;
+
+        if (!m_info.range().containsKey(**m_forwardIterator))
+            return;
+    }
+}
+
+void MemoryObjectStoreCursor::incrementReverseIterator(std::set&lt;IDBKeyData&gt;&amp; set, const IDBKeyData&amp; key, uint32_t count)
+{
+    // We might need to re-grab the current iterator.
+    // e.g. If the record it was pointed to had been deleted.
+    bool didResetIterator = false;
+    if (!hasIterators()) {
+        if (!m_currentPositionKey.isValid())
+            return;
+
+        m_remainingRange.upperKey = m_currentPositionKey;
+        m_remainingRange.upperOpen = false;
+        setFirstInRemainingRange(set);
+
+        didResetIterator = true;
+    }
+
+    if (*m_reverseIterator == set.rend())
+        return;
+
+    if (key.isValid()) {
+        // If iterating to a key, the count passed in must be zero, as there is no way to iterate by both a count and to a key.
+        ASSERT(!count);
+
+        if (!m_info.range().containsKey(key))
+            return;
+
+        if ((*m_reverseIterator)-&gt;compare(key) &gt; 0) {
+            m_remainingRange.upperKey = key;
+            m_remainingRange.upperOpen = false;
+
+            setFirstInRemainingRange(set);
+        }
+
+        return;
+    }
+
+    if (!count)
+        count = 1;
+
+    // If the reverseIterator was reset because it's previous record had been deleted,
+    // we might have already advanced past the current position, eating one one of the iteration counts.
+    if (didResetIterator &amp;&amp; (*m_reverseIterator)-&gt;compare(m_currentPositionKey) &lt; 0)
+        --count;
+
+    while (count) {
+        --count;
+
+        ++*m_reverseIterator;
+
+        if (*m_reverseIterator == set.rend())
+            return;
+
+        if (!m_info.range().containsKey(**m_reverseIterator))
+            return;
+    }
+}
+
+bool MemoryObjectStoreCursor::hasIterators() const
+{
+    return m_forwardIterator || m_reverseIterator;
+}
+
+bool MemoryObjectStoreCursor::hasValidPosition() const
+{
+    if (!hasIterators())
+        return false;
+
+    auto* set = m_objectStore.orderedKeys();
+    if (!set)
+        return false;
+
+    if (m_info.isDirectionForward())
+        return *m_forwardIterator != set-&gt;end();
+
+    return *m_reverseIterator != set-&gt;rend();
+}
+
+void MemoryObjectStoreCursor::clearIterators()
+{
+    m_forwardIterator = Nullopt;
+    m_reverseIterator = Nullopt;
+}
+
+void MemoryObjectStoreCursor::iterate(const IDBKeyData&amp; key, uint32_t count, IDBGetResult&amp; outData)
+{
+    LOG(IndexedDB, &quot;MemoryObjectStoreCursor::iterate to key %s&quot;, key.loggingString().utf8().data());
+
+    if (!m_objectStore.orderedKeys()) {
+        m_currentPositionKey = { };
+        outData = { };
+        return;
+    }
+
+    if (key.isValid() &amp;&amp; !m_info.range().containsKey(key)) {
+        m_currentPositionKey = { };
+        outData = { };
+        return;
+    }
+
+    auto* set = m_objectStore.orderedKeys();
+    if (set) {
+        if (m_info.isDirectionForward())
+            incrementForwardIterator(*set, key, count);
+        else
+            incrementReverseIterator(*set, key, count);
+    }
+
+    m_currentPositionKey = { };
+
+    if (!hasValidPosition()) {
+        outData = { };
+        return;
+    }
+
+    currentData(outData);
+}
+
+} // namespace IDBServer
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryObjectStoreCursorh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStoreCursor.h (0 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStoreCursor.h                                (rev 0)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStoreCursor.h        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -0,0 +1,82 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MemoryObjectStoreCursor_h
+#define MemoryObjectStoreCursor_h
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include &quot;IDBCursorInfo.h&quot;
+#include &quot;IDBKeyData.h&quot;
+#include &quot;MemoryCursor.h&quot;
+#include &lt;set&gt;
+#include &lt;wtf/Optional.h&gt;
+
+namespace WebCore {
+namespace IDBServer {
+
+class MemoryObjectStore;
+
+class MemoryObjectStoreCursor : public MemoryCursor {
+    friend std::unique_ptr&lt;MemoryObjectStoreCursor&gt; std::make_unique&lt;MemoryObjectStoreCursor&gt;(WebCore::IDBServer::MemoryObjectStore&amp;, const WebCore::IDBCursorInfo&amp;);
+public:
+    static std::unique_ptr&lt;MemoryObjectStoreCursor&gt; create(MemoryObjectStore&amp;, const IDBCursorInfo&amp;);
+
+    void objectStoreCleared();
+    void keyDeleted(const IDBKeyData&amp;);
+    void keyAdded(std::set&lt;IDBKeyData&gt;::iterator);
+
+private:
+    MemoryObjectStoreCursor(MemoryObjectStore&amp;, const IDBCursorInfo&amp;);
+
+    virtual void currentData(IDBGetResult&amp;) override final;
+    virtual void iterate(const IDBKeyData&amp;, uint32_t count, IDBGetResult&amp;) override final;
+
+    void setFirstInRemainingRange(std::set&lt;IDBKeyData&gt;&amp;);
+    std::set&lt;IDBKeyData&gt;::iterator firstForwardIteratorInRemainingRange(std::set&lt;IDBKeyData&gt;&amp;);
+    std::set&lt;IDBKeyData&gt;::reverse_iterator firstReverseIteratorInRemainingRange(std::set&lt;IDBKeyData&gt;&amp;);
+
+    void incrementForwardIterator(std::set&lt;IDBKeyData&gt;&amp;, const IDBKeyData&amp;, uint32_t count);
+    void incrementReverseIterator(std::set&lt;IDBKeyData&gt;&amp;, const IDBKeyData&amp;, uint32_t count);
+
+    bool hasIterators() const;
+    bool hasValidPosition() const;
+    void clearIterators();
+
+    MemoryObjectStore&amp; m_objectStore;
+
+    IDBKeyRangeData m_remainingRange;
+
+    WTF::Optional&lt;std::set&lt;IDBKeyData&gt;::iterator&gt; m_forwardIterator;
+    WTF::Optional&lt;std::set&lt;IDBKeyData&gt;::reverse_iterator&gt; m_reverseIterator;
+
+    IDBKeyData m_currentPositionKey;
+};
+
+} // namespace IDBServer
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
+#endif // MemoryObjectStoreCursor_h
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverUniqueIDBDatabasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -587,16 +587,16 @@
</span><span class="cx">     LOG(IndexedDB, &quot;(main) UniqueIDBDatabase::iterateCursor&quot;);
</span><span class="cx"> 
</span><span class="cx">     uint64_t callbackID = storeCallback(callback);
</span><del>-    m_server.postDatabaseTask(createCrossThreadTask(*this, &amp;UniqueIDBDatabase::performIterateCursor, callbackID, requestData.transactionIdentifier(), key, count));
</del><ins>+    m_server.postDatabaseTask(createCrossThreadTask(*this, &amp;UniqueIDBDatabase::performIterateCursor, callbackID, requestData.transactionIdentifier(), requestData.cursorIdentifier(), key, count));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void UniqueIDBDatabase::performIterateCursor(uint64_t callbackIdentifier, const IDBResourceIdentifier&amp; transactionIdentifier, const IDBKeyData&amp; key, unsigned long count)
</del><ins>+void UniqueIDBDatabase::performIterateCursor(uint64_t callbackIdentifier, const IDBResourceIdentifier&amp; transactionIdentifier, const IDBResourceIdentifier&amp; cursorIdentifier, const IDBKeyData&amp; key, unsigned long count)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!isMainThread());
</span><span class="cx">     LOG(IndexedDB, &quot;(db) UniqueIDBDatabase::performIterateCursor&quot;);
</span><span class="cx"> 
</span><span class="cx">     IDBGetResult result;
</span><del>-    IDBError error = m_backingStore-&gt;iterateCursor(transactionIdentifier, key, count, result);
</del><ins>+    IDBError error = m_backingStore-&gt;iterateCursor(transactionIdentifier, cursorIdentifier, key, count, result);
</ins><span class="cx"> 
</span><span class="cx">     m_server.postDatabaseTaskReply(createCrossThreadTask(*this, &amp;UniqueIDBDatabase::didPerformIterateCursor, callbackIdentifier, error, result));
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverUniqueIDBDatabaseh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -120,7 +120,7 @@
</span><span class="cx">     void performGetCount(uint64_t callbackIdentifier, const IDBResourceIdentifier&amp; transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const IDBKeyRangeData&amp;);
</span><span class="cx">     void performDeleteRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier&amp; transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&amp;);
</span><span class="cx">     void performOpenCursor(uint64_t callbackIdentifier, const IDBResourceIdentifier&amp; transactionIdentifier, const IDBCursorInfo&amp;);
</span><del>-    void performIterateCursor(uint64_t callbackIdentifier, const IDBResourceIdentifier&amp; transactionIdentifier, const IDBKeyData&amp;, unsigned long count);
</del><ins>+    void performIterateCursor(uint64_t callbackIdentifier, const IDBResourceIdentifier&amp; transactionIdentifier, const IDBResourceIdentifier&amp; cursorIdentifier, const IDBKeyData&amp;, unsigned long count);
</ins><span class="cx">     void performActivateTransactionInBackingStore(uint64_t callbackIdentifier, const IDBTransactionInfo&amp;);
</span><span class="cx"> 
</span><span class="cx">     // Main thread callbacks
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbsharedIDBCursorInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/shared/IDBCursorInfo.h (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/shared/IDBCursorInfo.h        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/shared/IDBCursorInfo.h        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -56,6 +56,7 @@
</span><span class="cx">     IndexedDB::CursorSource cursorSource() const { return m_source; }
</span><span class="cx">     IndexedDB::CursorDirection cursorDirection() const { return m_direction; }
</span><span class="cx">     IndexedDB::CursorType cursorType() const { return m_type; }
</span><ins>+    const IDBKeyRangeData&amp; range() const { return m_range; }
</ins><span class="cx"> 
</span><span class="cx">     bool isDirectionForward() const;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbsharedIDBRequestDatacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/shared/IDBRequestData.cpp (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/shared/IDBRequestData.cpp        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/shared/IDBRequestData.cpp        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -50,6 +50,9 @@
</span><span class="cx"> {
</span><span class="cx">     if (m_indexIdentifier)
</span><span class="cx">         m_indexRecordType = operation.indexRecordType();
</span><ins>+
+    if (operation.cursorIdentifier())
+        m_cursorIdentifier = std::make_unique&lt;IDBResourceIdentifier&gt;(*operation.cursorIdentifier());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> IDBRequestData::IDBRequestData(const IDBRequestData&amp; other)
</span><span class="lines">@@ -64,6 +67,8 @@
</span><span class="cx">         m_requestIdentifier = std::make_unique&lt;IDBResourceIdentifier&gt;(*other.m_requestIdentifier);
</span><span class="cx">     if (other.m_transactionIdentifier)
</span><span class="cx">         m_transactionIdentifier = std::make_unique&lt;IDBResourceIdentifier&gt;(*other.m_transactionIdentifier);
</span><ins>+    if (other.m_cursorIdentifier)
+        m_cursorIdentifier = std::make_unique&lt;IDBResourceIdentifier&gt;(*other.m_cursorIdentifier);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> uint64_t IDBRequestData::serverConnectionIdentifier() const
</span><span class="lines">@@ -74,16 +79,22 @@
</span><span class="cx"> 
</span><span class="cx"> IDBResourceIdentifier IDBRequestData::requestIdentifier() const
</span><span class="cx"> {
</span><del>-    RELEASE_ASSERT(m_requestIdentifier);
</del><ins>+    ASSERT(m_requestIdentifier);
</ins><span class="cx">     return *m_requestIdentifier;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> IDBResourceIdentifier IDBRequestData::transactionIdentifier() const
</span><span class="cx"> {
</span><del>-    RELEASE_ASSERT(m_transactionIdentifier);
</del><ins>+    ASSERT(m_transactionIdentifier);
</ins><span class="cx">     return *m_transactionIdentifier;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+IDBResourceIdentifier IDBRequestData::cursorIdentifier() const
+{
+    ASSERT(m_cursorIdentifier);
+    return *m_cursorIdentifier;
+}
+
</ins><span class="cx"> uint64_t IDBRequestData::objectStoreIdentifier() const
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_objectStoreIdentifier);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbsharedIDBRequestDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/shared/IDBRequestData.h (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/shared/IDBRequestData.h        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/Modules/indexeddb/shared/IDBRequestData.h        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -56,6 +56,7 @@
</span><span class="cx">     uint64_t objectStoreIdentifier() const;
</span><span class="cx">     uint64_t indexIdentifier() const;
</span><span class="cx">     IndexedDB::IndexRecordType indexRecordType() const;
</span><ins>+    IDBResourceIdentifier cursorIdentifier() const;
</ins><span class="cx"> 
</span><span class="cx">     const IDBDatabaseIdentifier&amp; databaseIdentifier() const { return m_databaseIdentifier; }
</span><span class="cx">     uint64_t requestedVersion() const;
</span><span class="lines">@@ -66,6 +67,7 @@
</span><span class="cx">     uint64_t m_serverConnectionIdentifier { 0 };
</span><span class="cx">     std::unique_ptr&lt;IDBResourceIdentifier&gt; m_requestIdentifier;
</span><span class="cx">     std::unique_ptr&lt;IDBResourceIdentifier&gt; m_transactionIdentifier;
</span><ins>+    std::unique_ptr&lt;IDBResourceIdentifier&gt; m_cursorIdentifier;
</ins><span class="cx">     uint64_t m_objectStoreIdentifier { 0 };
</span><span class="cx">     uint64_t m_indexIdentifier { 0 };
</span><span class="cx">     IndexedDB::IndexRecordType m_indexRecordType;
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (192489 => 192490)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2015-11-16 23:13:39 UTC (rev 192489)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2015-11-16 23:17:46 UTC (rev 192490)
</span><span class="lines">@@ -2042,6 +2042,10 @@
</span><span class="cx">                 517138F81BF128BB000D5F01 /* IndexValueStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 517138F61BF12262000D5F01 /* IndexValueStore.h */; };
</span><span class="cx">                 517138FB1BF3ADF4000D5F01 /* IDBCursorInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 517138F91BF3ADAC000D5F01 /* IDBCursorInfo.cpp */; };
</span><span class="cx">                 517138FC1BF3ADF4000D5F01 /* IDBCursorInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 517138FA1BF3ADAC000D5F01 /* IDBCursorInfo.h */; };
</span><ins>+                517139051BF64DEC000D5F01 /* MemoryObjectStoreCursor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 517139031BF64DE3000D5F01 /* MemoryObjectStoreCursor.cpp */; };
+                517139061BF64DEC000D5F01 /* MemoryObjectStoreCursor.h in Headers */ = {isa = PBXBuildFile; fileRef = 517139041BF64DE3000D5F01 /* MemoryObjectStoreCursor.h */; };
+                517139071BF64DEF000D5F01 /* MemoryCursor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 517139011BF64DE3000D5F01 /* MemoryCursor.cpp */; };
+                517139081BF64DEF000D5F01 /* MemoryCursor.h in Headers */ = {isa = PBXBuildFile; fileRef = 517139021BF64DE3000D5F01 /* MemoryCursor.h */; };
</ins><span class="cx">                 51741D0F0B07259A00ED442C /* BackForwardClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 51741D0B0B07259A00ED442C /* BackForwardClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 51741D110B07259A00ED442C /* HistoryItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 51741D0D0B07259A00ED442C /* HistoryItem.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 51741D120B07259A00ED442C /* HistoryItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51741D0E0B07259A00ED442C /* HistoryItem.cpp */; };
</span><span class="lines">@@ -9502,6 +9506,10 @@
</span><span class="cx">                 517138F61BF12262000D5F01 /* IndexValueStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IndexValueStore.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 517138F91BF3ADAC000D5F01 /* IDBCursorInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBCursorInfo.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 517138FA1BF3ADAC000D5F01 /* IDBCursorInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBCursorInfo.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                517139011BF64DE3000D5F01 /* MemoryCursor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryCursor.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                517139021BF64DE3000D5F01 /* MemoryCursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryCursor.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                517139031BF64DE3000D5F01 /* MemoryObjectStoreCursor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryObjectStoreCursor.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                517139041BF64DE3000D5F01 /* MemoryObjectStoreCursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryObjectStoreCursor.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 51741D0B0B07259A00ED442C /* BackForwardClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BackForwardClient.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 51741D0D0B07259A00ED442C /* HistoryItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HistoryItem.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 51741D0E0B07259A00ED442C /* HistoryItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = HistoryItem.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -16940,12 +16948,16 @@
</span><span class="cx">                                 517138F61BF12262000D5F01 /* IndexValueStore.h */,
</span><span class="cx">                                 51E1BAC01BD806470055D81F /* MemoryBackingStoreTransaction.cpp */,
</span><span class="cx">                                 51E1BAC11BD806470055D81F /* MemoryBackingStoreTransaction.h */,
</span><ins>+                                517139011BF64DE3000D5F01 /* MemoryCursor.cpp */,
+                                517139021BF64DE3000D5F01 /* MemoryCursor.h */,
</ins><span class="cx">                                 51BA4AC81BBC5B9E00DF3D6D /* MemoryIDBBackingStore.cpp */,
</span><span class="cx">                                 51BA4AC91BBC5B9E00DF3D6D /* MemoryIDBBackingStore.h */,
</span><span class="cx">                                 518F97001BE94C5B0023187C /* MemoryIndex.cpp */,
</span><span class="cx">                                 518F97011BE94C5B0023187C /* MemoryIndex.h */,
</span><span class="cx">                                 51771DFC1BDB475600CAE8E4 /* MemoryObjectStore.cpp */,
</span><span class="cx">                                 51771DFD1BDB475600CAE8E4 /* MemoryObjectStore.h */,
</span><ins>+                                517139031BF64DE3000D5F01 /* MemoryObjectStoreCursor.cpp */,
+                                517139041BF64DE3000D5F01 /* MemoryObjectStoreCursor.h */,
</ins><span class="cx">                                 518864DE1BBAF30F00E540C9 /* UniqueIDBDatabase.cpp */,
</span><span class="cx">                                 518864DF1BBAF30F00E540C9 /* UniqueIDBDatabase.h */,
</span><span class="cx">                                 5198F7A21BBDAA2900E2CC5F /* UniqueIDBDatabaseConnection.cpp */,
</span><span class="lines">@@ -25085,6 +25097,7 @@
</span><span class="cx">                                 656D37360ADBA5DE00A4554D /* DocumentLoader.h in Headers */,
</span><span class="cx">                                 8A12E35D11FA33280025836A /* DocumentLoadTiming.h in Headers */,
</span><span class="cx">                                 ED2BA83C09A24B91006C0AC4 /* DocumentMarker.h in Headers */,
</span><ins>+                                517139061BF64DEC000D5F01 /* MemoryObjectStoreCursor.h in Headers */,
</ins><span class="cx">                                 CE057FA61220731100A476D5 /* DocumentMarkerController.h in Headers */,
</span><span class="cx">                                 14947FFE12F80CD200A0F631 /* DocumentOrderedMap.h in Headers */,
</span><span class="cx">                                 BCCFBAE80B5152ED0001F1D7 /* DocumentParser.h in Headers */,
</span><span class="lines">@@ -25873,6 +25886,7 @@
</span><span class="cx">                                 51D7236D1BB6174900478CA3 /* IDBResultData.h in Headers */,
</span><span class="cx">                                 5185FCBB1BB4CBF80012898F /* IDBServer.h in Headers */,
</span><span class="cx">                                 5185FCAB1BB4C4E80012898F /* IDBServerConnection.h in Headers */,
</span><ins>+                                517139081BF64DEF000D5F01 /* MemoryCursor.h in Headers */,
</ins><span class="cx">                                 518864E71BBB4B8300E540C9 /* IDBServerOperation.h in Headers */,
</span><span class="cx">                                 5185FCAD1BB4C4E80012898F /* IDBTransaction.h in Headers */,
</span><span class="cx">                                 51F41A741BA73B5B002E053B /* IDBTransactionBackend.h in Headers */,
</span><span class="lines">@@ -29718,6 +29732,7 @@
</span><span class="cx">                                 A9C6E64D0D7465E7006442E9 /* JSDOMPluginCustom.cpp in Sources */,
</span><span class="cx">                                 E172AF8F1811BC3700FBADB9 /* JSDOMPromise.cpp in Sources */,
</span><span class="cx">                                 BC5A86B50C3367E800EEA649 /* JSDOMSelection.cpp in Sources */,
</span><ins>+                                517139051BF64DEC000D5F01 /* MemoryObjectStoreCursor.cpp in Sources */,
</ins><span class="cx">                                 4ACBC0CA12713D0A0094F9B2 /* JSDOMSettableTokenList.cpp in Sources */,
</span><span class="cx">                                 C5137CF211A58378004ADB99 /* JSDOMStringList.cpp in Sources */,
</span><span class="cx">                                 9A1B6F97158869C80011A8C4 /* JSDOMStringListCustom.cpp in Sources */,
</span><span class="lines">@@ -31020,6 +31035,7 @@
</span><span class="cx">                                 9393E604151A9A1800066F06 /* StyleCachedImageSet.cpp in Sources */,
</span><span class="cx">                                 A8C4A7FE09D563270003AC8D /* StyledElement.cpp in Sources */,
</span><span class="cx">                                 BC5EB8B80E8201BD00B25965 /* StyleDeprecatedFlexibleBoxData.cpp in Sources */,
</span><ins>+                                517139071BF64DEF000D5F01 /* MemoryCursor.cpp in Sources */,
</ins><span class="cx">                                 319AE063142D6B24006563A1 /* StyleFilterData.cpp in Sources */,
</span><span class="cx">                                 5317612213C516690026E454 /* StyleFlexibleBoxData.cpp in Sources */,
</span><span class="cx">                                 E4D58EB817B4ED8900CBDCA8 /* StyleFontSizeFunctions.cpp in Sources */,
</span></span></pre>
</div>
</div>

</body>
</html>