<!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>):
(WebCore::IDBKeyData::operator<=):
(WebCore::IDBKeyData::operator>=):
* 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 <beidson@apple.com>
+
+ 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 <graouts@apple.com>
</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 <beidson@apple.com>
</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 <beidson@apple.com>
+
</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 "function () {
- cursor.continuePrimaryKey("..." threw object "TypeError: cursor.continuePrimaryKey is not a function. (..." that is not a DOMException TransactionInactiveError: property "code" 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 "function () {
- cursor.continuePrimaryKey("..." threw object "TypeError: cursor.continuePrimaryKey is not a function. (..." that is not a DOMException TransactionInactiveError: property "code" 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 "function () {
- cursor.continuePrimaryKey("..." threw object "TypeError: cursor.continuePrimaryKey is not a function. (..." that is not a DOMException InvalidStateError: property "code" 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 "function () {
- cursor.continuePrimaryKey("A"..." threw object "TypeError: cursor.continuePrimaryKey is not a function. (..." that is not a DOMException InvalidStateError: property "code" 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 "function () {
- cursor.continuePrimaryKey("..." threw object "TypeError: cursor.continuePrimaryKey is not a function. (..." that is not a DOMException InvalidAccessError: property "code" 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 "function () {
- cursor.continuePrimaryK..." threw object "TypeError: cursor.continuePrimaryKey is not a function. (..." that is not a DOMException InvalidAccessError: property "code" 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 "function () {
- cursor.continuePrimaryK..." threw object "TypeError: cursor.continuePrimaryKey is not a function. (..." that is not a DOMException InvalidAccessError: property "code" 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 "function () {
- cursor.continuePrimaryKey("..." threw object "TypeError: cursor.continuePrimaryKey is not a function. (..." that is not a DOMException InvalidAccessError: property "code" 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 "function () {
- cursor.continuePrimaryK..." threw object "TypeError: cursor.continuePrimaryKey is not a function. (..." that is not a DOMException InvalidStateError: property "code" 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 "function () {
- cursor.continuePrimaryKey(n..." threw object "TypeError: cursor.continuePrimaryKey is not a function. (..." that is not a DOMException InvalidStateError: property "code" is equal to undefined, expected 11
-FAIL DataError(unset key) assert_throws: DataError is expected if key is unset. function "function () {
- cursor.continuePrimaryKey(n..." threw object "TypeError: cursor.continuePrimaryKey is not a function. (..." that is not a DOMException DataError: property "code" is equal to undefined, expected 0
-FAIL DataError(unset primary key) assert_throws: DataError is expected if primary key is unset. function "function () {
- cursor.continuePrimaryKey("..." threw object "TypeError: cursor.continuePrimaryKey is not a function. (..." that is not a DOMException DataError: property "code" 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 "function () {
- cursor.continuePrimaryKey("..." threw object "TypeError: cursor.continuePrimaryKey is not a function. (..." that is not a DOMException DataError: property "code" 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 "function () {
- cursor.continuePrimaryKey("..." threw object "TypeError: cursor.continuePrimaryKey is not a function. (..." that is not a DOMException DataError: property "code" 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 "function"
</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 "function"
</ins><span class="cx"> PASS 'advance' in cursor is true
</span><span class="cx"> PASS typeof cursor.advance is "function"
</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 "function"
</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 "function"
</ins><span class="cx"> PASS 'advance' in cursor is true
</span><span class="cx"> PASS typeof cursor.advance is "function"
</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 "function"
</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 "function"
</ins><span class="cx"> PASS 'advance' in cursor is true
</span><span class="cx"> PASS typeof cursor.advance is "function"
</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 "function"
</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 "function"
</ins><span class="cx"> PASS 'advance' in cursor is true
</span><span class="cx"> PASS typeof cursor.advance is "function"
</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 "function"
</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 "function"
</ins><span class="cx"> PASS 'advance' in cursor is true
</span><span class="cx"> PASS typeof cursor.advance is "function"
</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 "function"
</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 "function"
</ins><span class="cx"> PASS 'advance' in cursor is true
</span><span class="cx"> PASS typeof cursor.advance is "function"
</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 "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS !!cursor is true
+PASS "transaction-state check should precede deletion check" threw as expected
+PASS !!cursor is true
+PASS "deletion check should precede index source check" threw as expected
+PASS !!cursor is true
+PASS "deletion check should precede cursor direction check" threw as expected
+PASS "direction check should precede got_value_flag check" threw as expected
+PASS !!cursor is true
+PASS "direction check should precede iteration ongoing check" threw as expected
+PASS !!cursor is true
+PASS "index source check should precede iteration ongoing check" threw as expected
+PASS "index source check should precede got_value_flag check" threw as expected
+PASS !!cursor is true
+PASS "iteration ongoing check should precede unset key check" threw as expected
+PASS "got_value_flag check should precede unset key check" threw as expected
+PASS !!cursor is true
+PASS "DataError is expected if key is unset." threw as expected
+PASS !!cursor is true
+PASS "DataError is expected if primary key is unset." threw as expected
+PASS !!cursor is true
+PASS "DataError is expected if key is lower then current one." threw as expected
+PASS "DataError is expected if primary key is equal to current one." threw as expected
+PASS "DataError is expected if primary key is lower than current one." threw as expected
+PASS !!cursor is true
+PASS "DataError is expected if key is larger then current one." threw as expected
+PASS "DataError is expected if primary key is equal to current one." threw as expected
+PASS "DataError is expected if primary key is larger than current one." 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 "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS !!cursor is true
+PASS "transaction-state check should precede deletion check" threw as expected
+PASS !!cursor is true
+PASS "deletion check should precede index source check" threw as expected
+PASS !!cursor is true
+PASS "deletion check should precede cursor direction check" threw as expected
+PASS "direction check should precede got_value_flag check" threw as expected
+PASS !!cursor is true
+PASS "direction check should precede iteration ongoing check" threw as expected
+PASS !!cursor is true
+PASS "index source check should precede iteration ongoing check" threw as expected
+PASS "index source check should precede got_value_flag check" threw as expected
+PASS !!cursor is true
+PASS "iteration ongoing check should precede unset key check" threw as expected
+PASS "got_value_flag check should precede unset key check" threw as expected
+PASS !!cursor is true
+PASS "DataError is expected if key is unset." threw as expected
+PASS !!cursor is true
+PASS "DataError is expected if primary key is unset." threw as expected
+PASS !!cursor is true
+PASS "DataError is expected if key is lower then current one." threw as expected
+PASS "DataError is expected if primary key is equal to current one." threw as expected
+PASS "DataError is expected if primary key is lower than current one." threw as expected
+PASS !!cursor is true
+PASS "DataError is expected if key is larger then current one." threw as expected
+PASS "DataError is expected if primary key is equal to current one." threw as expected
+PASS "DataError is expected if primary key is larger than current one." 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>+<html>
+<head>
+<script>
+enablePrivateBrowsing = true;
+</script>
+<script src="../../../resources/js-test.js"></script>
+<script src="../resources/shared.js"></script>
+</head>
+<body>
+
+<script src="resources/idbcursor-continue-primary-key-1.js"></script>
+</body>
+</html>
</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>+<html>
+<head>
+<script src="../../../resources/js-test.js"></script>
+<script src="../resources/shared.js"></script>
+</head>
+<body>
+
+<script src="resources/idbcursor-continue-primary-key-1.js"></script>
+</body>
+</html>
</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("This test verifies the basic functionality of IDBCursor.continuePrimaryKey().");
+
+function setup_test_store(db) {
+        var records = [ { iKey: "A", pKey: 1 },
+         { iKey: "A", pKey: 2 },
+         { iKey: "A", pKey: 3 },
+         { iKey: "A", pKey: 4 },
+         { iKey: "B", pKey: 5 },
+         { iKey: "B", pKey: 6 },
+         { iKey: "B", pKey: 7 },
+         { iKey: "C", pKey: 8 },
+         { iKey: "C", pKey: 9 },
+         { iKey: "D", pKey: 10 } ];
+
+ var store = db.createObjectStore("test", { keyPath: "pKey" });
+ var index = store.createIndex("idx", "iKey");
+
+ for(var i = 0; i < records.length; i++)
+ store.add(records[i]);
+
+ return store;
+}
+
+function log(message)
+{
+ debug(message);
+}
+
+function next()
+{
+ testGenerator.next();
+}
+
+function asyncNext()
+{
+ setTimeout("testGenerator.next();", 0);
+}
+
+function unreached(description)
+{
+        return function() {
+                debug("FAIL: " + description);
+                finishJSTest();
+        }
+};
+
+var dbName = window.location.href + " test";
+var db;
+
+var testGenerator = testSteps();
+testGenerator.next();
+
+function shouldThrowType(name, func, text) {
+ var errorText = text + " should throw an exception";
+ try {
+ func();
+ testFailed(errorText);
+ } catch (e) {
+                if (e.name == name)
+         testPassed('"' + text + "\" threw as expected");
+ else
+                        testFailed(text + " should throw exception type " + name + ", but threw " + e.name + " instead");
+ }
+}
+
+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("idx");
+                var cursor_rq = index.openCursor();
+
+                cursor_rq.onerror = unreached('openCursor should succeed');
+                cursor_rq.onsuccess = function(e) {
+                 cursor = e.target.result;
+ shouldBeTrue("!!cursor");
+
+                 store.deleteIndex("idx");
+                };
+                txn.oncomplete = function() {
+                 shouldThrowType("TransactionInactiveError", function() {
+                 cursor.continuePrimaryKey("A", 4);
+                 }, "transaction-state check should precede deletion check");
+                        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("!!cursor");
+
+ db.deleteObjectStore("test");
+
+ shouldThrowType("InvalidStateError", function() {
+ cursor.continuePrimaryKey("A", 4);
+ }, "deletion check should precede index source check");
+
+                        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("idx");
+ var cursor_rq = index.openCursor(null, "nextunique");
+
+ cursor_rq.onerror = unreached('openCursor should succeed');
+ cursor_rq.onsuccess = function(e) {
+ cursor = e.target.result;
+ shouldBeTrue("!!cursor");
+
+ store.deleteIndex("idx");
+
+ shouldThrowType("InvalidStateError", function() {
+ cursor.continuePrimaryKey("A", 4);
+ }, "deletion check should precede cursor direction check");
+                        
+                        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("test", {keyPath:"pKey"});
+ var index = store.createIndex("idx", "iKey");
+
+ store.add({ iKey: "A", pKey: 1 });
+
+ var cursor_rq = index.openCursor(null, "nextunique");
+
+ cursor_rq.onerror = unreached('openCursor should succeed');
+ cursor_rq.onsuccess = function(e) {
+ if (e.target.result) {
+ cursor = e.target.result;
+ cursor.continue();
+ return;
+ }
+
+ shouldThrowType("InvalidAccessError", function() {
+ cursor.continuePrimaryKey("A", 4);
+ }, "direction check should precede got_value_flag check");
+
+                        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("test", {keyPath:"pKey"});
+ var index = store.createIndex("idx", "iKey");
+
+ store.add({ iKey: "A", pKey: 1 });
+
+ var cursor_rq = index.openCursor(null, "nextunique");
+
+ cursor_rq.onerror = unreached('openCursor should succeed');
+ cursor_rq.onsuccess = function(e) {
+ if (!cursor) {
+ cursor = e.target.result;
+ shouldBeTrue("!!cursor");
+
+ cursor.continue();
+
+ shouldThrowType("InvalidAccessError", function() {
+ cursor.continuePrimaryKey("A", 4);
+ }, "direction check should precede iteration ongoing check");
+
+                                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("!!cursor");
+
+ cursor.continue();
+
+ shouldThrowType("InvalidAccessError", function() {
+ cursor.continuePrimaryKey("A", 4);
+ }, "index source check should precede iteration ongoing check");
+
+                                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("test", {keyPath:"pKey"});
+
+ store.add({ iKey: "A", 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("InvalidAccessError", function() {
+ cursor.continuePrimaryKey("A", 4);
+ }, "index source check should precede got_value_flag check");
+                 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("idx");
+ var cursor_rq = index.openCursor();
+
+ cursor_rq.onerror = unreached('openCursor should succeed');
+ cursor_rq.onsuccess = function(e) {
+ if (!cursor) {
+ cursor = e.target.result;
+ shouldBeTrue("!!cursor");
+
+ cursor.continue();
+
+ shouldThrowType("InvalidStateError", function() {
+ cursor.continuePrimaryKey(null, 4);
+ }, "iteration ongoing check should precede unset key check");
+
+                                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("test", {keyPath:"pKey"});
+ var index = store.createIndex("idx", "iKey");
+
+ store.add({ iKey: "A", 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("InvalidStateError", function() {
+ cursor.continuePrimaryKey(null, 4);
+ }, "got_value_flag check should precede unset key check");
+                         
+                        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("idx");
+ var cursor_rq = index.openCursor();
+
+ cursor_rq.onerror = unreached('openCursor should succeed');
+ cursor_rq.onsuccess = function(e) {
+ cursor = e.target.result;
+ shouldBeTrue("!!cursor");
+
+ shouldThrowType("DataError", function() {
+ cursor.continuePrimaryKey(null, 4);
+ }, "DataError is expected if key is unset.");
+
+                        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("idx");
+ var cursor_rq = index.openCursor();
+
+ cursor_rq.onerror = unreached('openCursor should succeed');
+ cursor_rq.onsuccess = function(e) {
+ cursor = e.target.result;
+ shouldBeTrue("!!cursor");
+
+ shouldThrowType("DataError", function() {
+ cursor.continuePrimaryKey("A", null);
+ }, "DataError is expected if primary key is unset.");
+
+                        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("idx");
+ var cursor_rq = index.openCursor(IDBKeyRange.lowerBound("B"));
+
+ cursor_rq.onerror = unreached('openCursor should succeed');
+ cursor_rq.onsuccess = function(e) {
+ cursor = e.target.result;
+ shouldBeTrue("!!cursor");
+
+ shouldBeTrue("cursor.key == 'B'", "expected key");
+ shouldBeTrue("cursor.primaryKey == 5", "expected primary key");
+
+ shouldThrowType("DataError", function() {
+ cursor.continuePrimaryKey("A", 6);
+ }, "DataError is expected if key is lower then current one.");
+
+ shouldThrowType("DataError", function() {
+ cursor.continuePrimaryKey("B", 5);
+ }, "DataError is expected if primary key is equal to current one.");
+
+ shouldThrowType("DataError", function() {
+ cursor.continuePrimaryKey("B", 4);
+ }, "DataError is expected if primary key is lower than current one.");
+
+                        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("idx");
+ var cursor_rq = index.openCursor(IDBKeyRange.upperBound("B"), "prev");
+
+ cursor_rq.onerror = unreached('openCursor should succeed');
+ cursor_rq.onsuccess = function(e) {
+ cursor = e.target.result;
+ shouldBeTrue("!!cursor");
+
+ shouldBeTrue("cursor.key == 'B'", "expected key");
+ shouldBeTrue("cursor.primaryKey == 7", "expected primary key");
+
+ shouldThrowType("DataError", function() {
+ cursor.continuePrimaryKey("C", 6);
+ }, "DataError is expected if key is larger then current one.");
+
+ shouldThrowType("DataError", function() {
+ cursor.continuePrimaryKey("B", 7);
+ }, "DataError is expected if primary key is equal to current one.");
+
+ shouldThrowType("DataError", function() {
+ cursor.continuePrimaryKey("B", 8);
+ }, "DataError is expected if primary key is larger than current one.");
+
+                        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 <beidson@apple.com>
+
+ 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>):
+ (WebCore::IDBKeyData::operator<=):
+ (WebCore::IDBKeyData::operator>=):
+
+ * 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 <graouts@apple.com>
</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<void> IDBCursor::continuePrimaryKey(ExecState& state, JSValue keyValue, JSValue primaryKeyValue)
+{
+ if (!transaction().isActive())
+ return Exception { IDBDatabaseException::TransactionInactiveError, ASCIILiteral("Failed to execute 'continuePrimaryKey' on 'IDBCursor': The transaction is inactive or finished.") };
+
+ if (sourcesDeleted())
+ return Exception { IDBDatabaseException::InvalidStateError, ASCIILiteral("Failed to execute 'continuePrimaryKey' on 'IDBCursor': The cursor's source or effective object store has been deleted.") };
+
+ if (!m_index)
+ return Exception { IDBDatabaseException::InvalidAccessError, ASCIILiteral("Failed to execute 'continuePrimaryKey' on 'IDBCursor': The cursor's source is not an index.") };
+
+ auto direction = m_info.cursorDirection();
+ if (direction != IndexedDB::CursorDirection::Next && direction != IndexedDB::CursorDirection::Prev)
+ return Exception { IDBDatabaseException::InvalidAccessError, ASCIILiteral("Failed to execute 'continuePrimaryKey' on 'IDBCursor': The cursor's direction must be either \"next\" or \"prev\".") };
+
+ if (!m_gotValue)
+ return Exception { IDBDatabaseException::InvalidStateError, ASCIILiteral("Failed to execute 'continuePrimaryKey' on 'IDBCursor': The cursor is being iterated or has iterated past its end.") };
+
+ RefPtr<IDBKey> key = scriptValueToIDBKey(state, keyValue);
+ if (!key->isValid())
+ return Exception { IDBDatabaseException::DataError, ASCIILiteral("Failed to execute 'continuePrimaryKey' on 'IDBCursor': The first parameter is not a valid key.") };
+
+ RefPtr<IDBKey> primaryKey = scriptValueToIDBKey(state, primaryKeyValue);
+ if (!primaryKey->isValid())
+ return Exception { IDBDatabaseException::DataError, ASCIILiteral("Failed to execute 'continuePrimaryKey' on 'IDBCursor': The second parameter is not a valid key.") };
+
+ IDBKeyData keyData = { key.get() };
+ IDBKeyData primaryKeyData = { primaryKey.get() };
+
+ if (keyData < m_currentKeyData && direction == IndexedDB::CursorDirection::Next)
+ return Exception { IDBDatabaseException::DataError, ASCIILiteral("Failed to execute 'continuePrimaryKey' on 'IDBCursor': The first parameter is less than this cursor's position and this cursor's direction is \"next\".") };
+
+ if (keyData > m_currentKeyData && direction == IndexedDB::CursorDirection::Prev)
+ return Exception { IDBDatabaseException::DataError, ASCIILiteral("Failed to execute 'continuePrimaryKey' on 'IDBCursor': The first parameter is greater than this cursor's position and this cursor's direction is \"prev\".") };
+
+ if (keyData == m_currentKeyData) {
+ if (primaryKeyData <= m_currentPrimaryKeyData && direction == IndexedDB::CursorDirection::Next)
+ return Exception { IDBDatabaseException::DataError, ASCIILiteral("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 \"next\".") };
+ if (primaryKeyData >= m_currentPrimaryKeyData && direction == IndexedDB::CursorDirection::Prev)
+ return Exception { IDBDatabaseException::DataError, ASCIILiteral("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 \"prev\".") };
+ }
+
+ m_gotValue = false;
+
+ uncheckedIterateCursor(keyData, primaryKeyData);
+
+ return { };
+}
+
</ins><span class="cx"> ExceptionOr<void> IDBCursor::continueFunction(ExecState& execState, JSValue keyValue)
</span><span class="cx"> {
</span><span class="cx"> RefPtr<IDBKey> 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->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& key, const IDBKeyData& primaryKey)
+{
+ ASSERT(currentThread() == effectiveObjectStore().transaction().database().originThreadID());
+
+ ++m_outstandingRequestCount;
+
+ m_request->willIterateCursor(*this);
+ transaction().iterateCursor(*this, { key, primaryKey, 0 });
+}
+
</ins><span class="cx"> ExceptionOr<Ref<WebCore::IDBRequest>> IDBCursor::deleteFunction(ExecState& state)
</span><span class="cx"> {
</span><span class="cx"> LOG(IndexedDB, "IDBCursor::deleteFunction");
</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<Ref<IDBRequest>> update(JSC::ExecState&, JSC::JSValue);
</span><span class="cx"> ExceptionOr<void> advance(unsigned);
</span><span class="cx"> ExceptionOr<void> continueFunction(JSC::ExecState&, JSC::JSValue key);
</span><ins>+ ExceptionOr<void> continuePrimaryKey(JSC::ExecState&, JSC::JSValue key, JSC::JSValue primaryKey);
</ins><span class="cx"> ExceptionOr<Ref<IDBRequest>> deleteFunction(JSC::ExecState&);
</span><span class="cx">
</span><span class="cx"> ExceptionOr<void> continueFunction(const IDBKeyData&);
</span><span class="lines">@@ -96,6 +97,7 @@
</span><span class="cx"> IDBTransaction& transaction() const;
</span><span class="cx">
</span><span class="cx"> void uncheckedIterateCursor(const IDBKeyData&, unsigned count);
</span><ins>+ void uncheckedIterateCursor(const IDBKeyData&, const IDBKeyData&);
</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<(const IDBKeyData&) const;
</span><ins>+ bool operator>(const IDBKeyData& other) const
+ {
+ return !(*this < other) && !(*this == other);
+ }
+
+ bool operator<=(const IDBKeyData& other) const
+ {
+ return !(*this > other);
+ }
+
+ bool operator>=(const IDBKeyData& other) const
+ {
+ return !(*this < other);
+ }
+
</ins><span class="cx"> bool operator==(const IDBKeyData& other) const;
</span><span class="cx"> bool operator!=(const IDBKeyData& 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&) = 0;
</span><del>- virtual void iterate(const IDBKeyData&, uint32_t count, IDBGetResult&) = 0;
</del><ins>+ virtual void iterate(const IDBKeyData&, const IDBKeyData& primaryKey, uint32_t count, IDBGetResult&) = 0;
</ins><span class="cx">
</span><span class="cx"> static MemoryCursor* cursorForIdentifier(const IDBResourceIdentifier&);
</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("No backing store cursor found in which to iterate cursor") };
</span><span class="cx">
</span><del>- cursor->iterate(data.keyData, data.count, outData);
</del><ins>+ cursor->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& key, uint32_t count, IDBGetResult& getResult)
</del><ins>+void MemoryIndexCursor::iterate(const IDBKeyData& key, const IDBKeyData& primaryKey, uint32_t count, IDBGetResult& getResult)
</ins><span class="cx"> {
</span><span class="cx"> LOG(IndexedDB, "MemoryIndexCursor::iterate to key %s, %u count", 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->find(key);
- else
- m_currentIterator = valueStore->reverseFind(key, m_info.duplicity());
</del><ins>+ if (primaryKey.isValid()) {
+ if (m_info.isDirectionForward())
+ m_currentIterator = valueStore->find(key, primaryKey);
+ else
+ m_currentIterator = valueStore->reverseFind(key, primaryKey, m_info.duplicity());
+ } else {
+ if (m_info.isDirectionForward())
+ m_currentIterator = valueStore->find(key);
+ else
+ m_currentIterator = valueStore->reverseFind(key, m_info.duplicity());
+ }
</ins><span class="cx">
</span><span class="cx"> if (m_currentIterator.isValid() && !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&) final;
</span><del>- void iterate(const IDBKeyData&, uint32_t count, IDBGetResult&) final;
</del><ins>+ void iterate(const IDBKeyData&, const IDBKeyData& primaryKey, uint32_t count, IDBGetResult&) final;
</ins><span class="cx">
</span><span class="cx"> MemoryIndex& 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& key, uint32_t count, IDBGetResult& outData)
</del><ins>+void MemoryObjectStoreCursor::iterate(const IDBKeyData& key, const IDBKeyData& primaryKeyData, uint32_t count, IDBGetResult& outData)
</ins><span class="cx"> {
</span><span class="cx"> LOG(IndexedDB, "MemoryObjectStoreCursor::iterate to key %s", 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&) final;
</span><del>- void iterate(const IDBKeyData&, uint32_t count, IDBGetResult&) final;
</del><ins>+ void iterate(const IDBKeyData&, const IDBKeyData& primaryKey, uint32_t count, IDBGetResult&) final;
</ins><span class="cx">
</span><span class="cx"> void setFirstInRemainingRange(std::set<IDBKeyData>&);
</span><span class="cx"> void setForwardIteratorFromRemainingRange(std::set<IDBKeyData>&);
</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->iterate(key)) {
</del><ins>+ if (!cursor->iterate(key, primaryKey)) {
</ins><span class="cx"> LOG_ERROR("Attempt to iterate cursor failed");
</span><span class="cx"> return { IDBDatabaseException::UnknownError, ASCIILiteral("Attempt to iterate cursor failed") };
</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->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& targetKey)
</del><ins>+bool SQLiteIDBCursor::iterate(const IDBKeyData& targetKey, const IDBKeyData& targetPrimaryKey)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(m_transaction->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 && !m_currentKey.compare(targetKey)) {
+ if (!result)
+ return false;
+
+ // Search for the next primary key >= the primary target if the cursor is a Next cursor, or the next key <= if the cursor is a Previous cursor.
+ if (m_cursorDirection == IndexedDB::CursorDirection::Next || m_cursorDirection == IndexedDB::CursorDirection::NextNoDuplicate) {
+ if (m_currentPrimaryKey.compare(targetPrimaryKey) >= 0)
+ break;
+ } else if (m_currentPrimaryKey.compare(targetPrimaryKey) <= 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& targetKey);
</del><ins>+ bool iterate(const IDBKeyData& targetKey, const IDBKeyData& 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<class Encoder>
</span><span class="cx"> void IDBIterateCursorData::encode(Encoder& encoder) const
</span><span class="cx"> {
</span><del>- encoder << keyData << static_cast<uint64_t>(count);
</del><ins>+ encoder << keyData << primaryKeyData << static_cast<uint64_t>(count);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> template<class Decoder>
</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>