idbindex-rename.any.js (15594B)
1 // META: title=IndexedDB: index renaming support 2 // META: global=window,worker 3 // META: script=resources/support-promises.js 4 // META: timeout=long 5 6 // Spec: https://w3c.github.io/IndexedDB/#dom-idbindex-name 7 8 'use strict'; 9 10 promise_test(testCase => { 11 let authorIndex = null; 12 let authorIndex2 = null; 13 let renamedAuthorIndex = null; 14 let renamedAuthorIndex2 = null; 15 return createDatabase( 16 testCase, 17 (database, transaction) => { 18 const store = createBooksStore(testCase, database); 19 authorIndex = store.index('by_author'); 20 }) 21 .then(database => { 22 const transaction = database.transaction('books', 'readonly'); 23 const store = transaction.objectStore('books'); 24 assert_array_equals( 25 store.indexNames, ['by_author', 'by_title'], 26 'Test setup should have created two indexes'); 27 authorIndex2 = store.index('by_author'); 28 return checkAuthorIndexContents( 29 testCase, authorIndex2, 30 'The index should have the expected contents before any renaming') 31 .then(() => database.close()); 32 }) 33 .then( 34 () => migrateDatabase( 35 testCase, 2, 36 (database, transaction) => { 37 const store = transaction.objectStore('books'); 38 renamedAuthorIndex = store.index('by_author'); 39 renamedAuthorIndex.name = 'renamed_by_author'; 40 41 assert_equals( 42 renamedAuthorIndex.name, 'renamed_by_author', 43 'IDBIndex name should change immediately after a rename'); 44 assert_array_equals( 45 store.indexNames, ['by_title', 'renamed_by_author'], 46 'IDBObjectStore.indexNames should immediately reflect the rename'); 47 assert_equals( 48 store.index('renamed_by_author'), renamedAuthorIndex, 49 'IDBObjectStore.index should return the renamed index store when ' + 50 'queried using the new name immediately after the rename'); 51 assert_throws_dom( 52 'NotFoundError', () => store.index('by_author'), 53 'IDBObjectStore.index should throw when queried using the ' + 54 'renamed index\'s old name immediately after the rename'); 55 })) 56 .then(database => { 57 const transaction = database.transaction('books', 'readonly'); 58 const store = transaction.objectStore('books'); 59 assert_array_equals( 60 store.indexNames, ['by_title', 'renamed_by_author'], 61 'IDBObjectStore.indexNames should still reflect the rename after ' + 62 'the versionchange transaction commits'); 63 renamedAuthorIndex2 = store.index('renamed_by_author'); 64 return checkAuthorIndexContents( 65 testCase, renamedAuthorIndex2, 66 'Renaming an index should not change its contents') 67 .then(() => database.close()); 68 }) 69 .then(() => { 70 assert_equals( 71 authorIndex.name, 'by_author', 72 'IDBIndex obtained before the rename transaction should not ' + 73 'reflect the rename'); 74 assert_equals( 75 authorIndex2.name, 'by_author', 76 'IDBIndex obtained before the rename transaction should not ' + 77 'reflect the rename'); 78 assert_equals( 79 renamedAuthorIndex.name, 'renamed_by_author', 80 'IDBIndex used in the rename transaction should keep reflecting ' + 81 'the new name after the transaction is committed'); 82 assert_equals( 83 renamedAuthorIndex2.name, 'renamed_by_author', 84 'IDBIndex obtained after the rename transaction should reflect ' + 85 'the new name'); 86 }); 87 }, 'IndexedDB index rename in new transaction'); 88 89 promise_test(testCase => { 90 let renamedAuthorIndex = null; 91 let renamedAuthorIndex2 = null; 92 return createDatabase( 93 testCase, 94 (database, transaction) => { 95 const store = createBooksStore(testCase, database); 96 renamedAuthorIndex = store.index('by_author'); 97 renamedAuthorIndex.name = 'renamed_by_author'; 98 99 assert_equals( 100 renamedAuthorIndex.name, 'renamed_by_author', 101 'IDBIndex name should change immediately after a rename'); 102 assert_array_equals( 103 store.indexNames, ['by_title', 'renamed_by_author'], 104 'IDBObjectStore.indexNames should immediately reflect the rename'); 105 assert_equals( 106 store.index('renamed_by_author'), renamedAuthorIndex, 107 'IDBObjectStore.index should return the renamed index store when ' + 108 'queried using the new name immediately after the rename'); 109 assert_throws_dom( 110 'NotFoundError', () => store.index('by_author'), 111 'IDBObjectStore.index should throw when queried using the ' + 112 'renamed index\'s old name immediately after the rename'); 113 }) 114 .then(database => { 115 const transaction = database.transaction('books', 'readonly'); 116 const store = transaction.objectStore('books'); 117 assert_array_equals( 118 store.indexNames, ['by_title', 'renamed_by_author'], 119 'IDBObjectStore.indexNames should still reflect the rename after ' + 120 'the versionchange transaction commits'); 121 renamedAuthorIndex2 = store.index('renamed_by_author'); 122 return checkAuthorIndexContents( 123 testCase, renamedAuthorIndex2, 124 'Renaming an index should not change its contents') 125 .then(() => database.close()); 126 }) 127 .then(() => { 128 assert_equals( 129 renamedAuthorIndex.name, 'renamed_by_author', 130 'IDBIndex used in the rename transaction should keep reflecting ' + 131 'the new name after the transaction is committed'); 132 assert_equals( 133 renamedAuthorIndex2.name, 'renamed_by_author', 134 'IDBIndex obtained after the rename transaction should reflect ' + 135 'the new name'); 136 }); 137 }, 'IndexedDB index rename in the transaction where it is created'); 138 139 promise_test(testCase => { 140 return createDatabase( 141 testCase, 142 (database, transaction) => { 143 createBooksStore(testCase, database); 144 }) 145 .then(database => { 146 database.close(); 147 }) 148 .then( 149 () => migrateDatabase( 150 testCase, 2, 151 (database, transaction) => { 152 const store = transaction.objectStore('books'); 153 const index = store.index('by_author'); 154 index.name = 'by_author'; 155 assert_array_equals( 156 store.indexNames, ['by_author', 'by_title'], 157 'Renaming an index to the same name should not change the ' + 158 'index\'s IDBObjectStore.indexNames'); 159 })) 160 .then(database => { 161 const transaction = database.transaction('books', 'readonly'); 162 const store = transaction.objectStore('books'); 163 assert_array_equals( 164 store.indexNames, ['by_author', 'by_title'], 165 'Committing a transaction that renames a store to the same name ' + 166 'should not change the index\'s IDBObjectStore.indexNames'); 167 const index = store.index('by_author'); 168 return checkAuthorIndexContents( 169 testCase, index, 170 'Committing a transaction that renames an index to the same name ' + 171 'should not change the index\'s contents') 172 .then(() => database.close()); 173 }); 174 }, 'IndexedDB index rename to the same name succeeds'); 175 176 promise_test(testCase => { 177 return createDatabase( 178 testCase, 179 (database, transaction) => { 180 createBooksStore(testCase, database); 181 }) 182 .then(database => { 183 database.close(); 184 }) 185 .then( 186 () => migrateDatabase( 187 testCase, 2, 188 (database, transaction) => { 189 const store = transaction.objectStore('books'); 190 const index = store.index('by_author'); 191 store.deleteIndex('by_title'); 192 index.name = 'by_title'; 193 assert_array_equals( 194 store.indexNames, ['by_title'], 195 'IDBObjectStore.indexNames should immediately reflect the rename'); 196 })) 197 .then(database => { 198 const transaction = database.transaction('books', 'readonly'); 199 const store = transaction.objectStore('books'); 200 assert_array_equals( 201 store.indexNames, ['by_title'], 202 'IDBObjectStore.indexNames should still reflect the rename after ' + 203 'the versionchange transaction commits'); 204 const index = store.index('by_title'); 205 return checkAuthorIndexContents( 206 testCase, index, 207 'Renaming an index should not change its contents') 208 .then(() => database.close()); 209 }); 210 }, 'IndexedDB index rename to the name of a deleted index succeeds'); 211 212 promise_test(testCase => { 213 return createDatabase( 214 testCase, 215 (database, transaction) => { 216 createBooksStore(testCase, database); 217 }) 218 .then(database => { 219 database.close(); 220 }) 221 .then( 222 () => migrateDatabase( 223 testCase, 2, 224 (database, transaction) => { 225 const store = transaction.objectStore('books'); 226 store.index('by_author').name = 'tmp'; 227 store.index('by_title').name = 'by_author'; 228 store.index('tmp').name = 'by_title'; 229 assert_array_equals( 230 store.indexNames, ['by_author', 'by_title'], 231 'IDBObjectStore.indexNames should reflect the swap immediately ' + 232 'after the renames'); 233 return checkTitleIndexContents( 234 testCase, store.index('by_author'), 235 'Renaming an index should not change its contents'); 236 })) 237 .then(database => { 238 const transaction = database.transaction('books', 'readonly'); 239 const store = transaction.objectStore('books'); 240 assert_array_equals( 241 store.indexNames, ['by_author', 'by_title'], 242 'IDBObjectStore.indexNames should still reflect the swap after ' + 243 'the versionchange transaction commits'); 244 const index = store.index('by_title'); 245 return checkAuthorIndexContents( 246 testCase, index, 247 'Renaming an index should not change its contents') 248 .then(() => database.close()); 249 }); 250 }, 'IndexedDB index swapping via renames succeeds'); 251 252 promise_test(testCase => { 253 return createDatabase( 254 testCase, 255 (database, transaction) => { 256 createBooksStore(testCase, database); 257 }) 258 .then(database => { 259 database.close(); 260 }) 261 .then( 262 () => migrateDatabase( 263 testCase, 2, 264 (database, transaction) => { 265 const store = transaction.objectStore('books'); 266 const index = store.index('by_author'); 267 268 index.name = 42; 269 assert_equals( 270 index.name, '42', 271 'IDBIndex name should change immediately after a rename to a ' + 272 'number'); 273 assert_array_equals( 274 store.indexNames, ['42', 'by_title'], 275 'IDBObjectStore.indexNames should immediately reflect the ' + 276 'stringifying rename'); 277 278 index.name = true; 279 assert_equals( 280 index.name, 'true', 281 'IDBIndex name should change immediately after a rename to a ' + 282 'boolean'); 283 284 index.name = {}; 285 assert_equals( 286 index.name, '[object Object]', 287 'IDBIndex name should change immediately after a rename to an ' + 288 'object'); 289 290 index.name = () => null; 291 assert_equals( 292 index.name, '() => null', 293 'IDBIndex name should change immediately after a rename to a ' + 294 'function'); 295 296 index.name = undefined; 297 assert_equals( 298 index.name, 'undefined', 299 'IDBIndex name should change immediately after a rename to ' + 300 'undefined'); 301 })) 302 .then(database => { 303 const transaction = database.transaction('books', 'readonly'); 304 const store = transaction.objectStore('books'); 305 assert_array_equals( 306 store.indexNames, ['by_title', 'undefined'], 307 'IDBObjectStore.indexNames should reflect the last rename ' + 308 'after the versionchange transaction commits'); 309 const index = store.index('undefined'); 310 return checkAuthorIndexContents( 311 testCase, index, 312 'Renaming an index should not change its contents') 313 .then(() => database.close()); 314 }); 315 }, 'IndexedDB index rename stringifies non-string names'); 316 317 for (let escapedName of ['', '\\u0000', '\\uDC00\\uD800']) 318 ((escapedName) => { 319 const name = JSON.parse('"' + escapedName + '"'); 320 promise_test(testCase => { 321 return createDatabase( 322 testCase, 323 (database, transaction) => { 324 createBooksStore(testCase, database); 325 }) 326 .then(database => { 327 database.close(); 328 }) 329 .then( 330 () => migrateDatabase( 331 testCase, 2, 332 (database, transaction) => { 333 const store = transaction.objectStore('books'); 334 const index = store.index('by_author'); 335 336 index.name = name; 337 assert_equals( 338 index.name, name, 339 'IDBIndex name should change immediately after the rename'); 340 assert_array_equals( 341 store.indexNames, [name, 'by_title'].sort(), 342 'IDBObjectStore.indexNames should immediately reflect the rename'); 343 })) 344 .then(database => { 345 const transaction = database.transaction('books', 'readonly'); 346 const store = transaction.objectStore('books'); 347 assert_array_equals( 348 store.indexNames, [name, 'by_title'].sort(), 349 'IDBObjectStore.indexNames should reflect the rename ' + 350 'after the versionchange transaction commits'); 351 const index = store.index(name); 352 return checkAuthorIndexContents( 353 testCase, index, 354 'Renaming an index should not change its contents') 355 .then(() => database.close()); 356 }); 357 }, 'IndexedDB index can be renamed to "' + escapedName + '"'); 358 })(escapedName);