OLD | NEW |
(Empty) | |
| 1 <!doctype html> |
| 2 <title>IndexedDB: user-abort()ed versionchange transaction lifecycle</title> |
| 3 <link rel="help" |
| 4 href="https://w3c.github.io/IndexedDB/#upgrade-transaction-steps"> |
| 5 <link rel="help" |
| 6 href="https://w3c.github.io/IndexedDB/#dom-idbdatabase-createobjectstore"> |
| 7 <link rel="help" |
| 8 href="https://w3c.github.io/IndexedDB/#dom-idbdatabase-deleteobjectstore"> |
| 9 <link rel="author" href="pwnall@chromium.org" title="Victor Costan"> |
| 10 <script src="../../resources/testharness.js"></script> |
| 11 <script src="../../resources/testharnessreport.js"></script> |
| 12 <script src="resources/support-promises.js"></script> |
| 13 <script> |
| 14 'use strict'; |
| 15 |
| 16 promise_test(t => { |
| 17 return createDatabase(t, database => { |
| 18 createBooksStore(t, database); |
| 19 }).then(database => { |
| 20 database.close(); |
| 21 }).then(() => migrateDatabase(t, 2, (database, transaction, request) => { |
| 22 transaction.abort(); |
| 23 assert_equals( |
| 24 request.transaction, transaction, |
| 25 "The open request's transaction should be reset after onabort"); |
| 26 |
| 27 assert_throws( |
| 28 'TransactionInactiveError', |
| 29 () => { database.createObjectStore('books2'); }, |
| 30 'createObjectStore exception should reflect that the transaction is ' + |
| 31 'still running'); |
| 32 assert_throws( |
| 33 'TransactionInactiveError', |
| 34 () => { database.deleteObjectStore('books'); }, |
| 35 'deleteObjectStore exception should reflect that the transaction is' + |
| 36 'still running'); |
| 37 })); |
| 38 }, 'synchronously after abort() is called'); |
| 39 |
| 40 promise_test(t => { |
| 41 let testStepPromise = null, abortPromise = null; |
| 42 return createDatabase(t, database => { |
| 43 createBooksStore(t, database); |
| 44 }).then(database => { |
| 45 database.close(); |
| 46 }).then(() => migrateDatabase(t, 2, (database, transaction, request) => { |
| 47 let abortFired = false; |
| 48 |
| 49 testStepPromise = Promise.resolve().then(() => { |
| 50 assert_false( |
| 51 abortFired, |
| 52 'The abort event should fire after promises are resolved'); |
| 53 assert_equals( |
| 54 request.transaction, transaction, |
| 55 "The open request's transaction should be reset after onabort"); |
| 56 assert_throws( |
| 57 'TransactionInactiveError', |
| 58 () => { database.createObjectStore('books2'); }, |
| 59 'createObjectStore exception should reflect that the transaction ' + |
| 60 'is still running'); |
| 61 assert_throws( |
| 62 'TransactionInactiveError', |
| 63 () => { database.deleteObjectStore('books'); }, |
| 64 'deleteObjectStore exception should reflect that the transaction ' + |
| 65 'is still running'); |
| 66 }); |
| 67 abortPromise = new Promise((resolve, reject) => { |
| 68 transaction.addEventListener('abort', () => { |
| 69 abortFired = true; |
| 70 resolve(); |
| 71 }, false); |
| 72 transaction.abort(); |
| 73 }); |
| 74 })).then(() => Promise.all([testStepPromise, abortPromise])); |
| 75 }, 'asynchronously after abort() is called, before the abort event is fired'); |
| 76 |
| 77 promise_test(t => { |
| 78 let timeoutPromise = null, abortPromise = null; |
| 79 return createDatabase(t, database => { |
| 80 createBooksStore(t, database); |
| 81 }).then(database => { |
| 82 database.close(); |
| 83 }).then(() => migrateDatabase(t, 2, (database, transaction, request) => { |
| 84 // Queue I/O operations to make sure the transaction does not complete |
| 85 // before setTimeout's callback is called. |
| 86 createNotBooksStore(t, database); |
| 87 const store = transaction.objectStore('books'); |
| 88 for (let i = 0; i < 1000; ++i) |
| 89 store.put({ title: 'Bedrock Nights ' + i, author: 'Barney' }); |
| 90 |
| 91 let abortFired = false; |
| 92 abortPromise = new Promise((resolve, reject) => { |
| 93 transaction.addEventListener('abort', () => { |
| 94 abortFired = true; |
| 95 resolve(); |
| 96 }, false); |
| 97 }); |
| 98 |
| 99 timeoutPromise = new Promise((resolve, reject) => { |
| 100 setTimeout(() => { |
| 101 const testStepPromise = new Promise((resolve, reject) => { |
| 102 assert_false( |
| 103 abortFired, |
| 104 'The abort event should fire after setTimeout expires'); |
| 105 assert_equals( |
| 106 request.transaction, transaction, |
| 107 "The open request's transaction should be reset after onabort"); |
| 108 assert_throws( |
| 109 'TransactionInactiveError', |
| 110 () => { database.createObjectStore('books2'); }, |
| 111 'createObjectStore exception should reflect that the ' + |
| 112 'transaction is still running'); |
| 113 assert_throws( |
| 114 'TransactionInactiveError', |
| 115 () => { database.deleteObjectStore('books'); }, |
| 116 'deleteObjectStore exception should reflect that the ' + |
| 117 'transaction is still running'); |
| 118 resolve(); |
| 119 }); |
| 120 resolve(testStepPromise); |
| 121 }, 0); |
| 122 }); |
| 123 |
| 124 transaction.abort(); |
| 125 })).then(() => Promise.all([timeoutPromise, abortPromise])); |
| 126 }, 'in a setTimeout(0) callback after abort() is called, before the abort ' + |
| 127 'event is fired'); |
| 128 |
| 129 promise_test(t => { |
| 130 let abortPromise = null; |
| 131 return createDatabase(t, database => { |
| 132 createBooksStore(t, database); |
| 133 }).then(database => { |
| 134 database.close(); |
| 135 }).then(() => migrateDatabase(t, 2, (database, transaction, request) => { |
| 136 abortPromise = new Promise((resolve, reject) => { |
| 137 transaction.addEventListener('abort', () => { |
| 138 const testStepPromise = new Promise((resolve, reject) => { |
| 139 assert_equals( |
| 140 request.transaction, transaction, |
| 141 "The open request's transaction should be reset after onabort"); |
| 142 assert_throws( |
| 143 'InvalidStateError', |
| 144 () => { database.createObjectStore('books2'); }, |
| 145 'createObjectStore exception should reflect that the ' + |
| 146 'transaction is no longer running'); |
| 147 assert_throws( |
| 148 'InvalidStateError', |
| 149 () => { database.deleteObjectStore('books'); }, |
| 150 'deleteObjectStore exception should reflect that the ' + |
| 151 'transaction is no longer running'); |
| 152 resolve(); |
| 153 }); |
| 154 resolve(testStepPromise); |
| 155 }, false); |
| 156 transaction.abort(); |
| 157 }); |
| 158 })).then(() => abortPromise); |
| 159 }, 'while the abort event is fired due to an abort() call'); |
| 160 |
| 161 promise_test(t => { |
| 162 let abortPromise = null; |
| 163 return createDatabase(t, database => { |
| 164 createBooksStore(t, database); |
| 165 }).then(database => { |
| 166 database.close(); |
| 167 }).then(() => migrateDatabase(t, 2, (database, transaction, request) => { |
| 168 abortPromise = new Promise((resolve, reject) => { |
| 169 transaction.addEventListener('abort', () => { |
| 170 const timeoutPromise = new Promise((resolve, reject) => { |
| 171 setTimeout(() => { |
| 172 const testStepPromise = new Promise((resolve, reject) => { |
| 173 assert_equals( |
| 174 request.transaction, null, |
| 175 "The open request's transaction should be reset after " + |
| 176 'onabort microtasks'); |
| 177 assert_throws( |
| 178 'InvalidStateError', |
| 179 () => { database.createObjectStore('books2'); }, |
| 180 'createObjectStore exception should reflect that the ' + |
| 181 'transaction is no longer running'); |
| 182 assert_throws( |
| 183 'InvalidStateError', |
| 184 () => { database.deleteObjectStore('books'); }, |
| 185 'deleteObjectStore exception should reflect that the ' + |
| 186 'transaction is no longer running'); |
| 187 resolve(); |
| 188 }); |
| 189 resolve(testStepPromise); |
| 190 }, 0); |
| 191 }); |
| 192 resolve(timeoutPromise); |
| 193 }, false); |
| 194 transaction.abort(); |
| 195 }); |
| 196 })).then(() => abortPromise); |
| 197 }, 'in a setTimeout(0) callback after the abort event is fired due to an ' + |
| 198 'abort() call'); |
| 199 |
| 200 </script> |
OLD | NEW |