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