Skip to content

Commit

Permalink
Indexed DB: Use correct range upper limit for index iteration
Browse files Browse the repository at this point in the history
When iterating a forwards, comparisons are done between each record
found and the range's bound to know when to stop. There's an special
case for reverse cursors where a starting key is needed at the upper
end of the range, so the uppermost key in the range is looked up as
the starting cursor position.

The code to do this for indexes was not guarded by a check for the
cursor direction, though. This was harmless for most forward
iterations as the uppermost actual key would match the upper bound
anyway. But when iterating a cursor over a range in an index, records
can change their index keys and thus appear again in the iteration.
This would lead to the cursor stopping at what was no longer the
actual uppermost key in the range, missing records in the iteration.

Add the missing check, and a WPT to verify this behavior.

(The code dates back to before 2013, so this is not a recent regression.)

Bug: 1091731
Change-Id: I23336ba03d31607607d496fc7e18c28bcf644cf0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2274085
Commit-Queue: Joshua Bell <[email protected]>
Reviewed-by: enne <[email protected]>
Cr-Commit-Position: refs/heads/master@{#783792}
  • Loading branch information
inexorabletash authored and chromium-wpt-export-bot committed Jun 30, 2020
1 parent 825a7c1 commit 93caf8c
Showing 1 changed file with 43 additions and 0 deletions.
43 changes: 43 additions & 0 deletions IndexedDB/idbcursor_update_index9.any.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// META: script=support-promises.js

promise_test(async t => {
const db = await createDatabase(t, db => {
const store = db.createObjectStore('store');
store.createIndex('index', 'value');
store.put({value: 1}, 1);
store.put({value: 2}, 2);
store.put({value: 3}, 3);
});

{
// Iterate over all index entries until an upper bound is reached.
// On each record found, increment the value used as the index
// key, which will make it show again up later in the iteration.
const tx = db.transaction('store', 'readwrite');
const range = IDBKeyRange.upperBound(9);
const index = tx.objectStore('store').index('index');
const request = index.openCursor(range);
request.onsuccess = t.step_func(e => {
const cursor = e.target.result;
if (!cursor)
return;

const record = cursor.value;
record.value += 1;
cursor.update(record);

cursor.continue();
});

await promiseForTransaction(t, tx);
}

{
const tx = db.transaction('store', 'readonly');
const results = await promiseForRequest(t, tx.objectStore('store').getAll());
assert_array_equals(
results.map(record => record.value),
[10, 10, 10],
'Values should all be incremented until bound reached');
}
}, 'Index cursor - indexed values updated during iteration');

0 comments on commit 93caf8c

Please sign in to comment.