1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
<!doctype html>
<meta charset="utf8">
<title>IndexedDB: user-abort()ed versionchange transaction lifecycle</title>
<link rel="help"
href="https://w3c.github.io/IndexedDB/#upgrade-transaction-steps">
<link rel="help"
href="https://w3c.github.io/IndexedDB/#dom-idbdatabase-createobjectstore">
<link rel="help"
href="https://w3c.github.io/IndexedDB/#dom-idbdatabase-deleteobjectstore">
<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/support-promises.js"></script>
<script>
'use strict';
promise_test(t => {
return createDatabase(t, database => {
createBooksStore(t, database);
}).then(database => {
database.close();
}).then(() => migrateDatabase(t, 2, (database, transaction, request) => {
transaction.abort();
assert_equals(
request.transaction, transaction,
"The open request's transaction should be reset after onabort");
assert_throws_dom(
'TransactionInactiveError',
() => { database.createObjectStore('books2'); },
'createObjectStore exception should reflect that the transaction is ' +
'still running');
assert_throws_dom(
'TransactionInactiveError',
() => { database.deleteObjectStore('books'); },
'deleteObjectStore exception should reflect that the transaction is' +
'still running');
}));
}, 'synchronously after abort() is called');
promise_test(t => {
return createDatabase(t, database => {
createBooksStore(t, database);
}).then(database => {
database.close();
}).then(() => migrateDatabase(t, 2, (database, transaction, request) => {
let abortFired = false;
const abortPromise = new Promise((resolve, reject) => {
transaction.addEventListener('abort', () => {
abortFired = true;
resolve();
}, false);
transaction.abort();
});
return Promise.resolve().then(() => {
assert_false(
abortFired,
'The abort event should fire after promises are resolved');
assert_equals(
request.transaction, transaction,
"The open request's transaction should be reset after onabort");
assert_throws_dom(
'TransactionInactiveError',
() => { database.createObjectStore('books2'); },
'createObjectStore exception should reflect that the transaction ' +
'is still running');
assert_throws_dom(
'TransactionInactiveError',
() => { database.deleteObjectStore('books'); },
'deleteObjectStore exception should reflect that the transaction ' +
'is still running');
}).then(() => abortPromise);
}));
}, 'in a promise microtask after abort() is called, before the transaction ' +
'abort event is fired');
promise_test(t => {
return createDatabase(t, database => {
createBooksStore(t, database);
}).then(database => {
database.close();
}).then(() => migrateDatabase(t, 2, (database, transaction, request) => {
return new Promise((resolve, reject) => {
transaction.addEventListener('abort', () => {
resolve(new Promise((resolve, reject) => {
assert_equals(
request.transaction, transaction,
"The open request's transaction should be reset after onabort");
assert_throws_dom(
'InvalidStateError',
() => { database.createObjectStore('books2'); },
'createObjectStore exception should reflect that the ' +
'transaction is no longer running');
assert_throws_dom(
'InvalidStateError',
() => { database.deleteObjectStore('books'); },
'deleteObjectStore exception should reflect that the ' +
'transaction is no longer running');
resolve();
}));
}, false);
transaction.abort();
});
}));
}, 'in the abort event handler for a transaction aborted due to an abort() ' +
'call');
promise_test(t => {
return createDatabase(t, database => {
createBooksStore(t, database);
}).then(database => {
database.close();
}).then(() => migrateDatabase(t, 2, (database, transaction, request) => {
return new Promise((resolve, reject) => {
transaction.addEventListener('abort', () => {
setTimeout(() => {
resolve(new Promise((resolve, reject) => {
assert_equals(
request.transaction, null,
"The open request's transaction should be reset after " +
'onabort microtasks');
assert_throws_dom(
'InvalidStateError',
() => { database.createObjectStore('books2'); },
'createObjectStore exception should reflect that the ' +
'transaction is no longer running');
assert_throws_dom(
'InvalidStateError',
() => { database.deleteObjectStore('books'); },
'deleteObjectStore exception should reflect that the ' +
'transaction is no longer running');
resolve();
}));
}, 0);
}, false);
transaction.abort();
});
}));
}, 'in a setTimeout(0) callback after the abort event is fired for a ' +
'transaction aborted due to an abort() call');
</script>
|