| OLD | NEW |
| (Empty) | |
| 1 <!DOCTYPE html> |
| 2 <title>IndexedDB: aborting transactions reverts metadata correctly</title> |
| 3 <script src='../../resources/testharness.js'></script> |
| 4 <link rel="help" href="https://w3c.github.io/IndexedDB/#abort-transaction"> |
| 5 <link rel="author" href="pwnall@chromium.org" title="Victor Costan"> |
| 6 <script src='../../resources/testharnessreport.js'></script> |
| 7 <script src='resources/rename-common.js'></script> |
| 8 <script> |
| 9 |
| 10 promise_test(testCase => { |
| 11 let store = null, migrationTransaction = null, migrationDatabase = null; |
| 12 return createDatabase(testCase, (database, transaction) => { |
| 13 createBooksStore(testCase, database); |
| 14 }).then(database => { |
| 15 database.close(); |
| 16 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 17 store = createNotBooksStore(testCase, database); |
| 18 migrationDatabase = database; |
| 19 migrationTransaction = transaction; |
| 20 assert_array_equals( |
| 21 database.objectStoreNames, ['books', 'not_books'], |
| 22 'IDBDatabase.objectStoreNames should include a newly created ' + |
| 23 'store before the transaction is aborted'); |
| 24 assert_array_equals( |
| 25 transaction.objectStoreNames, ['books', 'not_books'], |
| 26 'IDBTransaction.objectStoreNames should include a newly created ' + |
| 27 'store before the transaction is aborted'); |
| 28 |
| 29 transaction.abort(); |
| 30 assert_throws( |
| 31 'InvalidStateError', () => store.get('query'), |
| 32 'IDBObjectStore.get should throw InvalidStateError, indicating ' + |
| 33 'that the store is marked for deletion, immediately after ' + |
| 34 'IDBTransaction.abort() returns'); |
| 35 assert_array_equals( |
| 36 transaction.objectStoreNames, ['books'], |
| 37 'IDBTransaction.objectStoreNames should stop including the newly ' + |
| 38 'created store immediately after IDBTransaction.abort() returns'); |
| 39 assert_array_equals( |
| 40 database.objectStoreNames, ['books'], |
| 41 'IDBDatabase.objectStoreNames should stop including the newly ' + |
| 42 'created store immediately after IDBTransaction.abort() returns'); |
| 43 })).then(() => { |
| 44 assert_throws( |
| 45 'InvalidStateError', () => store.get('query'), |
| 46 'IDBObjectStore.get should throw InvalidStateError, indicating ' + |
| 47 'that the store is marked for deletion, after the transaction is ' + |
| 48 'aborted'); |
| 49 assert_array_equals( |
| 50 migrationDatabase.objectStoreNames, ['books'], |
| 51 'IDBDatabase.objectStoreNames should stop including the newly ' + |
| 52 'created store after the transaction is aborted'); |
| 53 assert_array_equals( |
| 54 migrationTransaction.objectStoreNames, ['books'], |
| 55 'IDBTransaction.objectStoreNames should stop including the newly ' + |
| 56 'created store after the transaction is aborted'); |
| 57 }); |
| 58 }, 'Created stores get marked as deleted after their transaction aborts'); |
| 59 |
| 60 promise_test(testCase => { |
| 61 let store = null, migrationTransaction = null, migrationDatabase = null; |
| 62 return createDatabase(testCase, (database, transaction) => { |
| 63 createBooksStore(testCase, database); |
| 64 createNotBooksStore(testCase, database); |
| 65 }).then(database => { |
| 66 database.close(); |
| 67 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 68 migrationDatabase = database; |
| 69 migrationTransaction = transaction; |
| 70 store = transaction.objectStore('not_books'); |
| 71 |
| 72 database.deleteObjectStore('not_books'); |
| 73 assert_throws( |
| 74 'InvalidStateError', () => store.get('query'), |
| 75 'IDBObjectStore.get should throw InvalidStateError, indicating ' + |
| 76 'that the store is marked for deletion, immediately after ' + |
| 77 'IDBDatabase.deleteObjectStore() returns'); |
| 78 assert_array_equals( |
| 79 transaction.objectStoreNames, ['books'], |
| 80 'IDBTransaction.objectStoreNames should stop including the ' + |
| 81 'deleted store immediately after IDBDatabase.deleteObjectStore() ' + |
| 82 'returns'); |
| 83 assert_array_equals( |
| 84 database.objectStoreNames, ['books'], |
| 85 'IDBDatabase.objectStoreNames should stop including the newly ' + |
| 86 'created store immediately after IDBDatabase.deleteObjectStore() ' + |
| 87 'returns'); |
| 88 |
| 89 transaction.abort(); |
| 90 assert_throws( |
| 91 'TransactionInactiveError', () => store.get('query'), |
| 92 'IDBObjectStore.get should throw TransactionInactiveError, ' + |
| 93 'indicating that the store is no longer marked for deletion, ' + |
| 94 'immediately after IDBTransaction.abort() returns'); |
| 95 assert_array_equals( |
| 96 database.objectStoreNames, ['books', 'not_books'], |
| 97 'IDBDatabase.objectStoreNames should include the deleted store ' + |
| 98 'store immediately after IDBTransaction.abort() returns'); |
| 99 assert_array_equals( |
| 100 transaction.objectStoreNames, ['books', 'not_books'], |
| 101 'IDBTransaction.objectStoreNames should include the deleted ' + |
| 102 'store immediately after IDBTransaction.abort() returns'); |
| 103 })).then(() => { |
| 104 assert_throws( |
| 105 'TransactionInactiveError', () => store.get('query'), |
| 106 'IDBObjectStore.get should throw TransactionInactiveError, ' + |
| 107 'indicating that the store is no longer marked for deletion, ' + |
| 108 'after the transaction is aborted'); |
| 109 assert_array_equals( |
| 110 migrationDatabase.objectStoreNames, ['books', 'not_books'], |
| 111 'IDBDatabase.objectStoreNames should include the previously ' + |
| 112 'deleted store after the transaction is aborted'); |
| 113 assert_array_equals( |
| 114 migrationTransaction.objectStoreNames, ['books', 'not_books'], |
| 115 'IDBTransaction.objectStoreNames should include the previously ' + |
| 116 'deleted store after the transaction is aborted'); |
| 117 }); |
| 118 }, 'Deleted stores get marked as not-deleted after the transaction aborts'); |
| 119 |
| 120 |
| 121 promise_test(testCase => { |
| 122 let store = null, migrationTransaction = null, migrationDatabase = null; |
| 123 return createDatabase(testCase, (database, transaction) => { |
| 124 createBooksStore(testCase, database); |
| 125 }).then(database => { |
| 126 database.close(); |
| 127 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 128 store = createNotBooksStore(testCase, database); |
| 129 migrationDatabase = database; |
| 130 migrationTransaction = transaction; |
| 131 assert_array_equals( |
| 132 database.objectStoreNames, ['books', 'not_books'], |
| 133 'IDBDatabase.objectStoreNames should include a newly created ' + |
| 134 'store before the transaction is aborted'); |
| 135 assert_array_equals( |
| 136 transaction.objectStoreNames, ['books', 'not_books'], |
| 137 'IDBTransaction.objectStoreNames should include a newly created ' + |
| 138 'store before the transaction is aborted'); |
| 139 |
| 140 database.deleteObjectStore('not_books'); |
| 141 assert_throws( |
| 142 'InvalidStateError', () => store.get('query'), |
| 143 'IDBObjectStore.get should throw InvalidStateError, indicating ' + |
| 144 'that the store is marked for deletion, immediately after ' + |
| 145 'IDBDatabase.deleteObjectStore() returns'); |
| 146 assert_array_equals( |
| 147 transaction.objectStoreNames, ['books'], |
| 148 'IDBTransaction.objectStoreNames should stop including the ' + |
| 149 'deleted store immediately after IDBDatabase.deleteObjectStore() ' + |
| 150 'returns'); |
| 151 assert_array_equals( |
| 152 database.objectStoreNames, ['books'], |
| 153 'IDBDatabase.objectStoreNames should stop including the newly ' + |
| 154 'created store immediately after IDBDatabase.deleteObjectStore() ' + |
| 155 'returns'); |
| 156 |
| 157 transaction.abort(); |
| 158 assert_throws( |
| 159 'InvalidStateError', () => store.get('query'), |
| 160 'IDBObjectStore.get should throw InvalidStateError, indicating ' + |
| 161 'that the store is still marked for deletion, immediately after ' + |
| 162 'IDBTransaction.abort() returns'); |
| 163 assert_array_equals( |
| 164 transaction.objectStoreNames, ['books'], |
| 165 'IDBTransaction.objectStoreNames should not include the newly ' + |
| 166 'created store immediately after IDBTransaction.abort() returns'); |
| 167 assert_array_equals( |
| 168 database.objectStoreNames, ['books'], |
| 169 'IDBDatabase.objectStoreNames should not include the newly ' + |
| 170 'created store immediately after IDBTransaction.abort() returns'); |
| 171 })).then(() => { |
| 172 assert_throws( |
| 173 'InvalidStateError', () => store.get('query'), |
| 174 'IDBObjectStore.get should throw InvalidStateError, indicating ' + |
| 175 'that the store is still marked for deletion, after the ' + |
| 176 'transaction is aborted'); |
| 177 assert_array_equals( |
| 178 migrationDatabase.objectStoreNames, ['books'], |
| 179 'IDBDatabase.objectStoreNames should not include the newly ' + |
| 180 'created store after the transaction is aborted'); |
| 181 assert_array_equals( |
| 182 migrationTransaction.objectStoreNames, ['books'], |
| 183 'IDBTransaction.objectStoreNames should not include the newly ' + |
| 184 'created store after the transaction is aborted'); |
| 185 }); |
| 186 }, 'Created+deleted stores are still marked as deleted after their ' + |
| 187 'transaction aborts'); |
| 188 |
| 189 promise_test(testCase => { |
| 190 let store = null, index = null; |
| 191 return createDatabase(testCase, (database, transaction) => { |
| 192 createBooksStore(testCase, database); |
| 193 }).then(database => { |
| 194 database.close(); |
| 195 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 196 store = createNotBooksStore(testCase, database); |
| 197 index = store.index('not_by_author'); |
| 198 assert_array_equals( |
| 199 store.indexNames, ['not_by_author', 'not_by_title'], |
| 200 'IDBObjectStore.indexNames should include newly created indexes ' + |
| 201 'before the transaction is aborted'); |
| 202 |
| 203 transaction.abort(); |
| 204 assert_throws( |
| 205 'InvalidStateError', () => index.get('query'), |
| 206 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 207 'the index is marked for deletion, immediately after ' + |
| 208 'IDBTransaction.abort() returns'); |
| 209 assert_array_equals( |
| 210 store.indexNames, [], |
| 211 'IDBObjectStore.indexNames should stop including the newly ' + |
| 212 'created indexes immediately after IDBTransaction.abort() returns'); |
| 213 })).then(() => { |
| 214 assert_throws( |
| 215 'InvalidStateError', () => index.get('query'), |
| 216 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 217 'the index is marked for deletion, after the transaction is ' + |
| 218 'aborted'); |
| 219 assert_array_equals( |
| 220 store.indexNames, [], |
| 221 'IDBObjectStore.indexNames should stop including the newly ' + |
| 222 'created indexes after the transaction is aborted'); |
| 223 }); |
| 224 }, 'Created stores get their indexes marked as deleted after the transaction ' + |
| 225 'that created them aborts'); |
| 226 |
| 227 promise_test(testCase => { |
| 228 let store = null, index = null; |
| 229 return createDatabase(testCase, (database, transaction) => { |
| 230 createBooksStore(testCase, database); |
| 231 createNotBooksStore(testCase, database); |
| 232 }).then(database => { |
| 233 database.close(); |
| 234 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 235 store = transaction.objectStore('not_books'); |
| 236 index = store.index('not_by_author'); |
| 237 |
| 238 database.deleteObjectStore('not_books'); |
| 239 assert_throws( |
| 240 'InvalidStateError', () => index.get('query'), |
| 241 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 242 'the index is marked for deletion, immediately after ' + |
| 243 'IDBDatabase.deleteObjectStore() returns'); |
| 244 assert_array_equals( |
| 245 store.indexNames, [], |
| 246 'IDBObjectStore.indexNames should be empty immediately after ' + |
| 247 'IDBDatabase.deleteObjectStore() returns'); |
| 248 |
| 249 transaction.abort(); |
| 250 assert_throws( |
| 251 'TransactionInactiveError', () => index.get('query'), |
| 252 'IDBIndex.get should throw TransactionInactiveError, indicating ' + |
| 253 'that the index is no longer marked for deletion, immediately ' + |
| 254 'after IDBTransaction.abort() returns'); |
| 255 assert_array_equals( |
| 256 store.indexNames, ['not_by_author', 'not_by_title'], |
| 257 'IDBObjectStore.indexNames should include the deleted indexes ' + |
| 258 'immediately after IDBTransaction.abort() returns'); |
| 259 })).then(() => { |
| 260 assert_throws( |
| 261 'TransactionInactiveError', () => index.get('query'), |
| 262 'IDBIndex.get should throw TransactionInactiveError, indicating ' + |
| 263 'that the index is no longer marked for deletion, after the ' + |
| 264 'transaction is aborted'); |
| 265 assert_array_equals( |
| 266 store.indexNames, ['not_by_author', 'not_by_title'], |
| 267 'IDBObjectStore.indexNames should include the deleted indexes ' + |
| 268 'after the transaction is aborted'); |
| 269 }); |
| 270 }, 'Deleted stores get their indexes marked as not-deleted after the ' + |
| 271 'transaction that deleted them aborts'); |
| 272 |
| 273 promise_test(testCase => { |
| 274 let store = null, index = null; |
| 275 return createDatabase(testCase, (database, transaction) => { |
| 276 createBooksStore(testCase, database); |
| 277 }).then(database => { |
| 278 database.close(); |
| 279 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 280 store = createNotBooksStore(testCase, database); |
| 281 index = store.index('not_by_author'); |
| 282 assert_array_equals( |
| 283 store.indexNames, ['not_by_author', 'not_by_title'], |
| 284 'IDBObjectStore.indexNames should include newly created indexes ' + |
| 285 'before the transaction is aborted'); |
| 286 |
| 287 database.deleteObjectStore('not_books'); |
| 288 assert_throws( |
| 289 'InvalidStateError', () => index.get('query'), |
| 290 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 291 'the index is marked for deletion, immediately after ' + |
| 292 'IDBDatabase.deleteObjectStore() returns'); |
| 293 assert_array_equals( |
| 294 store.indexNames, [], |
| 295 'IDBObjectStore.indexNames should be empty immediately after ' + |
| 296 'IDBDatabase.deleteObjectStore() returns'); |
| 297 |
| 298 transaction.abort(); |
| 299 assert_throws( |
| 300 'InvalidStateError', () => index.get('query'), |
| 301 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 302 'the index is still marked for deletion, immediately after ' + |
| 303 'IDBTransaction.abort() returns'); |
| 304 assert_array_equals( |
| 305 store.indexNames, [], |
| 306 'IDBObjectStore.indexNames should not include the newly ' + |
| 307 'created indexes immediately after IDBTransaction.abort() returns'); |
| 308 })).then(() => { |
| 309 assert_throws( |
| 310 'InvalidStateError', () => index.get('query'), |
| 311 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 312 'the index is still marked for deletion, after the transaction ' + |
| 313 'is aborted'); |
| 314 assert_array_equals( |
| 315 store.indexNames, [], |
| 316 'IDBObjectStore.indexNames should not include the newly ' + |
| 317 'created indexes after the transaction is aborted'); |
| 318 }); |
| 319 }, 'Created+deleted stores still have their indexes marked as deleted after ' + |
| 320 'the transaction aborts'); |
| 321 |
| 322 promise_test(testCase => { |
| 323 let store = null, index = null; |
| 324 return createDatabase(testCase, (database, transaction) => { |
| 325 createBooksStore(testCase, database); |
| 326 createNotBooksStore(testCase, database); |
| 327 }).then(database => { |
| 328 database.close(); |
| 329 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 330 store = transaction.objectStore('not_books'); |
| 331 index = store.createIndex('not_by_isbn', 'isbn'); |
| 332 assert_array_equals( |
| 333 store.indexNames, ['not_by_author', 'not_by_isbn', 'not_by_title'], |
| 334 'IDBObjectStore.indexNames should include newly created indexes ' + |
| 335 'before the transaction is aborted'); |
| 336 |
| 337 transaction.abort(); |
| 338 assert_throws( |
| 339 'InvalidStateError', () => index.get('query'), |
| 340 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 341 'the index is marked for deletion, immediately after ' + |
| 342 'IDBTransaction.abort() returns'); |
| 343 assert_array_equals( |
| 344 store.indexNames, ['not_by_author', 'not_by_title'], |
| 345 'IDBObjectStore.indexNames should stop including the newly ' + |
| 346 'created index immediately after IDBTransaction.abort() returns'); |
| 347 })).then(() => { |
| 348 assert_throws( |
| 349 'InvalidStateError', () => index.get('query'), |
| 350 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 351 'the index is marked for deletion, after the transaction is ' + |
| 352 'aborted'); |
| 353 assert_array_equals( |
| 354 store.indexNames, ['not_by_author', 'not_by_title'], |
| 355 'IDBObjectStore.indexNames should stop including the newly ' + |
| 356 'created index after the transaction is aborted'); |
| 357 }); |
| 358 }, 'Created indexes get marked as deleted after their transaction aborts'); |
| 359 |
| 360 promise_test(testCase => { |
| 361 let store = null, index = null; |
| 362 return createDatabase(testCase, (database, transaction) => { |
| 363 createBooksStore(testCase, database); |
| 364 createNotBooksStore(testCase, database); |
| 365 }).then(database => { |
| 366 database.close(); |
| 367 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 368 store = transaction.objectStore('not_books'); |
| 369 index = store.index('not_by_author'); |
| 370 |
| 371 store.deleteIndex('not_by_author'); |
| 372 assert_throws( |
| 373 'InvalidStateError', () => index.get('query'), |
| 374 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 375 'the index is marked for deletion, immediately after ' + |
| 376 'IDBObjectStore.deleteIndex() returns'); |
| 377 assert_array_equals( |
| 378 store.indexNames, ['not_by_title'], |
| 379 'IDBObjectStore.indexNames should not include the deleted index ' + |
| 380 'immediately after IDBObjectStore.deleteIndex() returns'); |
| 381 |
| 382 transaction.abort(); |
| 383 /* TODO(pwnall): Firefox fails this -- figure it out |
| 384 assert_throws( |
| 385 'TransactionInactiveError', () => index.get('query'), |
| 386 'IDBIndex.get should throw TransactionInactiveError, indicating ' + |
| 387 'that the index is no longer marked for deletion, immediately ' + |
| 388 'after IDBTransaction.abort() returns'); |
| 389 */ |
| 390 assert_array_equals( |
| 391 store.indexNames, ['not_by_author', 'not_by_title'], |
| 392 'IDBObjectStore.indexNames should include the deleted indexes ' + |
| 393 'immediately after IDBTransaction.abort() returns'); |
| 394 })).then(() => { |
| 395 /* TODO(pwnall): Firefox fails this -- figure it out |
| 396 assert_throws( |
| 397 'TransactionInactiveError', () => index.get('query'), |
| 398 'IDBIndex.get should throw TransactionInactiveError, indicating ' + |
| 399 'that the index is no longer marked for deletion, after the ' + |
| 400 'transaction is aborted'); |
| 401 */ |
| 402 assert_array_equals( |
| 403 store.indexNames, ['not_by_author', 'not_by_title'], |
| 404 'IDBObjectStore.indexNames should include the deleted indexes ' + |
| 405 'after the transaction is aborted'); |
| 406 }); |
| 407 }, 'Deleted indexes get marked as not-deleted after the transaction aborts'); |
| 408 |
| 409 promise_test(testCase => { |
| 410 let store = null, index = null; |
| 411 return createDatabase(testCase, (database, transaction) => { |
| 412 createBooksStore(testCase, database); |
| 413 createNotBooksStore(testCase, database); |
| 414 }).then(database => { |
| 415 database.close(); |
| 416 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 417 store = transaction.objectStore('not_books'); |
| 418 index = store.createIndex('not_by_isbn', 'isbn'); |
| 419 assert_array_equals( |
| 420 store.indexNames, ['not_by_author', 'not_by_isbn', 'not_by_title'], |
| 421 'IDBObjectStore.indexNames should include newly created indexes ' + |
| 422 'before the transaction is aborted'); |
| 423 |
| 424 store.deleteIndex('not_by_isbn'); |
| 425 assert_throws( |
| 426 'InvalidStateError', () => index.get('query'), |
| 427 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 428 'the index is marked for deletion, immediately after ' + |
| 429 'IDBObjectStore.deleteIndex() returns'); |
| 430 assert_array_equals( |
| 431 store.indexNames, ['not_by_author', 'not_by_title'], |
| 432 'IDBObjectStore.indexNames should not include the deleted index ' + |
| 433 'immediately after IDBObjectStore.deleteIndex() returns'); |
| 434 |
| 435 transaction.abort(); |
| 436 assert_throws( |
| 437 'InvalidStateError', () => index.get('query'), |
| 438 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 439 'the index is still marked for deletion, immediately after ' + |
| 440 'IDBTransaction.abort() returns'); |
| 441 assert_array_equals( |
| 442 store.indexNames, ['not_by_author', 'not_by_title'], |
| 443 'IDBObjectStore.indexNames should stop including the newly ' + |
| 444 'created index immediately after IDBTransaction.abort() returns'); |
| 445 })).then(() => { |
| 446 assert_throws( |
| 447 'InvalidStateError', () => index.get('query'), |
| 448 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 449 'the index is marked for deletion, after the transaction is ' + |
| 450 'aborted'); |
| 451 assert_array_equals( |
| 452 store.indexNames, ['not_by_author', 'not_by_title'], |
| 453 'IDBObjectStore.indexNames should stop including the newly ' + |
| 454 'created index after the transaction is aborted'); |
| 455 }); |
| 456 }, 'Created+deleted indexes are still marked as deleted after their ' + |
| 457 'transaction aborts'); |
| 458 |
| 459 promise_test(testCase => { |
| 460 let store = null, index = null; |
| 461 let migrationTransaction = null, migrationDatabase = null; |
| 462 return createDatabase(testCase, (database, transaction) => { |
| 463 createBooksStore(testCase, database); |
| 464 }).then(database => { |
| 465 database.close(); |
| 466 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 467 store = createNotBooksStore(testCase, database); |
| 468 migrationDatabase = database; |
| 469 migrationTransaction = transaction; |
| 470 assert_array_equals( |
| 471 database.objectStoreNames, ['books', 'not_books'], |
| 472 'IDBDatabase.objectStoreNames should include a newly created ' + |
| 473 'store before the transaction is aborted'); |
| 474 assert_array_equals( |
| 475 transaction.objectStoreNames, ['books', 'not_books'], |
| 476 'IDBTransaction.objectStoreNames should include a newly created ' + |
| 477 'store before the transaction is aborted'); |
| 478 |
| 479 index = store.index('not_by_author'); |
| 480 store.deleteIndex('not_by_author'); |
| 481 assert_throws( |
| 482 'InvalidStateError', () => index.get('query'), |
| 483 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 484 'the index is marked for deletion, immediately after ' + |
| 485 'IDBObjectStore.deleteIndex() returns'); |
| 486 assert_array_equals( |
| 487 store.indexNames, ['not_by_title'], |
| 488 'IDBObjectStore.indexNames should not include the deleted index ' + |
| 489 'immediately after IDBObjectStore.deleteIndex() returns'); |
| 490 |
| 491 transaction.abort(); |
| 492 assert_throws( |
| 493 'InvalidStateError', () => store.get('query'), |
| 494 'IDBObjectStore.get should throw InvalidStateError, indicating ' + |
| 495 'that the store is marked for deletion, immediately after ' + |
| 496 'IDBTransaction.abort() returns'); |
| 497 assert_throws( |
| 498 'InvalidStateError', () => index.get('query'), |
| 499 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 500 'the index is still marked for deletion, immediately after ' + |
| 501 'IDBTransaction.abort() returns'); |
| 502 assert_array_equals( |
| 503 transaction.objectStoreNames, ['books'], |
| 504 'IDBTransaction.objectStoreNames should stop including the newly ' + |
| 505 'created store immediately after IDBTransaction.abort() returns'); |
| 506 assert_array_equals( |
| 507 database.objectStoreNames, ['books'], |
| 508 'IDBDatabase.objectStoreNames should stop including the newly ' + |
| 509 'created store immediately after IDBTransaction.abort() returns'); |
| 510 assert_array_equals( |
| 511 store.indexNames, [], |
| 512 'IDBObjectStore.indexNames for the newly created store should be ' + |
| 513 'empty immediately after IDBTransaction.abort() returns'); |
| 514 })).then(() => { |
| 515 assert_throws( |
| 516 'InvalidStateError', () => store.get('query'), |
| 517 'IDBObjectStore.get should throw InvalidStateError, indicating ' + |
| 518 'that the store is marked for deletion, after the transaction is ' + |
| 519 'aborted'); |
| 520 assert_throws( |
| 521 'InvalidStateError', () => index.get('query'), |
| 522 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 523 'the index is still marked for deletion, after the transaction ' + |
| 524 'is aborted'); |
| 525 assert_array_equals( |
| 526 migrationDatabase.objectStoreNames, ['books'], |
| 527 'IDBDatabase.objectStoreNames should stop including the newly ' + |
| 528 'created store after the transaction is aborted'); |
| 529 assert_array_equals( |
| 530 migrationTransaction.objectStoreNames, ['books'], |
| 531 'IDBTransaction.objectStoreNames should stop including the newly ' + |
| 532 'created store after the transaction is aborted'); |
| 533 assert_array_equals( |
| 534 store.indexNames, [], |
| 535 'IDBObjectStore.indexNames for the newly created store should be ' + |
| 536 'empty after the transaction is aborted'); |
| 537 }); |
| 538 }, 'Deleted indexes in newly created stores are still marked as deleted ' + |
| 539 'after the transaction aborts'); |
| 540 |
| 541 promise_test(testCase => { |
| 542 let store = null, index = null; |
| 543 let migrationTransaction = null, migrationDatabase = null; |
| 544 return createDatabase(testCase, (database, transaction) => { |
| 545 createBooksStore(testCase, database); |
| 546 createNotBooksStore(testCase, database); |
| 547 }).then(database => { |
| 548 database.close(); |
| 549 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 550 migrationDatabase = database; |
| 551 migrationTransaction = transaction; |
| 552 store = transaction.objectStore('not_books'); |
| 553 index = store.index('not_by_author'); |
| 554 store.deleteIndex('not_by_author'); |
| 555 assert_throws( |
| 556 'InvalidStateError', () => index.get('query'), |
| 557 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 558 'the index is marked for deletion, immediately after ' + |
| 559 'IDBObjectStore.deleteIndex() returns'); |
| 560 assert_array_equals( |
| 561 store.indexNames, ['not_by_title'], |
| 562 'IDBObjectStore.indexNames should not include the deleted index ' + |
| 563 'immediately after IDBObjectStore.deleteIndex() returns'); |
| 564 |
| 565 database.deleteObjectStore('not_books'); |
| 566 assert_throws( |
| 567 'InvalidStateError', () => store.get('query'), |
| 568 'IDBObjectStore.get should throw InvalidStateError, indicating ' + |
| 569 'that the store is marked for deletion, immediately after ' + |
| 570 'IDBDatabase.deleteObjectStore() returns'); |
| 571 assert_throws( |
| 572 'InvalidStateError', () => index.get('query'), |
| 573 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 574 'the index is still marked for deletion, immediately after ' + |
| 575 'IDBObjectStore.deleteIndex() returns'); |
| 576 assert_array_equals( |
| 577 transaction.objectStoreNames, ['books'], |
| 578 'IDBTransaction.objectStoreNames should stop including the ' + |
| 579 'deleted store immediately after IDBDatabase.deleteObjectStore() ' + |
| 580 'returns'); |
| 581 assert_array_equals( |
| 582 database.objectStoreNames, ['books'], |
| 583 'IDBDatabase.objectStoreNames should stop including the newly ' + |
| 584 'created store immediately after IDBDatabase.deleteObjectStore() ' + |
| 585 'returns'); |
| 586 assert_array_equals( |
| 587 store.indexNames, [], |
| 588 'IDBObjectStore.indexNames for the deleted store should be empty ' + |
| 589 'immediately after IDBDatabase.deleteObjectStore() returns'); |
| 590 |
| 591 transaction.abort(); |
| 592 assert_throws( |
| 593 'TransactionInactiveError', () => store.get('query'), |
| 594 'IDBObjectStore.get should throw TransactionInactiveError, ' + |
| 595 'indicating that the store is no longer marked for deletion, ' + |
| 596 'immediately after IDBTransaction.abort() returns'); |
| 597 /* TODO(pwnall): Firefox fails this, figure it out. |
| 598 assert_throws( |
| 599 'TransactionInactiveError', () => index.get('query'), |
| 600 'IDBIndex.get should throw TransactionInactiveError, indicating ' + |
| 601 'that the index is no longer marked for deletion, immediately ' + |
| 602 'after IDBObjectStore.deleteIndex() returns'); |
| 603 */ |
| 604 assert_array_equals( |
| 605 database.objectStoreNames, ['books', 'not_books'], |
| 606 'IDBDatabase.objectStoreNames should include the deleted store ' + |
| 607 'store immediately after IDBTransaction.abort() returns'); |
| 608 assert_array_equals( |
| 609 transaction.objectStoreNames, ['books', 'not_books'], |
| 610 'IDBTransaction.objectStoreNames should include the deleted ' + |
| 611 'store immediately after IDBTransaction.abort() returns'); |
| 612 assert_array_equals( |
| 613 store.indexNames, ['not_by_author', 'not_by_title'], |
| 614 'IDBObjectStore.indexNames for the deleted store should not be ' + |
| 615 'empty any more immediately after IDBTransaction.abort() returns'); |
| 616 })).then(() => { |
| 617 assert_throws( |
| 618 'TransactionInactiveError', () => store.get('query'), |
| 619 'IDBObjectStore.get should throw TransactionInactiveError, ' + |
| 620 'indicating that the store is no longer marked for deletion, ' + |
| 621 'after the transaction is aborted'); |
| 622 /* TODO(pwnall): Firefox fails this, figure it out. |
| 623 assert_throws( |
| 624 'TransactionInactiveError', () => index.get('query'), |
| 625 'IDBIndex.get should throw TransactionInactiveError, indicating ' + |
| 626 'that the index is no longer marked for deletion, after the ' + |
| 627 'transaction is aborted'); |
| 628 */ |
| 629 assert_array_equals( |
| 630 migrationDatabase.objectStoreNames, ['books', 'not_books'], |
| 631 'IDBDatabase.objectStoreNames should include the previously ' + |
| 632 'deleted store after the transaction is aborted'); |
| 633 assert_array_equals( |
| 634 migrationTransaction.objectStoreNames, ['books', 'not_books'], |
| 635 'IDBTransaction.objectStoreNames should include the previously ' + |
| 636 'deleted store after the transaction is aborted'); |
| 637 assert_array_equals( |
| 638 store.indexNames, ['not_by_author', 'not_by_title'], |
| 639 'IDBObjectStore.indexNames for the deleted store should not be ' + |
| 640 'empty after the transaction is aborted'); |
| 641 }); |
| 642 }, 'Deleted indexes in deleted stores are still marked as not-deleted after ' + |
| 643 'the transaction aborts'); |
| 644 |
| 645 promise_test(testCase => { |
| 646 let store = null, index = null; |
| 647 let migrationTransaction = null, migrationDatabase = null; |
| 648 return createDatabase(testCase, (database, transaction) => { |
| 649 createBooksStore(testCase, database); |
| 650 }).then(database => { |
| 651 database.close(); |
| 652 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 653 store = createNotBooksStore(testCase, database); |
| 654 migrationDatabase = database; |
| 655 migrationTransaction = transaction; |
| 656 index = store.index('not_by_author'); |
| 657 store.deleteIndex('not_by_author'); |
| 658 assert_throws( |
| 659 'InvalidStateError', () => index.get('query'), |
| 660 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 661 'the index is marked for deletion, immediately after ' + |
| 662 'IDBObjectStore.deleteIndex() returns'); |
| 663 assert_array_equals( |
| 664 store.indexNames, ['not_by_title'], |
| 665 'IDBObjectStore.indexNames should not include the deleted index ' + |
| 666 'immediately after IDBObjectStore.deleteIndex() returns'); |
| 667 |
| 668 database.deleteObjectStore('not_books'); |
| 669 assert_throws( |
| 670 'InvalidStateError', () => store.get('query'), |
| 671 'IDBObjectStore.get should throw InvalidStateError, indicating ' + |
| 672 'that the store is marked for deletion, immediately after ' + |
| 673 'IDBDatabase.deleteObjectStore() returns'); |
| 674 assert_throws( |
| 675 'InvalidStateError', () => index.get('query'), |
| 676 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 677 'the index is still marked for deletion, immediately after ' + |
| 678 'IDBDatabase.deleteObjectStore() returns'); |
| 679 assert_array_equals( |
| 680 transaction.objectStoreNames, ['books'], |
| 681 'IDBTransaction.objectStoreNames should stop including the ' + |
| 682 'deleted store immediately after IDBDatabase.deleteObjectStore() ' + |
| 683 'returns'); |
| 684 assert_array_equals( |
| 685 database.objectStoreNames, ['books'], |
| 686 'IDBDatabase.objectStoreNames should stop including the newly ' + |
| 687 'created store immediately after IDBDatabase.deleteObjectStore() ' + |
| 688 'returns'); |
| 689 assert_array_equals( |
| 690 store.indexNames, [], |
| 691 'IDBObjectStore.indexNames should be empty immediately after ' + |
| 692 'IDBDatabase.deleteObjectStore() returns'); |
| 693 |
| 694 transaction.abort(); |
| 695 assert_throws( |
| 696 'InvalidStateError', () => store.get('query'), |
| 697 'IDBObjectStore.get should throw InvalidStateError, indicating ' + |
| 698 'that the store is still marked for deletion, immediately after ' + |
| 699 'IDBTransaction.abort() returns'); |
| 700 assert_throws( |
| 701 'InvalidStateError', () => index.get('query'), |
| 702 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 703 'the index is still marked for deletion, immediately after ' + |
| 704 'IDBTransaction.abort() returns'); |
| 705 assert_array_equals( |
| 706 transaction.objectStoreNames, ['books'], |
| 707 'IDBTransaction.objectStoreNames should not include the newly ' + |
| 708 'created store immediately after IDBTransaction.abort() returns'); |
| 709 assert_array_equals( |
| 710 database.objectStoreNames, ['books'], |
| 711 'IDBDatabase.objectStoreNames should not include the newly ' + |
| 712 'created store immediately after IDBTransaction.abort() returns'); |
| 713 assert_array_equals( |
| 714 store.indexNames, [], |
| 715 'IDBObjectStore.indexNames should be empty immediately after ' + |
| 716 'IDBTransaction.abort() returns'); |
| 717 })).then(() => { |
| 718 assert_throws( |
| 719 'InvalidStateError', () => store.get('query'), |
| 720 'IDBObjectStore.get should throw InvalidStateError, indicating ' + |
| 721 'that the store is still marked for deletion, after the ' + |
| 722 'transaction is aborted'); |
| 723 assert_throws( |
| 724 'InvalidStateError', () => index.get('query'), |
| 725 'IDBIndex.get should throw InvalidStateError, indicating that ' + |
| 726 'the index is still marked for deletion, after the transaction ' + |
| 727 'is aborted'); |
| 728 assert_array_equals( |
| 729 migrationDatabase.objectStoreNames, ['books'], |
| 730 'IDBDatabase.objectStoreNames should not include the newly ' + |
| 731 'created store after the transaction is aborted'); |
| 732 assert_array_equals( |
| 733 migrationTransaction.objectStoreNames, ['books'], |
| 734 'IDBTransaction.objectStoreNames should not include the newly ' + |
| 735 'created store after the transaction is aborted'); |
| 736 assert_array_equals( |
| 737 store.indexNames, [], |
| 738 'IDBObjectStore.indexNames should be empty after the transaction ' + |
| 739 'is aborted'); |
| 740 }); |
| 741 }, 'Deleted indexes in created+deleted stores are still marked as deleted ' + |
| 742 'after their transaction aborts'); |
| 743 |
| 744 </script> |
| OLD | NEW |