<!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>[208500] 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/208500">208500</a></dd>
<dt>Author</dt> <dd>beidson@apple.com</dd>
<dt>Date</dt> <dd>2016-11-09 15:29:38 -0800 (Wed, 09 Nov 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>IndexedDB 2.0: Implement new IDBCursor.continuePrimaryKey function.
https://bugs.webkit.org/show_bug.cgi?id=164404

Reviewed by Alex Christensen.

LayoutTests/imported/w3c:

* web-platform-tests/IndexedDB/idbcursor-continuePrimaryKey-exception-order-expected.txt:

Source/WebCore:

Tests: storage/indexeddb/modern/idbcursor-continue-primary-key-1-private.html
       storage/indexeddb/modern/idbcursor-continue-primary-key-1.html
       Also covered by existing tests.

* Modules/indexeddb/IDBCursor.cpp:
(WebCore::IDBCursor::continuePrimaryKey):
(WebCore::IDBCursor::uncheckedIterateCursor):
* Modules/indexeddb/IDBCursor.h:
* Modules/indexeddb/IDBCursor.idl:

* Modules/indexeddb/IDBKeyData.h:
(WebCore::IDBKeyData::operator&gt;):
(WebCore::IDBKeyData::operator&lt;=):
(WebCore::IDBKeyData::operator&gt;=):

* Modules/indexeddb/server/MemoryCursor.h:

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

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

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

* Modules/indexeddb/server/SQLiteIDBBackingStore.cpp:
(WebCore::IDBServer::SQLiteIDBBackingStore::iterateCursor):

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

* Modules/indexeddb/shared/IDBIterateCursorData.cpp:
(WebCore::IDBIterateCursorData::isolatedCopy):
* Modules/indexeddb/shared/IDBIterateCursorData.h:
(WebCore::IDBIterateCursorData::encode):
(WebCore::IDBIterateCursorData::decode):

LayoutTests:

* storage/indexeddb/cursor-basics-expected.txt:
* storage/indexeddb/cursor-basics-private-expected.txt:
* storage/indexeddb/modern/idbcursor-continue-primary-key-1-expected.txt: Added.
* storage/indexeddb/modern/idbcursor-continue-primary-key-1-private-expected.txt: Added.
* storage/indexeddb/modern/idbcursor-continue-primary-key-1-private.html: Added.
* storage/indexeddb/modern/idbcursor-continue-primary-key-1.html: Added.
* storage/indexeddb/modern/resources/idbcursor-continue-primary-key-1.js: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsimportedw3cChangeLog">trunk/LayoutTests/imported/w3c/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsimportedw3cwebplatformtestsIndexedDBidbcursorcontinuePrimaryKeyexceptionorderexpectedtxt">trunk/LayoutTests/imported/w3c/web-platform-tests/IndexedDB/idbcursor-continuePrimaryKey-exception-order-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbcursorbasicsexpectedtxt">trunk/LayoutTests/storage/indexeddb/cursor-basics-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbcursorbasicsprivateexpectedtxt">trunk/LayoutTests/storage/indexeddb/cursor-basics-private-expected.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbIDBCursorcpp">trunk/Source/WebCore/Modules/indexeddb/IDBCursor.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbIDBCursorh">trunk/Source/WebCore/Modules/indexeddb/IDBCursor.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbIDBCursoridl">trunk/Source/WebCore/Modules/indexeddb/IDBCursor.idl</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbIDBKeyDatah">trunk/Source/WebCore/Modules/indexeddb/IDBKeyData.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverMemoryCursorh">trunk/Source/WebCore/Modules/indexeddb/server/MemoryCursor.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverMemoryIDBBackingStorecpp">trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverMemoryIndexCursorcpp">trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndexCursor.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverMemoryIndexCursorh">trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndexCursor.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>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverSQLiteIDBBackingStorecpp">trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverSQLiteIDBCursorcpp">trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBCursor.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverSQLiteIDBCursorh">trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBCursor.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbsharedIDBIterateCursorDatacpp">trunk/Source/WebCore/Modules/indexeddb/shared/IDBIterateCursorData.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbsharedIDBIterateCursorDatah">trunk/Source/WebCore/Modules/indexeddb/shared/IDBIterateCursorData.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsstorageindexeddbmodernidbcursorcontinueprimarykey1expectedtxt">trunk/LayoutTests/storage/indexeddb/modern/idbcursor-continue-primary-key-1-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmodernidbcursorcontinueprimarykey1privateexpectedtxt">trunk/LayoutTests/storage/indexeddb/modern/idbcursor-continue-primary-key-1-private-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmodernidbcursorcontinueprimarykey1privatehtml">trunk/LayoutTests/storage/indexeddb/modern/idbcursor-continue-primary-key-1-private.html</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmodernidbcursorcontinueprimarykey1html">trunk/LayoutTests/storage/indexeddb/modern/idbcursor-continue-primary-key-1.html</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmodernresourcesidbcursorcontinueprimarykey1js">trunk/LayoutTests/storage/indexeddb/modern/resources/idbcursor-continue-primary-key-1.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/LayoutTests/ChangeLog        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2016-11-09  Brady Eidson  &lt;beidson@apple.com&gt;
+
+        IndexedDB 2.0: Implement new IDBCursor.continuePrimaryKey function.
+        https://bugs.webkit.org/show_bug.cgi?id=164404
+
+        Reviewed by Alex Christensen.
+
+        * storage/indexeddb/cursor-basics-expected.txt:
+        * storage/indexeddb/cursor-basics-private-expected.txt:
+        * storage/indexeddb/modern/idbcursor-continue-primary-key-1-expected.txt: Added.
+        * storage/indexeddb/modern/idbcursor-continue-primary-key-1-private-expected.txt: Added.
+        * storage/indexeddb/modern/idbcursor-continue-primary-key-1-private.html: Added.
+        * storage/indexeddb/modern/idbcursor-continue-primary-key-1.html: Added.
+        * storage/indexeddb/modern/resources/idbcursor-continue-primary-key-1.js: Added.
+
</ins><span class="cx"> 2016-11-09  Antoine Quint  &lt;graouts@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Modern Media Controls] Media Controller: set status label according to media state
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/ChangeLog (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/ChangeLog        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/LayoutTests/imported/w3c/ChangeLog        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -1,5 +1,14 @@
</span><span class="cx"> 2016-11-09  Brady Eidson  &lt;beidson@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        IndexedDB 2.0: Implement new IDBCursor.continuePrimaryKey function.
+        https://bugs.webkit.org/show_bug.cgi?id=164404
+
+        Reviewed by Alex Christensen.
+
+        * web-platform-tests/IndexedDB/idbcursor-continuePrimaryKey-exception-order-expected.txt:
+
+2016-11-09  Brady Eidson  &lt;beidson@apple.com&gt;
+
</ins><span class="cx">         IndexedDB 2.0: Clean up more transaction abort behavior, including tweaks to Index/ObjectStore lifetime.
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=164466
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsimportedw3cwebplatformtestsIndexedDBidbcursorcontinuePrimaryKeyexceptionorderexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/IndexedDB/idbcursor-continuePrimaryKey-exception-order-expected.txt (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/imported/w3c/web-platform-tests/IndexedDB/idbcursor-continuePrimaryKey-exception-order-expected.txt        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/IndexedDB/idbcursor-continuePrimaryKey-exception-order-expected.txt        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -1,32 +1,15 @@
</span><del>-CONSOLE MESSAGE: line 2422: Error: assert_throws: transaction-state check should precede deletion check function &quot;function () {
-                cursor.continuePrimaryKey(&quot;...&quot; threw object &quot;TypeError: cursor.continuePrimaryKey is not a function. (...&quot; that is not a DOMException TransactionInactiveError: property &quot;code&quot; is equal to undefined, expected 0
</del><span class="cx"> 
</span><del>-Harness Error (FAIL), message = Error: assert_throws: transaction-state check should precede deletion check function &quot;function () {
-                cursor.continuePrimaryKey(&quot;...&quot; threw object &quot;TypeError: cursor.continuePrimaryKey is not a function. (...&quot; that is not a DOMException TransactionInactiveError: property &quot;code&quot; is equal to undefined, expected 0
</del><ins>+PASS TransactionInactiveError v.s. InvalidStateError(deleted index) 
+PASS InvalidStateError(deleted source) v.s. InvalidAccessError(incorrect source) 
+PASS InvalidStateError(deleted source) v.s. InvalidAccessError(incorrect direction) 
+PASS InvalidAccessError(incorrect direction) v.s. InvalidStateError(iteration complete) 
+PASS InvalidAccessError(incorrect direction) v.s. InvalidStateError(iteration ongoing) 
+PASS InvalidAccessError(incorrect source) v.s. InvalidStateError(iteration ongoing) 
+PASS InvalidAccessError(incorrect source) v.s. InvalidStateError(iteration complete) 
+PASS InvalidStateError(iteration ongoing) v.s. DataError(unset key) 
+PASS InvalidStateError(iteration complete) v.s. DataError(unset key) 
+PASS DataError(unset key) 
+PASS DataError(unset primary key) 
+PASS DataError(keys are lower then current one) in 'next' direction 
+PASS DataError(keys are larger then current one) in 'prev' direction 
</ins><span class="cx"> 
</span><del>-TIMEOUT TransactionInactiveError v.s. InvalidStateError(deleted index) Test timed out
-FAIL InvalidStateError(deleted source) v.s. InvalidAccessError(incorrect source) assert_throws: deletion check should precede index source check function &quot;function () {
-                cursor.continuePrimaryKey(&quot;...&quot; threw object &quot;TypeError: cursor.continuePrimaryKey is not a function. (...&quot; that is not a DOMException InvalidStateError: property &quot;code&quot; is equal to undefined, expected 11
-FAIL InvalidStateError(deleted source) v.s. InvalidAccessError(incorrect direction) assert_throws: deletion check should precede cursor direction check function &quot;function () {
-              cursor.continuePrimaryKey(&quot;A&quot;...&quot; threw object &quot;TypeError: cursor.continuePrimaryKey is not a function. (...&quot; that is not a DOMException InvalidStateError: property &quot;code&quot; is equal to undefined, expected 11
-FAIL InvalidAccessError(incorrect direction) v.s. InvalidStateError(iteration complete) assert_throws: direction check should precede got_value_flag check function &quot;function () {
-                cursor.continuePrimaryKey(&quot;...&quot; threw object &quot;TypeError: cursor.continuePrimaryKey is not a function. (...&quot; that is not a DOMException InvalidAccessError: property &quot;code&quot; is equal to undefined, expected 15
-FAIL InvalidAccessError(incorrect direction) v.s. InvalidStateError(iteration ongoing) assert_throws: direction check should precede iteration ongoing check function &quot;function () {
-                    cursor.continuePrimaryK...&quot; threw object &quot;TypeError: cursor.continuePrimaryKey is not a function. (...&quot; that is not a DOMException InvalidAccessError: property &quot;code&quot; is equal to undefined, expected 15
-FAIL InvalidAccessError(incorrect source) v.s. InvalidStateError(iteration ongoing) assert_throws: index source check should precede iteration ongoing check function &quot;function () {
-                    cursor.continuePrimaryK...&quot; threw object &quot;TypeError: cursor.continuePrimaryKey is not a function. (...&quot; that is not a DOMException InvalidAccessError: property &quot;code&quot; is equal to undefined, expected 15
-FAIL InvalidAccessError(incorrect source) v.s. InvalidStateError(iteration complete) assert_throws: index source check should precede got_value_flag check function &quot;function () {
-                cursor.continuePrimaryKey(&quot;...&quot; threw object &quot;TypeError: cursor.continuePrimaryKey is not a function. (...&quot; that is not a DOMException InvalidAccessError: property &quot;code&quot; is equal to undefined, expected 15
-FAIL InvalidStateError(iteration ongoing) v.s. DataError(unset key) assert_throws: iteration ongoing check should precede unset key check function &quot;function () {
-                    cursor.continuePrimaryK...&quot; threw object &quot;TypeError: cursor.continuePrimaryKey is not a function. (...&quot; that is not a DOMException InvalidStateError: property &quot;code&quot; is equal to undefined, expected 11
-FAIL InvalidStateError(iteration complete) v.s. DataError(unset key) assert_throws: got_value_flag check should precede unset key check function &quot;function () {
-                cursor.continuePrimaryKey(n...&quot; threw object &quot;TypeError: cursor.continuePrimaryKey is not a function. (...&quot; that is not a DOMException InvalidStateError: property &quot;code&quot; is equal to undefined, expected 11
-FAIL DataError(unset key) assert_throws: DataError is expected if key is unset. function &quot;function () {
-                cursor.continuePrimaryKey(n...&quot; threw object &quot;TypeError: cursor.continuePrimaryKey is not a function. (...&quot; that is not a DOMException DataError: property &quot;code&quot; is equal to undefined, expected 0
-FAIL DataError(unset primary key) assert_throws: DataError is expected if primary key is unset. function &quot;function () {
-                cursor.continuePrimaryKey(&quot;...&quot; threw object &quot;TypeError: cursor.continuePrimaryKey is not a function. (...&quot; that is not a DOMException DataError: property &quot;code&quot; is equal to undefined, expected 0
-FAIL DataError(keys are lower then current one) in 'next' direction assert_throws: DataError is expected if key is lower then current one. function &quot;function () {
-                cursor.continuePrimaryKey(&quot;...&quot; threw object &quot;TypeError: cursor.continuePrimaryKey is not a function. (...&quot; that is not a DOMException DataError: property &quot;code&quot; is equal to undefined, expected 0
-FAIL DataError(keys are larger then current one) in 'prev' direction assert_throws: DataError is expected if key is larger then current one. function &quot;function () {
-                cursor.continuePrimaryKey(&quot;...&quot; threw object &quot;TypeError: cursor.continuePrimaryKey is not a function. (...&quot; that is not a DOMException DataError: property &quot;code&quot; is equal to undefined, expected 0
-
</del></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbcursorbasicsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/storage/indexeddb/cursor-basics-expected.txt (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/cursor-basics-expected.txt        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/LayoutTests/storage/indexeddb/cursor-basics-expected.txt        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -24,8 +24,8 @@
</span><span class="cx"> PASS 'primaryKey' in cursor is true
</span><span class="cx"> PASS 'continue' in cursor is true
</span><span class="cx"> PASS typeof cursor.continue is &quot;function&quot;
</span><del>-FAIL 'continuePrimaryKey' in cursor should be true. Was false.
-FAIL typeof cursor.continuePrimaryKey should be function. Was undefined.
</del><ins>+PASS 'continuePrimaryKey' in cursor is true
+PASS typeof cursor.continuePrimaryKey is &quot;function&quot;
</ins><span class="cx"> PASS 'advance' in cursor is true
</span><span class="cx"> PASS typeof cursor.advance is &quot;function&quot;
</span><span class="cx"> PASS 'update' in cursor is true
</span><span class="lines">@@ -46,8 +46,8 @@
</span><span class="cx"> PASS 'primaryKey' in cursor is true
</span><span class="cx"> PASS 'continue' in cursor is true
</span><span class="cx"> PASS typeof cursor.continue is &quot;function&quot;
</span><del>-FAIL 'continuePrimaryKey' in cursor should be true. Was false.
-FAIL typeof cursor.continuePrimaryKey should be function. Was undefined.
</del><ins>+PASS 'continuePrimaryKey' in cursor is true
+PASS typeof cursor.continuePrimaryKey is &quot;function&quot;
</ins><span class="cx"> PASS 'advance' in cursor is true
</span><span class="cx"> PASS typeof cursor.advance is &quot;function&quot;
</span><span class="cx"> PASS 'update' in cursor is true
</span><span class="lines">@@ -68,8 +68,8 @@
</span><span class="cx"> PASS 'primaryKey' in cursor is true
</span><span class="cx"> PASS 'continue' in cursor is true
</span><span class="cx"> PASS typeof cursor.continue is &quot;function&quot;
</span><del>-FAIL 'continuePrimaryKey' in cursor should be true. Was false.
-FAIL typeof cursor.continuePrimaryKey should be function. Was undefined.
</del><ins>+PASS 'continuePrimaryKey' in cursor is true
+PASS typeof cursor.continuePrimaryKey is &quot;function&quot;
</ins><span class="cx"> PASS 'advance' in cursor is true
</span><span class="cx"> PASS typeof cursor.advance is &quot;function&quot;
</span><span class="cx"> PASS 'update' in cursor is true
</span><span class="lines">@@ -82,7 +82,6 @@
</span><span class="cx"> PASS cursor.primaryKey is 0
</span><span class="cx"> PASS 'value' in cursor is false
</span><span class="cx"> PASS successfullyParsed is true
</span><del>-Some tests failed.
</del><span class="cx"> 
</span><span class="cx"> TEST COMPLETE
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbcursorbasicsprivateexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/storage/indexeddb/cursor-basics-private-expected.txt (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/cursor-basics-private-expected.txt        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/LayoutTests/storage/indexeddb/cursor-basics-private-expected.txt        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -24,8 +24,8 @@
</span><span class="cx"> PASS 'primaryKey' in cursor is true
</span><span class="cx"> PASS 'continue' in cursor is true
</span><span class="cx"> PASS typeof cursor.continue is &quot;function&quot;
</span><del>-FAIL 'continuePrimaryKey' in cursor should be true. Was false.
-FAIL typeof cursor.continuePrimaryKey should be function. Was undefined.
</del><ins>+PASS 'continuePrimaryKey' in cursor is true
+PASS typeof cursor.continuePrimaryKey is &quot;function&quot;
</ins><span class="cx"> PASS 'advance' in cursor is true
</span><span class="cx"> PASS typeof cursor.advance is &quot;function&quot;
</span><span class="cx"> PASS 'update' in cursor is true
</span><span class="lines">@@ -46,8 +46,8 @@
</span><span class="cx"> PASS 'primaryKey' in cursor is true
</span><span class="cx"> PASS 'continue' in cursor is true
</span><span class="cx"> PASS typeof cursor.continue is &quot;function&quot;
</span><del>-FAIL 'continuePrimaryKey' in cursor should be true. Was false.
-FAIL typeof cursor.continuePrimaryKey should be function. Was undefined.
</del><ins>+PASS 'continuePrimaryKey' in cursor is true
+PASS typeof cursor.continuePrimaryKey is &quot;function&quot;
</ins><span class="cx"> PASS 'advance' in cursor is true
</span><span class="cx"> PASS typeof cursor.advance is &quot;function&quot;
</span><span class="cx"> PASS 'update' in cursor is true
</span><span class="lines">@@ -68,8 +68,8 @@
</span><span class="cx"> PASS 'primaryKey' in cursor is true
</span><span class="cx"> PASS 'continue' in cursor is true
</span><span class="cx"> PASS typeof cursor.continue is &quot;function&quot;
</span><del>-FAIL 'continuePrimaryKey' in cursor should be true. Was false.
-FAIL typeof cursor.continuePrimaryKey should be function. Was undefined.
</del><ins>+PASS 'continuePrimaryKey' in cursor is true
+PASS typeof cursor.continuePrimaryKey is &quot;function&quot;
</ins><span class="cx"> PASS 'advance' in cursor is true
</span><span class="cx"> PASS typeof cursor.advance is &quot;function&quot;
</span><span class="cx"> PASS 'update' in cursor is true
</span><span class="lines">@@ -82,7 +82,6 @@
</span><span class="cx"> PASS cursor.primaryKey is 0
</span><span class="cx"> PASS 'value' in cursor is false
</span><span class="cx"> PASS successfullyParsed is true
</span><del>-Some tests failed.
</del><span class="cx"> 
</span><span class="cx"> TEST COMPLETE
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmodernidbcursorcontinueprimarykey1expectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/idbcursor-continue-primary-key-1-expected.txt (0 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/idbcursor-continue-primary-key-1-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/idbcursor-continue-primary-key-1-expected.txt        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -0,0 +1,36 @@
</span><ins>+This test verifies the basic functionality of IDBCursor.continuePrimaryKey().
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS !!cursor is true
+PASS &quot;transaction-state check should precede deletion check&quot; threw as expected
+PASS !!cursor is true
+PASS &quot;deletion check should precede index source check&quot; threw as expected
+PASS !!cursor is true
+PASS &quot;deletion check should precede cursor direction check&quot; threw as expected
+PASS &quot;direction check should precede got_value_flag check&quot; threw as expected
+PASS !!cursor is true
+PASS &quot;direction check should precede iteration ongoing check&quot; threw as expected
+PASS !!cursor is true
+PASS &quot;index source check should precede iteration ongoing check&quot; threw as expected
+PASS &quot;index source check should precede got_value_flag check&quot; threw as expected
+PASS !!cursor is true
+PASS &quot;iteration ongoing check should precede unset key check&quot; threw as expected
+PASS &quot;got_value_flag check should precede unset key check&quot; threw as expected
+PASS !!cursor is true
+PASS &quot;DataError is expected if key is unset.&quot; threw as expected
+PASS !!cursor is true
+PASS &quot;DataError is expected if primary key is unset.&quot; threw as expected
+PASS !!cursor is true
+PASS &quot;DataError is expected if key is lower then current one.&quot; threw as expected
+PASS &quot;DataError is expected if primary key is equal to current one.&quot; threw as expected
+PASS &quot;DataError is expected if primary key is lower than current one.&quot; threw as expected
+PASS !!cursor is true
+PASS &quot;DataError is expected if key is larger then current one.&quot; threw as expected
+PASS &quot;DataError is expected if primary key is equal to current one.&quot; threw as expected
+PASS &quot;DataError is expected if primary key is larger than current one.&quot; threw as expected
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmodernidbcursorcontinueprimarykey1privateexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/idbcursor-continue-primary-key-1-private-expected.txt (0 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/idbcursor-continue-primary-key-1-private-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/idbcursor-continue-primary-key-1-private-expected.txt        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -0,0 +1,36 @@
</span><ins>+This test verifies the basic functionality of IDBCursor.continuePrimaryKey().
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS !!cursor is true
+PASS &quot;transaction-state check should precede deletion check&quot; threw as expected
+PASS !!cursor is true
+PASS &quot;deletion check should precede index source check&quot; threw as expected
+PASS !!cursor is true
+PASS &quot;deletion check should precede cursor direction check&quot; threw as expected
+PASS &quot;direction check should precede got_value_flag check&quot; threw as expected
+PASS !!cursor is true
+PASS &quot;direction check should precede iteration ongoing check&quot; threw as expected
+PASS !!cursor is true
+PASS &quot;index source check should precede iteration ongoing check&quot; threw as expected
+PASS &quot;index source check should precede got_value_flag check&quot; threw as expected
+PASS !!cursor is true
+PASS &quot;iteration ongoing check should precede unset key check&quot; threw as expected
+PASS &quot;got_value_flag check should precede unset key check&quot; threw as expected
+PASS !!cursor is true
+PASS &quot;DataError is expected if key is unset.&quot; threw as expected
+PASS !!cursor is true
+PASS &quot;DataError is expected if primary key is unset.&quot; threw as expected
+PASS !!cursor is true
+PASS &quot;DataError is expected if key is lower then current one.&quot; threw as expected
+PASS &quot;DataError is expected if primary key is equal to current one.&quot; threw as expected
+PASS &quot;DataError is expected if primary key is lower than current one.&quot; threw as expected
+PASS !!cursor is true
+PASS &quot;DataError is expected if key is larger then current one.&quot; threw as expected
+PASS &quot;DataError is expected if primary key is equal to current one.&quot; threw as expected
+PASS &quot;DataError is expected if primary key is larger than current one.&quot; threw as expected
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmodernidbcursorcontinueprimarykey1privatehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/idbcursor-continue-primary-key-1-private.html (0 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/idbcursor-continue-primary-key-1-private.html                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/idbcursor-continue-primary-key-1-private.html        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -0,0 +1,13 @@
</span><ins>+&lt;html&gt;
+&lt;head&gt;
+&lt;script&gt;
+enablePrivateBrowsing = true;
+&lt;/script&gt;
+&lt;script src=&quot;../../../resources/js-test.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../resources/shared.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+
+&lt;script src=&quot;resources/idbcursor-continue-primary-key-1.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmodernidbcursorcontinueprimarykey1html"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/idbcursor-continue-primary-key-1.html (0 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/idbcursor-continue-primary-key-1.html                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/idbcursor-continue-primary-key-1.html        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../../resources/js-test.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../resources/shared.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+
+&lt;script src=&quot;resources/idbcursor-continue-primary-key-1.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmodernresourcesidbcursorcontinueprimarykey1js"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/resources/idbcursor-continue-primary-key-1.js (0 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/resources/idbcursor-continue-primary-key-1.js                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/resources/idbcursor-continue-primary-key-1.js        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -0,0 +1,483 @@
</span><ins>+// Test modeled after imported/w3c/web-platform-tests/IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm
+
+description(&quot;This test verifies the basic functionality of IDBCursor.continuePrimaryKey().&quot;);
+
+function setup_test_store(db) {
+        var records = [ { iKey: &quot;A&quot;, pKey: 1 },
+                        { iKey: &quot;A&quot;, pKey: 2 },
+                        { iKey: &quot;A&quot;, pKey: 3 },
+                        { iKey: &quot;A&quot;, pKey: 4 },
+                        { iKey: &quot;B&quot;, pKey: 5 },
+                        { iKey: &quot;B&quot;, pKey: 6 },
+                        { iKey: &quot;B&quot;, pKey: 7 },
+                        { iKey: &quot;C&quot;, pKey: 8 },
+                        { iKey: &quot;C&quot;, pKey: 9 },
+                        { iKey: &quot;D&quot;, pKey: 10 } ];
+
+    var store = db.createObjectStore(&quot;test&quot;, { keyPath: &quot;pKey&quot; });
+    var index = store.createIndex(&quot;idx&quot;, &quot;iKey&quot;);
+
+    for(var i = 0; i &lt; records.length; i++)
+        store.add(records[i]);
+
+    return store;
+}
+
+function log(message)
+{
+    debug(message);
+}
+
+function next()
+{
+    testGenerator.next();
+}
+
+function asyncNext()
+{
+    setTimeout(&quot;testGenerator.next();&quot;, 0);
+}
+
+function unreached(description)
+{
+        return function() {
+                debug(&quot;FAIL: &quot; + description);
+                finishJSTest();
+        }
+};
+
+var dbName = window.location.href + &quot; test&quot;;
+var db;
+
+var testGenerator = testSteps();
+testGenerator.next();
+
+function shouldThrowType(name, func, text) {
+    var errorText = text + &quot; should throw an exception&quot;;
+    try {
+        func();
+        testFailed(errorText);
+    } catch (e) {
+                if (e.name == name)
+                testPassed('&quot;' + text + &quot;\&quot; threw as expected&quot;);
+        else
+                        testFailed(text + &quot; should throw exception type &quot; + name + &quot;, but threw &quot; + e.name + &quot; instead&quot;);
+    }
+}
+
+var db;
+function* testSteps()
+{
+        indexedDB.deleteDatabase(dbName).onsuccess = next;
+        yield;
+        
+        request = indexedDB.open(dbName);
+        request.onupgradeneeded = function() {
+                db = request.result;
+                var txn = request.transaction;
+
+                var store = setup_test_store(db);
+                var index = store.index(&quot;idx&quot;);
+                var cursor_rq = index.openCursor();
+
+                cursor_rq.onerror = unreached('openCursor should succeed');
+                cursor_rq.onsuccess = function(e) {
+                    cursor = e.target.result;
+            shouldBeTrue(&quot;!!cursor&quot;);
+
+                    store.deleteIndex(&quot;idx&quot;);
+                };
+                txn.oncomplete = function() {
+                    shouldThrowType(&quot;TransactionInactiveError&quot;, function() {
+                        cursor.continuePrimaryKey(&quot;A&quot;, 4);
+                    }, &quot;transaction-state check should precede deletion check&quot;);
+                        db.close();
+                        next();
+                };
+        };
+        yield;
+
+        cursor = undefined;
+        indexedDB.deleteDatabase(dbName).onsuccess = next;
+        yield;
+
+        request = indexedDB.open(dbName);
+        request.onupgradeneeded = function() {
+                db = request.result;
+
+                var store = setup_test_store(db);
+        var cursor_rq = store.openCursor();
+
+        cursor_rq.onerror = unreached('openCursor should succeed');
+        cursor_rq.onsuccess = function(e) {
+            cursor = e.target.result;
+            shouldBeTrue(&quot;!!cursor&quot;);
+
+            db.deleteObjectStore(&quot;test&quot;);
+
+            shouldThrowType(&quot;InvalidStateError&quot;, function() {
+                cursor.continuePrimaryKey(&quot;A&quot;, 4);
+            }, &quot;deletion check should precede index source check&quot;);
+
+                        db.close();
+            next();
+        };
+        };
+        yield;
+
+        cursor = undefined;
+        indexedDB.deleteDatabase(dbName).onsuccess = next;
+        yield;
+
+        request = indexedDB.open(dbName);
+        request.onupgradeneeded = function() {
+                db = request.result;
+                
+        var store = setup_test_store(db);
+        var index = store.index(&quot;idx&quot;);
+        var cursor_rq = index.openCursor(null, &quot;nextunique&quot;);
+
+        cursor_rq.onerror = unreached('openCursor should succeed');
+        cursor_rq.onsuccess = function(e) {
+            cursor = e.target.result;
+            shouldBeTrue(&quot;!!cursor&quot;);
+
+            store.deleteIndex(&quot;idx&quot;);
+
+            shouldThrowType(&quot;InvalidStateError&quot;, function() {
+              cursor.continuePrimaryKey(&quot;A&quot;, 4);
+            }, &quot;deletion check should precede cursor direction check&quot;);
+                        
+                        db.close();
+            next();
+        };
+        };
+        yield;
+
+        cursor = undefined;
+        indexedDB.deleteDatabase(dbName).onsuccess = next;
+        yield;
+
+        request = indexedDB.open(dbName);
+        request.onupgradeneeded = function() {
+                db = request.result;
+                
+        var store = db.createObjectStore(&quot;test&quot;, {keyPath:&quot;pKey&quot;});
+        var index = store.createIndex(&quot;idx&quot;, &quot;iKey&quot;);
+
+        store.add({ iKey: &quot;A&quot;, pKey: 1 });
+
+        var cursor_rq = index.openCursor(null, &quot;nextunique&quot;);
+
+        cursor_rq.onerror = unreached('openCursor should succeed');
+        cursor_rq.onsuccess = function(e) {
+            if (e.target.result) {
+                cursor = e.target.result;
+                cursor.continue();
+                return;
+            }
+
+            shouldThrowType(&quot;InvalidAccessError&quot;, function() {
+                cursor.continuePrimaryKey(&quot;A&quot;, 4);
+            }, &quot;direction check should precede got_value_flag check&quot;);
+
+                        db.close();
+            next();
+        };
+        };
+        yield;
+
+        indexedDB.deleteDatabase(dbName).onsuccess = next;
+        cursor = undefined;
+        yield;
+        
+        request = indexedDB.open(dbName);
+        request.onupgradeneeded = function() {
+                db = request.result;
+        
+        var store = db.createObjectStore(&quot;test&quot;, {keyPath:&quot;pKey&quot;});
+        var index = store.createIndex(&quot;idx&quot;, &quot;iKey&quot;);
+
+        store.add({ iKey: &quot;A&quot;, pKey: 1 });
+
+        var cursor_rq = index.openCursor(null, &quot;nextunique&quot;);
+
+        cursor_rq.onerror = unreached('openCursor should succeed');
+        cursor_rq.onsuccess = function(e) {
+            if (!cursor) {
+                cursor = e.target.result;
+                shouldBeTrue(&quot;!!cursor&quot;);
+
+                cursor.continue();
+
+                shouldThrowType(&quot;InvalidAccessError&quot;, function() {
+                    cursor.continuePrimaryKey(&quot;A&quot;, 4);
+                }, &quot;direction check should precede iteration ongoing check&quot;);
+
+                                cursor_rq.onsuccess = undefined;
+                                db.close();
+                next();
+            }
+        };
+        };
+        yield;
+        
+        indexedDB.deleteDatabase(dbName).onsuccess = next;
+        cursor = undefined;
+        yield;
+        
+        request = indexedDB.open(dbName);
+        request.onupgradeneeded = function() {
+                db = request.result;
+                
+        var store = setup_test_store(db);
+        var cursor_rq = store.openCursor();
+
+        cursor_rq.onerror = unreached('openCursor should succeed');
+        cursor_rq.onsuccess = function(e) {
+            if (!cursor) {
+                cursor = e.target.result;
+                shouldBeTrue(&quot;!!cursor&quot;);
+
+                cursor.continue();
+
+                shouldThrowType(&quot;InvalidAccessError&quot;, function() {
+                    cursor.continuePrimaryKey(&quot;A&quot;, 4);
+                }, &quot;index source check should precede iteration ongoing check&quot;);
+
+                                cursor_rq.onsuccess = undefined;
+                        db.close();
+                next();
+            }
+               };
+        };
+        yield;
+
+        indexedDB.deleteDatabase(dbName).onsuccess = next;
+        cursor = undefined;
+        yield;
+        
+        request = indexedDB.open(dbName);
+        request.onupgradeneeded = function() {
+                db = request.result;
+                
+        var store = db.createObjectStore(&quot;test&quot;, {keyPath:&quot;pKey&quot;});
+
+        store.add({ iKey: &quot;A&quot;, pKey: 1 });
+
+        var cursor_rq = store.openCursor();
+
+        cursor_rq.onerror = unreached('openCursor should succeed');
+        cursor_rq.onsuccess = function(e) {
+            if (e.target.result) {
+                cursor = e.target.result;
+                cursor.continue();
+                return;
+            }
+
+            shouldThrowType(&quot;InvalidAccessError&quot;, function() {
+                cursor.continuePrimaryKey(&quot;A&quot;, 4);
+            }, &quot;index source check should precede got_value_flag check&quot;);
+                    db.close();
+            next();
+        };
+        };
+        yield;
+
+        indexedDB.deleteDatabase(dbName).onsuccess = next;
+        cursor = undefined;
+        yield;
+        
+        request = indexedDB.open(dbName);
+        request.onupgradeneeded = function() {
+                db = request.result;
+                
+        var store = setup_test_store(db);
+        var index = store.index(&quot;idx&quot;);
+        var cursor_rq = index.openCursor();
+
+        cursor_rq.onerror = unreached('openCursor should succeed');
+        cursor_rq.onsuccess = function(e) {
+            if (!cursor) {
+                cursor = e.target.result;
+                shouldBeTrue(&quot;!!cursor&quot;);
+
+                cursor.continue();
+
+                shouldThrowType(&quot;InvalidStateError&quot;, function() {
+                    cursor.continuePrimaryKey(null, 4);
+                }, &quot;iteration ongoing check should precede unset key check&quot;);
+
+                                cursor_rq.onsuccess = undefined;
+                            db.close();
+                next();
+            }
+        };
+        };
+        yield;
+
+        indexedDB.deleteDatabase(dbName).onsuccess = next;
+        cursor = undefined;
+        yield;
+        
+        request = indexedDB.open(dbName);
+        request.onupgradeneeded = function() {
+                db = request.result;
+                
+        var store = db.createObjectStore(&quot;test&quot;, {keyPath:&quot;pKey&quot;});
+        var index = store.createIndex(&quot;idx&quot;, &quot;iKey&quot;);
+
+        store.add({ iKey: &quot;A&quot;, pKey: 1 });
+
+        var cursor_rq = index.openCursor();
+
+        cursor_rq.onerror = unreached('openCursor should succeed');
+        cursor_rq.onsuccess = function(e) {
+            if (e.target.result) {
+                cursor = e.target.result;
+                cursor.continue();
+                return;
+            }
+
+            shouldThrowType(&quot;InvalidStateError&quot;, function() {
+                cursor.continuePrimaryKey(null, 4);
+            }, &quot;got_value_flag check should precede unset key check&quot;);
+                           
+                        db.close();
+            next();
+        };
+        };
+        yield;
+
+        indexedDB.deleteDatabase(dbName).onsuccess = next;
+        cursor = undefined;
+        yield;
+        
+        request = indexedDB.open(dbName);
+        request.onupgradeneeded = function() {
+                db = request.result;
+
+        var store = setup_test_store(db);
+        var index = store.index(&quot;idx&quot;);
+        var cursor_rq = index.openCursor();
+
+        cursor_rq.onerror = unreached('openCursor should succeed');
+        cursor_rq.onsuccess = function(e) {
+            cursor = e.target.result;
+            shouldBeTrue(&quot;!!cursor&quot;);
+
+            shouldThrowType(&quot;DataError&quot;, function() {
+                cursor.continuePrimaryKey(null, 4);
+            }, &quot;DataError is expected if key is unset.&quot;);
+
+                        db.close();
+            next();
+        };
+        };
+        yield;
+
+        indexedDB.deleteDatabase(dbName).onsuccess = next;
+        cursor = undefined;
+        yield;
+        
+        request = indexedDB.open(dbName);
+        request.onupgradeneeded = function() {
+                db = request.result;
+
+        var store = setup_test_store(db);
+        var index = store.index(&quot;idx&quot;);
+        var cursor_rq = index.openCursor();
+
+        cursor_rq.onerror = unreached('openCursor should succeed');
+        cursor_rq.onsuccess = function(e) {
+            cursor = e.target.result;
+            shouldBeTrue(&quot;!!cursor&quot;);
+
+            shouldThrowType(&quot;DataError&quot;, function() {
+                cursor.continuePrimaryKey(&quot;A&quot;, null);
+            }, &quot;DataError is expected if primary key is unset.&quot;);
+
+                        db.close();
+            next();
+        };
+        };
+        yield;
+        
+        indexedDB.deleteDatabase(dbName).onsuccess = next;
+        cursor = undefined;
+        yield;
+        
+        request = indexedDB.open(dbName);
+        request.onupgradeneeded = function() {
+                db = request.result;
+
+        var store = setup_test_store(db);
+        var index = store.index(&quot;idx&quot;);
+        var cursor_rq = index.openCursor(IDBKeyRange.lowerBound(&quot;B&quot;));
+
+        cursor_rq.onerror = unreached('openCursor should succeed');
+        cursor_rq.onsuccess = function(e) {
+            cursor = e.target.result;
+            shouldBeTrue(&quot;!!cursor&quot;);
+
+            shouldBeTrue(&quot;cursor.key == 'B'&quot;, &quot;expected key&quot;);
+            shouldBeTrue(&quot;cursor.primaryKey == 5&quot;, &quot;expected primary key&quot;);
+
+            shouldThrowType(&quot;DataError&quot;, function() {
+                cursor.continuePrimaryKey(&quot;A&quot;, 6);
+            }, &quot;DataError is expected if key is lower then current one.&quot;);
+
+            shouldThrowType(&quot;DataError&quot;, function() {
+                cursor.continuePrimaryKey(&quot;B&quot;, 5);
+            }, &quot;DataError is expected if primary key is equal to current one.&quot;);
+
+            shouldThrowType(&quot;DataError&quot;, function() {
+                cursor.continuePrimaryKey(&quot;B&quot;, 4);
+            }, &quot;DataError is expected if primary key is lower than current one.&quot;);
+
+                        db.close();
+            next();
+        };
+        };
+        yield;
+
+        indexedDB.deleteDatabase(dbName).onsuccess = next;
+        cursor = undefined;
+        yield;
+        
+        request = indexedDB.open(dbName);
+        request.onupgradeneeded = function() {
+                db = request.result;
+        
+        var store = setup_test_store(db);
+        var index = store.index(&quot;idx&quot;);
+        var cursor_rq = index.openCursor(IDBKeyRange.upperBound(&quot;B&quot;), &quot;prev&quot;);
+
+        cursor_rq.onerror = unreached('openCursor should succeed');
+        cursor_rq.onsuccess = function(e) {
+            cursor = e.target.result;
+            shouldBeTrue(&quot;!!cursor&quot;);
+
+            shouldBeTrue(&quot;cursor.key == 'B'&quot;, &quot;expected key&quot;);
+            shouldBeTrue(&quot;cursor.primaryKey == 7&quot;, &quot;expected primary key&quot;);
+
+            shouldThrowType(&quot;DataError&quot;, function() {
+                cursor.continuePrimaryKey(&quot;C&quot;, 6);
+            }, &quot;DataError is expected if key is larger then current one.&quot;);
+
+            shouldThrowType(&quot;DataError&quot;, function() {
+                cursor.continuePrimaryKey(&quot;B&quot;, 7);
+            }, &quot;DataError is expected if primary key is equal to current one.&quot;);
+
+            shouldThrowType(&quot;DataError&quot;, function() {
+                cursor.continuePrimaryKey(&quot;B&quot;, 8);
+            }, &quot;DataError is expected if primary key is larger than current one.&quot;);
+
+                        db.close();
+            next();
+        };
+        };
+        yield;
+
+        finishJSTest();
+}
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/Source/WebCore/ChangeLog        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -1,3 +1,51 @@
</span><ins>+2016-11-09  Brady Eidson  &lt;beidson@apple.com&gt;
+
+        IndexedDB 2.0: Implement new IDBCursor.continuePrimaryKey function.
+        https://bugs.webkit.org/show_bug.cgi?id=164404
+
+        Reviewed by Alex Christensen.
+
+        Tests: storage/indexeddb/modern/idbcursor-continue-primary-key-1-private.html
+               storage/indexeddb/modern/idbcursor-continue-primary-key-1.html
+               Also covered by existing tests.
+
+        * Modules/indexeddb/IDBCursor.cpp:
+        (WebCore::IDBCursor::continuePrimaryKey):
+        (WebCore::IDBCursor::uncheckedIterateCursor):
+        * Modules/indexeddb/IDBCursor.h:
+        * Modules/indexeddb/IDBCursor.idl:
+
+        * Modules/indexeddb/IDBKeyData.h:
+        (WebCore::IDBKeyData::operator&gt;):
+        (WebCore::IDBKeyData::operator&lt;=):
+        (WebCore::IDBKeyData::operator&gt;=):
+
+        * Modules/indexeddb/server/MemoryCursor.h:
+
+        * Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
+        (WebCore::IDBServer::MemoryIDBBackingStore::iterateCursor):
+
+        * Modules/indexeddb/server/MemoryIndexCursor.cpp:
+        (WebCore::IDBServer::MemoryIndexCursor::iterate):
+        * Modules/indexeddb/server/MemoryIndexCursor.h:
+
+        * Modules/indexeddb/server/MemoryObjectStoreCursor.cpp:
+        (WebCore::IDBServer::MemoryObjectStoreCursor::iterate):
+        * Modules/indexeddb/server/MemoryObjectStoreCursor.h:
+
+        * Modules/indexeddb/server/SQLiteIDBBackingStore.cpp:
+        (WebCore::IDBServer::SQLiteIDBBackingStore::iterateCursor):
+
+        * Modules/indexeddb/server/SQLiteIDBCursor.cpp:
+        (WebCore::IDBServer::SQLiteIDBCursor::iterate):
+        * Modules/indexeddb/server/SQLiteIDBCursor.h:
+
+        * Modules/indexeddb/shared/IDBIterateCursorData.cpp:
+        (WebCore::IDBIterateCursorData::isolatedCopy):
+        * Modules/indexeddb/shared/IDBIterateCursorData.h:
+        (WebCore::IDBIterateCursorData::encode):
+        (WebCore::IDBIterateCursorData::decode):
+
</ins><span class="cx"> 2016-11-09  Antoine Quint  &lt;graouts@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Modern Media Controls] Media Controller: set status label according to media state
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbIDBCursorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/IDBCursor.cpp (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/IDBCursor.cpp        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBCursor.cpp        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -242,6 +242,55 @@
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ExceptionOr&lt;void&gt; IDBCursor::continuePrimaryKey(ExecState&amp; state, JSValue keyValue, JSValue primaryKeyValue)
+{
+    if (!transaction().isActive())
+        return Exception { IDBDatabaseException::TransactionInactiveError, ASCIILiteral(&quot;Failed to execute 'continuePrimaryKey' on 'IDBCursor': The transaction is inactive or finished.&quot;) };
+
+    if (sourcesDeleted())
+        return Exception { IDBDatabaseException::InvalidStateError, ASCIILiteral(&quot;Failed to execute 'continuePrimaryKey' on 'IDBCursor': The cursor's source or effective object store has been deleted.&quot;) };
+
+    if (!m_index)
+        return Exception { IDBDatabaseException::InvalidAccessError, ASCIILiteral(&quot;Failed to execute 'continuePrimaryKey' on 'IDBCursor': The cursor's source is not an index.&quot;) };
+
+    auto direction = m_info.cursorDirection();
+    if (direction != IndexedDB::CursorDirection::Next &amp;&amp; direction != IndexedDB::CursorDirection::Prev)
+        return Exception { IDBDatabaseException::InvalidAccessError, ASCIILiteral(&quot;Failed to execute 'continuePrimaryKey' on 'IDBCursor': The cursor's direction must be either \&quot;next\&quot; or \&quot;prev\&quot;.&quot;) };
+
+    if (!m_gotValue)
+        return Exception { IDBDatabaseException::InvalidStateError, ASCIILiteral(&quot;Failed to execute 'continuePrimaryKey' on 'IDBCursor': The cursor is being iterated or has iterated past its end.&quot;) };
+
+    RefPtr&lt;IDBKey&gt; key = scriptValueToIDBKey(state, keyValue);
+    if (!key-&gt;isValid())
+        return Exception { IDBDatabaseException::DataError, ASCIILiteral(&quot;Failed to execute 'continuePrimaryKey' on 'IDBCursor': The first parameter is not a valid key.&quot;) };
+
+    RefPtr&lt;IDBKey&gt; primaryKey = scriptValueToIDBKey(state, primaryKeyValue);
+    if (!primaryKey-&gt;isValid())
+        return Exception { IDBDatabaseException::DataError, ASCIILiteral(&quot;Failed to execute 'continuePrimaryKey' on 'IDBCursor': The second parameter is not a valid key.&quot;) };
+
+    IDBKeyData keyData = { key.get() };
+    IDBKeyData primaryKeyData = { primaryKey.get() };
+
+    if (keyData &lt; m_currentKeyData &amp;&amp; direction == IndexedDB::CursorDirection::Next)
+        return Exception { IDBDatabaseException::DataError, ASCIILiteral(&quot;Failed to execute 'continuePrimaryKey' on 'IDBCursor': The first parameter is less than this cursor's position and this cursor's direction is \&quot;next\&quot;.&quot;) };
+
+    if (keyData &gt; m_currentKeyData &amp;&amp; direction == IndexedDB::CursorDirection::Prev)
+        return Exception { IDBDatabaseException::DataError, ASCIILiteral(&quot;Failed to execute 'continuePrimaryKey' on 'IDBCursor': The first parameter is greater than this cursor's position and this cursor's direction is \&quot;prev\&quot;.&quot;) };
+
+    if (keyData == m_currentKeyData) {
+        if (primaryKeyData &lt;= m_currentPrimaryKeyData &amp;&amp; direction == IndexedDB::CursorDirection::Next)
+            return Exception { IDBDatabaseException::DataError, ASCIILiteral(&quot;Failed to execute 'continuePrimaryKey' on 'IDBCursor': The key parameters represent a position less-than-or-equal-to this cursor's position and this cursor's direction is \&quot;next\&quot;.&quot;) };
+        if (primaryKeyData &gt;= m_currentPrimaryKeyData &amp;&amp; direction == IndexedDB::CursorDirection::Prev)
+            return Exception { IDBDatabaseException::DataError, ASCIILiteral(&quot;Failed to execute 'continuePrimaryKey' on 'IDBCursor': The key parameters represent a position greater-than-or-equal-to this cursor's position and this cursor's direction is \&quot;prev\&quot;.&quot;) };
+    }
+
+    m_gotValue = false;
+
+    uncheckedIterateCursor(keyData, primaryKeyData);
+
+    return { };
+}
+
</ins><span class="cx"> ExceptionOr&lt;void&gt; IDBCursor::continueFunction(ExecState&amp; execState, JSValue keyValue)
</span><span class="cx"> {
</span><span class="cx">     RefPtr&lt;IDBKey&gt; key;
</span><span class="lines">@@ -293,9 +342,19 @@
</span><span class="cx">     ++m_outstandingRequestCount;
</span><span class="cx"> 
</span><span class="cx">     m_request-&gt;willIterateCursor(*this);
</span><del>-    transaction().iterateCursor(*this, { key, count });
</del><ins>+    transaction().iterateCursor(*this, { key, { }, count });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void IDBCursor::uncheckedIterateCursor(const IDBKeyData&amp; key, const IDBKeyData&amp; primaryKey)
+{
+    ASSERT(currentThread() == effectiveObjectStore().transaction().database().originThreadID());
+
+    ++m_outstandingRequestCount;
+
+    m_request-&gt;willIterateCursor(*this);
+    transaction().iterateCursor(*this, { key, primaryKey, 0 });
+}
+
</ins><span class="cx"> ExceptionOr&lt;Ref&lt;WebCore::IDBRequest&gt;&gt; IDBCursor::deleteFunction(ExecState&amp; state)
</span><span class="cx"> {
</span><span class="cx">     LOG(IndexedDB, &quot;IDBCursor::deleteFunction&quot;);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbIDBCursorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/IDBCursor.h (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/IDBCursor.h        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBCursor.h        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -65,6 +65,7 @@
</span><span class="cx">     ExceptionOr&lt;Ref&lt;IDBRequest&gt;&gt; update(JSC::ExecState&amp;, JSC::JSValue);
</span><span class="cx">     ExceptionOr&lt;void&gt; advance(unsigned);
</span><span class="cx">     ExceptionOr&lt;void&gt; continueFunction(JSC::ExecState&amp;, JSC::JSValue key);
</span><ins>+    ExceptionOr&lt;void&gt; continuePrimaryKey(JSC::ExecState&amp;, JSC::JSValue key, JSC::JSValue primaryKey);
</ins><span class="cx">     ExceptionOr&lt;Ref&lt;IDBRequest&gt;&gt; deleteFunction(JSC::ExecState&amp;);
</span><span class="cx"> 
</span><span class="cx">     ExceptionOr&lt;void&gt; continueFunction(const IDBKeyData&amp;);
</span><span class="lines">@@ -96,6 +97,7 @@
</span><span class="cx">     IDBTransaction&amp; transaction() const;
</span><span class="cx"> 
</span><span class="cx">     void uncheckedIterateCursor(const IDBKeyData&amp;, unsigned count);
</span><ins>+    void uncheckedIterateCursor(const IDBKeyData&amp;, const IDBKeyData&amp;);
</ins><span class="cx"> 
</span><span class="cx">     // Cursors are created with an outstanding iteration request.
</span><span class="cx">     unsigned m_outstandingRequestCount { 1 };
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbIDBCursoridl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/IDBCursor.idl (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/IDBCursor.idl        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBCursor.idl        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -39,5 +39,6 @@
</span><span class="cx">     [CallWith=ScriptState, MayThrowException] IDBRequest update(any value);
</span><span class="cx">     [MayThrowException] void advance([EnforceRange] unsigned long count);
</span><span class="cx">     [CallWith=ScriptState, ImplementedAs=continueFunction, MayThrowException] void continue(optional any key);
</span><ins>+    [CallWith=ScriptState, MayThrowException] void continuePrimaryKey(any key, any primaryKey);
</ins><span class="cx">     [CallWith=ScriptState, ImplementedAs=deleteFunction, MayThrowException] IDBRequest delete();
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbIDBKeyDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/IDBKeyData.h (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/IDBKeyData.h        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBKeyData.h        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -95,6 +95,21 @@
</span><span class="cx">     KeyType type() const { return m_type; }
</span><span class="cx"> 
</span><span class="cx">     bool operator&lt;(const IDBKeyData&amp;) const;
</span><ins>+    bool operator&gt;(const IDBKeyData&amp; other) const
+    {
+        return !(*this &lt; other) &amp;&amp; !(*this == other);
+    }
+
+    bool operator&lt;=(const IDBKeyData&amp; other) const
+    {
+        return !(*this &gt; other);
+    }
+
+    bool operator&gt;=(const IDBKeyData&amp; other) const
+    {
+        return !(*this &lt; other);
+    }
+
</ins><span class="cx">     bool operator==(const IDBKeyData&amp; other) const;
</span><span class="cx">     bool operator!=(const IDBKeyData&amp; other) const
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryCursorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryCursor.h (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryCursor.h        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryCursor.h        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -43,7 +43,7 @@
</span><span class="cx">     virtual ~MemoryCursor();
</span><span class="cx"> 
</span><span class="cx">     virtual void currentData(IDBGetResult&amp;) = 0;
</span><del>-    virtual void iterate(const IDBKeyData&amp;, uint32_t count, IDBGetResult&amp;) = 0;
</del><ins>+    virtual void iterate(const IDBKeyData&amp;, const IDBKeyData&amp; primaryKey, uint32_t count, IDBGetResult&amp;) = 0;
</ins><span class="cx"> 
</span><span class="cx">     static MemoryCursor* cursorForIdentifier(const IDBResourceIdentifier&amp;);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryIDBBackingStorecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -538,7 +538,7 @@
</span><span class="cx">     if (!cursor)
</span><span class="cx">         return { IDBDatabaseException::UnknownError, ASCIILiteral(&quot;No backing store cursor found in which to iterate cursor&quot;) };
</span><span class="cx"> 
</span><del>-    cursor-&gt;iterate(data.keyData, data.count, outData);
</del><ins>+    cursor-&gt;iterate(data.keyData, data.primaryKeyData, data.count, outData);
</ins><span class="cx"> 
</span><span class="cx">     return { };
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryIndexCursorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndexCursor.cpp (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndexCursor.cpp        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndexCursor.cpp        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -81,12 +81,17 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MemoryIndexCursor::iterate(const IDBKeyData&amp; key, uint32_t count, IDBGetResult&amp; getResult)
</del><ins>+void MemoryIndexCursor::iterate(const IDBKeyData&amp; key, const IDBKeyData&amp; primaryKey, uint32_t count, IDBGetResult&amp; getResult)
</ins><span class="cx"> {
</span><span class="cx">     LOG(IndexedDB, &quot;MemoryIndexCursor::iterate to key %s, %u count&quot;, key.loggingString().utf8().data(), count);
</span><span class="cx"> 
</span><ins>+#ifndef NDEBUG
+    if (primaryKey.isValid())
+        ASSERT(key.isValid());
+#endif
+
</ins><span class="cx">     if (key.isValid()) {
</span><del>-        // Cannot iterator by both a count and to a key
</del><ins>+        // Cannot iterate by both a count and to a key
</ins><span class="cx">         ASSERT(!count);
</span><span class="cx"> 
</span><span class="cx">         auto* valueStore = m_index.valueStore();
</span><span class="lines">@@ -97,10 +102,17 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (m_info.isDirectionForward())
-            m_currentIterator = valueStore-&gt;find(key);
-        else
-            m_currentIterator = valueStore-&gt;reverseFind(key, m_info.duplicity());
</del><ins>+        if (primaryKey.isValid()) {
+            if (m_info.isDirectionForward())
+                m_currentIterator = valueStore-&gt;find(key, primaryKey);
+            else
+                m_currentIterator = valueStore-&gt;reverseFind(key, primaryKey, m_info.duplicity());
+        } else {
+            if (m_info.isDirectionForward())
+                m_currentIterator = valueStore-&gt;find(key);
+            else
+                m_currentIterator = valueStore-&gt;reverseFind(key, m_info.duplicity());
+        }
</ins><span class="cx"> 
</span><span class="cx">         if (m_currentIterator.isValid() &amp;&amp; !m_info.range().containsKey(m_currentIterator.key()))
</span><span class="cx">             m_currentIterator.invalidate();
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryIndexCursorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndexCursor.h (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndexCursor.h        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndexCursor.h        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -47,7 +47,7 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     void currentData(IDBGetResult&amp;) final;
</span><del>-    void iterate(const IDBKeyData&amp;, uint32_t count, IDBGetResult&amp;) final;
</del><ins>+    void iterate(const IDBKeyData&amp;, const IDBKeyData&amp; primaryKey, uint32_t count, IDBGetResult&amp;) final;
</ins><span class="cx"> 
</span><span class="cx">     MemoryIndex&amp; m_index;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryObjectStoreCursorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStoreCursor.cpp (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStoreCursor.cpp        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStoreCursor.cpp        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -314,10 +314,12 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MemoryObjectStoreCursor::iterate(const IDBKeyData&amp; key, uint32_t count, IDBGetResult&amp; outData)
</del><ins>+void MemoryObjectStoreCursor::iterate(const IDBKeyData&amp; key, const IDBKeyData&amp; primaryKeyData, uint32_t count, IDBGetResult&amp; outData)
</ins><span class="cx"> {
</span><span class="cx">     LOG(IndexedDB, &quot;MemoryObjectStoreCursor::iterate to key %s&quot;, key.loggingString().utf8().data());
</span><span class="cx"> 
</span><ins>+    ASSERT_UNUSED(primaryKeyData, primaryKeyData.isNull());
+
</ins><span class="cx">     if (!m_objectStore.orderedKeys()) {
</span><span class="cx">         m_currentPositionKey = { };
</span><span class="cx">         outData = { };
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryObjectStoreCursorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStoreCursor.h (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStoreCursor.h        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStoreCursor.h        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -49,7 +49,7 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     void currentData(IDBGetResult&amp;) final;
</span><del>-    void iterate(const IDBKeyData&amp;, uint32_t count, IDBGetResult&amp;) final;
</del><ins>+    void iterate(const IDBKeyData&amp;, const IDBKeyData&amp; primaryKey, uint32_t count, IDBGetResult&amp;) final;
</ins><span class="cx"> 
</span><span class="cx">     void setFirstInRemainingRange(std::set&lt;IDBKeyData&gt;&amp;);
</span><span class="cx">     void setForwardIteratorFromRemainingRange(std::set&lt;IDBKeyData&gt;&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverSQLiteIDBBackingStorecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -2290,14 +2290,16 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     auto key = data.keyData;
</span><ins>+    auto primaryKey = data.primaryKeyData;
</ins><span class="cx">     auto count = data.count;
</span><span class="cx"> 
</span><span class="cx">     if (key.isValid()) {
</span><del>-        if (!cursor-&gt;iterate(key)) {
</del><ins>+        if (!cursor-&gt;iterate(key, primaryKey)) {
</ins><span class="cx">             LOG_ERROR(&quot;Attempt to iterate cursor failed&quot;);
</span><span class="cx">             return { IDBDatabaseException::UnknownError, ASCIILiteral(&quot;Attempt to iterate cursor failed&quot;) };
</span><span class="cx">         }
</span><span class="cx">     } else {
</span><ins>+        ASSERT(!primaryKey.isValid());
</ins><span class="cx">         if (!count)
</span><span class="cx">             count = 1;
</span><span class="cx">         if (!cursor-&gt;advance(count)) {
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverSQLiteIDBCursorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBCursor.cpp (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBCursor.cpp        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBCursor.cpp        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -440,7 +440,7 @@
</span><span class="cx">     return AdvanceResult::Success;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool SQLiteIDBCursor::iterate(const WebCore::IDBKeyData&amp; targetKey)
</del><ins>+bool SQLiteIDBCursor::iterate(const IDBKeyData&amp; targetKey, const IDBKeyData&amp; targetPrimaryKey)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_transaction-&gt;sqliteTransaction());
</span><span class="cx">     ASSERT(m_statement);
</span><span class="lines">@@ -465,6 +465,22 @@
</span><span class="cx">         result = advance(1);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    if (targetPrimaryKey.isValid()) {
+        while (!m_completed &amp;&amp; !m_currentKey.compare(targetKey)) {
+            if (!result)
+                return false;
+
+            // Search for the next primary key &gt;= the primary target if the cursor is a Next cursor, or the next key &lt;= if the cursor is a Previous cursor.
+            if (m_cursorDirection == IndexedDB::CursorDirection::Next || m_cursorDirection == IndexedDB::CursorDirection::NextNoDuplicate) {
+                if (m_currentPrimaryKey.compare(targetPrimaryKey) &gt;= 0)
+                    break;
+            } else if (m_currentPrimaryKey.compare(targetPrimaryKey) &lt;= 0)
+                break;
+
+            result = advance(1);
+        }
+    }
+
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverSQLiteIDBCursorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBCursor.h (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBCursor.h        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBCursor.h        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -65,7 +65,7 @@
</span><span class="cx">     IDBValue* currentValue() const { return m_currentValue.get(); }
</span><span class="cx"> 
</span><span class="cx">     bool advance(uint64_t count);
</span><del>-    bool iterate(const IDBKeyData&amp; targetKey);
</del><ins>+    bool iterate(const IDBKeyData&amp; targetKey, const IDBKeyData&amp; targetPrimaryKey);
</ins><span class="cx"> 
</span><span class="cx">     bool didComplete() const { return m_completed; }
</span><span class="cx">     bool didError() const { return m_errored; }
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbsharedIDBIterateCursorDatacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/shared/IDBIterateCursorData.cpp (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/shared/IDBIterateCursorData.cpp        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/Source/WebCore/Modules/indexeddb/shared/IDBIterateCursorData.cpp        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -32,7 +32,7 @@
</span><span class="cx"> 
</span><span class="cx"> IDBIterateCursorData IDBIterateCursorData::isolatedCopy() const
</span><span class="cx"> {
</span><del>-    return { keyData.isolatedCopy(), count };
</del><ins>+    return { keyData.isolatedCopy(), primaryKeyData.isolatedCopy(), count };
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbsharedIDBIterateCursorDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/shared/IDBIterateCursorData.h (208499 => 208500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/shared/IDBIterateCursorData.h        2016-11-09 23:28:12 UTC (rev 208499)
+++ trunk/Source/WebCore/Modules/indexeddb/shared/IDBIterateCursorData.h        2016-11-09 23:29:38 UTC (rev 208500)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> 
</span><span class="cx"> struct IDBIterateCursorData {
</span><span class="cx">     IDBKeyData keyData;
</span><ins>+    IDBKeyData primaryKeyData;
</ins><span class="cx">     unsigned count;
</span><span class="cx"> 
</span><span class="cx">     IDBIterateCursorData isolatedCopy() const;
</span><span class="lines">@@ -44,7 +45,7 @@
</span><span class="cx"> template&lt;class Encoder&gt;
</span><span class="cx"> void IDBIterateCursorData::encode(Encoder&amp; encoder) const
</span><span class="cx"> {
</span><del>-    encoder &lt;&lt; keyData &lt;&lt; static_cast&lt;uint64_t&gt;(count);
</del><ins>+    encoder &lt;&lt; keyData &lt;&lt; primaryKeyData &lt;&lt; static_cast&lt;uint64_t&gt;(count);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;class Decoder&gt;
</span><span class="lines">@@ -53,6 +54,9 @@
</span><span class="cx">     if (!decoder.decode(iteratorCursorData.keyData))
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><ins>+    if (!decoder.decode(iteratorCursorData.primaryKeyData))
+        return false;
+
</ins><span class="cx">     uint64_t count;
</span><span class="cx">     if (!decoder.decode(count))
</span><span class="cx">         return false;
</span></span></pre>
</div>
</div>

</body>
</html>