Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 <!doctype html> | |
|
jsbell
2017/03/22 22:35:33
I don't think this is appropriate for wpt - it's n
pwnall
2017/03/23 03:18:57
I thought it would be useful to contribute this to
| |
| 2 <meta charset="utf-8"> | |
| 3 <title>IndexedDB: Interleaved iteration of multiple cursors</title> | |
| 4 <script src="/resources/testharness.js"></script> | |
| 5 <script src="/resources/testharnessreport.js"></script> | |
| 6 <script src="support-promises.js"></script> | |
| 7 <script> | |
| 8 // Number of objects that each iterator goes over. | |
| 9 const itemCount = 10; | |
| 10 // Ratio of small objects to large objects. | |
| 11 const largeObjectRatio = 5; | |
| 12 // Size of large objects. This should be big enough to force the next object to | |
| 13 // spill to a different block. | |
|
jsbell
2017/03/22 22:35:33
This is a very implementation-specific assumption.
pwnall
2017/03/23 03:18:57
I meant "block in the backend used by IndexedDB".
| |
| 14 const largeObjectSize = 48 * 1024; | |
| 15 | |
| 16 function objectKey(cursorIndex, itemIndex) { | |
| 17 return `${cursorIndex}-key-${itemIndex}`; | |
| 18 } | |
| 19 | |
| 20 function objectValue(cursorIndex, itemIndex) { | |
| 21 if (itemIndex % 2 === 0) { | |
| 22 const char = String.fromCharCode( | |
|
jsbell
2017/03/22 22:35:33
WDTY about using a Uint8Array() to get an exact by
pwnall
2017/03/23 03:18:57
Done.
I didn't use crypto.getRandomValues() becau
| |
| 23 32 + (cursorIndex * itemCount + itemIndex) % (128 - 32)); | |
| 24 return new Array(largeObjectSize + 1).join(char); | |
| 25 } | |
| 26 return `${cursorIndex}-small-${itemIndex}`; | |
| 27 } | |
| 28 | |
| 29 function writeObjects(testCase, database, cursorCount, cursorIndex) { | |
| 30 if (cursorCount == cursorIndex) | |
| 31 return Promise.resolve(); | |
| 32 | |
| 33 return new Promise((resolve, reject) => { | |
| 34 const transaction = database.transaction('cache', 'readwrite'); | |
|
jsbell
2017/03/22 22:35:33
Can you explain/document why we're writing the obj
pwnall
2017/03/23 03:18:57
Done.
I don't have an explanation for the promise
| |
| 35 const store = transaction.objectStore('cache'); | |
| 36 for (let i = 0; i < itemCount; ++i) { | |
| 37 store.put({ | |
| 38 key: objectKey(cursorIndex, i), value: objectValue(cursorIndex, i)}); | |
| 39 } | |
| 40 transaction.oncomplete = resolve; | |
| 41 transaction.onerror = testCase.unreached_func( | |
| 42 'write transaction should not fail'); | |
| 43 }).then(() => { | |
| 44 return writeObjects(testCase, database, cursorCount, cursorIndex + 1); | |
| 45 }); | |
| 46 } | |
| 47 | |
| 48 function readObjects(testCase, store, cursorCount) { | |
| 49 const cursors = new Array(cursorCount); | |
|
jsbell
2017/03/22 22:35:33
I'd just use `cursors = []` - the Array constructo
jsbell
2017/03/22 22:35:33
Also, you may as well pull this and itemIndex into
pwnall
2017/03/23 03:18:57
Done.
pwnall
2017/03/23 03:18:57
Done.
| |
| 50 | |
| 51 let itemIndex = 0; | |
| 52 | |
| 53 return new Promise((resolve, reject) => { | |
| 54 const startCursor = (cursorIndex) => { | |
| 55 const request = store.openCursor( | |
| 56 IDBKeyRange.lowerBound(objectKey(cursorIndex, 0))); | |
| 57 | |
| 58 request.onsuccess = testCase.step_func(() => { | |
| 59 const cursor = request.result; | |
| 60 cursors[cursorIndex] = cursor; | |
| 61 | |
| 62 assert_equals(cursor.key, objectKey(cursorIndex, itemIndex)); | |
| 63 assert_equals(cursor.value.key, objectKey(cursorIndex, itemIndex)); | |
| 64 assert_equals(cursor.value.value, objectValue(cursorIndex, itemIndex)); | |
| 65 | |
|
dmurph
2017/03/22 23:34:54
I'm really confused about what's happening here...
pwnall
2017/03/23 03:18:57
I split up the logic so it's clearer what the curr
| |
| 66 let nextCursorIndex = cursorIndex + 1; | |
| 67 if (nextCursorIndex == cursorCount) { | |
| 68 nextCursorIndex = 0; | |
| 69 itemIndex += 1; | |
| 70 } | |
| 71 | |
| 72 if (!itemIndex) { | |
| 73 startCursor(nextCursorIndex); | |
| 74 } else if (itemIndex == itemCount) { | |
| 75 resolve(); | |
| 76 } else { | |
| 77 cursors[nextCursorIndex].continue(); | |
| 78 } | |
| 79 }); | |
| 80 }; | |
| 81 | |
| 82 startCursor(0); | |
| 83 }); | |
| 84 } | |
| 85 | |
| 86 for (let i of [1, 10, 100, 500]) { | |
| 87 const cursorCount = i; | |
|
jsbell
2017/03/22 22:35:33
I don't think this extra const adds a lot here. (A
pwnall
2017/03/23 03:18:57
Done.
| |
| 88 promise_test(testCase => { | |
| 89 return createDatabase(testCase, (database, transaction) => { | |
| 90 const store = database.createObjectStore('cache', | |
| 91 { keyPath: 'key', autoIncrement: true }); | |
| 92 }).then(database => { | |
| 93 return writeObjects(testCase, database, cursorCount, 0).then( | |
| 94 () => database); | |
|
jsbell
2017/03/22 22:35:33
(rant: someday we'll be able to use async/await...
pwnall
2017/03/23 03:18:57
Done.
pwnall
2017/03/23 22:09:30
I think I meant to "Done" the above comment. Whoop
| |
| 95 }).then(database => { | |
| 96 database.close(); | |
| 97 }).then(() => { | |
| 98 return openDatabase(testCase); | |
| 99 }).then(database => { | |
| 100 const transaction = database.transaction('cache', 'readonly'); | |
| 101 const store = transaction.objectStore('cache'); | |
| 102 return readObjects(testCase, store, cursorCount).then(() => database); | |
| 103 }).then(database => { | |
| 104 database.close() | |
|
jsbell
2017/03/22 22:35:33
Add a test cleanup step to delete the database? Pe
pwnall
2017/03/23 03:18:57
I fixed the helpers :D
| |
| 105 }); | |
| 106 }, `${cursorCount} cursors`); | |
| 107 } | |
| 108 </script> | |
| OLD | NEW |