<!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>[192294] 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/192294">192294</a></dd>
<dt>Author</dt> <dd>beidson@apple.com</dd>
<dt>Date</dt> <dd>2015-11-10 22:07:03 -0800 (Tue, 10 Nov 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>Modern IDB: Make indexes actually index.
https://bugs.webkit.org/show_bug.cgi?id=150939
Reviewed by Alex Christensen.
Source/WebCore:
Tests: storage/indexeddb/modern/index-1.html
storage/indexeddb/modern/index-2.html
storage/indexeddb/modern/index-3.html
* CMakeLists.txt:
* WebCore.xcodeproj/project.pbxproj:
* Modules/indexeddb/IDBKeyData.h:
(WebCore::IDBKeyData::hash): Deleted.
* Modules/indexeddb/IDBKeyRangeData.cpp:
(WebCore::IDBKeyRangeData::isExactlyOneKey):
* Modules/indexeddb/client/IDBTransactionImpl.cpp:
(WebCore::IDBClient::IDBTransaction::didGetRecordOnServer):
* Modules/indexeddb/server/IndexValueEntry.cpp: Copied from Source/WebCore/Modules/indexeddb/server/MemoryIndex.cpp.
(WebCore::IDBServer::IndexValueEntry::IndexValueEntry):
(WebCore::IDBServer::IndexValueEntry::~IndexValueEntry):
(WebCore::IDBServer::IndexValueEntry::addKey):
(WebCore::IDBServer::IndexValueEntry::removeKey):
(WebCore::IDBServer::IndexValueEntry::getLowest):
(WebCore::IDBServer::IndexValueEntry::getCount):
* Modules/indexeddb/server/IndexValueEntry.h: Copied from Source/WebCore/Modules/indexeddb/server/MemoryIndex.h.
* Modules/indexeddb/server/IndexValueStore.cpp: Added.
(WebCore::IDBServer::IndexValueStore::IndexValueStore):
(WebCore::IDBServer::IndexValueStore::lowestValueForKey):
(WebCore::IDBServer::IndexValueStore::countForKey):
(WebCore::IDBServer::IndexValueStore::contains):
(WebCore::IDBServer::IndexValueStore::addRecord):
(WebCore::IDBServer::IndexValueStore::removeRecord):
(WebCore::IDBServer::IndexValueStore::removeEntriesWithValueKey):
(WebCore::IDBServer::IndexValueStore::lowestKeyWithRecordInRange):
* Modules/indexeddb/server/IndexValueStore.h: Copied from Source/WebCore/Modules/indexeddb/server/MemoryIndex.h.
* Modules/indexeddb/server/MemoryBackingStoreTransaction.cpp:
(WebCore::IDBServer::MemoryBackingStoreTransaction::objectStoreCleared):
(WebCore::IDBServer::MemoryBackingStoreTransaction::indexCleared):
(WebCore::IDBServer::MemoryBackingStoreTransaction::abort):
* Modules/indexeddb/server/MemoryBackingStoreTransaction.h:
* Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
(WebCore::IDBServer::MemoryIDBBackingStore::addRecord):
* Modules/indexeddb/server/MemoryIndex.cpp:
(WebCore::IDBServer::MemoryIndex::create):
(WebCore::IDBServer::MemoryIndex::MemoryIndex):
(WebCore::IDBServer::MemoryIndex::objectStoreCleared):
(WebCore::IDBServer::MemoryIndex::replaceIndexValueStore):
(WebCore::IDBServer::MemoryIndex::getResultForKeyRange):
(WebCore::IDBServer::MemoryIndex::countForKeyRange):
(WebCore::IDBServer::MemoryIndex::putIndexKey):
(WebCore::IDBServer::MemoryIndex::removeRecord):
(WebCore::IDBServer::MemoryIndex::removeEntriesWithValueKey):
(WebCore::IDBServer::MemoryIndex::valueForKeyRange): Deleted.
* Modules/indexeddb/server/MemoryIndex.h:
* Modules/indexeddb/server/MemoryObjectStore.cpp:
(WebCore::IDBServer::MemoryObjectStore::createIndex):
(WebCore::IDBServer::MemoryObjectStore::clear):
(WebCore::IDBServer::MemoryObjectStore::deleteRecord):
(WebCore::IDBServer::MemoryObjectStore::addRecord):
(WebCore::IDBServer::indexVM):
(WebCore::IDBServer::indexGlobalExec):
(WebCore::IDBServer::MemoryObjectStore::updateIndexesForDeleteRecord):
(WebCore::IDBServer::MemoryObjectStore::updateIndexesForPutRecord):
(WebCore::IDBServer::MemoryObjectStore::indexValueForKeyRange):
* Modules/indexeddb/server/MemoryObjectStore.h:
(WebCore::IDBServer::MemoryObjectStore::writeTransaction):
* Modules/indexeddb/shared/IndexKey.cpp: Copied from Source/WebCore/Modules/indexeddb/IDBKeyRangeData.cpp.
(WebCore::IndexKey::IndexKey):
(WebCore::IndexKey::isolatedCopy):
(WebCore::IndexKey::asOneKey):
(WebCore::IndexKey::multiEntry):
* Modules/indexeddb/shared/IndexKey.h: Added.
(WebCore::IndexKey::isNull):
* bindings/js/IDBBindingUtilities.cpp:
(WebCore::idbValueDataToJSValue):
(WebCore::deserializeIDBValueBuffer):
(WebCore::idbKeyDataToScriptValue):
(WebCore::createKeyPathArray):
(WebCore::generateIndexKeyForValue):
* bindings/js/IDBBindingUtilities.h:
LayoutTests:
* storage/indexeddb/modern/index-1-expected.txt: Added.
* storage/indexeddb/modern/index-1.html: Added.
* storage/indexeddb/modern/index-2-expected.txt: Added.
* storage/indexeddb/modern/index-2.html: Added.
* storage/indexeddb/modern/index-3-expected.txt: Added.
* storage/indexeddb/modern/index-3.html: Added.
* storage/indexeddb/modern/index-get-count-basic-expected.txt:
* storage/indexeddb/modern/index-get-count-basic.html:</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmodernindexgetcountbasicexpectedtxt">trunk/LayoutTests/storage/indexeddb/modern/index-get-count-basic-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmodernindexgetcountbasichtml">trunk/LayoutTests/storage/indexeddb/modern/index-get-count-basic.html</a></li>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbIDBKeyDatah">trunk/Source/WebCore/Modules/indexeddb/IDBKeyData.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbIDBKeyRangeDatacpp">trunk/Source/WebCore/Modules/indexeddb/IDBKeyRangeData.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbclientIDBTransactionImplcpp">trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverMemoryBackingStoreTransactioncpp">trunk/Source/WebCore/Modules/indexeddb/server/MemoryBackingStoreTransaction.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverMemoryBackingStoreTransactionh">trunk/Source/WebCore/Modules/indexeddb/server/MemoryBackingStoreTransaction.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverMemoryIDBBackingStorecpp">trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverMemoryIndexcpp">trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndex.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverMemoryIndexh">trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndex.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverMemoryObjectStorecpp">trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverMemoryObjectStoreh">trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.h</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCorebindingsjsIDBBindingUtilitiescpp">trunk/Source/WebCore/bindings/js/IDBBindingUtilities.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsIDBBindingUtilitiesh">trunk/Source/WebCore/bindings/js/IDBBindingUtilities.h</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsstorageindexeddbmodernindex1expectedtxt">trunk/LayoutTests/storage/indexeddb/modern/index-1-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmodernindex1html">trunk/LayoutTests/storage/indexeddb/modern/index-1.html</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmodernindex2expectedtxt">trunk/LayoutTests/storage/indexeddb/modern/index-2-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmodernindex2html">trunk/LayoutTests/storage/indexeddb/modern/index-2.html</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmodernindex3expectedtxt">trunk/LayoutTests/storage/indexeddb/modern/index-3-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbmodernindex3html">trunk/LayoutTests/storage/indexeddb/modern/index-3.html</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverIndexValueEntrycpp">trunk/Source/WebCore/Modules/indexeddb/server/IndexValueEntry.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverIndexValueEntryh">trunk/Source/WebCore/Modules/indexeddb/server/IndexValueEntry.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverIndexValueStorecpp">trunk/Source/WebCore/Modules/indexeddb/server/IndexValueStore.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbserverIndexValueStoreh">trunk/Source/WebCore/Modules/indexeddb/server/IndexValueStore.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbsharedIndexKeycpp">trunk/Source/WebCore/Modules/indexeddb/shared/IndexKey.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbsharedIndexKeyh">trunk/Source/WebCore/Modules/indexeddb/shared/IndexKey.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (192293 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-11-11 05:19:56 UTC (rev 192293)
+++ trunk/LayoutTests/ChangeLog        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -1,3 +1,19 @@
</span><ins>+2015-11-10 Brady Eidson <beidson@apple.com>
+
+ Modern IDB: Make indexes actually index.
+ https://bugs.webkit.org/show_bug.cgi?id=150939
+
+ Reviewed by Alex Christensen.
+
+ * storage/indexeddb/modern/index-1-expected.txt: Added.
+ * storage/indexeddb/modern/index-1.html: Added.
+ * storage/indexeddb/modern/index-2-expected.txt: Added.
+ * storage/indexeddb/modern/index-2.html: Added.
+ * storage/indexeddb/modern/index-3-expected.txt: Added.
+ * storage/indexeddb/modern/index-3.html: Added.
+ * storage/indexeddb/modern/index-get-count-basic-expected.txt:
+ * storage/indexeddb/modern/index-get-count-basic.html:
+
</ins><span class="cx"> 2015-11-10 Myles C. Maxfield <mmaxfield@apple.com>
</span><span class="cx">
</span><span class="cx"> Updating test expected results after r192269
</span></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmodernindex1expectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/index-1-expected.txt (0 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/index-1-expected.txt         (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/index-1-expected.txt        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -0,0 +1,136 @@
</span><ins>+This tests the expected values from some more complex index situations.
+Initial upgrade needed: Old version - 0 New version - 1
+get "good" result is: [object Object]
+bar is good
+baz is bad
+getKey "good" result is: 1
+get "bad" result is: undefined
+getKey "bad" result is: undefined
+get "ok" result is: [object Object]
+bar is ok
+baz is meh
+getKey "ok" result is: 4
+get "meh" result is: undefined
+getKey "meh" result is: undefined
+get "super" result is: [object Object]
+bar is super
+baz is thanksForAsking
+getKey "super" result is: 7
+get "thanksForAsking" result is: undefined
+getKey "thanksForAsking" result is: undefined
+get "good,bad" result is: undefined
+getKey "good,bad" result is: undefined
+get "ok,meh" result is: undefined
+getKey "ok,meh" result is: undefined
+get "super,thanksForAsking" result is: undefined
+getKey "super,thanksForAsking" result is: undefined
+get "This is to test" result is: undefined
+getKey "This is to test" result is: undefined
+get "multiEntry indexes" result is: undefined
+getKey "multiEntry indexes" result is: undefined
+get "This is to test,multiEntry indexes" result is: [object Object]
+bar is This is to test,multiEntry indexes
+getKey "This is to test,multiEntry indexes" result is: 10
+count result is: 10
+
+get "good" result is: undefined
+getKey "good" result is: undefined
+get "bad" result is: [object Object]
+bar is good
+baz is bad
+getKey "bad" result is: 1
+get "ok" result is: undefined
+getKey "ok" result is: undefined
+get "meh" result is: [object Object]
+bar is ok
+baz is meh
+getKey "meh" result is: 4
+get "super" result is: undefined
+getKey "super" result is: undefined
+get "thanksForAsking" result is: [object Object]
+bar is super
+baz is thanksForAsking
+getKey "thanksForAsking" result is: 7
+get "good,bad" result is: undefined
+getKey "good,bad" result is: undefined
+get "ok,meh" result is: undefined
+getKey "ok,meh" result is: undefined
+get "super,thanksForAsking" result is: undefined
+getKey "super,thanksForAsking" result is: undefined
+get "This is to test" result is: undefined
+getKey "This is to test" result is: undefined
+get "multiEntry indexes" result is: undefined
+getKey "multiEntry indexes" result is: undefined
+get "This is to test,multiEntry indexes" result is: undefined
+getKey "This is to test,multiEntry indexes" result is: undefined
+count result is: 9
+
+get "good" result is: undefined
+getKey "good" result is: undefined
+get "bad" result is: undefined
+getKey "bad" result is: undefined
+get "ok" result is: undefined
+getKey "ok" result is: undefined
+get "meh" result is: undefined
+getKey "meh" result is: undefined
+get "super" result is: undefined
+getKey "super" result is: undefined
+get "thanksForAsking" result is: undefined
+getKey "thanksForAsking" result is: undefined
+get "good,bad" result is: [object Object]
+bar is good
+baz is bad
+getKey "good,bad" result is: 1
+get "ok,meh" result is: [object Object]
+bar is ok
+baz is meh
+getKey "ok,meh" result is: 4
+get "super,thanksForAsking" result is: [object Object]
+bar is super
+baz is thanksForAsking
+getKey "super,thanksForAsking" result is: 7
+get "This is to test" result is: undefined
+getKey "This is to test" result is: undefined
+get "multiEntry indexes" result is: undefined
+getKey "multiEntry indexes" result is: undefined
+get "This is to test,multiEntry indexes" result is: undefined
+getKey "This is to test,multiEntry indexes" result is: undefined
+count result is: 9
+
+get "good" result is: [object Object]
+bar is good
+baz is bad
+getKey "good" result is: 1
+get "bad" result is: undefined
+getKey "bad" result is: undefined
+get "ok" result is: [object Object]
+bar is ok
+baz is meh
+getKey "ok" result is: 4
+get "meh" result is: undefined
+getKey "meh" result is: undefined
+get "super" result is: [object Object]
+bar is super
+baz is thanksForAsking
+getKey "super" result is: 7
+get "thanksForAsking" result is: undefined
+getKey "thanksForAsking" result is: undefined
+get "good,bad" result is: undefined
+getKey "good,bad" result is: undefined
+get "ok,meh" result is: undefined
+getKey "ok,meh" result is: undefined
+get "super,thanksForAsking" result is: undefined
+getKey "super,thanksForAsking" result is: undefined
+get "This is to test" result is: [object Object]
+bar is This is to test,multiEntry indexes
+getKey "This is to test" result is: 10
+get "multiEntry indexes" result is: [object Object]
+bar is This is to test,multiEntry indexes
+getKey "multiEntry indexes" result is: 10
+get "This is to test,multiEntry indexes" result is: undefined
+getKey "This is to test,multiEntry indexes" result is: undefined
+count result is: 11
+
+Initial upgrade versionchange transaction complete
+Done
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmodernindex1html"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/index-1.html (0 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/index-1.html         (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/index-1.html        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -0,0 +1,106 @@
</span><ins>+This tests the expected values from some more complex index situations.<br>
+<div id="logger"></div>
+<script>
+
+if (window.testRunner) {
+ testRunner.waitUntilDone();
+ testRunner.dumpAsText();
+}
+
+function done()
+{
+ log("Done");
+ if (window.testRunner)
+ testRunner.notifyDone();
+}
+
+function log(message)
+{
+ document.getElementById("logger").innerHTML += message + "<br>";
+}
+
+var createRequest = window.indexedDB.open("Index1Database", 1);
+
+function checkKey(index, key)
+{
+ var request1 = index.get(key);
+ var request2 = index.getKey(key);
+
+ request1.onsuccess = function() {
+ log("get \"" + key + "\" result is: " + request1.result);
+ for (n in request1.result)
+ log(n + " is " + request1.result[n]);
+ }
+ request2.onsuccess = function() {
+ log("getKey \"" + key + "\" result is: " + request2.result);
+ for (n in request2.result)
+ log(n + " is " + request2.result[n]);
+ }
+}
+
+function checkIndex(index)
+{
+ checkKey(index, "good");
+ checkKey(index, "bad");
+ checkKey(index, "ok");
+ checkKey(index, "meh");
+ checkKey(index, "super");
+ checkKey(index, "thanksForAsking");
+ checkKey(index, [ "good", "bad" ]);
+ checkKey(index, [ "ok", "meh" ]);
+ checkKey(index, [ "super", "thanksForAsking" ]);
+ checkKey(index, "This is to test");
+ checkKey(index, "multiEntry indexes");
+ checkKey(index, ["This is to test", "multiEntry indexes" ]);
+
+ var request = index.count();
+ request.onsuccess = function() {
+ log("count result is: " + request.result);
+ log(" ");
+ }
+}
+
+createRequest.onupgradeneeded = function(event) {
+ log("Initial upgrade needed: Old version - " + event.oldVersion + " New version - " + event.newVersion);
+
+ var versionTransaction = createRequest.transaction;
+ var database = event.target.result;
+ var objectStore = database.createObjectStore("TestObjectStore");
+ var index1 = objectStore.createIndex("TestIndex1", "bar");
+ var index2 = objectStore.createIndex("TestIndex2", "baz");
+ var index3 = objectStore.createIndex("TestIndex3", [ "bar", "baz" ]);
+ var index4 = objectStore.createIndex("TestIndex4", "bar", { multiEntry: true });
+
+ objectStore.put({ bar: "good", baz: "bad" }, 1);
+ objectStore.put({ bar: "good", baz: "bad" }, 2);
+ objectStore.put({ bar: "good", baz: "bad" }, 3);
+ objectStore.put({ bar: "ok", baz: "meh" }, 4);
+ objectStore.put({ bar: "ok", baz: "meh" }, 5);
+ objectStore.put({ bar: "ok", baz: "meh" }, 6);
+ objectStore.put({ bar: "super", baz: "thanksForAsking" }, 7);
+ objectStore.put({ bar: "super", baz: "thanksForAsking" }, 8);
+ objectStore.put({ bar: "super", baz: "thanksForAsking" }, 9);
+ objectStore.put({ bar: [ "This is to test", "multiEntry indexes" ]}, 10);
+
+ checkIndex(index1);
+ checkIndex(index2);
+ checkIndex(index3);
+ checkIndex(index4);
+
+ versionTransaction.onabort = function(event) {
+ log("Initial upgrade versionchange transaction unexpected aborted");
+ done();
+ }
+
+ versionTransaction.oncomplete = function(event) {
+ log("Initial upgrade versionchange transaction complete");
+ done();
+ }
+
+ versionTransaction.onerror = function(event) {
+ log("Initial upgrade versionchange transaction unexpected error" + event);
+ done();
+ }
+}
+
+</script>
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmodernindex2expectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/index-2-expected.txt (0 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/index-2-expected.txt         (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/index-2-expected.txt        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -0,0 +1,150 @@
</span><ins>+This tests indexes are left in appropriate states after aborted transactions.
+Initial upgrade needed: Old version - 0 New version - 1
+get "good" result is: [object Object]
+bar is good
+baz is bad
+getKey "good" result is: 1
+get "bad" result is: undefined
+getKey "bad" result is: undefined
+get "multiEntry" result is: undefined
+getKey "multiEntry" result is: undefined
+get "test" result is: undefined
+getKey "test" result is: undefined
+count result is: 2
+
+get "good" result is: undefined
+getKey "good" result is: undefined
+get "bad" result is: [object Object]
+bar is good
+baz is bad
+getKey "bad" result is: 1
+get "multiEntry" result is: undefined
+getKey "multiEntry" result is: undefined
+get "test" result is: undefined
+getKey "test" result is: undefined
+count result is: 1
+
+get "good" result is: [object Object]
+bar is good
+baz is bad
+getKey "good" result is: 1
+get "bad" result is: undefined
+getKey "bad" result is: undefined
+get "multiEntry" result is: [object Object]
+bar is multiEntry,test
+getKey "multiEntry" result is: 2
+get "test" result is: [object Object]
+bar is multiEntry,test
+getKey "test" result is: 2
+count result is: 3
+
+Initial upgrade versionchange transaction complete
+Deleted key 1 from objectstore
+
+get "good" result is: undefined
+getKey "good" result is: undefined
+get "bad" result is: undefined
+getKey "bad" result is: undefined
+get "multiEntry" result is: undefined
+getKey "multiEntry" result is: undefined
+get "test" result is: undefined
+getKey "test" result is: undefined
+count result is: 1
+
+get "good" result is: undefined
+getKey "good" result is: undefined
+get "bad" result is: undefined
+getKey "bad" result is: undefined
+get "multiEntry" result is: undefined
+getKey "multiEntry" result is: undefined
+get "test" result is: undefined
+getKey "test" result is: undefined
+count result is: 0
+
+get "good" result is: undefined
+getKey "good" result is: undefined
+get "bad" result is: undefined
+getKey "bad" result is: undefined
+get "multiEntry" result is: [object Object]
+bar is multiEntry,test
+getKey "multiEntry" result is: 2
+get "test" result is: [object Object]
+bar is multiEntry,test
+getKey "test" result is: 2
+count result is: 2
+
+Cleared objectstore
+
+get "good" result is: undefined
+getKey "good" result is: undefined
+get "bad" result is: undefined
+getKey "bad" result is: undefined
+get "multiEntry" result is: undefined
+getKey "multiEntry" result is: undefined
+get "test" result is: undefined
+getKey "test" result is: undefined
+count result is: 0
+
+get "good" result is: undefined
+getKey "good" result is: undefined
+get "bad" result is: undefined
+getKey "bad" result is: undefined
+get "multiEntry" result is: undefined
+getKey "multiEntry" result is: undefined
+get "test" result is: undefined
+getKey "test" result is: undefined
+count result is: 0
+
+get "good" result is: undefined
+getKey "good" result is: undefined
+get "bad" result is: undefined
+getKey "bad" result is: undefined
+get "multiEntry" result is: undefined
+getKey "multiEntry" result is: undefined
+get "test" result is: undefined
+getKey "test" result is: undefined
+count result is: 0
+
+All done. Moving on to final part
+readwrite transaction aborted
+get "good" result is: [object Object]
+bar is good
+baz is bad
+getKey "good" result is: 1
+get "bad" result is: undefined
+getKey "bad" result is: undefined
+get "multiEntry" result is: undefined
+getKey "multiEntry" result is: undefined
+get "test" result is: undefined
+getKey "test" result is: undefined
+count result is: 2
+
+get "good" result is: undefined
+getKey "good" result is: undefined
+get "bad" result is: [object Object]
+bar is good
+baz is bad
+getKey "bad" result is: 1
+get "multiEntry" result is: undefined
+getKey "multiEntry" result is: undefined
+get "test" result is: undefined
+getKey "test" result is: undefined
+count result is: 1
+
+get "good" result is: [object Object]
+bar is good
+baz is bad
+getKey "good" result is: 1
+get "bad" result is: undefined
+getKey "bad" result is: undefined
+get "multiEntry" result is: [object Object]
+bar is multiEntry,test
+getKey "multiEntry" result is: 2
+get "test" result is: [object Object]
+bar is multiEntry,test
+getKey "test" result is: 2
+count result is: 3
+
+readwrite transaction complete
+Done
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmodernindex2html"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/index-2.html (0 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/index-2.html         (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/index-2.html        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -0,0 +1,165 @@
</span><ins>+This tests indexes are left in appropriate states after aborted transactions.<br>
+<div id="logger"></div>
+<script>
+
+if (window.testRunner) {
+ testRunner.waitUntilDone();
+ testRunner.dumpAsText();
+}
+
+function done()
+{
+ log("Done");
+ if (window.testRunner)
+ testRunner.notifyDone();
+}
+
+function log(message)
+{
+ document.getElementById("logger").innerHTML += message + "<br>";
+}
+
+var createRequest = window.indexedDB.open("Index2Database", 1);
+
+function checkKey(index, key)
+{
+ var request1 = index.get(key);
+ var request2 = index.getKey(key);
+
+ request1.onsuccess = function() {
+ log("get \"" + key + "\" result is: " + request1.result);
+ for (n in request1.result)
+ log(n + " is " + request1.result[n]);
+ }
+ request2.onsuccess = function() {
+ log("getKey \"" + key + "\" result is: " + request2.result);
+ for (n in request2.result)
+ log(n + " is " + request2.result[n]);
+ }
+}
+
+function checkIndex(index)
+{
+ checkKey(index, "good");
+ checkKey(index, "bad");
+ checkKey(index, "multiEntry");
+ checkKey(index, "test");
+
+ var request = index.count();
+ request.onsuccess = function() {
+ log("count result is: " + request.result);
+ log(" ");
+ }
+}
+
+var database;
+
+createRequest.onupgradeneeded = function(event) {
+ log("Initial upgrade needed: Old version - " + event.oldVersion + " New version - " + event.newVersion);
+
+ var versionTransaction = createRequest.transaction;
+ database = event.target.result;
+ var objectStore = database.createObjectStore("TestObjectStore");
+ var index1 = objectStore.createIndex("TestIndex1", "bar");
+ var index2 = objectStore.createIndex("TestIndex2", "baz");
+ var index3 = objectStore.createIndex("TestIndex3", "bar", { multiEntry: true });
+
+ objectStore.put({ bar: "good", baz: "bad" }, 1);
+ objectStore.put({ bar: [ "multiEntry", "test" ]}, 2);
+
+ checkIndex(index1);
+ checkIndex(index2);
+ checkIndex(index3);
+
+ versionTransaction.onabort = function(event) {
+ log("Initial upgrade versionchange transaction unexpected abort");
+ done();
+ }
+
+ versionTransaction.oncomplete = function(event) {
+ log("Initial upgrade versionchange transaction complete");
+ continueTest1();
+ }
+
+ versionTransaction.onerror = function(event) {
+ log("Initial upgrade versionchange transaction unexpected error" + event);
+ done();
+ }
+}
+
+function continueTest1()
+{
+ var transaction = database.transaction("TestObjectStore", "readwrite");
+ var objectStore = transaction.objectStore("TestObjectStore");
+ var index1 = objectStore.index("TestIndex1");
+ var index2 = objectStore.index("TestIndex2");
+ var index3 = objectStore.index("TestIndex3");
+
+ objectStore.delete(1).onsuccess = function() {
+ log("Deleted key 1 from objectstore");
+ log("");
+ }
+
+ checkIndex(index1);
+ checkIndex(index2);
+ checkIndex(index3);
+
+ objectStore.clear().onsuccess = function() {
+ log("Cleared objectstore");
+ log("");
+ }
+
+ checkIndex(index1);
+ checkIndex(index2);
+ checkIndex(index3);
+
+ objectStore.get(0).onsuccess = function() {
+ log("All done. Moving on to final part");
+ transaction.abort();
+ }
+
+ transaction.onabort = function(event) {
+ log("readwrite transaction aborted");
+ continueTest2();
+ }
+
+ transaction.oncomplete = function(event) {
+ log("readwrite transaction unexpected complete");
+ done();
+ }
+
+ transaction.onerror = function(event) {
+ log("readwrite transaction unexpected error");
+ done();
+ }
+}
+
+function continueTest2()
+{
+ var transaction = database.transaction("TestObjectStore", "readonly");
+ var objectStore = transaction.objectStore("TestObjectStore");
+ var index1 = objectStore.index("TestIndex1");
+ var index2 = objectStore.index("TestIndex2");
+ var index3 = objectStore.index("TestIndex3");
+
+ checkIndex(index1);
+ checkIndex(index2);
+ checkIndex(index3);
+
+ transaction.onabort = function(event) {
+ log("readwrite transaction unexpected abort");
+ done();
+ }
+
+ transaction.oncomplete = function(event) {
+ log("readwrite transaction complete");
+ done();
+ }
+
+ transaction.onerror = function(event) {
+ log("readwrite transaction unexpected error");
+ done();
+ }
+}
+
+</script>
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmodernindex3expectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/index-3-expected.txt (0 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/index-3-expected.txt         (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/index-3-expected.txt        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+This test exercises the "unique" constraint of indexes.
+Initial upgrade needed: Old version - 0 New version - 1
+First put success
+Value of 1 is: [object Object]
+Value of 2 is: undefined
+Value of 3 is: undefined
+Count in index 1 is: 1
+Count in index 2 is: 1
+Second put failure
+Value of 1 is: [object Object]
+Value of 2 is: undefined
+Value of 3 is: undefined
+Count in index 1 is: 1
+Count in index 2 is: 1
+Third put failure
+Value of 1 is: [object Object]
+Value of 2 is: undefined
+Value of 3 is: undefined
+Count in index 1 is: 1
+Count in index 2 is: 1
+Initial upgrade versionchange transaction complete
+Done
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmodernindex3html"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/modern/index-3.html (0 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/index-3.html         (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/modern/index-3.html        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -0,0 +1,115 @@
</span><ins>+This test exercises the "unique" constraint of indexes.<br>
+<div id="logger"></div>
+<script>
+
+if (window.testRunner) {
+ testRunner.waitUntilDone();
+ testRunner.dumpAsText();
+}
+
+function done()
+{
+ log("Done");
+ if (window.testRunner)
+ testRunner.notifyDone();
+}
+
+function log(message)
+{
+ document.getElementById("logger").innerHTML += message + "<br>";
+}
+
+var createRequest = window.indexedDB.open("Index3Database", 1);
+var objectStore;
+
+function checkObjectStore()
+{
+ var req1 = objectStore.get(1);
+ req1.onsuccess = function() {
+ log("Value of 1 is: " + req1.result);
+ }
+ var req2 = objectStore.get(2);
+ req2.onsuccess = function() {
+ log("Value of 2 is: " + req2.result);
+ }
+ var req3 = objectStore.get(3);
+ req3.onsuccess = function() {
+ log("Value of 3 is: " + req3.result);
+ }
+}
+
+function checkIndex(index, name)
+{
+ var req = index.count();
+ req.onsuccess = function() {
+ log("Count in index " + name + " is: " + req.result);
+ }
+}
+
+createRequest.onupgradeneeded = function(event) {
+ log("Initial upgrade needed: Old version - " + event.oldVersion + " New version - " + event.newVersion);
+
+ var versionTransaction = createRequest.transaction;
+ var database = event.target.result;
+ objectStore = database.createObjectStore("TestObjectStore");
+ var i1 = objectStore.createIndex("TestIndex1", "bar", { unique: true });
+ var i2 = objectStore.createIndex("TestIndex2", "bar", { multiEntry: true, unique: true });
+
+ var request1 = objectStore.put({ bar: "good", baz: "bad" }, 1);
+ request1.onsuccess = function() {
+ log("First put success");
+ }
+ request1.onerror = function() {
+ log("First put unexpected failure");
+ done();
+ }
+
+ checkObjectStore();
+ checkIndex(i1, 1);
+ checkIndex(i2, 2);
+
+ var request2 = objectStore.put({ bar: "good", baz: "bad" }, 2);
+ request2.onsuccess = function() {
+ log("Second put unexpected success");
+ done();
+ }
+ request2.onerror = function(e) {
+ log("Second put failure");
+ e.stopPropagation();
+ }
+
+ checkObjectStore();
+ checkIndex(i1, 1);
+ checkIndex(i2, 2);
+
+ var request3 = objectStore.put({ bar: [ "gnarly", "great", "good" ]}, 3);
+ request3.onsuccess = function() {
+ log("Third put unexpected success");
+ done();
+ }
+ request3.onerror = function(e) {
+ log("Third put failure");
+ e.stopPropagation();
+ }
+
+ checkObjectStore();
+ checkIndex(i1, 1);
+ checkIndex(i2, 2);
+
+ versionTransaction.onabort = function(event) {
+ log("Initial upgrade versionchange transaction unexpected aborted");
+ done();
+ }
+
+ versionTransaction.oncomplete = function(event) {
+ log("Initial upgrade versionchange transaction complete");
+ done();
+ }
+
+ versionTransaction.onerror = function(event) {
+ log("Initial upgrade versionchange transaction unexpected error" + event);
+ done();
+ }
+}
+
+</script>
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmodernindexgetcountbasicexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/storage/indexeddb/modern/index-get-count-basic-expected.txt (192293 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/index-get-count-basic-expected.txt        2015-11-11 05:19:56 UTC (rev 192293)
+++ trunk/LayoutTests/storage/indexeddb/modern/index-get-count-basic-expected.txt        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -1,9 +1,10 @@
</span><del>-ALERT: Initial upgrade needed: Old version - 0 New version - 1
-ALERT: get result is: undefined
-ALERT: getKey result is: undefined
-ALERT: count result is: 0
-ALERT: Initial upgrade versionchange transaction complete
-ALERT: Done
</del><span class="cx"> This tests the most basic operation of the IDBIndex methods get(), getKey(), and count().
</span><del>-It doesn't actually do anything other than exercise the requests themselves because we don't actually index yet.
</del><ins>+Initial upgrade needed: Old version - 0 New version - 1
+get result is: [object Object]
+bar is good
+baz is bad
+getKey result is: foo
+count result is: 1
+Initial upgrade versionchange transaction complete
+Done
</ins><span class="cx">
</span></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbmodernindexgetcountbasichtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/storage/indexeddb/modern/index-get-count-basic.html (192293 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/modern/index-get-count-basic.html        2015-11-11 05:19:56 UTC (rev 192293)
+++ trunk/LayoutTests/storage/indexeddb/modern/index-get-count-basic.html        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -1,5 +1,4 @@
</span><span class="cx"> This tests the most basic operation of the IDBIndex methods get(), getKey(), and count().<br>
</span><del>-It doesn't actually do anything other than exercise the requests themselves because we don't actually index yet.<br>
</del><span class="cx"> <div id="logger"></div>
</span><span class="cx"> <script>
</span><span class="cx">
</span><span class="lines">@@ -10,12 +9,12 @@
</span><span class="cx">
</span><span class="cx"> function done()
</span><span class="cx"> {
</span><del>- alert("Done");
</del><ins>+ log("Done");
</ins><span class="cx"> if (window.testRunner)
</span><span class="cx"> testRunner.notifyDone();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-function gol(message)
</del><ins>+function log(message)
</ins><span class="cx"> {
</span><span class="cx"> document.getElementById("logger").innerHTML += message + "<br>";
</span><span class="cx"> }
</span><span class="lines">@@ -23,42 +22,44 @@
</span><span class="cx"> var createRequest = window.indexedDB.open("IndexGetCountBasicDatabase", 1);
</span><span class="cx">
</span><span class="cx"> createRequest.onupgradeneeded = function(event) {
</span><del>- alert("Initial upgrade needed: Old version - " + event.oldVersion + " New version - " + event.newVersion);
</del><ins>+ log("Initial upgrade needed: Old version - " + event.oldVersion + " New version - " + event.newVersion);
</ins><span class="cx">
</span><span class="cx"> var versionTransaction = createRequest.transaction;
</span><span class="cx"> var database = event.target.result;
</span><span class="cx"> var objectStore = database.createObjectStore("TestObjectStore");
</span><del>- var index = objectStore.createIndex("TestIndex", "foo");
</del><ins>+ var index = objectStore.createIndex("TestIndex", "bar");
</ins><span class="cx">
</span><del>- objectStore.put("bar", "foo");
</del><ins>+ objectStore.put({ bar: "good", baz: "bad" }, "foo");
</ins><span class="cx">
</span><del>- var request1 = index.get("bar");
</del><ins>+ var request1 = index.get("good");
</ins><span class="cx"> request1.onsuccess = function() {
</span><del>- alert("get result is: " + request1.result);
</del><ins>+ log("get result is: " + request1.result);
+ for (n in request1.result)
+ log(n + " is " + request1.result[n]);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- request2 = index.getKey("bar");
</del><ins>+ request2 = index.getKey("good");
</ins><span class="cx"> request2.onsuccess = function() {
</span><del>- alert("getKey result is: " + request2.result);
</del><ins>+ log("getKey result is: " + request2.result);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> var request3 = index.count();
</span><span class="cx"> request3.onsuccess = function() {
</span><del>- alert("count result is: " + request3.result);
</del><ins>+ log("count result is: " + request3.result);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> versionTransaction.onabort = function(event) {
</span><del>- alert("Initial upgrade versionchange transaction unexpected aborted");
</del><ins>+ log("Initial upgrade versionchange transaction unexpected aborted");
</ins><span class="cx"> done();
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> versionTransaction.oncomplete = function(event) {
</span><del>- alert("Initial upgrade versionchange transaction complete");
</del><ins>+ log("Initial upgrade versionchange transaction complete");
</ins><span class="cx"> done();
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> versionTransaction.onerror = function(event) {
</span><del>- alert("Initial upgrade versionchange transaction unexpected error" + event);
</del><ins>+ log("Initial upgrade versionchange transaction unexpected error" + event);
</ins><span class="cx"> done();
</span><span class="cx"> }
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (192293 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/CMakeLists.txt        2015-11-11 05:19:56 UTC (rev 192293)
+++ trunk/Source/WebCore/CMakeLists.txt        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -902,6 +902,8 @@
</span><span class="cx"> Modules/indexeddb/server/IDBConnectionToClient.cpp
</span><span class="cx"> Modules/indexeddb/server/IDBServer.cpp
</span><span class="cx"> Modules/indexeddb/server/IDBServerOperation.cpp
</span><ins>+ Modules/indexeddb/server/IndexValueEntry.cpp
+ Modules/indexeddb/server/IndexValueStore.cpp
</ins><span class="cx"> Modules/indexeddb/server/MemoryBackingStoreTransaction.cpp
</span><span class="cx"> Modules/indexeddb/server/MemoryIDBBackingStore.cpp
</span><span class="cx"> Modules/indexeddb/server/MemoryIndex.cpp
</span><span class="lines">@@ -919,6 +921,7 @@
</span><span class="cx"> Modules/indexeddb/shared/IDBResultData.cpp
</span><span class="cx"> Modules/indexeddb/shared/IDBTransactionInfo.cpp
</span><span class="cx"> Modules/indexeddb/shared/InProcessIDBServer.cpp
</span><ins>+ Modules/indexeddb/shared/IndexKey.cpp
</ins><span class="cx">
</span><span class="cx"> Modules/mediacontrols/MediaControlsHost.cpp
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (192293 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-11-11 05:19:56 UTC (rev 192293)
+++ trunk/Source/WebCore/ChangeLog        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -1,3 +1,97 @@
</span><ins>+2015-11-10 Brady Eidson <beidson@apple.com>
+
+ Modern IDB: Make indexes actually index.
+ https://bugs.webkit.org/show_bug.cgi?id=150939
+
+ Reviewed by Alex Christensen.
+
+ Tests: storage/indexeddb/modern/index-1.html
+ storage/indexeddb/modern/index-2.html
+ storage/indexeddb/modern/index-3.html
+
+ * CMakeLists.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+
+ * Modules/indexeddb/IDBKeyData.h:
+ (WebCore::IDBKeyData::hash): Deleted.
+
+ * Modules/indexeddb/IDBKeyRangeData.cpp:
+ (WebCore::IDBKeyRangeData::isExactlyOneKey):
+
+ * Modules/indexeddb/client/IDBTransactionImpl.cpp:
+ (WebCore::IDBClient::IDBTransaction::didGetRecordOnServer):
+
+ * Modules/indexeddb/server/IndexValueEntry.cpp: Copied from Source/WebCore/Modules/indexeddb/server/MemoryIndex.cpp.
+ (WebCore::IDBServer::IndexValueEntry::IndexValueEntry):
+ (WebCore::IDBServer::IndexValueEntry::~IndexValueEntry):
+ (WebCore::IDBServer::IndexValueEntry::addKey):
+ (WebCore::IDBServer::IndexValueEntry::removeKey):
+ (WebCore::IDBServer::IndexValueEntry::getLowest):
+ (WebCore::IDBServer::IndexValueEntry::getCount):
+ * Modules/indexeddb/server/IndexValueEntry.h: Copied from Source/WebCore/Modules/indexeddb/server/MemoryIndex.h.
+
+ * Modules/indexeddb/server/IndexValueStore.cpp: Added.
+ (WebCore::IDBServer::IndexValueStore::IndexValueStore):
+ (WebCore::IDBServer::IndexValueStore::lowestValueForKey):
+ (WebCore::IDBServer::IndexValueStore::countForKey):
+ (WebCore::IDBServer::IndexValueStore::contains):
+ (WebCore::IDBServer::IndexValueStore::addRecord):
+ (WebCore::IDBServer::IndexValueStore::removeRecord):
+ (WebCore::IDBServer::IndexValueStore::removeEntriesWithValueKey):
+ (WebCore::IDBServer::IndexValueStore::lowestKeyWithRecordInRange):
+ * Modules/indexeddb/server/IndexValueStore.h: Copied from Source/WebCore/Modules/indexeddb/server/MemoryIndex.h.
+
+ * Modules/indexeddb/server/MemoryBackingStoreTransaction.cpp:
+ (WebCore::IDBServer::MemoryBackingStoreTransaction::objectStoreCleared):
+ (WebCore::IDBServer::MemoryBackingStoreTransaction::indexCleared):
+ (WebCore::IDBServer::MemoryBackingStoreTransaction::abort):
+ * Modules/indexeddb/server/MemoryBackingStoreTransaction.h:
+
+ * Modules/indexeddb/server/MemoryIDBBackingStore.cpp:
+ (WebCore::IDBServer::MemoryIDBBackingStore::addRecord):
+
+ * Modules/indexeddb/server/MemoryIndex.cpp:
+ (WebCore::IDBServer::MemoryIndex::create):
+ (WebCore::IDBServer::MemoryIndex::MemoryIndex):
+ (WebCore::IDBServer::MemoryIndex::objectStoreCleared):
+ (WebCore::IDBServer::MemoryIndex::replaceIndexValueStore):
+ (WebCore::IDBServer::MemoryIndex::getResultForKeyRange):
+ (WebCore::IDBServer::MemoryIndex::countForKeyRange):
+ (WebCore::IDBServer::MemoryIndex::putIndexKey):
+ (WebCore::IDBServer::MemoryIndex::removeRecord):
+ (WebCore::IDBServer::MemoryIndex::removeEntriesWithValueKey):
+ (WebCore::IDBServer::MemoryIndex::valueForKeyRange): Deleted.
+ * Modules/indexeddb/server/MemoryIndex.h:
+
+ * Modules/indexeddb/server/MemoryObjectStore.cpp:
+ (WebCore::IDBServer::MemoryObjectStore::createIndex):
+ (WebCore::IDBServer::MemoryObjectStore::clear):
+ (WebCore::IDBServer::MemoryObjectStore::deleteRecord):
+ (WebCore::IDBServer::MemoryObjectStore::addRecord):
+ (WebCore::IDBServer::indexVM):
+ (WebCore::IDBServer::indexGlobalExec):
+ (WebCore::IDBServer::MemoryObjectStore::updateIndexesForDeleteRecord):
+ (WebCore::IDBServer::MemoryObjectStore::updateIndexesForPutRecord):
+ (WebCore::IDBServer::MemoryObjectStore::indexValueForKeyRange):
+ * Modules/indexeddb/server/MemoryObjectStore.h:
+ (WebCore::IDBServer::MemoryObjectStore::writeTransaction):
+
+ * Modules/indexeddb/shared/IndexKey.cpp: Copied from Source/WebCore/Modules/indexeddb/IDBKeyRangeData.cpp.
+ (WebCore::IndexKey::IndexKey):
+ (WebCore::IndexKey::isolatedCopy):
+ (WebCore::IndexKey::asOneKey):
+ (WebCore::IndexKey::multiEntry):
+ * Modules/indexeddb/shared/IndexKey.h: Added.
+ (WebCore::IndexKey::isNull):
+
+ * bindings/js/IDBBindingUtilities.cpp:
+ (WebCore::idbValueDataToJSValue):
+ (WebCore::deserializeIDBValueBuffer):
+ (WebCore::idbKeyDataToScriptValue):
+ (WebCore::createKeyPathArray):
+ (WebCore::generateIndexKeyForValue):
+ * bindings/js/IDBBindingUtilities.h:
+
</ins><span class="cx"> 2015-11-10 Myles C. Maxfield <mmaxfield@apple.com>
</span><span class="cx">
</span><span class="cx"> Move locale information into FontDescription
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbIDBKeyDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/IDBKeyData.h (192293 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/IDBKeyData.h        2015-11-11 05:19:56 UTC (rev 192293)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBKeyData.h        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -122,9 +122,6 @@
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- unsigned targetSize = WTF::roundUpToPowerOfTwo(hashCodes.size());
- hashCodes.resize(targetSize);
-
</del><span class="cx"> return StringHasher::hashMemory(hashCodes.data(), hashCodes.size() * sizeof(unsigned));
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbIDBKeyRangeDatacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/IDBKeyRangeData.cpp (192293 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/IDBKeyRangeData.cpp        2015-11-11 05:19:56 UTC (rev 192293)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBKeyRangeData.cpp        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -73,7 +73,7 @@
</span><span class="cx">
</span><span class="cx"> bool IDBKeyRangeData::isExactlyOneKey() const
</span><span class="cx"> {
</span><del>- if (isNull || lowerOpen || upperOpen)
</del><ins>+ if (isNull || lowerOpen || upperOpen || !upperKey.isValid() || !lowerKey.isValid())
</ins><span class="cx"> return false;
</span><span class="cx">
</span><span class="cx"> return !lowerKey.compare(upperKey);
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbclientIDBTransactionImplcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.cpp (192293 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.cpp        2015-11-11 05:19:56 UTC (rev 192293)
+++ trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.cpp        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -484,9 +484,11 @@
</span><span class="cx"> {
</span><span class="cx"> LOG(IndexedDB, "IDBTransaction::didGetRecordOnServer");
</span><span class="cx">
</span><ins>+ const IDBGetResult& result = resultData.getResult();
+
</ins><span class="cx"> if (request.sourceIndexIdentifier() && request.requestedIndexRecordType() == IndexedDB::IndexRecordType::Key) {
</span><del>- if (resultData.resultKey())
- request.setResult(resultData.resultKey());
</del><ins>+ if (!result.keyData.isNull())
+ request.setResult(&result.keyData);
</ins><span class="cx"> else
</span><span class="cx"> request.setResultToUndefined();
</span><span class="cx"> } else {
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverIndexValueEntrycppfromrev192293trunkSourceWebCoreModulesindexeddbserverMemoryIndexcpp"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/Modules/indexeddb/server/IndexValueEntry.cpp (from rev 192293, trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndex.cpp) (0 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/IndexValueEntry.cpp         (rev 0)
+++ trunk/Source/WebCore/Modules/indexeddb/server/IndexValueEntry.cpp        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -0,0 +1,96 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "IndexValueEntry.h"
+
+#if ENABLE(INDEXED_DATABASE)
+
+namespace WebCore {
+namespace IDBServer {
+
+IndexValueEntry::IndexValueEntry(bool unique)
+ : m_unique(unique)
+{
+ if (m_unique)
+ m_key = nullptr;
+ else
+ m_orderedKeys = new std::set<IDBKeyData>;
+}
+
+IndexValueEntry::~IndexValueEntry()
+{
+ if (m_unique)
+ delete m_key;
+ else
+ delete m_orderedKeys;
+}
+
+void IndexValueEntry::addKey(const IDBKeyData& key)
+{
+ if (m_unique) {
+ delete m_key;
+ m_key = new IDBKeyData(key);
+ return;
+ }
+
+ m_orderedKeys->insert(key);
+}
+
+bool IndexValueEntry::removeKey(const IDBKeyData& key)
+{
+ if (m_unique && m_key && *m_key == key) {
+ delete m_key;
+ m_key = nullptr;
+ return true;
+ }
+
+ m_orderedKeys->erase(key);
+ return m_orderedKeys->empty();
+}
+
+const IDBKeyData* IndexValueEntry::getLowest() const
+{
+ if (m_unique)
+ return m_key;
+
+ if (m_orderedKeys->empty())
+ return nullptr;
+
+ return &(*m_orderedKeys->begin());
+}
+
+uint64_t IndexValueEntry::getCount() const
+{
+ if (m_unique)
+ return m_key ? 1 : 0;
+
+ return m_orderedKeys->size();
+}
+
+} // namespace IDBServer
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverIndexValueEntryhfromrev192293trunkSourceWebCoreModulesindexeddbserverMemoryIndexh"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/Modules/indexeddb/server/IndexValueEntry.h (from rev 192293, trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndex.h) (0 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/IndexValueEntry.h         (rev 0)
+++ trunk/Source/WebCore/Modules/indexeddb/server/IndexValueEntry.h        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -0,0 +1,64 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef IndexValueEntry_h
+#define IndexValueEntry_h
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "IDBKeyData.h"
+#include <set>
+
+namespace WebCore {
+namespace IDBServer {
+
+class IndexValueEntry {
+public:
+ IndexValueEntry(bool unique);
+ ~IndexValueEntry();
+
+ void addKey(const IDBKeyData&);
+
+ // Returns true if the IndexValueEntry is empty after removing the key;
+ bool removeKey(const IDBKeyData&);
+
+ const IDBKeyData* getLowest() const;
+
+ uint64_t getCount() const;
+
+private:
+ union {
+ std::set<IDBKeyData>* m_orderedKeys;
+ IDBKeyData* m_key;
+ };
+
+ bool m_unique;
+};
+
+} // namespace IDBServer
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
+#endif // IndexValueEntry_h
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverIndexValueStorecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/indexeddb/server/IndexValueStore.cpp (0 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/IndexValueStore.cpp         (rev 0)
+++ trunk/Source/WebCore/Modules/indexeddb/server/IndexValueStore.cpp        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -0,0 +1,141 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "IndexValueStore.h"
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "IDBError.h"
+#include "IDBKeyRangeData.h"
+
+namespace WebCore {
+namespace IDBServer {
+
+IndexValueStore::IndexValueStore(bool unique)
+ : m_unique(unique)
+{
+}
+
+const IDBKeyData* IndexValueStore::lowestValueForKey(const IDBKeyData& key) const
+{
+ const auto& entry = m_records.get(key);
+ if (!entry)
+ return nullptr;
+
+ return entry->getLowest();
+}
+
+uint64_t IndexValueStore::countForKey(const IDBKeyData& key) const
+{
+ const auto& entry = m_records.get(key);
+ if (!entry)
+ return 0;
+
+ return entry->getCount();
+}
+
+bool IndexValueStore::contains(const IDBKeyData& key) const
+{
+ const auto& entry = m_records.get(key);
+ if (!entry)
+ return false;
+
+ ASSERT(entry->getCount());
+
+ return true;
+}
+
+IDBError IndexValueStore::addRecord(const IDBKeyData& indexKey, const IDBKeyData& valueKey)
+{
+ auto result = m_records.add(indexKey, nullptr);
+
+ if (!result.isNewEntry && m_unique)
+ return IDBError(IDBExceptionCode::ConstraintError);
+
+ if (result.isNewEntry)
+ result.iterator->value = std::make_unique<IndexValueEntry>(m_unique);
+
+ result.iterator->value->addKey(valueKey);
+ m_orderedKeys.insert(indexKey);
+
+ return { };
+}
+
+void IndexValueStore::removeRecord(const IDBKeyData& indexKey, const IDBKeyData& valueKey)
+{
+ auto iterator = m_records.find(indexKey);
+ if (!iterator->value)
+ return;
+
+ if (iterator->value->removeKey(valueKey))
+ m_records.remove(iterator);
+}
+
+void IndexValueStore::removeEntriesWithValueKey(const IDBKeyData& valueKey)
+{
+ HashSet<IDBKeyData*> entryKeysToRemove;
+
+ for (auto& entry : m_records) {
+ if (entry.value->removeKey(valueKey))
+ entryKeysToRemove.add(&entry.key);
+ }
+
+ for (auto* entry : entryKeysToRemove) {
+ m_orderedKeys.erase(*entry);
+ m_records.remove(*entry);
+ }
+}
+
+IDBKeyData IndexValueStore::lowestKeyWithRecordInRange(const IDBKeyRangeData& range) const
+{
+ if (range.isExactlyOneKey())
+ return m_records.contains(range.lowerKey) ? range.lowerKey : IDBKeyData();
+
+ auto lowestInRange = m_orderedKeys.lower_bound(range.lowerKey);
+
+ if (lowestInRange == m_orderedKeys.end())
+ return { };
+
+ if (range.lowerOpen && *lowestInRange == range.lowerKey)
+ ++lowestInRange;
+
+ if (lowestInRange == m_orderedKeys.end())
+ return { };
+
+ if (!range.upperKey.isNull()) {
+ if (lowestInRange->compare(range.upperKey) > 0)
+ return { };
+ if (range.upperOpen && *lowestInRange == range.upperKey)
+ return { };
+ }
+
+ return *lowestInRange;
+}
+
+} // namespace IDBServer
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverIndexValueStorehfromrev192293trunkSourceWebCoreModulesindexeddbserverMemoryIndexh"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/Modules/indexeddb/server/IndexValueStore.h (from rev 192293, trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndex.h) (0 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/IndexValueStore.h         (rev 0)
+++ trunk/Source/WebCore/Modules/indexeddb/server/IndexValueStore.h        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -0,0 +1,71 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef IndexValueStore_h
+#define IndexValueStore_h
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "IDBKeyData.h"
+#include "IndexValueEntry.h"
+#include <set>
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+class IDBError;
+
+struct IDBKeyRangeData;
+
+namespace IDBServer {
+
+typedef HashMap<IDBKeyData, std::unique_ptr<IndexValueEntry>, IDBKeyDataHash, IDBKeyDataHashTraits> IndexKeyValueMap;
+
+class IndexValueStore {
+public:
+ IndexValueStore(bool unique);
+
+ const IDBKeyData* lowestValueForKey(const IDBKeyData&) const;
+ uint64_t countForKey(const IDBKeyData&) const;
+ IDBKeyData lowestKeyWithRecordInRange(const IDBKeyRangeData&) const;
+ bool contains(const IDBKeyData&) const;
+
+ IDBError addRecord(const IDBKeyData& indexKey, const IDBKeyData& valueKey);
+ void removeRecord(const IDBKeyData& indexKey, const IDBKeyData& valueKey);
+
+ void removeEntriesWithValueKey(const IDBKeyData& valueKey);
+
+private:
+ IndexKeyValueMap m_records;
+ std::set<IDBKeyData> m_orderedKeys;
+
+ bool m_unique;
+};
+
+} // namespace IDBServer
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
+#endif // IndexValueStore_h
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryBackingStoreTransactioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryBackingStoreTransaction.cpp (192293 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryBackingStoreTransaction.cpp        2015-11-11 05:19:56 UTC (rev 192293)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryBackingStoreTransaction.cpp        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -117,21 +117,24 @@
</span><span class="cx">
</span><span class="cx"> auto addResult = m_clearedKeyValueMaps.add(&objectStore, nullptr);
</span><span class="cx">
</span><del>- // If this object store has already been cleared during this transaction, we don't need to remember this clearing.
</del><ins>+ // If this object store has already been cleared during this transaction, we shouldn't remember this clearing.
</ins><span class="cx"> if (!addResult.isNewEntry)
</span><span class="cx"> return;
</span><span class="cx">
</span><del>- // If values had previously been changed during this transaction, fold those changes back into the
- // cleared key-value map now, so we have exactly the map that will need to be restored if the transaction is aborted.
- auto originalValues = m_originalValues.take(&objectStore);
- if (originalValues) {
- for (auto iterator : *originalValues)
- keyValueMap->set(iterator.key, iterator.value);
- }
-
</del><span class="cx"> addResult.iterator->value = WTF::move(keyValueMap);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void MemoryBackingStoreTransaction::indexCleared(MemoryIndex& index, std::unique_ptr<IndexValueStore>&& valueStore)
+{
+ auto addResult = m_clearedIndexValueStores.add(&index, nullptr);
+
+ // If this index has already been cleared during this transaction, we shouldn't remember this clearing.
+ if (!addResult.isNewEntry)
+ return;
+
+ addResult.iterator->value = WTF::move(valueStore);
+}
+
</ins><span class="cx"> void MemoryBackingStoreTransaction::recordValueChanged(MemoryObjectStore& objectStore, const IDBKeyData& key, ThreadSafeDataBuffer* value)
</span><span class="cx"> {
</span><span class="cx"> ASSERT(m_objectStores.contains(&objectStore));
</span><span class="lines">@@ -182,15 +185,19 @@
</span><span class="cx"> m_backingStore.setDatabaseInfo(*m_originalDatabaseInfo);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ // Restore cleared index value stores before we re-insert values into object stores
+ // because inserting those values will regenerate the appropriate index values.
+ for (auto& iterator : m_clearedIndexValueStores)
+ iterator.key->replaceIndexValueStore(WTF::move(iterator.value));
+ m_clearedIndexValueStores.clear();
+
</ins><span class="cx"> for (auto objectStore : m_objectStores) {
</span><span class="cx"> ASSERT(m_originalKeyGenerators.contains(objectStore));
</span><span class="cx"> objectStore->setKeyGeneratorValue(m_originalKeyGenerators.get(objectStore));
</span><span class="cx">
</span><span class="cx"> auto clearedKeyValueMap = m_clearedKeyValueMaps.take(objectStore);
</span><del>- if (clearedKeyValueMap) {
</del><ins>+ if (clearedKeyValueMap)
</ins><span class="cx"> objectStore->replaceKeyValueStore(WTF::move(clearedKeyValueMap));
</span><del>- continue;
- }
</del><span class="cx">
</span><span class="cx"> auto keyValueMap = m_originalValues.take(objectStore);
</span><span class="cx"> if (!keyValueMap)
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryBackingStoreTransactionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryBackingStoreTransaction.h (192293 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryBackingStoreTransaction.h        2015-11-11 05:19:56 UTC (rev 192293)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryBackingStoreTransaction.h        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #include "IDBDatabaseInfo.h"
</span><span class="cx"> #include "IDBKeyData.h"
</span><span class="cx"> #include "IDBTransactionInfo.h"
</span><ins>+#include "IndexValueStore.h"
</ins><span class="cx"> #include "ThreadSafeDataBuffer.h"
</span><span class="cx"> #include <wtf/HashMap.h>
</span><span class="cx"> #include <wtf/HashSet.h>
</span><span class="lines">@@ -63,6 +64,7 @@
</span><span class="cx"> void recordValueChanged(MemoryObjectStore&, const IDBKeyData&, ThreadSafeDataBuffer*);
</span><span class="cx"> void objectStoreDeleted(std::unique_ptr<MemoryObjectStore>);
</span><span class="cx"> void objectStoreCleared(MemoryObjectStore&, std::unique_ptr<KeyValueMap>&&);
</span><ins>+ void indexCleared(MemoryIndex&, std::unique_ptr<IndexValueStore>&&);
</ins><span class="cx">
</span><span class="cx"> void addNewIndex(MemoryIndex&);
</span><span class="cx"> void addExistingIndex(MemoryIndex&);
</span><span class="lines">@@ -90,8 +92,10 @@
</span><span class="cx">
</span><span class="cx"> HashMap<MemoryObjectStore*, uint64_t> m_originalKeyGenerators;
</span><span class="cx"> HashMap<String, std::unique_ptr<MemoryObjectStore>> m_deletedObjectStores;
</span><ins>+ HashMap<String, std::unique_ptr<MemoryIndex>> m_deletedIndexes;
</ins><span class="cx"> HashMap<MemoryObjectStore*, std::unique_ptr<KeyValueMap>> m_originalValues;
</span><span class="cx"> HashMap<MemoryObjectStore*, std::unique_ptr<KeyValueMap>> m_clearedKeyValueMaps;
</span><ins>+ HashMap<MemoryIndex*, std::unique_ptr<IndexValueStore>> m_clearedIndexValueStores;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> } // namespace IDBServer
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryIDBBackingStorecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp (192293 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp        2015-11-11 05:19:56 UTC (rev 192293)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -258,8 +258,7 @@
</span><span class="cx"> if (!objectStore)
</span><span class="cx"> return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral("No backing store object store found to put record"));
</span><span class="cx">
</span><del>- objectStore->addRecord(*transaction, keyData, value);
- return IDBError();
</del><ins>+ return objectStore->addRecord(*transaction, keyData, value);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> IDBError MemoryIDBBackingStore::getRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& range, ThreadSafeDataBuffer& outValue)
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryIndexcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndex.cpp (192293 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndex.cpp        2015-11-11 05:19:56 UTC (rev 192293)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndex.cpp        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -28,18 +28,26 @@
</span><span class="cx">
</span><span class="cx"> #if ENABLE(INDEXED_DATABASE)
</span><span class="cx">
</span><ins>+#include "IDBError.h"
</ins><span class="cx"> #include "IDBGetResult.h"
</span><ins>+#include "IDBKeyRangeData.h"
+#include "IndexKey.h"
+#include "Logging.h"
+#include "MemoryBackingStoreTransaction.h"
+#include "MemoryObjectStore.h"
+#include "ThreadSafeDataBuffer.h"
</ins><span class="cx">
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> namespace IDBServer {
</span><span class="cx">
</span><del>-std::unique_ptr<MemoryIndex> MemoryIndex::create(const IDBIndexInfo& info)
</del><ins>+std::unique_ptr<MemoryIndex> MemoryIndex::create(const IDBIndexInfo& info, MemoryObjectStore& objectStore)
</ins><span class="cx"> {
</span><del>- return std::make_unique<MemoryIndex>(info);
</del><ins>+ return std::make_unique<MemoryIndex>(info, objectStore);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-MemoryIndex::MemoryIndex(const IDBIndexInfo& info)
</del><ins>+MemoryIndex::MemoryIndex(const IDBIndexInfo& info, MemoryObjectStore& objectStore)
</ins><span class="cx"> : m_info(info)
</span><ins>+ , m_objectStore(objectStore)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -47,20 +55,125 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><del>-IDBGetResult MemoryIndex::valueForKeyRange(IndexedDB::IndexRecordType, const IDBKeyRangeData&) const
</del><ins>+void MemoryIndex::objectStoreCleared()
</ins><span class="cx"> {
</span><del>- // FIXME: Once indexes actually index, we'll return something real.
- // https://bugs.webkit.org/show_bug.cgi?id=150939
</del><ins>+ auto transaction = m_objectStore.writeTransaction();
+ ASSERT(transaction);
+
+ transaction->indexCleared(*this, WTF::move(m_records));
+}
+
+void MemoryIndex::replaceIndexValueStore(std::unique_ptr<IndexValueStore>&& valueStore)
+{
+ ASSERT(m_objectStore.writeTransaction());
+ ASSERT(m_objectStore.writeTransaction()->isAborting());
+
+ m_records = WTF::move(valueStore);
+}
+
+IDBGetResult MemoryIndex::getResultForKeyRange(IndexedDB::IndexRecordType type, const IDBKeyRangeData& range) const
+{
+ LOG(IndexedDB, "MemoryIndex::getResultForKeyRange");
+
+ if (!m_records)
+ return { };
+
+ IDBKeyData keyToLookFor;
+ if (range.isExactlyOneKey())
+ keyToLookFor = range.lowerKey;
+ else
+ keyToLookFor = m_records->lowestKeyWithRecordInRange(range);
+
+ if (keyToLookFor.isNull())
+ return { };
+
+ const IDBKeyData* keyValue = m_records->lowestValueForKey(keyToLookFor);
+
+ if (!keyValue)
+ return { };
+
+ return type == IndexedDB::IndexRecordType::Key ? IDBGetResult(*keyValue) : IDBGetResult(m_objectStore.valueForKeyRange(*keyValue));
+}
+
+uint64_t MemoryIndex::countForKeyRange(const IDBKeyRangeData& inRange)
+{
+ LOG(IndexedDB, "MemoryIndex::countForKeyRange");
+
+ if (!m_records)
+ return 0;
+
+ uint64_t count = 0;
+ IDBKeyRangeData range = inRange;
+ while (true) {
+ auto key = m_records->lowestKeyWithRecordInRange(range);
+ if (key.isNull())
+ break;
+
+ count += m_records->countForKey(key);
+
+ range.lowerKey = key;
+ range.lowerOpen = true;
+ }
+
+ return count;
+}
+
+IDBError MemoryIndex::putIndexKey(const IDBKeyData& valueKey, const IndexKey& indexKey)
+{
+ LOG(IndexedDB, "MemoryIndex::provisionalPutIndexKey");
+
+ if (!m_records)
+ m_records = std::make_unique<IndexValueStore>(m_info.unique());
+
+ if (!m_info.multiEntry()) {
+ IDBKeyData key = indexKey.asOneKey();
+ return m_records->addRecord(key, valueKey);
+ }
+
+ Vector<IDBKeyData> keys = indexKey.multiEntry();
+
+ if (m_info.unique()) {
+ for (auto& key : keys) {
+ if (m_records->contains(key))
+ return IDBError(IDBExceptionCode::ConstraintError);
+ }
+ }
+
+ for (auto& key : keys) {
+ auto error = m_records->addRecord(key, valueKey);
+ ASSERT_UNUSED(error, error.isNull());
+ }
+
</ins><span class="cx"> return { };
</span><span class="cx"> }
</span><span class="cx">
</span><del>-uint64_t MemoryIndex::countForKeyRange(const IDBKeyRangeData&)
</del><ins>+void MemoryIndex::removeRecord(const IDBKeyData& valueKey, const IndexKey& indexKey)
</ins><span class="cx"> {
</span><del>- // FIXME: Once indexes actually index, we'll return something real.
- // https://bugs.webkit.org/show_bug.cgi?id=150939
- return 0;
</del><ins>+ LOG(IndexedDB, "MemoryIndex::removeRecord");
+
+ ASSERT(m_records);
+
+ if (!m_info.multiEntry()) {
+ IDBKeyData key = indexKey.asOneKey();
+ m_records->removeRecord(key, valueKey);
+ return;
+ }
+
+ Vector<IDBKeyData> keys = indexKey.multiEntry();
+ for (auto& key : keys)
+ m_records->removeRecord(key, valueKey);
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+void MemoryIndex::removeEntriesWithValueKey(const IDBKeyData& valueKey)
+{
+ LOG(IndexedDB, "MemoryIndex::removeEntriesWithValueKey");
+
+ if (!m_records)
+ return;
+
+ m_records->removeEntriesWithValueKey(valueKey);
+}
+
</ins><span class="cx"> } // namespace IDBServer
</span><span class="cx"> } // namespace WebCore
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryIndexh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndex.h (192293 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndex.h        2015-11-11 05:19:56 UTC (rev 192293)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndex.h        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -30,9 +30,15 @@
</span><span class="cx">
</span><span class="cx"> #include "IDBGetResult.h"
</span><span class="cx"> #include "IDBIndexInfo.h"
</span><ins>+#include "IDBKeyData.h"
+#include "IndexValueStore.h"
+#include <set>
+#include <wtf/HashMap.h>
</ins><span class="cx">
</span><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><ins>+class IDBError;
+class IndexKey;
</ins><span class="cx"> class ThreadSafeDataBuffer;
</span><span class="cx">
</span><span class="cx"> struct IDBKeyRangeData;
</span><span class="lines">@@ -43,22 +49,38 @@
</span><span class="cx">
</span><span class="cx"> namespace IDBServer {
</span><span class="cx">
</span><ins>+class MemoryBackingStoreTransaction;
+class MemoryObjectStore;
+
</ins><span class="cx"> class MemoryIndex {
</span><del>- friend std::unique_ptr<MemoryIndex> std::make_unique<MemoryIndex>(const WebCore::IDBIndexInfo&);
</del><ins>+ friend std::unique_ptr<MemoryIndex> std::make_unique<MemoryIndex>(const WebCore::IDBIndexInfo&, WebCore::IDBServer::MemoryObjectStore&);
</ins><span class="cx"> public:
</span><del>- static std::unique_ptr<MemoryIndex> create(const IDBIndexInfo&);
</del><ins>+ static std::unique_ptr<MemoryIndex> create(const IDBIndexInfo&, MemoryObjectStore&);
</ins><span class="cx">
</span><span class="cx"> ~MemoryIndex();
</span><span class="cx">
</span><span class="cx"> const IDBIndexInfo& info() const { return m_info; }
</span><span class="cx">
</span><del>- IDBGetResult valueForKeyRange(IndexedDB::IndexRecordType, const IDBKeyRangeData&) const;
</del><ins>+ IDBGetResult getResultForKeyRange(IndexedDB::IndexRecordType, const IDBKeyRangeData&) const;
</ins><span class="cx"> uint64_t countForKeyRange(const IDBKeyRangeData&);
</span><del>-
</del><ins>+
+ IDBError putIndexKey(const IDBKeyData&, const IndexKey&);
+
+ void removeEntriesWithValueKey(const IDBKeyData&);
+ void removeRecord(const IDBKeyData&, const IndexKey&);
+
+ void objectStoreCleared();
+ void replaceIndexValueStore(std::unique_ptr<IndexValueStore>&&);
+
</ins><span class="cx"> private:
</span><del>- MemoryIndex(const IDBIndexInfo&);
</del><ins>+ MemoryIndex(const IDBIndexInfo&, MemoryObjectStore&);
</ins><span class="cx">
</span><ins>+ uint64_t recordCountForKey(const IDBKeyData&) const;
+
</ins><span class="cx"> IDBIndexInfo m_info;
</span><ins>+ MemoryObjectStore& m_objectStore;
+
+ std::unique_ptr<IndexValueStore> m_records;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> } // namespace IDBServer
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryObjectStorecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.cpp (192293 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.cpp        2015-11-11 05:19:56 UTC (rev 192293)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.cpp        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -28,12 +28,18 @@
</span><span class="cx">
</span><span class="cx"> #if ENABLE(INDEXED_DATABASE)
</span><span class="cx">
</span><ins>+#include "IDBBindingUtilities.h"
</ins><span class="cx"> #include "IDBDatabaseException.h"
</span><span class="cx"> #include "IDBError.h"
</span><span class="cx"> #include "IDBKeyRangeData.h"
</span><ins>+#include "IndexKey.h"
</ins><span class="cx"> #include "Logging.h"
</span><span class="cx"> #include "MemoryBackingStoreTransaction.h"
</span><span class="cx">
</span><ins>+#include <wtf/NeverDestroyed.h>
+
+using namespace JSC;
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx"> namespace IDBServer {
</span><span class="cx">
</span><span class="lines">@@ -76,7 +82,7 @@
</span><span class="cx"> return IDBError(IDBExceptionCode::ConstraintError);
</span><span class="cx">
</span><span class="cx"> ASSERT(!m_indexesByIdentifier.contains(info.identifier()));
</span><del>- auto index = MemoryIndex::create(info);
</del><ins>+ auto index = MemoryIndex::create(info, *this);
</ins><span class="cx">
</span><span class="cx"> m_info.addExistingIndex(info);
</span><span class="cx">
</span><span class="lines">@@ -100,6 +106,8 @@
</span><span class="cx"> ASSERT(m_writeTransaction);
</span><span class="cx">
</span><span class="cx"> m_writeTransaction->objectStoreCleared(*this, WTF::move(m_keyValueStore));
</span><ins>+ for (auto& index : m_indexesByIdentifier.values())
+ index->objectStoreCleared();
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void MemoryObjectStore::replaceKeyValueStore(std::unique_ptr<KeyValueMap>&& store)
</span><span class="lines">@@ -132,6 +140,8 @@
</span><span class="cx"> m_writeTransaction->recordValueChanged(*this, key, &iterator->value);
</span><span class="cx"> m_keyValueStore->remove(iterator);
</span><span class="cx"> m_orderedKeys->erase(key);
</span><ins>+
+ updateIndexesForDeleteRecord(key);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void MemoryObjectStore::deleteRange(const IDBKeyRangeData& inputRange)
</span><span class="lines">@@ -158,7 +168,7 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void MemoryObjectStore::addRecord(MemoryBackingStoreTransaction& transaction, const IDBKeyData& keyData, const ThreadSafeDataBuffer& value)
</del><ins>+IDBError MemoryObjectStore::addRecord(MemoryBackingStoreTransaction& transaction, const IDBKeyData& keyData, const ThreadSafeDataBuffer& value)
</ins><span class="cx"> {
</span><span class="cx"> LOG(IndexedDB, "MemoryObjectStore::addRecord");
</span><span class="cx">
</span><span class="lines">@@ -173,11 +183,82 @@
</span><span class="cx"> m_orderedKeys = std::make_unique<std::set<IDBKeyData>>();
</span><span class="cx"> }
</span><span class="cx">
</span><del>- auto result = m_keyValueStore->set(keyData, value);
- if (result.isNewEntry)
- m_orderedKeys->insert(keyData);
</del><ins>+ auto mapResult = m_keyValueStore->set(keyData, value);
+ ASSERT(mapResult.isNewEntry);
+ auto listResult = m_orderedKeys->insert(keyData);
+ ASSERT(listResult.second);
+
+ // If there was an error indexing this addition, then revert it.
+ auto error = updateIndexesForPutRecord(keyData, value);
+ if (!error.isNull()) {
+ m_keyValueStore->remove(mapResult.iterator);
+ m_orderedKeys->erase(listResult.first);
+ }
+
+ return error;
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+static VM& indexVM()
+{
+ ASSERT(!isMainThread());
+ static NeverDestroyed<RefPtr<VM>> vm = VM::create();
+ return *vm.get();
+}
+
+static ExecState& indexGlobalExec()
+{
+ ASSERT(!isMainThread());
+ static NeverDestroyed<Strong<JSGlobalObject>> globalObject;
+ static bool initialized = false;
+ if (!initialized) {
+ globalObject.get().set(indexVM(), JSGlobalObject::create(indexVM(), JSGlobalObject::createStructure(indexVM(), jsNull())));
+ initialized = true;
+ }
+
+ RELEASE_ASSERT(globalObject.get()->globalExec());
+ return *globalObject.get()->globalExec();
+}
+
+void MemoryObjectStore::updateIndexesForDeleteRecord(const IDBKeyData& value)
+{
+ for (auto* index : m_indexesByName.values())
+ index->removeEntriesWithValueKey(value);
+}
+
+IDBError MemoryObjectStore::updateIndexesForPutRecord(const IDBKeyData& key, const ThreadSafeDataBuffer& value)
+{
+ JSLockHolder locker(indexVM());
+
+ auto jsValue = idbValueDataToJSValue(indexGlobalExec(), value);
+ if (jsValue.isUndefinedOrNull())
+ return { };
+
+ IDBError error;
+ Vector<std::pair<MemoryIndex*, IndexKey>> changedIndexRecords;
+
+ for (auto* index : m_indexesByName.values()) {
+ IndexKey indexKey;
+ generateIndexKeyForValue(indexGlobalExec(), index->info(), jsValue, indexKey);
+
+ if (indexKey.isNull())
+ continue;
+
+ error = index->putIndexKey(key, indexKey);
+ if (!error.isNull())
+ break;
+
+ changedIndexRecords.append(std::make_pair(index, indexKey));
+ }
+
+ // If any of the index puts failed, revert all of the ones that went through.
+ if (!error.isNull()) {
+ for (auto& record : changedIndexRecords)
+ record.first->removeRecord(key, record.second);
+ }
+
+ return error;
+}
+
</ins><span class="cx"> uint64_t MemoryObjectStore::countForKeyRange(uint64_t indexIdentifier, const IDBKeyRangeData& inRange) const
</span><span class="cx"> {
</span><span class="cx"> LOG(IndexedDB, "MemoryObjectStore::countForKeyRange");
</span><span class="lines">@@ -224,7 +305,7 @@
</span><span class="cx">
</span><span class="cx"> auto* index = m_indexesByIdentifier.get(indexIdentifier);
</span><span class="cx"> ASSERT(index);
</span><del>- return index->valueForKeyRange(recordType, range);
</del><ins>+ return index->getResultForKeyRange(recordType, range);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> IDBKeyData MemoryObjectStore::lowestKeyWithRecordInRange(const IDBKeyRangeData& keyRangeData) const
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbserverMemoryObjectStoreh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.h (192293 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.h        2015-11-11 05:19:56 UTC (rev 192293)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.h        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -61,13 +61,14 @@
</span><span class="cx">
</span><span class="cx"> void writeTransactionStarted(MemoryBackingStoreTransaction&);
</span><span class="cx"> void writeTransactionFinished(MemoryBackingStoreTransaction&);
</span><ins>+ MemoryBackingStoreTransaction* writeTransaction() { return m_writeTransaction; }
</ins><span class="cx">
</span><span class="cx"> IDBError createIndex(MemoryBackingStoreTransaction&, const IDBIndexInfo&);
</span><span class="cx">
</span><span class="cx"> bool containsRecord(const IDBKeyData&);
</span><span class="cx"> void deleteRecord(const IDBKeyData&);
</span><span class="cx"> void deleteRange(const IDBKeyRangeData&);
</span><del>- void addRecord(MemoryBackingStoreTransaction&, const IDBKeyData&, const ThreadSafeDataBuffer& value);
</del><ins>+ IDBError addRecord(MemoryBackingStoreTransaction&, const IDBKeyData&, const ThreadSafeDataBuffer& value);
</ins><span class="cx">
</span><span class="cx"> uint64_t currentKeyGeneratorValue() const { return m_keyGeneratorValue; }
</span><span class="cx"> void setKeyGeneratorValue(uint64_t value) { m_keyGeneratorValue = value; }
</span><span class="lines">@@ -86,6 +87,9 @@
</span><span class="cx">
</span><span class="cx"> IDBKeyData lowestKeyWithRecordInRange(const IDBKeyRangeData&) const;
</span><span class="cx">
</span><ins>+ IDBError updateIndexesForPutRecord(const IDBKeyData&, const ThreadSafeDataBuffer& value);
+ void updateIndexesForDeleteRecord(const IDBKeyData& value);
+
</ins><span class="cx"> IDBObjectStoreInfo m_info;
</span><span class="cx">
</span><span class="cx"> MemoryBackingStoreTransaction* m_writeTransaction { nullptr };
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbsharedIndexKeycppfromrev192293trunkSourceWebCoreModulesindexeddbIDBKeyRangeDatacpp"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/Modules/indexeddb/shared/IndexKey.cpp (from rev 192293, trunk/Source/WebCore/Modules/indexeddb/IDBKeyRangeData.cpp) (0 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/shared/IndexKey.cpp         (rev 0)
+++ trunk/Source/WebCore/Modules/indexeddb/shared/IndexKey.cpp        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -0,0 +1,89 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "IndexKey.h"
+
+#if ENABLE(INDEXED_DATABASE)
+
+namespace WebCore {
+
+IndexKey::IndexKey()
+{
+}
+
+IndexKey::IndexKey(Vector<IDBKeyData>&& keys)
+{
+ m_keys.swap(keys);
+}
+
+IndexKey IndexKey::isolatedCopy() const
+{
+ Vector<IDBKeyData> keys;
+ keys.reserveInitialCapacity(m_keys.size());
+ for (auto& key : m_keys)
+ keys.uncheckedAppend(key.isolatedCopy());
+
+ return { WTF::move(keys) };
+}
+
+IDBKeyData IndexKey::asOneKey() const
+{
+ if (m_keys.isEmpty())
+ return { };
+
+ if (m_keys.size() == 1)
+ return m_keys[0];
+
+ IDBKeyData result;
+ result.setArrayValue(m_keys);
+ return result;
+}
+
+Vector<IDBKeyData> IndexKey::multiEntry() const
+{
+ Vector<IDBKeyData> multiEntry;
+ for (auto& key : m_keys) {
+ if (!key.isValid())
+ continue;
+
+ bool skip = false;
+ for (auto& otherKey : multiEntry) {
+ if (key == otherKey) {
+ skip = true;
+ break;
+ }
+ }
+
+ if (!skip)
+ multiEntry.append(key);
+ }
+
+ return multiEntry;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
</ins></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbsharedIndexKeyh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/Modules/indexeddb/shared/IndexKey.h (0 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/shared/IndexKey.h         (rev 0)
+++ trunk/Source/WebCore/Modules/indexeddb/shared/IndexKey.h        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -0,0 +1,56 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef IndexKey_h
+#define IndexKey_h
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "IDBKeyData.h"
+#include <wtf/HashMap.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class IndexKey {
+public:
+ IndexKey();
+ IndexKey(Vector<IDBKeyData>&&);
+
+ IndexKey isolatedCopy() const;
+
+ IDBKeyData asOneKey() const;
+ Vector<IDBKeyData> multiEntry() const;
+
+ bool isNull() const { return m_keys.isEmpty(); }
+
+private:
+ Vector<IDBKeyData> m_keys;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
+#endif // IndexKey_h
</ins></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (192293 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2015-11-11 05:19:56 UTC (rev 192293)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -2047,6 +2047,10 @@
</span><span class="cx">                 516D7D701BB5F0BD00AF7C77 /* IDBConnectionToServerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5185FCBD1BB5CB770012898F /* IDBConnectionToServerDelegate.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 516D7D711BB5F0BD00AF7C77 /* IDBConnectionToClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 516D7D6D1BB5F06500AF7C77 /* IDBConnectionToClient.cpp */; };
</span><span class="cx">                 516D7D721BB5F0BD00AF7C77 /* IDBConnectionToClientDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 516D7D6E1BB5F06500AF7C77 /* IDBConnectionToClientDelegate.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                517138EF1BED1D1A000D5F01 /* IndexKey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 517138ED1BED1D17000D5F01 /* IndexKey.cpp */; };
+                517138F01BED1D1A000D5F01 /* IndexKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 517138EE1BED1D17000D5F01 /* IndexKey.h */; };
+                517138F71BF128BB000D5F01 /* IndexValueStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 517138F51BF12262000D5F01 /* IndexValueStore.cpp */; };
+                517138F81BF128BB000D5F01 /* IndexValueStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 517138F61BF12262000D5F01 /* IndexValueStore.h */; };
</ins><span class="cx">                 51741D0F0B07259A00ED442C /* BackForwardClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 51741D0B0B07259A00ED442C /* BackForwardClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 51741D110B07259A00ED442C /* HistoryItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 51741D0D0B07259A00ED442C /* HistoryItem.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 51741D120B07259A00ED442C /* HistoryItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51741D0E0B07259A00ED442C /* HistoryItem.cpp */; };
</span><span class="lines">@@ -2211,6 +2215,8 @@
</span><span class="cx">                 51EC92650CE90DD400F90308 /* JSCustomSQLStatementErrorCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51EC925D0CE90DD400F90308 /* JSCustomSQLStatementErrorCallback.cpp */; };
</span><span class="cx">                 51EE7B381AA50B0500F92B21 /* ResourceLoadInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 51EE7B371AA50B0500F92B21 /* ResourceLoadInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 51EE7B3A1AA5123100F92B21 /* ResourceLoadInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51EE7B391AA5123100F92B21 /* ResourceLoadInfo.cpp */; };
</span><ins>+                51EEAA731BEFFAB100218008 /* IndexValueEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51EEAA711BEFFA7900218008 /* IndexValueEntry.cpp */; };
+                51EEAA741BEFFAB100218008 /* IndexValueEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = 51EEAA721BEFFA7900218008 /* IndexValueEntry.h */; };
</ins><span class="cx">                 51F41A681BA73B5B002E053B /* IDBCallbacks.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F41A481BA73B2C002E053B /* IDBCallbacks.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 51F41A691BA73B5B002E053B /* IDBCursorBackend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51F41A491BA73B2C002E053B /* IDBCursorBackend.cpp */; };
</span><span class="cx">                 51F41A6A1BA73B5B002E053B /* IDBCursorBackend.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F41A4A1BA73B2C002E053B /* IDBCursorBackend.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -9497,6 +9503,10 @@
</span><span class="cx">                 516C62241950E2B900337E75 /* JSGamepadEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGamepadEvent.h; sourceTree = "<group>"; };
</span><span class="cx">                 516D7D6D1BB5F06500AF7C77 /* IDBConnectionToClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBConnectionToClient.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 516D7D6E1BB5F06500AF7C77 /* IDBConnectionToClientDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBConnectionToClientDelegate.h; sourceTree = "<group>"; };
</span><ins>+                517138ED1BED1D17000D5F01 /* IndexKey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndexKey.cpp; sourceTree = "<group>"; };
+                517138EE1BED1D17000D5F01 /* IndexKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IndexKey.h; sourceTree = "<group>"; };
+                517138F51BF12262000D5F01 /* IndexValueStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndexValueStore.cpp; sourceTree = "<group>"; };
+                517138F61BF12262000D5F01 /* IndexValueStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IndexValueStore.h; sourceTree = "<group>"; };
</ins><span class="cx">                 51741D0B0B07259A00ED442C /* BackForwardClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BackForwardClient.h; sourceTree = "<group>"; };
</span><span class="cx">                 51741D0D0B07259A00ED442C /* HistoryItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HistoryItem.h; sourceTree = "<group>"; };
</span><span class="cx">                 51741D0E0B07259A00ED442C /* HistoryItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = HistoryItem.cpp; sourceTree = "<group>"; };
</span><span class="lines">@@ -9654,6 +9664,8 @@
</span><span class="cx">                 51EC925D0CE90DD400F90308 /* JSCustomSQLStatementErrorCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCustomSQLStatementErrorCallback.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 51EE7B371AA50B0500F92B21 /* ResourceLoadInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResourceLoadInfo.h; sourceTree = "<group>"; };
</span><span class="cx">                 51EE7B391AA5123100F92B21 /* ResourceLoadInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ResourceLoadInfo.cpp; sourceTree = "<group>"; };
</span><ins>+                51EEAA711BEFFA7900218008 /* IndexValueEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndexValueEntry.cpp; sourceTree = "<group>"; };
+                51EEAA721BEFFA7900218008 /* IndexValueEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IndexValueEntry.h; sourceTree = "<group>"; };
</ins><span class="cx">                 51F41A481BA73B2C002E053B /* IDBCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBCallbacks.h; sourceTree = "<group>"; };
</span><span class="cx">                 51F41A491BA73B2C002E053B /* IDBCursorBackend.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBCursorBackend.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 51F41A4A1BA73B2C002E053B /* IDBCursorBackend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBCursorBackend.h; sourceTree = "<group>"; };
</span><span class="lines">@@ -16878,6 +16890,8 @@
</span><span class="cx">                                 5198F7AB1BBDD3E300E2CC5F /* IDBTransactionInfo.h */,
</span><span class="cx">                                 510A58E21BAA40AE00C19282 /* InProcessIDBServer.cpp */,
</span><span class="cx">                                 510A58E31BAA40AE00C19282 /* InProcessIDBServer.h */,
</span><ins>+                                517138ED1BED1D17000D5F01 /* IndexKey.cpp */,
+                                517138EE1BED1D17000D5F01 /* IndexKey.h */,
</ins><span class="cx">                         );
</span><span class="cx">                         path = shared;
</span><span class="cx">                         sourceTree = "<group>";
</span><span class="lines">@@ -16893,6 +16907,10 @@
</span><span class="cx">                                 510A58F01BAB720F00C19282 /* IDBServer.h */,
</span><span class="cx">                                 518864E41BBB4B7E00E540C9 /* IDBServerOperation.cpp */,
</span><span class="cx">                                 518864E51BBB4B7E00E540C9 /* IDBServerOperation.h */,
</span><ins>+                                51EEAA711BEFFA7900218008 /* IndexValueEntry.cpp */,
+                                51EEAA721BEFFA7900218008 /* IndexValueEntry.h */,
+                                517138F51BF12262000D5F01 /* IndexValueStore.cpp */,
+                                517138F61BF12262000D5F01 /* IndexValueStore.h */,
</ins><span class="cx">                                 51E1BAC01BD806470055D81F /* MemoryBackingStoreTransaction.cpp */,
</span><span class="cx">                                 51E1BAC11BD806470055D81F /* MemoryBackingStoreTransaction.h */,
</span><span class="cx">                                 51BA4AC81BBC5B9E00DF3D6D /* MemoryIDBBackingStore.cpp */,
</span><span class="lines">@@ -25682,6 +25700,7 @@
</span><span class="cx">                                 A871DE2D0A152AC800B12A68 /* HTMLHeadElement.h in Headers */,
</span><span class="cx">                                 A8EA7CB80A192B9C00A8EF5F /* HTMLHeadingElement.h in Headers */,
</span><span class="cx">                                 A8EA7CAF0A192B9C00A8EF5F /* HTMLHRElement.h in Headers */,
</span><ins>+                                517138F81BF128BB000D5F01 /* IndexValueStore.h in Headers */,
</ins><span class="cx">                                 A871DE270A152AC800B12A68 /* HTMLHtmlElement.h in Headers */,
</span><span class="cx">                                 A871DE2A0A152AC800B12A68 /* HTMLIFrameElement.h in Headers */,
</span><span class="cx">                                 A8EA7D2D0A19385500A8EF5F /* HTMLImageElement.h in Headers */,
</span><span class="lines">@@ -26960,6 +26979,7 @@
</span><span class="cx">                                 CE12523D1A1676CD00864480 /* QuartzCoreSPI.h in Headers */,
</span><span class="cx">                                 442AF7A9102CDDEA008FD4D3 /* QuickLook.h in Headers */,
</span><span class="cx">                                 A10DBF4718F92317000D70C6 /* QuickLookHandleClient.h in Headers */,
</span><ins>+                                51EEAA741BEFFAB100218008 /* IndexValueEntry.h in Headers */,
</ins><span class="cx">                                 937F4CCC1A2D48C100BB39F5 /* QuickLookMacSPI.h in Headers */,
</span><span class="cx">                                 443918001A91B2F8006E04F2 /* QuickLookSoftLink.h in Headers */,
</span><span class="cx">                                 CE1252391A166FA000864480 /* QuickLookSPI.h in Headers */,
</span><span class="lines">@@ -27321,6 +27341,7 @@
</span><span class="cx">                                 93309E10099E64920056E581 /* SetNodeAttributeCommand.h in Headers */,
</span><span class="cx">                                 B8DBDB4C130B0F8A00F5CDB1 /* SetSelectionCommand.h in Headers */,
</span><span class="cx">                                 93F1994F08245E59001E9ABC /* Settings.h in Headers */,
</span><ins>+                                517138F01BED1D1A000D5F01 /* IndexKey.h in Headers */,
</ins><span class="cx">                                 53EF766B16530A61004CBE49 /* SettingsMacros.h in Headers */,
</span><span class="cx">                                 0F3DD45012F5EA1B000D9190 /* ShadowBlur.h in Headers */,
</span><span class="cx">                                 BC5EB8C40E82031B00B25965 /* ShadowData.h in Headers */,
</span><span class="lines">@@ -28718,6 +28739,7 @@
</span><span class="cx">                                 31BC742D1AAFF45C006B4340 /* CSSAnimationTriggerScrollValue.cpp in Sources */,
</span><span class="cx">                                 CAE9F90F146441F000C245B0 /* CSSAspectRatioValue.cpp in Sources */,
</span><span class="cx">                                 FBD6AF8B15EF25E5008B7110 /* CSSBasicShapes.cpp in Sources */,
</span><ins>+                                51EEAA731BEFFAB100218008 /* IndexValueEntry.cpp in Sources */,
</ins><span class="cx">                                 E16A84F914C85CCC002977DF /* CSSBorderImage.cpp in Sources */,
</span><span class="cx">                                 BC274B31140EBED800EADFA6 /* CSSBorderImageSliceValue.cpp in Sources */,
</span><span class="cx">                                 49AE2D8E134EE50C0072920A /* CSSCalculationValue.cpp in Sources */,
</span><span class="lines">@@ -29789,6 +29811,7 @@
</span><span class="cx">                                 9752D38D1413104B003305BD /* JSHTMLSpanElement.cpp in Sources */,
</span><span class="cx">                                 A80E7B0F0A19D606007FB8C5 /* JSHTMLStyleElement.cpp in Sources */,
</span><span class="cx">                                 BCA169A20BFD55B40019CA76 /* JSHTMLTableCaptionElement.cpp in Sources */,
</span><ins>+                                517138F71BF128BB000D5F01 /* IndexValueStore.cpp in Sources */,
</ins><span class="cx">                                 BC06EDE30BFD6D0D00856E9D /* JSHTMLTableCellElement.cpp in Sources */,
</span><span class="cx">                                 BC06ED9D0BFD660600856E9D /* JSHTMLTableColElement.cpp in Sources */,
</span><span class="cx">                                 836CB1F91BD1E41800AF1591 /* JSHTMLTableDataCellElement.cpp in Sources */,
</span><span class="lines">@@ -29961,6 +29984,7 @@
</span><span class="cx">                                 AA7FEEA416A4E6F3004C0C33 /* JSSpeechSynthesis.cpp in Sources */,
</span><span class="cx">                                 AA2A5AD316A4860D00976A25 /* JSSpeechSynthesisEvent.cpp in Sources */,
</span><span class="cx">                                 AA7FEEA616A4E6F3004C0C33 /* JSSpeechSynthesisUtterance.cpp in Sources */,
</span><ins>+                                517138EF1BED1D1A000D5F01 /* IndexKey.cpp in Sources */,
</ins><span class="cx">                                 AA7FEEA816A4E6F3004C0C33 /* JSSpeechSynthesisVoice.cpp in Sources */,
</span><span class="cx">                                 514C76370CE9225E007EF3CD /* JSSQLError.cpp in Sources */,
</span><span class="cx">                                 B525A96611CA2340003A23A8 /* JSSQLException.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsIDBBindingUtilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/IDBBindingUtilities.cpp (192293 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/IDBBindingUtilities.cpp        2015-11-11 05:19:56 UTC (rev 192293)
+++ trunk/Source/WebCore/bindings/js/IDBBindingUtilities.cpp        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -30,10 +30,12 @@
</span><span class="cx"> #include "IDBBindingUtilities.h"
</span><span class="cx">
</span><span class="cx"> #include "DOMRequestState.h"
</span><ins>+#include "IDBIndexInfo.h"
</ins><span class="cx"> #include "IDBIndexMetadata.h"
</span><span class="cx"> #include "IDBKey.h"
</span><span class="cx"> #include "IDBKeyData.h"
</span><span class="cx"> #include "IDBKeyPath.h"
</span><ins>+#include "IndexKey.h"
</ins><span class="cx"> #include "JSDOMBinding.h"
</span><span class="cx"> #include "Logging.h"
</span><span class="cx"> #include "SharedBuffer.h"
</span><span class="lines">@@ -398,8 +400,19 @@
</span><span class="cx"> return Deprecated::ScriptValue(requestState->exec()->vm(), jsNull());
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+static JSValue idbValueDataToJSValue(JSC::ExecState& exec, const Vector<uint8_t>& buffer)
+{
+ if (buffer.isEmpty())
+ return jsNull();
+
+ RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::createFromWireBytes(buffer);
+ return serializedValue->deserialize(&exec, exec.lexicalGlobalObject(), 0, NonThrowing);
+}
+
</ins><span class="cx"> Deprecated::ScriptValue deserializeIDBValueBuffer(JSC::ExecState* exec, const Vector<uint8_t>& buffer, bool keyIsDefined)
</span><span class="cx"> {
</span><ins>+ ASSERT(exec);
+
</ins><span class="cx"> // If the key doesn't exist, then the value must be undefined (as opposed to null).
</span><span class="cx"> if (!keyIsDefined) {
</span><span class="cx"> // We either shouldn't have a buffer or it should be of size 0.
</span><span class="lines">@@ -407,16 +420,18 @@
</span><span class="cx"> return Deprecated::ScriptValue(exec->vm(), jsUndefined());
</span><span class="cx"> }
</span><span class="cx">
</span><del>- JSValue result;
- if (buffer.size()) {
- RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::createFromWireBytes(buffer);
- result = serializedValue->deserialize(exec, exec->lexicalGlobalObject(), 0, NonThrowing);
- } else
- result = jsNull();
-
</del><ins>+ JSValue result = idbValueDataToJSValue(*exec, buffer);
</ins><span class="cx"> return Deprecated::ScriptValue(exec->vm(), result);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+JSValue idbValueDataToJSValue(JSC::ExecState& exec, const ThreadSafeDataBuffer& valueData)
+{
+ if (!valueData.data())
+ return jsUndefined();
+
+ return idbValueDataToJSValue(exec, *valueData.data());
+}
+
</ins><span class="cx"> Deprecated::ScriptValue idbKeyToScriptValue(DOMRequestState* requestState, PassRefPtr<IDBKey> key)
</span><span class="cx"> {
</span><span class="cx"> ExecState* exec = requestState->exec();
</span><span class="lines">@@ -434,6 +449,13 @@
</span><span class="cx"> return createIDBKeyFromValue(&exec, scriptValue);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+Deprecated::ScriptValue idbKeyDataToScriptValue(ScriptExecutionContext* context, const IDBKeyData& keyData)
+{
+ RefPtr<IDBKey> key = keyData.maybeCreateIDBKey();
+ DOMRequestState requestState(context);
+ return idbKeyToScriptValue(&requestState, key.get());
+}
+
</ins><span class="cx"> void generateIndexKeysForValue(ExecState* exec, const IDBIndexMetadata& indexMetadata, const Deprecated::ScriptValue& objectValue, Vector<IDBKeyData>& indexKeys)
</span><span class="cx"> {
</span><span class="cx"> RefPtr<IDBKey> indexKey = createIDBKeyFromScriptValueAndKeyPath(exec, objectValue, indexMetadata.keyPath);
</span><span class="lines">@@ -459,13 +481,49 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-Deprecated::ScriptValue idbKeyDataToScriptValue(ScriptExecutionContext* context, const IDBKeyData& keyData)
</del><ins>+static Vector<IDBKeyData> createKeyPathArray(ExecState& exec, JSValue value, const IDBIndexInfo& info)
</ins><span class="cx"> {
</span><del>- RefPtr<IDBKey> key = keyData.maybeCreateIDBKey();
- DOMRequestState requestState(context);
- return idbKeyToScriptValue(&requestState, key.get());
</del><ins>+ Vector<IDBKeyData> keys;
+
+ switch (info.keyPath().type()) {
+ case IndexedDB::KeyPathType::Array:
+ for (auto& entry : info.keyPath().array()) {
+ auto key = internalCreateIDBKeyFromScriptValueAndKeyPath(&exec, value, entry);
+ if (!key)
+ return { };
+ keys.append(key.get());
+ }
+ break;
+ case IndexedDB::KeyPathType::String: {
+ auto idbKey = internalCreateIDBKeyFromScriptValueAndKeyPath(&exec, value, info.keyPath().string());
+ if (!idbKey)
+ return { };
+
+ if (info.multiEntry() && idbKey->type() == IndexedDB::Array) {
+ for (auto& key : idbKey->array())
+ keys.append(key.get());
+ } else
+ keys.append(idbKey.get());
+
+ break;
+ }
+ case IndexedDB::KeyPathType::Null:
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+
+ return keys;
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+void generateIndexKeyForValue(ExecState& exec, const IDBIndexInfo& info, JSValue value, IndexKey& outKey)
+{
+ auto keyDatas = createKeyPathArray(exec, value, info);
+
+ if (keyDatas.isEmpty())
+ return;
+
+ outKey = IndexKey(WTF::move(keyDatas));
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx">
</span><span class="cx"> #endif // ENABLE(INDEXED_DATABASE)
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsIDBBindingUtilitiesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/IDBBindingUtilities.h (192293 => 192294)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/IDBBindingUtilities.h        2015-11-11 05:19:56 UTC (rev 192293)
+++ trunk/Source/WebCore/bindings/js/IDBBindingUtilities.h        2015-11-11 06:07:03 UTC (rev 192294)
</span><span class="lines">@@ -35,8 +35,10 @@
</span><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><span class="cx"> class DOMRequestState;
</span><ins>+class IDBIndexInfo;
</ins><span class="cx"> class IDBKey;
</span><span class="cx"> class IDBKeyPath;
</span><ins>+class IndexKey;
</ins><span class="cx"> class SharedBuffer;
</span><span class="cx"> class ThreadSafeDataBuffer;
</span><span class="cx">
</span><span class="lines">@@ -58,12 +60,17 @@
</span><span class="cx"> Deprecated::ScriptValue deserializeIDBValueData(ScriptExecutionContext&, const ThreadSafeDataBuffer& valueData);
</span><span class="cx"> Deprecated::ScriptValue deserializeIDBValueBuffer(DOMRequestState*, PassRefPtr<SharedBuffer>, bool keyIsDefined);
</span><span class="cx"> WEBCORE_EXPORT Deprecated::ScriptValue deserializeIDBValueBuffer(JSC::ExecState*, const Vector<uint8_t>&, bool keyIsDefined);
</span><ins>+
</ins><span class="cx"> Deprecated::ScriptValue idbKeyToScriptValue(DOMRequestState*, PassRefPtr<IDBKey>);
</span><span class="cx"> RefPtr<IDBKey> scriptValueToIDBKey(DOMRequestState*, const JSC::JSValue&);
</span><span class="cx"> RefPtr<IDBKey> scriptValueToIDBKey(JSC::ExecState&, const JSC::JSValue&);
</span><span class="cx"> WEBCORE_EXPORT void generateIndexKeysForValue(JSC::ExecState*, const IDBIndexMetadata&, const Deprecated::ScriptValue& objectValue, Vector<IDBKeyData>& indexKeys);
</span><span class="cx">
</span><span class="cx"> Deprecated::ScriptValue idbKeyDataToScriptValue(ScriptExecutionContext*, const IDBKeyData&);
</span><ins>+
+JSC::JSValue idbValueDataToJSValue(JSC::ExecState&, const ThreadSafeDataBuffer& valueData);
+void generateIndexKeyForValue(JSC::ExecState&, const IDBIndexInfo&, JSC::JSValue, IndexKey& outKey);
+
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> #endif // ENABLE(INDEXED_DATABASE)
</span></span></pre>
</div>
</div>
</body>
</html>