transaction-abort-index-metadata-revert.any.js (15951B)
1 // META: title=IndexedDB: aborting transactions reverts index metadata 2 // META: global=window,worker 3 // META: script=resources/support-promises.js 4 // META: script=resources/support.js 5 6 // Spec: https://w3c.github.io/IndexedDB/#abort-transaction 7 8 'use strict'; 9 10 promise_test( 11 testCase => { 12 let store = null; 13 let index = null; 14 return createDatabase( 15 testCase, 16 (database, transaction) => { 17 createBooksStore(testCase, database); 18 }) 19 .then(database => { 20 database.close(); 21 }) 22 .then( 23 () => migrateDatabase( 24 testCase, 2, 25 (database, transaction) => { 26 store = createNotBooksStore(testCase, database); 27 index = store.index('not_by_author'); 28 assert_array_equals( 29 store.indexNames, ['not_by_author', 'not_by_title'], 30 'IDBObjectStore.indexNames should include newly created indexes ' + 31 'before the transaction is aborted'); 32 33 transaction.abort(); 34 assert_throws_dom( 35 'InvalidStateError', () => index.get('query'), 36 'IDBIndex.get should throw InvalidStateError, indicating that ' + 37 'the index is marked for deletion, immediately after ' + 38 'IDBTransaction.abort() returns'); 39 assert_array_equals( 40 store.indexNames, [], 41 'IDBObjectStore.indexNames should stop including the newly ' + 42 'created indexes immediately after IDBTransaction.abort() returns'); 43 })) 44 .then(() => { 45 assert_throws_dom( 46 'InvalidStateError', () => index.get('query'), 47 'IDBIndex.get should throw InvalidStateError, indicating that ' + 48 'the index is marked for deletion, after the transaction is ' + 49 'aborted'); 50 assert_array_equals( 51 store.indexNames, [], 52 'IDBObjectStore.indexNames should stop including the newly ' + 53 'created indexes after the transaction is aborted'); 54 }); 55 }, 56 'Created stores get their indexes marked as deleted after the transaction ' + 57 'that created them aborts'); 58 59 promise_test( 60 testCase => { 61 let store = null; 62 let index = null; 63 return createDatabase( 64 testCase, 65 (database, transaction) => { 66 createBooksStore(testCase, database); 67 createNotBooksStore(testCase, database); 68 }) 69 .then(database => { 70 database.close(); 71 }) 72 .then( 73 () => migrateDatabase( 74 testCase, 2, 75 (database, transaction) => { 76 store = transaction.objectStore('not_books'); 77 index = store.index('not_by_author'); 78 79 database.deleteObjectStore('not_books'); 80 assert_throws_dom( 81 'InvalidStateError', () => index.get('query'), 82 'IDBIndex.get should throw InvalidStateError, indicating that ' + 83 'the index is marked for deletion, immediately after ' + 84 'IDBDatabase.deleteObjectStore() returns'); 85 assert_array_equals( 86 store.indexNames, [], 87 'IDBObjectStore.indexNames should be empty immediately after ' + 88 'IDBDatabase.deleteObjectStore() returns'); 89 90 transaction.abort(); 91 assert_throws_dom( 92 'TransactionInactiveError', () => index.get('query'), 93 'IDBIndex.get should throw TransactionInactiveError, indicating ' + 94 'that the index is no longer marked for deletion, immediately ' + 95 'after IDBTransaction.abort() returns'); 96 assert_array_equals( 97 store.indexNames, ['not_by_author', 'not_by_title'], 98 'IDBObjectStore.indexNames should include the deleted indexes ' + 99 'immediately after IDBTransaction.abort() returns'); 100 })) 101 .then(() => { 102 assert_throws_dom( 103 'TransactionInactiveError', () => index.get('query'), 104 'IDBIndex.get should throw TransactionInactiveError, indicating ' + 105 'that the index is no longer marked for deletion, after the ' + 106 'transaction is aborted'); 107 assert_array_equals( 108 store.indexNames, ['not_by_author', 'not_by_title'], 109 'IDBObjectStore.indexNames should include the deleted indexes ' + 110 'after the transaction is aborted'); 111 }); 112 }, 113 'Deleted stores get their indexes marked as not-deleted after the ' + 114 'transaction that deleted them aborts'); 115 116 promise_test( 117 testCase => { 118 let store = null; 119 let index = null; 120 return createDatabase( 121 testCase, 122 (database, transaction) => { 123 createBooksStore(testCase, database); 124 }) 125 .then(database => { 126 database.close(); 127 }) 128 .then( 129 () => migrateDatabase( 130 testCase, 2, 131 (database, transaction) => { 132 store = createNotBooksStore(testCase, database); 133 index = store.index('not_by_author'); 134 assert_array_equals( 135 store.indexNames, ['not_by_author', 'not_by_title'], 136 'IDBObjectStore.indexNames should include newly created indexes ' + 137 'before the transaction is aborted'); 138 139 database.deleteObjectStore('not_books'); 140 assert_throws_dom( 141 'InvalidStateError', () => index.get('query'), 142 'IDBIndex.get should throw InvalidStateError, indicating that ' + 143 'the index is marked for deletion, immediately after ' + 144 'IDBDatabase.deleteObjectStore() returns'); 145 assert_array_equals( 146 store.indexNames, [], 147 'IDBObjectStore.indexNames should be empty immediately after ' + 148 'IDBDatabase.deleteObjectStore() returns'); 149 150 transaction.abort(); 151 assert_throws_dom( 152 'InvalidStateError', () => index.get('query'), 153 'IDBIndex.get should throw InvalidStateError, indicating that ' + 154 'the index is still marked for deletion, immediately after ' + 155 'IDBTransaction.abort() returns'); 156 assert_array_equals( 157 store.indexNames, [], 158 'IDBObjectStore.indexNames should not include the newly ' + 159 'created indexes immediately after IDBTransaction.abort() returns'); 160 })) 161 .then(() => { 162 assert_throws_dom( 163 'InvalidStateError', () => index.get('query'), 164 'IDBIndex.get should throw InvalidStateError, indicating that ' + 165 'the index is still marked for deletion, after the transaction ' + 166 'is aborted'); 167 assert_array_equals( 168 store.indexNames, [], 169 'IDBObjectStore.indexNames should not include the newly ' + 170 'created indexes after the transaction is aborted'); 171 }); 172 }, 173 'Created+deleted stores still have their indexes marked as deleted after ' + 174 'the transaction aborts'); 175 176 promise_test(testCase => { 177 let store = null; 178 let index = null; 179 return createDatabase( 180 testCase, 181 (database, transaction) => { 182 createBooksStore(testCase, database); 183 createNotBooksStore(testCase, database); 184 }) 185 .then(database => { 186 database.close(); 187 }) 188 .then( 189 () => migrateDatabase( 190 testCase, 2, 191 (database, transaction) => { 192 store = transaction.objectStore('not_books'); 193 index = store.createIndex('not_by_isbn', 'isbn'); 194 assert_array_equals( 195 store.indexNames, 196 ['not_by_author', 'not_by_isbn', 'not_by_title'], 197 'IDBObjectStore.indexNames should include newly created indexes ' + 198 'before the transaction is aborted'); 199 200 transaction.abort(); 201 assert_throws_dom( 202 'InvalidStateError', () => index.get('query'), 203 'IDBIndex.get should throw InvalidStateError, indicating that ' + 204 'the index is marked for deletion, immediately after ' + 205 'IDBTransaction.abort() returns'); 206 assert_array_equals( 207 store.indexNames, ['not_by_author', 'not_by_title'], 208 'IDBObjectStore.indexNames should stop including the newly ' + 209 'created index immediately after IDBTransaction.abort() returns'); 210 })) 211 .then(() => { 212 assert_throws_dom( 213 'InvalidStateError', () => index.get('query'), 214 'IDBIndex.get should throw InvalidStateError, indicating that ' + 215 'the index is marked for deletion, after the transaction is ' + 216 'aborted'); 217 assert_array_equals( 218 store.indexNames, ['not_by_author', 'not_by_title'], 219 'IDBObjectStore.indexNames should stop including the newly ' + 220 'created index after the transaction is aborted'); 221 }); 222 }, 'Created indexes get marked as deleted after their transaction aborts'); 223 224 promise_test(testCase => { 225 let store = null; 226 let index = null; 227 return createDatabase( 228 testCase, 229 (database, transaction) => { 230 createBooksStore(testCase, database); 231 createNotBooksStore(testCase, database); 232 }) 233 .then(database => { 234 database.close(); 235 }) 236 .then( 237 () => migrateDatabase( 238 testCase, 2, 239 (database, transaction) => { 240 store = transaction.objectStore('not_books'); 241 index = store.index('not_by_author'); 242 243 store.deleteIndex('not_by_author'); 244 assert_throws_dom( 245 'InvalidStateError', () => index.get('query'), 246 'IDBIndex.get should throw InvalidStateError, indicating that ' + 247 'the index is marked for deletion, immediately after ' + 248 'IDBObjectStore.deleteIndex() returns'); 249 assert_array_equals( 250 store.indexNames, ['not_by_title'], 251 'IDBObjectStore.indexNames should not include the deleted index ' + 252 'immediately after IDBObjectStore.deleteIndex() returns'); 253 254 transaction.abort(); 255 assert_throws_dom( 256 'TransactionInactiveError', () => index.get('query'), 257 'IDBIndex.get should throw TransactionInactiveError, indicating ' + 258 'that the index is no longer marked for deletion, immediately ' + 259 'after IDBTransaction.abort() returns'); 260 assert_array_equals( 261 store.indexNames, ['not_by_author', 'not_by_title'], 262 'IDBObjectStore.indexNames should include the deleted indexes ' + 263 'immediately after IDBTransaction.abort() returns'); 264 })) 265 .then(() => { 266 assert_throws_dom( 267 'TransactionInactiveError', () => index.get('query'), 268 'IDBIndex.get should throw TransactionInactiveError, indicating ' + 269 'that the index is no longer marked for deletion, after the ' + 270 'transaction is aborted'); 271 assert_array_equals( 272 store.indexNames, ['not_by_author', 'not_by_title'], 273 'IDBObjectStore.indexNames should include the deleted indexes ' + 274 'after the transaction is aborted'); 275 }); 276 }, 'Deleted indexes get marked as not-deleted after the transaction aborts'); 277 278 promise_test( 279 testCase => { 280 let store = null; 281 let index = null; 282 return createDatabase( 283 testCase, 284 (database, transaction) => { 285 createBooksStore(testCase, database); 286 createNotBooksStore(testCase, database); 287 }) 288 .then(database => { 289 database.close(); 290 }) 291 .then( 292 () => migrateDatabase( 293 testCase, 2, 294 (database, transaction) => { 295 store = transaction.objectStore('not_books'); 296 index = store.createIndex('not_by_isbn', 'isbn'); 297 assert_array_equals( 298 store.indexNames, 299 ['not_by_author', 'not_by_isbn', 'not_by_title'], 300 'IDBObjectStore.indexNames should include newly created indexes ' + 301 'before the transaction is aborted'); 302 303 store.deleteIndex('not_by_isbn'); 304 assert_throws_dom( 305 'InvalidStateError', () => index.get('query'), 306 'IDBIndex.get should throw InvalidStateError, indicating that ' + 307 'the index is marked for deletion, immediately after ' + 308 'IDBObjectStore.deleteIndex() returns'); 309 assert_array_equals( 310 store.indexNames, ['not_by_author', 'not_by_title'], 311 'IDBObjectStore.indexNames should not include the deleted index ' + 312 'immediately after IDBObjectStore.deleteIndex() returns'); 313 314 transaction.abort(); 315 assert_throws_dom( 316 'InvalidStateError', () => index.get('query'), 317 'IDBIndex.get should throw InvalidStateError, indicating that ' + 318 'the index is still marked for deletion, immediately after ' + 319 'IDBTransaction.abort() returns'); 320 assert_array_equals( 321 store.indexNames, ['not_by_author', 'not_by_title'], 322 'IDBObjectStore.indexNames should stop including the newly ' + 323 'created index immediately after IDBTransaction.abort() returns'); 324 })) 325 .then(() => { 326 assert_throws_dom( 327 'InvalidStateError', () => index.get('query'), 328 'IDBIndex.get should throw InvalidStateError, indicating that ' + 329 'the index is marked for deletion, after the transaction is ' + 330 'aborted'); 331 assert_array_equals( 332 store.indexNames, ['not_by_author', 'not_by_title'], 333 'IDBObjectStore.indexNames should stop including the newly ' + 334 'created index after the transaction is aborted'); 335 }); 336 }, 337 'Created+deleted indexes are still marked as deleted after their ' + 338 'transaction aborts');