Skip to content

Commit

Permalink
Bug 1523562 [wpt PR 14761] - [IndexedDB]: Explicit commit error timin…
Browse files Browse the repository at this point in the history
…g handling., a=testonly

Automatic update from web-platform-tests
[IndexedDB]: Explicit commit error timing handling.

When a transaction is explicitly committed, there may yet be unhandled
errors that the browser has sent but the renderer has not yet seen. This
can cause strange behaviour (see the Github discussion link below). This
patch keeps track of the 'handled errors' in the renderer and the 'sent
errors' in the backend. The 'handled errors' number is sent when the
transaction is explicitly committed, and the browser can compare this
with the 'sent errors'. If they don't match, the transaction is aborted

GitHub Discussion: w3c/IndexedDB#242

Bug: 911877
Change-Id: I7ea7b9e20c70528de3f363e961f87a3d8f5798d3
Reviewed-on: https://chromium-review.googlesource.com/c/1378806
Reviewed-by: Kinuko Yasuda <kinuko@chromium.org>
Reviewed-by: Chase Phillips <cmp@chromium.org>
Reviewed-by: Daniel Murphy <dmurph@chromium.org>
Commit-Queue: Andreas Butler <andreasbutler@google.com>
Cr-Commit-Position: refs/heads/master@{#625780}

--

wpt-commits: b0fbbb9ff451b18bf8a69fd54027bf59d21c2667
wpt-pr: 14761
  • Loading branch information
andreas-butler authored and jgraham committed Feb 5, 2019
1 parent 9a0b34e commit 43aa48a
Showing 1 changed file with 52 additions and 17 deletions.
69 changes: 52 additions & 17 deletions testing/web-platform/tests/IndexedDB/idb-explicit-commit.any.js
Expand Up @@ -188,20 +188,17 @@ promise_test(async testCase => {
});
// Txn1 should commit before txn2, even though txn2 uses commit().
const txn1 = db.transaction(['books'], 'readwrite');
const objectStore1 = txn1.objectStore('books');
const putRequest1 = objectStore1.put({isbn:'one', title:'title1'});
txn1.objectStore('books').put({isbn: 'one', title: 'title1'});
const releaseTxnFunction = keepAlive(testCase, txn1, 'books');

const txn2 = db.transaction(['books'], 'readwrite');
const objectStore2 = txn2.objectStore('books');
const putRequest2 = objectStore2.put({isbn:'one', title:'title2'});
txn2.objectStore('books').put({isbn:'one', title:'title2'});
txn2.commit();

// Exercise the IndexedDB transaction ordering by executing one with a
// different scope.
const txn3 = db.transaction(['not_books'], 'readwrite');
const objectStore3 = txn3.objectStore('not_books');
objectStore3.put({'title': 'not_title'}, 'key');
txn3.objectStore('not_books').put({'title': 'not_title'}, 'key');
txn3.oncomplete = function() {
releaseTxnFunction();
}
Expand All @@ -210,8 +207,7 @@ promise_test(async testCase => {

// Read the data back to verify that txn2 executed last.
const txn4 = db.transaction(['books'], 'readonly');
const objectStore4 = txn4.objectStore('books');
const getRequest4 = objectStore4.get('one');
const getRequest4 = txn4.objectStore('books').get('one');
await promiseForTransaction(testCase, txn4);
assert_equals(getRequest4.result.title, 'title2');
db.close();
Expand All @@ -225,8 +221,7 @@ promise_test(async testCase => {
});
// Txn1 creates the book 'one' so the 'add()' below fails.
const txn1 = db.transaction(['books'], 'readwrite');
const objectStore1 = txn1.objectStore('books');
const putRequest1 = objectStore1.add({isbn:'one', title:'title1'});
txn1.objectStore('books').add({isbn:'one', title:'title1'});
txn1.commit();
await promiseForTransaction(testCase, txn1);

Expand All @@ -235,15 +230,17 @@ promise_test(async testCase => {
const txn2 = db.transaction(['books'], 'readwrite');
const objectStore2 = txn2.objectStore('books');
objectStore2.put({isbn:'two', title:'title2'});
const addRequest2 = objectStore2.add({isbn:'one', title:'title2'});
const addRequest = objectStore2.add({isbn:'one', title:'title2'});
txn2.commit();
txn2.oncomplete = assert_unreached(
'Transaction with invalid "add" call should not be completed.');
txn2.oncomplete = () => { assert_unreached(
'Transaction with invalid "add" call should not be completed.'); };

var addWatcher = requestWatcher(testCase, addRequest2);
var txnWatcher = transactionWatcher(testCase, txn2);
await Promise.all([addWatcher.wait_for('error'),
txnWatcher.wait_for('error', 'abort')]);
// Wait for the transaction to complete. We have to explicitly wait for the
// error signal on the transaction because of the nature of the test tooling.
await Promise.all([
requestWatcher(testCase, addRequest).wait_for('error'),
transactionWatcher(testCase, txn2).wait_for(['error', 'abort'])
]);

// Read the data back to verify that txn2 was aborted.
const txn3 = db.transaction(['books'], 'readonly');
Expand All @@ -255,3 +252,41 @@ promise_test(async testCase => {
assert_equals(getRequest2.result, 0);
db.close();
}, 'Transactions that explicitly commit and have errors should abort.');


promise_test(async testCase => {
const db = await createDatabase(testCase, db => {
createBooksStore(testCase, db);
});
const txn1 = db.transaction(['books'], 'readwrite');
txn1.objectStore('books').add({isbn: 'one', title: 'title1'});
txn1.commit();
await promiseForTransaction(testCase, txn1);

// The second add request will throw an error, but the onerror handler will
// appropriately catch the error allowing the valid put request on the
// transaction to commit.
const txn2 = db.transaction(['books'], 'readwrite');
const objectStore2 = txn2.objectStore('books');
objectStore2.put({isbn: 'two', title:'title2'});
const addRequest = objectStore2.add({isbn: 'one', title:'unreached_title'});
addRequest.onerror = (event) => {
event.preventDefault();
addRequest.transaction.commit();
};

// Wait for the transaction to complete. We have to explicitly wait for the
// error signal on the transaction because of the nature of the test tooling.
await transactionWatcher(testCase,txn2).wait_for(['error', 'complete'])

// Read the data back to verify that txn2 was committed.
const txn3 = db.transaction(['books'], 'readonly');
const objectStore3 = txn3.objectStore('books');
const getRequest1 = objectStore3.get('one');
const getRequest2 = objectStore3.get('two');
await promiseForTransaction(testCase, txn3);
assert_equals(getRequest1.result.title, 'title1');
assert_equals(getRequest2.result.title, 'title2');
db.close();
}, 'Transactions that handle all errors properly should be behave as ' +
'expected when an explicit commit is called in an onerror handler.');

0 comments on commit 43aa48a

Please sign in to comment.