Diff
Modified: trunk/LayoutTests/ChangeLog (192293 => 192294)
--- trunk/LayoutTests/ChangeLog 2015-11-11 05:19:56 UTC (rev 192293)
+++ trunk/LayoutTests/ChangeLog 2015-11-11 06:07:03 UTC (rev 192294)
@@ -1,3 +1,19 @@
+2015-11-10 Brady Eidson <beid...@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:
+
2015-11-10 Myles C. Maxfield <mmaxfi...@apple.com>
Updating test expected results after r192269
Added: trunk/LayoutTests/storage/indexeddb/modern/index-1-expected.txt (0 => 192294)
--- 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)
@@ -0,0 +1,136 @@
+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
+
Added: trunk/LayoutTests/storage/indexeddb/modern/index-1.html (0 => 192294)
--- 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)
@@ -0,0 +1,106 @@
+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>
Added: trunk/LayoutTests/storage/indexeddb/modern/index-2-expected.txt (0 => 192294)
--- 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)
@@ -0,0 +1,150 @@
+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
+
Added: trunk/LayoutTests/storage/indexeddb/modern/index-2.html (0 => 192294)
--- 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)
@@ -0,0 +1,165 @@
+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>
Added: trunk/LayoutTests/storage/indexeddb/modern/index-3-expected.txt (0 => 192294)
--- 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)
@@ -0,0 +1,23 @@
+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
+
Added: trunk/LayoutTests/storage/indexeddb/modern/index-3.html (0 => 192294)
--- 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)
@@ -0,0 +1,115 @@
+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>
Modified: trunk/LayoutTests/storage/indexeddb/modern/index-get-count-basic-expected.txt (192293 => 192294)
--- 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)
@@ -1,9 +1,10 @@
-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
This tests the most basic operation of the IDBIndex methods get(), getKey(), and count().
-It doesn't actually do anything other than exercise the requests themselves because we don't actually index yet.
+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
Modified: trunk/LayoutTests/storage/indexeddb/modern/index-get-count-basic.html (192293 => 192294)
--- 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)
@@ -1,5 +1,4 @@
This tests the most basic operation of the IDBIndex methods get(), getKey(), and count().<br>
-It doesn't actually do anything other than exercise the requests themselves because we don't actually index yet.<br>
<div id="logger"></div>
<script>
@@ -10,12 +9,12 @@
function done()
{
- alert("Done");
+ log("Done");
if (window.testRunner)
testRunner.notifyDone();
}
-function gol(message)
+function log(message)
{
document.getElementById("logger").innerHTML += message + "<br>";
}
@@ -23,42 +22,44 @@
var createRequest = window.indexedDB.open("IndexGetCountBasicDatabase", 1);
createRequest._onupgradeneeded_ = function(event) {
- alert("Initial upgrade needed: Old version - " + event.oldVersion + " New version - " + event.newVersion);
+ 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 index = objectStore.createIndex("TestIndex", "foo");
+ var index = objectStore.createIndex("TestIndex", "bar");
- objectStore.put("bar", "foo");
+ objectStore.put({ bar: "good", baz: "bad" }, "foo");
- var request1 = index.get("bar");
+ var request1 = index.get("good");
request1._onsuccess_ = function() {
- alert("get result is: " + request1.result);
+ log("get result is: " + request1.result);
+ for (n in request1.result)
+ log(n + " is " + request1.result[n]);
}
- request2 = index.getKey("bar");
+ request2 = index.getKey("good");
request2._onsuccess_ = function() {
- alert("getKey result is: " + request2.result);
+ log("getKey result is: " + request2.result);
}
var request3 = index.count();
request3._onsuccess_ = function() {
- alert("count result is: " + request3.result);
+ log("count result is: " + request3.result);
}
versionTransaction._onabort_ = function(event) {
- alert("Initial upgrade versionchange transaction unexpected aborted");
+ log("Initial upgrade versionchange transaction unexpected aborted");
done();
}
versionTransaction._oncomplete_ = function(event) {
- alert("Initial upgrade versionchange transaction complete");
+ log("Initial upgrade versionchange transaction complete");
done();
}
versionTransaction._onerror_ = function(event) {
- alert("Initial upgrade versionchange transaction unexpected error" + event);
+ log("Initial upgrade versionchange transaction unexpected error" + event);
done();
}
}
Modified: trunk/Source/WebCore/CMakeLists.txt (192293 => 192294)
--- 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)
@@ -902,6 +902,8 @@
Modules/indexeddb/server/IDBConnectionToClient.cpp
Modules/indexeddb/server/IDBServer.cpp
Modules/indexeddb/server/IDBServerOperation.cpp
+ Modules/indexeddb/server/IndexValueEntry.cpp
+ Modules/indexeddb/server/IndexValueStore.cpp
Modules/indexeddb/server/MemoryBackingStoreTransaction.cpp
Modules/indexeddb/server/MemoryIDBBackingStore.cpp
Modules/indexeddb/server/MemoryIndex.cpp
@@ -919,6 +921,7 @@
Modules/indexeddb/shared/IDBResultData.cpp
Modules/indexeddb/shared/IDBTransactionInfo.cpp
Modules/indexeddb/shared/InProcessIDBServer.cpp
+ Modules/indexeddb/shared/IndexKey.cpp
Modules/mediacontrols/MediaControlsHost.cpp
Modified: trunk/Source/WebCore/ChangeLog (192293 => 192294)
--- 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)
@@ -1,3 +1,97 @@
+2015-11-10 Brady Eidson <beid...@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:
+
2015-11-10 Myles C. Maxfield <mmaxfi...@apple.com>
Move locale information into FontDescription
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBKeyData.h (192293 => 192294)
--- 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)
@@ -122,9 +122,6 @@
break;
}
- unsigned targetSize = WTF::roundUpToPowerOfTwo(hashCodes.size());
- hashCodes.resize(targetSize);
-
return StringHasher::hashMemory(hashCodes.data(), hashCodes.size() * sizeof(unsigned));
}
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBKeyRangeData.cpp (192293 => 192294)
--- 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)
@@ -73,7 +73,7 @@
bool IDBKeyRangeData::isExactlyOneKey() const
{
- if (isNull || lowerOpen || upperOpen)
+ if (isNull || lowerOpen || upperOpen || !upperKey.isValid() || !lowerKey.isValid())
return false;
return !lowerKey.compare(upperKey);
Modified: trunk/Source/WebCore/Modules/indexeddb/client/IDBTransactionImpl.cpp (192293 => 192294)
--- 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)
@@ -484,9 +484,11 @@
{
LOG(IndexedDB, "IDBTransaction::didGetRecordOnServer");
+ const IDBGetResult& result = resultData.getResult();
+
if (request.sourceIndexIdentifier() && request.requestedIndexRecordType() == IndexedDB::IndexRecordType::Key) {
- if (resultData.resultKey())
- request.setResult(resultData.resultKey());
+ if (!result.keyData.isNull())
+ request.setResult(&result.keyData);
else
request.setResultToUndefined();
} else {
Copied: trunk/Source/WebCore/Modules/indexeddb/server/IndexValueEntry.cpp (from rev 192293, trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndex.cpp) (0 => 192294)
--- 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)
@@ -0,0 +1,96 @@
+/*
+ * 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)
Copied: trunk/Source/WebCore/Modules/indexeddb/server/IndexValueEntry.h (from rev 192293, trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndex.h) (0 => 192294)
--- 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)
@@ -0,0 +1,64 @@
+/*
+ * 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
Added: trunk/Source/WebCore/Modules/indexeddb/server/IndexValueStore.cpp (0 => 192294)
--- 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)
@@ -0,0 +1,141 @@
+/*
+ * 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)
Copied: trunk/Source/WebCore/Modules/indexeddb/server/IndexValueStore.h (from rev 192293, trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndex.h) (0 => 192294)
--- 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)
@@ -0,0 +1,71 @@
+/*
+ * 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
Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryBackingStoreTransaction.cpp (192293 => 192294)
--- 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)
@@ -117,21 +117,24 @@
auto addResult = m_clearedKeyValueMaps.add(&objectStore, nullptr);
- // If this object store has already been cleared during this transaction, we don't need to remember this clearing.
+ // If this object store has already been cleared during this transaction, we shouldn't remember this clearing.
if (!addResult.isNewEntry)
return;
- // 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);
- }
-
addResult.iterator->value = WTF::move(keyValueMap);
}
+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);
+}
+
void MemoryBackingStoreTransaction::recordValueChanged(MemoryObjectStore& objectStore, const IDBKeyData& key, ThreadSafeDataBuffer* value)
{
ASSERT(m_objectStores.contains(&objectStore));
@@ -182,15 +185,19 @@
m_backingStore.setDatabaseInfo(*m_originalDatabaseInfo);
}
+ // 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();
+
for (auto objectStore : m_objectStores) {
ASSERT(m_originalKeyGenerators.contains(objectStore));
objectStore->setKeyGeneratorValue(m_originalKeyGenerators.get(objectStore));
auto clearedKeyValueMap = m_clearedKeyValueMaps.take(objectStore);
- if (clearedKeyValueMap) {
+ if (clearedKeyValueMap)
objectStore->replaceKeyValueStore(WTF::move(clearedKeyValueMap));
- continue;
- }
auto keyValueMap = m_originalValues.take(objectStore);
if (!keyValueMap)
Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryBackingStoreTransaction.h (192293 => 192294)
--- 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)
@@ -31,6 +31,7 @@
#include "IDBDatabaseInfo.h"
#include "IDBKeyData.h"
#include "IDBTransactionInfo.h"
+#include "IndexValueStore.h"
#include "ThreadSafeDataBuffer.h"
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
@@ -63,6 +64,7 @@
void recordValueChanged(MemoryObjectStore&, const IDBKeyData&, ThreadSafeDataBuffer*);
void objectStoreDeleted(std::unique_ptr<MemoryObjectStore>);
void objectStoreCleared(MemoryObjectStore&, std::unique_ptr<KeyValueMap>&&);
+ void indexCleared(MemoryIndex&, std::unique_ptr<IndexValueStore>&&);
void addNewIndex(MemoryIndex&);
void addExistingIndex(MemoryIndex&);
@@ -90,8 +92,10 @@
HashMap<MemoryObjectStore*, uint64_t> m_originalKeyGenerators;
HashMap<String, std::unique_ptr<MemoryObjectStore>> m_deletedObjectStores;
+ HashMap<String, std::unique_ptr<MemoryIndex>> m_deletedIndexes;
HashMap<MemoryObjectStore*, std::unique_ptr<KeyValueMap>> m_originalValues;
HashMap<MemoryObjectStore*, std::unique_ptr<KeyValueMap>> m_clearedKeyValueMaps;
+ HashMap<MemoryIndex*, std::unique_ptr<IndexValueStore>> m_clearedIndexValueStores;
};
} // namespace IDBServer
Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp (192293 => 192294)
--- 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)
@@ -258,8 +258,7 @@
if (!objectStore)
return IDBError(IDBExceptionCode::Unknown, WTF::ASCIILiteral("No backing store object store found to put record"));
- objectStore->addRecord(*transaction, keyData, value);
- return IDBError();
+ return objectStore->addRecord(*transaction, keyData, value);
}
IDBError MemoryIDBBackingStore::getRecord(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData& range, ThreadSafeDataBuffer& outValue)
Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndex.cpp (192293 => 192294)
--- 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)
@@ -28,18 +28,26 @@
#if ENABLE(INDEXED_DATABASE)
+#include "IDBError.h"
#include "IDBGetResult.h"
+#include "IDBKeyRangeData.h"
+#include "IndexKey.h"
+#include "Logging.h"
+#include "MemoryBackingStoreTransaction.h"
+#include "MemoryObjectStore.h"
+#include "ThreadSafeDataBuffer.h"
namespace WebCore {
namespace IDBServer {
-std::unique_ptr<MemoryIndex> MemoryIndex::create(const IDBIndexInfo& info)
+std::unique_ptr<MemoryIndex> MemoryIndex::create(const IDBIndexInfo& info, MemoryObjectStore& objectStore)
{
- return std::make_unique<MemoryIndex>(info);
+ return std::make_unique<MemoryIndex>(info, objectStore);
}
-MemoryIndex::MemoryIndex(const IDBIndexInfo& info)
+MemoryIndex::MemoryIndex(const IDBIndexInfo& info, MemoryObjectStore& objectStore)
: m_info(info)
+ , m_objectStore(objectStore)
{
}
@@ -47,20 +55,125 @@
{
}
-IDBGetResult MemoryIndex::valueForKeyRange(IndexedDB::IndexRecordType, const IDBKeyRangeData&) const
+void MemoryIndex::objectStoreCleared()
{
- // FIXME: Once indexes actually index, we'll return something real.
- // https://bugs.webkit.org/show_bug.cgi?id=150939
+ 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());
+ }
+
return { };
}
-uint64_t MemoryIndex::countForKeyRange(const IDBKeyRangeData&)
+void MemoryIndex::removeRecord(const IDBKeyData& valueKey, const IndexKey& indexKey)
{
- // FIXME: Once indexes actually index, we'll return something real.
- // https://bugs.webkit.org/show_bug.cgi?id=150939
- return 0;
+ 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);
}
+void MemoryIndex::removeEntriesWithValueKey(const IDBKeyData& valueKey)
+{
+ LOG(IndexedDB, "MemoryIndex::removeEntriesWithValueKey");
+
+ if (!m_records)
+ return;
+
+ m_records->removeEntriesWithValueKey(valueKey);
+}
+
} // namespace IDBServer
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryIndex.h (192293 => 192294)
--- 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)
@@ -30,9 +30,15 @@
#include "IDBGetResult.h"
#include "IDBIndexInfo.h"
+#include "IDBKeyData.h"
+#include "IndexValueStore.h"
+#include <set>
+#include <wtf/HashMap.h>
namespace WebCore {
+class IDBError;
+class IndexKey;
class ThreadSafeDataBuffer;
struct IDBKeyRangeData;
@@ -43,22 +49,38 @@
namespace IDBServer {
+class MemoryBackingStoreTransaction;
+class MemoryObjectStore;
+
class MemoryIndex {
- friend std::unique_ptr<MemoryIndex> std::make_unique<MemoryIndex>(const WebCore::IDBIndexInfo&);
+ friend std::unique_ptr<MemoryIndex> std::make_unique<MemoryIndex>(const WebCore::IDBIndexInfo&, WebCore::IDBServer::MemoryObjectStore&);
public:
- static std::unique_ptr<MemoryIndex> create(const IDBIndexInfo&);
+ static std::unique_ptr<MemoryIndex> create(const IDBIndexInfo&, MemoryObjectStore&);
~MemoryIndex();
const IDBIndexInfo& info() const { return m_info; }
- IDBGetResult valueForKeyRange(IndexedDB::IndexRecordType, const IDBKeyRangeData&) const;
+ IDBGetResult getResultForKeyRange(IndexedDB::IndexRecordType, const IDBKeyRangeData&) const;
uint64_t countForKeyRange(const IDBKeyRangeData&);
-
+
+ IDBError putIndexKey(const IDBKeyData&, const IndexKey&);
+
+ void removeEntriesWithValueKey(const IDBKeyData&);
+ void removeRecord(const IDBKeyData&, const IndexKey&);
+
+ void objectStoreCleared();
+ void replaceIndexValueStore(std::unique_ptr<IndexValueStore>&&);
+
private:
- MemoryIndex(const IDBIndexInfo&);
+ MemoryIndex(const IDBIndexInfo&, MemoryObjectStore&);
+ uint64_t recordCountForKey(const IDBKeyData&) const;
+
IDBIndexInfo m_info;
+ MemoryObjectStore& m_objectStore;
+
+ std::unique_ptr<IndexValueStore> m_records;
};
} // namespace IDBServer
Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.cpp (192293 => 192294)
--- 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)
@@ -28,12 +28,18 @@
#if ENABLE(INDEXED_DATABASE)
+#include "IDBBindingUtilities.h"
#include "IDBDatabaseException.h"
#include "IDBError.h"
#include "IDBKeyRangeData.h"
+#include "IndexKey.h"
#include "Logging.h"
#include "MemoryBackingStoreTransaction.h"
+#include <wtf/NeverDestroyed.h>
+
+using namespace JSC;
+
namespace WebCore {
namespace IDBServer {
@@ -76,7 +82,7 @@
return IDBError(IDBExceptionCode::ConstraintError);
ASSERT(!m_indexesByIdentifier.contains(info.identifier()));
- auto index = MemoryIndex::create(info);
+ auto index = MemoryIndex::create(info, *this);
m_info.addExistingIndex(info);
@@ -100,6 +106,8 @@
ASSERT(m_writeTransaction);
m_writeTransaction->objectStoreCleared(*this, WTF::move(m_keyValueStore));
+ for (auto& index : m_indexesByIdentifier.values())
+ index->objectStoreCleared();
}
void MemoryObjectStore::replaceKeyValueStore(std::unique_ptr<KeyValueMap>&& store)
@@ -132,6 +140,8 @@
m_writeTransaction->recordValueChanged(*this, key, &iterator->value);
m_keyValueStore->remove(iterator);
m_orderedKeys->erase(key);
+
+ updateIndexesForDeleteRecord(key);
}
void MemoryObjectStore::deleteRange(const IDBKeyRangeData& inputRange)
@@ -158,7 +168,7 @@
}
}
-void MemoryObjectStore::addRecord(MemoryBackingStoreTransaction& transaction, const IDBKeyData& keyData, const ThreadSafeDataBuffer& value)
+IDBError MemoryObjectStore::addRecord(MemoryBackingStoreTransaction& transaction, const IDBKeyData& keyData, const ThreadSafeDataBuffer& value)
{
LOG(IndexedDB, "MemoryObjectStore::addRecord");
@@ -173,11 +183,82 @@
m_orderedKeys = std::make_unique<std::set<IDBKeyData>>();
}
- auto result = m_keyValueStore->set(keyData, value);
- if (result.isNewEntry)
- m_orderedKeys->insert(keyData);
+ 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;
}
+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;
+}
+
uint64_t MemoryObjectStore::countForKeyRange(uint64_t indexIdentifier, const IDBKeyRangeData& inRange) const
{
LOG(IndexedDB, "MemoryObjectStore::countForKeyRange");
@@ -224,7 +305,7 @@
auto* index = m_indexesByIdentifier.get(indexIdentifier);
ASSERT(index);
- return index->valueForKeyRange(recordType, range);
+ return index->getResultForKeyRange(recordType, range);
}
IDBKeyData MemoryObjectStore::lowestKeyWithRecordInRange(const IDBKeyRangeData& keyRangeData) const
Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.h (192293 => 192294)
--- 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)
@@ -61,13 +61,14 @@
void writeTransactionStarted(MemoryBackingStoreTransaction&);
void writeTransactionFinished(MemoryBackingStoreTransaction&);
+ MemoryBackingStoreTransaction* writeTransaction() { return m_writeTransaction; }
IDBError createIndex(MemoryBackingStoreTransaction&, const IDBIndexInfo&);
bool containsRecord(const IDBKeyData&);
void deleteRecord(const IDBKeyData&);
void deleteRange(const IDBKeyRangeData&);
- void addRecord(MemoryBackingStoreTransaction&, const IDBKeyData&, const ThreadSafeDataBuffer& value);
+ IDBError addRecord(MemoryBackingStoreTransaction&, const IDBKeyData&, const ThreadSafeDataBuffer& value);
uint64_t currentKeyGeneratorValue() const { return m_keyGeneratorValue; }
void setKeyGeneratorValue(uint64_t value) { m_keyGeneratorValue = value; }
@@ -86,6 +87,9 @@
IDBKeyData lowestKeyWithRecordInRange(const IDBKeyRangeData&) const;
+ IDBError updateIndexesForPutRecord(const IDBKeyData&, const ThreadSafeDataBuffer& value);
+ void updateIndexesForDeleteRecord(const IDBKeyData& value);
+
IDBObjectStoreInfo m_info;
MemoryBackingStoreTransaction* m_writeTransaction { nullptr };
Copied: trunk/Source/WebCore/Modules/indexeddb/shared/IndexKey.cpp (from rev 192293, trunk/Source/WebCore/Modules/indexeddb/IDBKeyRangeData.cpp) (0 => 192294)
--- 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)
@@ -0,0 +1,89 @@
+/*
+ * 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)
Added: trunk/Source/WebCore/Modules/indexeddb/shared/IndexKey.h (0 => 192294)
--- 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)
@@ -0,0 +1,56 @@
+/*
+ * 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
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (192293 => 192294)
--- 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)
@@ -2047,6 +2047,10 @@
516D7D701BB5F0BD00AF7C77 /* IDBConnectionToServerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5185FCBD1BB5CB770012898F /* IDBConnectionToServerDelegate.h */; settings = {ATTRIBUTES = (Private, ); }; };
516D7D711BB5F0BD00AF7C77 /* IDBConnectionToClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 516D7D6D1BB5F06500AF7C77 /* IDBConnectionToClient.cpp */; };
516D7D721BB5F0BD00AF7C77 /* IDBConnectionToClientDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 516D7D6E1BB5F06500AF7C77 /* IDBConnectionToClientDelegate.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 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 */; };
51741D0F0B07259A00ED442C /* BackForwardClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 51741D0B0B07259A00ED442C /* BackForwardClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
51741D110B07259A00ED442C /* HistoryItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 51741D0D0B07259A00ED442C /* HistoryItem.h */; settings = {ATTRIBUTES = (Private, ); }; };
51741D120B07259A00ED442C /* HistoryItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51741D0E0B07259A00ED442C /* HistoryItem.cpp */; };
@@ -2211,6 +2215,8 @@
51EC92650CE90DD400F90308 /* JSCustomSQLStatementErrorCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51EC925D0CE90DD400F90308 /* JSCustomSQLStatementErrorCallback.cpp */; };
51EE7B381AA50B0500F92B21 /* ResourceLoadInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 51EE7B371AA50B0500F92B21 /* ResourceLoadInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
51EE7B3A1AA5123100F92B21 /* ResourceLoadInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51EE7B391AA5123100F92B21 /* ResourceLoadInfo.cpp */; };
+ 51EEAA731BEFFAB100218008 /* IndexValueEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51EEAA711BEFFA7900218008 /* IndexValueEntry.cpp */; };
+ 51EEAA741BEFFAB100218008 /* IndexValueEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = 51EEAA721BEFFA7900218008 /* IndexValueEntry.h */; };
51F41A681BA73B5B002E053B /* IDBCallbacks.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F41A481BA73B2C002E053B /* IDBCallbacks.h */; settings = {ATTRIBUTES = (Private, ); }; };
51F41A691BA73B5B002E053B /* IDBCursorBackend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51F41A491BA73B2C002E053B /* IDBCursorBackend.cpp */; };
51F41A6A1BA73B5B002E053B /* IDBCursorBackend.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F41A4A1BA73B2C002E053B /* IDBCursorBackend.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -9497,6 +9503,10 @@
516C62241950E2B900337E75 /* JSGamepadEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGamepadEvent.h; sourceTree = "<group>"; };
516D7D6D1BB5F06500AF7C77 /* IDBConnectionToClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBConnectionToClient.cpp; sourceTree = "<group>"; };
516D7D6E1BB5F06500AF7C77 /* IDBConnectionToClientDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBConnectionToClientDelegate.h; sourceTree = "<group>"; };
+ 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>"; };
51741D0B0B07259A00ED442C /* BackForwardClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BackForwardClient.h; sourceTree = "<group>"; };
51741D0D0B07259A00ED442C /* HistoryItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HistoryItem.h; sourceTree = "<group>"; };
51741D0E0B07259A00ED442C /* HistoryItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = HistoryItem.cpp; sourceTree = "<group>"; };
@@ -9654,6 +9664,8 @@
51EC925D0CE90DD400F90308 /* JSCustomSQLStatementErrorCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCustomSQLStatementErrorCallback.cpp; sourceTree = "<group>"; };
51EE7B371AA50B0500F92B21 /* ResourceLoadInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResourceLoadInfo.h; sourceTree = "<group>"; };
51EE7B391AA5123100F92B21 /* ResourceLoadInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ResourceLoadInfo.cpp; sourceTree = "<group>"; };
+ 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>"; };
51F41A481BA73B2C002E053B /* IDBCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBCallbacks.h; sourceTree = "<group>"; };
51F41A491BA73B2C002E053B /* IDBCursorBackend.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBCursorBackend.cpp; sourceTree = "<group>"; };
51F41A4A1BA73B2C002E053B /* IDBCursorBackend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBCursorBackend.h; sourceTree = "<group>"; };
@@ -16878,6 +16890,8 @@
5198F7AB1BBDD3E300E2CC5F /* IDBTransactionInfo.h */,
510A58E21BAA40AE00C19282 /* InProcessIDBServer.cpp */,
510A58E31BAA40AE00C19282 /* InProcessIDBServer.h */,
+ 517138ED1BED1D17000D5F01 /* IndexKey.cpp */,
+ 517138EE1BED1D17000D5F01 /* IndexKey.h */,
);
path = shared;
sourceTree = "<group>";
@@ -16893,6 +16907,10 @@
510A58F01BAB720F00C19282 /* IDBServer.h */,
518864E41BBB4B7E00E540C9 /* IDBServerOperation.cpp */,
518864E51BBB4B7E00E540C9 /* IDBServerOperation.h */,
+ 51EEAA711BEFFA7900218008 /* IndexValueEntry.cpp */,
+ 51EEAA721BEFFA7900218008 /* IndexValueEntry.h */,
+ 517138F51BF12262000D5F01 /* IndexValueStore.cpp */,
+ 517138F61BF12262000D5F01 /* IndexValueStore.h */,
51E1BAC01BD806470055D81F /* MemoryBackingStoreTransaction.cpp */,
51E1BAC11BD806470055D81F /* MemoryBackingStoreTransaction.h */,
51BA4AC81BBC5B9E00DF3D6D /* MemoryIDBBackingStore.cpp */,
@@ -25682,6 +25700,7 @@
A871DE2D0A152AC800B12A68 /* HTMLHeadElement.h in Headers */,
A8EA7CB80A192B9C00A8EF5F /* HTMLHeadingElement.h in Headers */,
A8EA7CAF0A192B9C00A8EF5F /* HTMLHRElement.h in Headers */,
+ 517138F81BF128BB000D5F01 /* IndexValueStore.h in Headers */,
A871DE270A152AC800B12A68 /* HTMLHtmlElement.h in Headers */,
A871DE2A0A152AC800B12A68 /* HTMLIFrameElement.h in Headers */,
A8EA7D2D0A19385500A8EF5F /* HTMLImageElement.h in Headers */,
@@ -26960,6 +26979,7 @@
CE12523D1A1676CD00864480 /* QuartzCoreSPI.h in Headers */,
442AF7A9102CDDEA008FD4D3 /* QuickLook.h in Headers */,
A10DBF4718F92317000D70C6 /* QuickLookHandleClient.h in Headers */,
+ 51EEAA741BEFFAB100218008 /* IndexValueEntry.h in Headers */,
937F4CCC1A2D48C100BB39F5 /* QuickLookMacSPI.h in Headers */,
443918001A91B2F8006E04F2 /* QuickLookSoftLink.h in Headers */,
CE1252391A166FA000864480 /* QuickLookSPI.h in Headers */,
@@ -27321,6 +27341,7 @@
93309E10099E64920056E581 /* SetNodeAttributeCommand.h in Headers */,
B8DBDB4C130B0F8A00F5CDB1 /* SetSelectionCommand.h in Headers */,
93F1994F08245E59001E9ABC /* Settings.h in Headers */,
+ 517138F01BED1D1A000D5F01 /* IndexKey.h in Headers */,
53EF766B16530A61004CBE49 /* SettingsMacros.h in Headers */,
0F3DD45012F5EA1B000D9190 /* ShadowBlur.h in Headers */,
BC5EB8C40E82031B00B25965 /* ShadowData.h in Headers */,
@@ -28718,6 +28739,7 @@
31BC742D1AAFF45C006B4340 /* CSSAnimationTriggerScrollValue.cpp in Sources */,
CAE9F90F146441F000C245B0 /* CSSAspectRatioValue.cpp in Sources */,
FBD6AF8B15EF25E5008B7110 /* CSSBasicShapes.cpp in Sources */,
+ 51EEAA731BEFFAB100218008 /* IndexValueEntry.cpp in Sources */,
E16A84F914C85CCC002977DF /* CSSBorderImage.cpp in Sources */,
BC274B31140EBED800EADFA6 /* CSSBorderImageSliceValue.cpp in Sources */,
49AE2D8E134EE50C0072920A /* CSSCalculationValue.cpp in Sources */,
@@ -29789,6 +29811,7 @@
9752D38D1413104B003305BD /* JSHTMLSpanElement.cpp in Sources */,
A80E7B0F0A19D606007FB8C5 /* JSHTMLStyleElement.cpp in Sources */,
BCA169A20BFD55B40019CA76 /* JSHTMLTableCaptionElement.cpp in Sources */,
+ 517138F71BF128BB000D5F01 /* IndexValueStore.cpp in Sources */,
BC06EDE30BFD6D0D00856E9D /* JSHTMLTableCellElement.cpp in Sources */,
BC06ED9D0BFD660600856E9D /* JSHTMLTableColElement.cpp in Sources */,
836CB1F91BD1E41800AF1591 /* JSHTMLTableDataCellElement.cpp in Sources */,
@@ -29961,6 +29984,7 @@
AA7FEEA416A4E6F3004C0C33 /* JSSpeechSynthesis.cpp in Sources */,
AA2A5AD316A4860D00976A25 /* JSSpeechSynthesisEvent.cpp in Sources */,
AA7FEEA616A4E6F3004C0C33 /* JSSpeechSynthesisUtterance.cpp in Sources */,
+ 517138EF1BED1D1A000D5F01 /* IndexKey.cpp in Sources */,
AA7FEEA816A4E6F3004C0C33 /* JSSpeechSynthesisVoice.cpp in Sources */,
514C76370CE9225E007EF3CD /* JSSQLError.cpp in Sources */,
B525A96611CA2340003A23A8 /* JSSQLException.cpp in Sources */,
Modified: trunk/Source/WebCore/bindings/js/IDBBindingUtilities.cpp (192293 => 192294)
--- 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)
@@ -30,10 +30,12 @@
#include "IDBBindingUtilities.h"
#include "DOMRequestState.h"
+#include "IDBIndexInfo.h"
#include "IDBIndexMetadata.h"
#include "IDBKey.h"
#include "IDBKeyData.h"
#include "IDBKeyPath.h"
+#include "IndexKey.h"
#include "JSDOMBinding.h"
#include "Logging.h"
#include "SharedBuffer.h"
@@ -398,8 +400,19 @@
return Deprecated::ScriptValue(requestState->exec()->vm(), jsNull());
}
+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);
+}
+
Deprecated::ScriptValue deserializeIDBValueBuffer(JSC::ExecState* exec, const Vector<uint8_t>& buffer, bool keyIsDefined)
{
+ ASSERT(exec);
+
// If the key doesn't exist, then the value must be undefined (as opposed to null).
if (!keyIsDefined) {
// We either shouldn't have a buffer or it should be of size 0.
@@ -407,16 +420,18 @@
return Deprecated::ScriptValue(exec->vm(), jsUndefined());
}
- JSValue result;
- if (buffer.size()) {
- RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::createFromWireBytes(buffer);
- result = serializedValue->deserialize(exec, exec->lexicalGlobalObject(), 0, NonThrowing);
- } else
- result = jsNull();
-
+ JSValue result = idbValueDataToJSValue(*exec, buffer);
return Deprecated::ScriptValue(exec->vm(), result);
}
+JSValue idbValueDataToJSValue(JSC::ExecState& exec, const ThreadSafeDataBuffer& valueData)
+{
+ if (!valueData.data())
+ return jsUndefined();
+
+ return idbValueDataToJSValue(exec, *valueData.data());
+}
+
Deprecated::ScriptValue idbKeyToScriptValue(DOMRequestState* requestState, PassRefPtr<IDBKey> key)
{
ExecState* exec = requestState->exec();
@@ -434,6 +449,13 @@
return createIDBKeyFromValue(&exec, scriptValue);
}
+Deprecated::ScriptValue idbKeyDataToScriptValue(ScriptExecutionContext* context, const IDBKeyData& keyData)
+{
+ RefPtr<IDBKey> key = keyData.maybeCreateIDBKey();
+ DOMRequestState requestState(context);
+ return idbKeyToScriptValue(&requestState, key.get());
+}
+
void generateIndexKeysForValue(ExecState* exec, const IDBIndexMetadata& indexMetadata, const Deprecated::ScriptValue& objectValue, Vector<IDBKeyData>& indexKeys)
{
RefPtr<IDBKey> indexKey = createIDBKeyFromScriptValueAndKeyPath(exec, objectValue, indexMetadata.keyPath);
@@ -459,13 +481,49 @@
}
}
-Deprecated::ScriptValue idbKeyDataToScriptValue(ScriptExecutionContext* context, const IDBKeyData& keyData)
+static Vector<IDBKeyData> createKeyPathArray(ExecState& exec, JSValue value, const IDBIndexInfo& info)
{
- RefPtr<IDBKey> key = keyData.maybeCreateIDBKey();
- DOMRequestState requestState(context);
- return idbKeyToScriptValue(&requestState, key.get());
+ 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;
}
+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));
+}
+
} // namespace WebCore
#endif // ENABLE(INDEXED_DATABASE)
Modified: trunk/Source/WebCore/bindings/js/IDBBindingUtilities.h (192293 => 192294)
--- 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)
@@ -35,8 +35,10 @@
namespace WebCore {
class DOMRequestState;
+class IDBIndexInfo;
class IDBKey;
class IDBKeyPath;
+class IndexKey;
class SharedBuffer;
class ThreadSafeDataBuffer;
@@ -58,12 +60,17 @@
Deprecated::ScriptValue deserializeIDBValueData(ScriptExecutionContext&, const ThreadSafeDataBuffer& valueData);
Deprecated::ScriptValue deserializeIDBValueBuffer(DOMRequestState*, PassRefPtr<SharedBuffer>, bool keyIsDefined);
WEBCORE_EXPORT Deprecated::ScriptValue deserializeIDBValueBuffer(JSC::ExecState*, const Vector<uint8_t>&, bool keyIsDefined);
+
Deprecated::ScriptValue idbKeyToScriptValue(DOMRequestState*, PassRefPtr<IDBKey>);
RefPtr<IDBKey> scriptValueToIDBKey(DOMRequestState*, const JSC::JSValue&);
RefPtr<IDBKey> scriptValueToIDBKey(JSC::ExecState&, const JSC::JSValue&);
WEBCORE_EXPORT void generateIndexKeysForValue(JSC::ExecState*, const IDBIndexMetadata&, const Deprecated::ScriptValue& objectValue, Vector<IDBKeyData>& indexKeys);
Deprecated::ScriptValue idbKeyDataToScriptValue(ScriptExecutionContext*, const IDBKeyData&);
+
+JSC::JSValue idbValueDataToJSValue(JSC::ExecState&, const ThreadSafeDataBuffer& valueData);
+void generateIndexKeyForValue(JSC::ExecState&, const IDBIndexInfo&, JSC::JSValue, IndexKey& outKey);
+
}
#endif // ENABLE(INDEXED_DATABASE)