OLD | NEW |
(Empty) | |
| 1 <!DOCTYPE html> |
| 2 <title>IndexedDB: object store renaming support</title> |
| 3 <script src='../../resources/testharness.js'></script> |
| 4 <link rel="help" |
| 5 href="https://w3c.github.io/IndexedDB/#dom-idbobjectstore-name"> |
| 6 <link rel="author" href="pwnall@chromium.org" title="Victor Costan"> |
| 7 <script src='../../resources/testharnessreport.js'></script> |
| 8 <script src='resources/rename-common.js'></script> |
| 9 <script> |
| 10 |
| 11 // Renames the 'books' store to 'renamed_books'. |
| 12 // |
| 13 // Returns a promise that resolves to an IndexedDB database. The caller must |
| 14 // close the database. |
| 15 const renameBooksStore = function(testCase) { |
| 16 return migrateDatabase(testCase, 2, (database, transaction) => { |
| 17 const store = transaction.objectStore('books'); |
| 18 store.name = 'renamed_books'; |
| 19 }); |
| 20 }; |
| 21 |
| 22 promise_test(testCase => { |
| 23 let bookStore = null, bookStore2 = null; |
| 24 let renamedBookStore = null, renamedBookStore2 = null; |
| 25 return createDatabase(testCase, (database, transaction) => { |
| 26 bookStore = createBooksStore(testCase, database); |
| 27 }).then(database => { |
| 28 assert_array_equals( |
| 29 database.objectStoreNames, ['books'], |
| 30 'Test setup should have created a "books" object store'); |
| 31 const transaction = database.transaction('books', 'readonly'); |
| 32 bookStore2 = transaction.objectStore('books'); |
| 33 return checkStoreContents( |
| 34 testCase, bookStore2, |
| 35 'The store should have the expected contents before any renaming'). |
| 36 then(() => database.close()); |
| 37 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 38 renamedBookStore = transaction.objectStore('books'); |
| 39 renamedBookStore.name = 'renamed_books'; |
| 40 |
| 41 assert_equals( |
| 42 renamedBookStore.name, 'renamed_books', |
| 43 'IDBObjectStore name should change immediately after a rename'); |
| 44 assert_array_equals( |
| 45 database.objectStoreNames, ['renamed_books'], |
| 46 'IDBDatabase.objectStoreNames should immediately reflect the ' + |
| 47 'rename'); |
| 48 assert_equals( |
| 49 transaction.objectStore('renamed_books'), renamedBookStore, |
| 50 'IDBTransaction.objectStore should return the renamed object ' + |
| 51 'store when queried using the new name immediately after the ' + |
| 52 'rename'); |
| 53 assert_throws( |
| 54 'NotFoundError', () => transaction.objectStore('books'), |
| 55 'IDBTransaction.objectStore should throw when queried using the ' + |
| 56 "renamed object store's old name immediately after the rename"); |
| 57 })).then(database => { |
| 58 assert_array_equals( |
| 59 database.objectStoreNames, ['renamed_books'], |
| 60 'IDBDatabase.objectStoreNames should still reflect the rename ' + |
| 61 'after the versionchange transaction commits'); |
| 62 const transaction = database.transaction('renamed_books', 'readonly'); |
| 63 renamedBookStore2 = transaction.objectStore('renamed_books'); |
| 64 return checkStoreContents( |
| 65 testCase, renamedBookStore2, |
| 66 'Renaming an object store should not change its records').then( |
| 67 () => database.close()); |
| 68 }).then(() => { |
| 69 assert_equals( |
| 70 bookStore.name, 'books', |
| 71 'IDBObjectStore obtained before the rename transaction should ' + |
| 72 'not reflect the rename'); |
| 73 assert_equals( |
| 74 bookStore2.name, 'books', |
| 75 'IDBObjectStore obtained before the rename transaction should ' + |
| 76 'not reflect the rename'); |
| 77 assert_equals( |
| 78 renamedBookStore.name, 'renamed_books', |
| 79 'IDBObjectStore used in the rename transaction should keep ' + |
| 80 'reflecting the new name after the transaction is committed'); |
| 81 assert_equals( |
| 82 renamedBookStore2.name, 'renamed_books', |
| 83 'IDBObjectStore obtained after the rename transaction should ' + |
| 84 'reflect the new name'); |
| 85 }); |
| 86 }, 'IndexedDB object store rename in new transaction'); |
| 87 |
| 88 promise_test(testCase => { |
| 89 let renamedBookStore = null, renamedBookStore2 = null; |
| 90 return createDatabase(testCase, (database, transaction) => { |
| 91 renamedBookStore = createBooksStore(testCase, database); |
| 92 renamedBookStore.name = 'renamed_books'; |
| 93 |
| 94 assert_equals( |
| 95 renamedBookStore.name, 'renamed_books', |
| 96 'IDBObjectStore name should change immediately after a rename'); |
| 97 assert_array_equals( |
| 98 database.objectStoreNames, ['renamed_books'], |
| 99 'IDBDatabase.objectStoreNames should immediately reflect the ' + |
| 100 'rename'); |
| 101 assert_equals( |
| 102 transaction.objectStore('renamed_books'), renamedBookStore, |
| 103 'IDBTransaction.objectStore should return the renamed object ' + |
| 104 'store when queried using the new name immediately after the ' + |
| 105 'rename'); |
| 106 assert_throws( |
| 107 'NotFoundError', () => transaction.objectStore('books'), |
| 108 'IDBTransaction.objectStore should throw when queried using the ' + |
| 109 "renamed object store's old name immediately after the rename"); |
| 110 }).then(database => { |
| 111 assert_array_equals( |
| 112 database.objectStoreNames, ['renamed_books'], |
| 113 'IDBDatabase.objectStoreNames should still reflect the rename ' + |
| 114 'after the versionchange transaction commits'); |
| 115 const transaction = database.transaction('renamed_books', 'readonly'); |
| 116 renamedBookStore2 = transaction.objectStore('renamed_books'); |
| 117 return checkStoreContents( |
| 118 testCase, renamedBookStore2, |
| 119 'Renaming an object store should not change its records').then( |
| 120 () => database.close()); |
| 121 }).then(() => { |
| 122 assert_equals( |
| 123 renamedBookStore.name, 'renamed_books', |
| 124 'IDBObjectStore used in the rename transaction should keep ' + |
| 125 'reflecting the new name after the transaction is committed'); |
| 126 assert_equals( |
| 127 renamedBookStore2.name, 'renamed_books', |
| 128 'IDBObjectStore obtained after the rename transaction should ' + |
| 129 'reflect the new name'); |
| 130 }); |
| 131 }, 'IndexedDB object store rename in the transaction where it is created'); |
| 132 |
| 133 promise_test(testCase => { |
| 134 return createDatabase(testCase, (database, transaction) => { |
| 135 createBooksStore(testCase, database); |
| 136 }).then(database => { |
| 137 const transaction = database.transaction('books', 'readonly'); |
| 138 const store = transaction.objectStore('books'); |
| 139 return checkStoreIndexes( |
| 140 testCase, store, |
| 141 'The object store index should have the expected contens before ' + |
| 142 'any renaming').then( |
| 143 () => database.close()); |
| 144 }).then(() => renameBooksStore(testCase) |
| 145 ).then(database => { |
| 146 const transaction = database.transaction('renamed_books', 'readonly'); |
| 147 const store = transaction.objectStore('renamed_books'); |
| 148 return checkStoreIndexes( |
| 149 testCase, store, |
| 150 'Renaming an object store should not change its indexes').then( |
| 151 () => database.close()); |
| 152 }); |
| 153 }, 'IndexedDB object store rename covers index'); |
| 154 |
| 155 promise_test(testCase => { |
| 156 return createDatabase(testCase, (database, transaction) => { |
| 157 createBooksStore(testCase, database); |
| 158 }).then(database => { |
| 159 const transaction = database.transaction('books', 'readwrite'); |
| 160 const store = transaction.objectStore('books'); |
| 161 return checkStoreGenerator( |
| 162 testCase, store, 345679, |
| 163 'The object store key generator should have the expected state ' + |
| 164 'before any renaming').then(() => database.close()); |
| 165 }).then(() => renameBooksStore(testCase) |
| 166 ).then(database => { |
| 167 const transaction = database.transaction('renamed_books', 'readwrite'); |
| 168 const store = transaction.objectStore('renamed_books'); |
| 169 return checkStoreGenerator( |
| 170 testCase, store, 345680, |
| 171 'Renaming an object store should not change the state of its key ' + |
| 172 'generator').then(() => database.close()); |
| 173 }); |
| 174 }, 'IndexedDB object store rename covers key generator'); |
| 175 |
| 176 promise_test(testCase => { |
| 177 return createDatabase(testCase, (database, transaction) => { |
| 178 createBooksStore(testCase, database); |
| 179 }).then(database => { |
| 180 database.close(); |
| 181 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 182 const store = transaction.objectStore('books'); |
| 183 database.deleteObjectStore('books'); |
| 184 assert_throws('InvalidStateError', () => store.name = 'renamed_books'); |
| 185 })).then(database => { |
| 186 database.close(); |
| 187 }); |
| 188 }, 'IndexedDB deleted object store rename throws'); |
| 189 |
| 190 promise_test(testCase => { |
| 191 return createDatabase(testCase, (database, transaction) => { |
| 192 createBooksStore(testCase, database); |
| 193 }).then(database => { |
| 194 const transaction = database.transaction('books', 'readonly'); |
| 195 const store = transaction.objectStore('books'); |
| 196 assert_throws('InvalidStateError', () => store.name = 'renamed_books'); |
| 197 database.close(); |
| 198 }); |
| 199 }, 'IndexedDB object store rename throws in a readonly transaction'); |
| 200 |
| 201 promise_test(testCase => { |
| 202 return createDatabase(testCase, (database, transaction) => { |
| 203 createBooksStore(testCase, database); |
| 204 }).then(database => { |
| 205 const transaction = database.transaction('books', 'readwrite'); |
| 206 const store = transaction.objectStore('books'); |
| 207 |
| 208 assert_throws('InvalidStateError', () => store.name = 'renamed_books'); |
| 209 database.close(); |
| 210 }); |
| 211 }, 'IndexedDB object store rename throws in a readwrite transaction'); |
| 212 |
| 213 promise_test(testCase => { |
| 214 let bookStore = null; |
| 215 return createDatabase(testCase, (database, transaction) => { |
| 216 bookStore = createBooksStore(testCase, database); |
| 217 }).then(database => { |
| 218 assert_throws('TransactionInactiveError', |
| 219 () => { bookStore.name = 'renamed_books'; }); |
| 220 database.close(); |
| 221 }); |
| 222 }, 'IndexedDB object store rename throws in an inactive transaction'); |
| 223 |
| 224 promise_test(testCase => { |
| 225 return createDatabase(testCase, (database, transaction) => { |
| 226 createBooksStore(testCase, database); |
| 227 }).then(database => { |
| 228 database.close(); |
| 229 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 230 const store = transaction.objectStore('books'); |
| 231 store.name = 'books'; |
| 232 assert_array_equals( |
| 233 database.objectStoreNames, ['books'], |
| 234 'Renaming a store to the same name should not change ' + |
| 235 "the store's IDBDatabase.objectStoreNames"); |
| 236 })).then(database => { |
| 237 assert_array_equals( |
| 238 database.objectStoreNames, ['books'], |
| 239 'Committing a transaction that renames a store to the same name ' + |
| 240 "should not change the store's IDBDatabase.objectStoreNames"); |
| 241 const transaction = database.transaction('books', 'readonly'); |
| 242 const store = transaction.objectStore('books'); |
| 243 return checkStoreContents( |
| 244 testCase, store, |
| 245 'Committing a transaction that renames a store to the same name ' + |
| 246 "should not change the store's contents").then( |
| 247 () => database.close()); |
| 248 }); |
| 249 }, 'IndexedDB object store rename to the same name succeeds'); |
| 250 |
| 251 promise_test(testCase => { |
| 252 return createDatabase(testCase, (database, transaction) => { |
| 253 createBooksStore(testCase, database); |
| 254 createNotBooksStore(testCase, database); |
| 255 }).then(database => { |
| 256 database.close(); |
| 257 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 258 const store = transaction.objectStore('books'); |
| 259 assert_throws('ConstraintError', () => store.name = 'not_books'); |
| 260 assert_array_equals( |
| 261 database.objectStoreNames, ['books', 'not_books'], |
| 262 'A store rename that throws an exception should not change the ' + |
| 263 "store's IDBDatabase.objectStoreNames"); |
| 264 })).then(database => { |
| 265 assert_array_equals( |
| 266 database.objectStoreNames, ['books', 'not_books'], |
| 267 'Committing a transaction with a failed store rename attempt ' + |
| 268 "should not change the store's IDBDatabase.objectStoreNames"); |
| 269 const transaction = database.transaction('books', 'readonly'); |
| 270 const store = transaction.objectStore('books'); |
| 271 return checkStoreContents( |
| 272 testCase, store, |
| 273 'Committing a transaction with a failed rename attempt should not' + |
| 274 "change the store's contents").then(() => database.close()); |
| 275 }); |
| 276 }, 'IndexedDB object store rename to the name of another store throws'); |
| 277 |
| 278 promise_test(testCase => { |
| 279 return createDatabase(testCase, (database, transaction) => { |
| 280 createBooksStore(testCase, database); |
| 281 createNotBooksStore(testCase, database); |
| 282 }).then(database => { |
| 283 database.close(); |
| 284 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 285 const store = transaction.objectStore('books'); |
| 286 database.deleteObjectStore('not_books'); |
| 287 store.name = 'not_books'; |
| 288 assert_array_equals( |
| 289 database.objectStoreNames, ['not_books'], |
| 290 'IDBDatabase.objectStoreNames should immediately reflect the ' + |
| 291 'rename'); |
| 292 })).then(database => { |
| 293 assert_array_equals( |
| 294 database.objectStoreNames, ['not_books'], |
| 295 'IDBDatabase.objectStoreNames should still reflect the rename ' + |
| 296 'after the versionchange transaction commits'); |
| 297 const transaction = database.transaction('not_books', 'readonly'); |
| 298 const store = transaction.objectStore('not_books'); |
| 299 return checkStoreContents( |
| 300 testCase, store, |
| 301 'Renaming an object store should not change its records').then( |
| 302 () => database.close()); |
| 303 }); |
| 304 }, 'IndexedDB object store rename to the name of a deleted store succeeds'); |
| 305 |
| 306 promise_test(testCase => { |
| 307 return createDatabase(testCase, (database, transaction) => { |
| 308 createBooksStore(testCase, database); |
| 309 createNotBooksStore(testCase, database); |
| 310 }).then(database => { |
| 311 database.close(); |
| 312 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 313 const bookStore = transaction.objectStore('books'); |
| 314 const notBookStore = transaction.objectStore('not_books'); |
| 315 |
| 316 transaction.objectStore('books').name = 'tmp'; |
| 317 transaction.objectStore('not_books').name = 'books'; |
| 318 transaction.objectStore('tmp').name = 'not_books'; |
| 319 |
| 320 assert_array_equals( |
| 321 database.objectStoreNames, ['books', 'not_books'], |
| 322 'IDBDatabase.objectStoreNames should immediately reflect the swap'); |
| 323 |
| 324 assert_equals( |
| 325 transaction.objectStore('books'), notBookStore, |
| 326 'IDBTransaction.objectStore should return the original "books" ' + |
| 327 'store when queried with "not_books" after the swap'); |
| 328 assert_equals( |
| 329 transaction.objectStore('not_books'), bookStore, |
| 330 'IDBTransaction.objectStore should return the original ' + |
| 331 '"not_books" store when queried with "books" after the swap'); |
| 332 })).then(database => { |
| 333 assert_array_equals( |
| 334 database.objectStoreNames, ['books', 'not_books'], |
| 335 'IDBDatabase.objectStoreNames should still reflect the swap ' + |
| 336 'after the versionchange transaction commits'); |
| 337 const transaction = database.transaction('not_books', 'readonly'); |
| 338 const store = transaction.objectStore('not_books'); |
| 339 assert_array_equals( |
| 340 store.indexNames, ['by_author', 'by_title'], |
| 341 '"not_books" index names should still reflect the swap after the ' + |
| 342 'versionchange transaction commits'); |
| 343 return checkStoreContents( |
| 344 testCase, store, |
| 345 'Swapping two object stores should not change their records').then( |
| 346 () => database.close()); |
| 347 }); |
| 348 }, 'IndexedDB object store swapping via renames succeeds'); |
| 349 |
| 350 promise_test(testCase => { |
| 351 return createDatabase(testCase, (database, transaction) => { |
| 352 createBooksStore(testCase, database); |
| 353 }).then(database => { |
| 354 database.close(); |
| 355 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 356 const store = transaction.objectStore('books'); |
| 357 |
| 358 store.name = 42; |
| 359 assert_equals(store.name, '42', |
| 360 'IDBObjectStore name should change immediately after a ' + |
| 361 'rename to a number'); |
| 362 assert_array_equals( |
| 363 database.objectStoreNames, ['42'], |
| 364 'IDBDatabase.objectStoreNames should immediately reflect the ' + |
| 365 'stringifying rename'); |
| 366 |
| 367 store.name = true; |
| 368 assert_equals(store.name, 'true', |
| 369 'IDBObjectStore name should change immediately after a ' + |
| 370 'rename to a boolean'); |
| 371 |
| 372 store.name = {}; |
| 373 assert_equals(store.name, '[object Object]', |
| 374 'IDBObjectStore name should change immediately after a ' + |
| 375 'rename to an object'); |
| 376 |
| 377 store.name = () => null; |
| 378 assert_equals(store.name, '() => null', |
| 379 'IDBObjectStore name should change immediately after a ' + |
| 380 'rename to a function'); |
| 381 |
| 382 store.name = undefined; |
| 383 assert_equals(store.name, 'undefined', |
| 384 'IDBObjectStore name should change immediately after a ' + |
| 385 'rename to undefined'); |
| 386 })).then(database => { |
| 387 assert_array_equals( |
| 388 database.objectStoreNames, ['undefined'], |
| 389 'IDBDatabase.objectStoreNames should reflect the last rename ' + |
| 390 'after the versionchange transaction commits'); |
| 391 const transaction = database.transaction('undefined', 'readonly'); |
| 392 const store = transaction.objectStore('undefined'); |
| 393 return checkStoreContents( |
| 394 testCase, store, |
| 395 'Renaming an object store should not change its records').then( |
| 396 () => database.close()); |
| 397 }); |
| 398 }, 'IndexedDB object store rename stringifies non-string names'); |
| 399 |
| 400 promise_test(testCase => { |
| 401 return createDatabase(testCase, (database, transaction) => { |
| 402 createBooksStore(testCase, database); |
| 403 }).then(database => { |
| 404 database.close(); |
| 405 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 406 const store = transaction.objectStore('books'); |
| 407 assert_throws( |
| 408 { name: 'Custom stringifying error'}, |
| 409 () => { |
| 410 store.name = { |
| 411 toString: () => { throw { name: 'Custom stringifying error'}; } |
| 412 }; |
| 413 }, 'IDBObjectStore rename should re-raise toString() exception'); |
| 414 assert_array_equals( |
| 415 database.objectStoreNames, ['books'], |
| 416 'A store rename that throws an exception should not change the ' + |
| 417 "store's IDBDatabase.objectStoreNames"); |
| 418 })).then(database => { |
| 419 assert_array_equals( |
| 420 database.objectStoreNames, ['books'], |
| 421 'Committing a transaction with a failed store rename attempt ' + |
| 422 "should not change the store's IDBDatabase.objectStoreNames"); |
| 423 const transaction = database.transaction('books', 'readonly'); |
| 424 const store = transaction.objectStore('books'); |
| 425 return checkStoreContents( |
| 426 testCase, store, |
| 427 'Committing a transaction with a failed rename attempt should not' + |
| 428 "change the store's contents").then(() => database.close()); |
| 429 }); |
| 430 }, 'IndexedDB object store rename handles exceptions when stringifying names'); |
| 431 |
| 432 for (let escapedName of ['', '\\u0000', '\\uDC00\\uD800']) ((escapedName) => { |
| 433 const name = JSON.parse('"' + escapedName + '"'); |
| 434 promise_test(testCase => { |
| 435 return createDatabase(testCase, (database, transaction) => { |
| 436 createBooksStore(testCase, database); |
| 437 }).then(database => { |
| 438 database.close(); |
| 439 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { |
| 440 const store = transaction.objectStore('books'); |
| 441 |
| 442 store.name = name; |
| 443 assert_equals(store.name, name, |
| 444 'IDBObjectStore name should change immediately after the ' + |
| 445 'rename'); |
| 446 assert_array_equals( |
| 447 database.objectStoreNames, [name], |
| 448 'IDBDatabase.objectStoreNames should immediately reflect the ' + |
| 449 'rename'); |
| 450 })).then(database => { |
| 451 assert_array_equals( |
| 452 database.objectStoreNames, [name], |
| 453 'IDBDatabase.objectStoreNames should reflect the rename ' + |
| 454 'after the versionchange transaction commits'); |
| 455 const transaction = database.transaction(name, 'readonly'); |
| 456 const store = transaction.objectStore(name); |
| 457 return checkStoreContents( |
| 458 testCase, store, |
| 459 'Renaming an object store should not change its records').then( |
| 460 () => database.close()); |
| 461 }); |
| 462 }, 'IndexedDB object store can be renamed to "' + escapedName + '"'); |
| 463 })(escapedName); |
| 464 |
| 465 promise_test(testCase => { |
| 466 const dbName = databaseName(testCase); |
| 467 let bookStore = null, bookStore2 = null; |
| 468 return createDatabase(testCase, (database, transaction) => { |
| 469 createBooksStore(testCase, database); |
| 470 }).then(database => { |
| 471 database.close(); |
| 472 }).then(() => new Promise((resolve, reject) => { |
| 473 const request = indexedDB.open(dbName, 2); |
| 474 request.onupgradeneeded = event => { |
| 475 const database = event.target.result; |
| 476 const transaction = event.target.transaction; |
| 477 bookStore = transaction.objectStore('books'); |
| 478 bookStore.name = 'renamed_books'; |
| 479 |
| 480 request.onerror = event => { |
| 481 event.preventDefault(); |
| 482 resolve(event); |
| 483 }; |
| 484 transaction.abort(); |
| 485 |
| 486 assert_equals( |
| 487 bookStore.name, 'books', |
| 488 'IDBObjectStore.name should not reflect the rename anymore ' + |
| 489 'immediately after transaction.abort() returns'); |
| 490 assert_array_equals( |
| 491 database.objectStoreNames, ['books'], |
| 492 'IDBDatabase.objectStoreNames should not reflect the rename ' + |
| 493 'anymore immediately after transaction.abort() returns'); |
| 494 }; |
| 495 request.onerror = event => reject(event.target.error); |
| 496 request.onsuccess = () => reject(new Error( |
| 497 'indexedDB.open was not supposed to succeed')); |
| 498 })).then(event => { |
| 499 assert_equals(bookStore.name, 'books', |
| 500 'IDBObjectStore.name should not reflect the rename anymore ' + |
| 501 'after the versionchange transaction is aborted'); |
| 502 const request = indexedDB.open(dbName, 1); |
| 503 return requestWatcher(testCase, request).wait_for('success'); |
| 504 }).then(event => { |
| 505 const database = event.target.result; |
| 506 assert_array_equals( |
| 507 database.objectStoreNames, ['books'], |
| 508 'IDBDatabase.objectStoreNames should not reflect the rename ' + |
| 509 'after the versionchange transaction is aborted'); |
| 510 |
| 511 const transaction = database.transaction('books', 'readonly'); |
| 512 bookStore2 = transaction.objectStore('books'); |
| 513 return checkStoreContents( |
| 514 testCase, bookStore2, |
| 515 'Aborting an object store rename transaction should not change ' + |
| 516 "the store's records").then(() => database.close()); |
| 517 }).then(() => { |
| 518 assert_equals( |
| 519 bookStore.name, 'books', |
| 520 'IDBObjectStore used in aborted rename transaction should not ' + |
| 521 'reflect the rename after the transaction is aborted'); |
| 522 assert_equals( |
| 523 bookStore2.name, 'books', |
| 524 'IDBObjectStore obtained after an aborted rename transaction ' + |
| 525 'should not reflect the rename'); |
| 526 }); |
| 527 }, 'IndexedDB object store rename in aborted transaction'); |
| 528 </script> |
OLD | NEW |