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