OLD | NEW |
| (Empty) |
1 <!DOCTYPE html> | |
2 <title>IndexedDB: aborting transactions reverts index metadata</title> | |
3 <link rel="help" href="https://w3c.github.io/IndexedDB/#abort-transaction"> | |
4 <link rel="author" href="pwnall@chromium.org" title="Victor Costan"> | |
5 <script src="/resources/testharness.js"></script> | |
6 <script src="/resources/testharnessreport.js"></script> | |
7 <script src="support-promises.js"></script> | |
8 <script> | |
9 | |
10 promise_test(testCase => { | |
11 let store = null, index = 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 index = store.index('not_by_author'); | |
19 assert_array_equals( | |
20 store.indexNames, ['not_by_author', 'not_by_title'], | |
21 'IDBObjectStore.indexNames should include newly created indexes ' + | |
22 'before the transaction is aborted'); | |
23 | |
24 transaction.abort(); | |
25 assert_throws( | |
26 'InvalidStateError', () => index.get('query'), | |
27 'IDBIndex.get should throw InvalidStateError, indicating that ' + | |
28 'the index is marked for deletion, immediately after ' + | |
29 'IDBTransaction.abort() returns'); | |
30 assert_array_equals( | |
31 store.indexNames, [], | |
32 'IDBObjectStore.indexNames should stop including the newly ' + | |
33 'created indexes immediately after IDBTransaction.abort() returns'); | |
34 })).then(() => { | |
35 assert_throws( | |
36 'InvalidStateError', () => index.get('query'), | |
37 'IDBIndex.get should throw InvalidStateError, indicating that ' + | |
38 'the index is marked for deletion, after the transaction is ' + | |
39 'aborted'); | |
40 assert_array_equals( | |
41 store.indexNames, [], | |
42 'IDBObjectStore.indexNames should stop including the newly ' + | |
43 'created indexes after the transaction is aborted'); | |
44 }); | |
45 }, 'Created stores get their indexes marked as deleted after the transaction ' + | |
46 'that created them aborts'); | |
47 | |
48 promise_test(testCase => { | |
49 let store = null, index = null; | |
50 return createDatabase(testCase, (database, transaction) => { | |
51 createBooksStore(testCase, database); | |
52 createNotBooksStore(testCase, database); | |
53 }).then(database => { | |
54 database.close(); | |
55 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { | |
56 store = transaction.objectStore('not_books'); | |
57 index = store.index('not_by_author'); | |
58 | |
59 database.deleteObjectStore('not_books'); | |
60 assert_throws( | |
61 'InvalidStateError', () => index.get('query'), | |
62 'IDBIndex.get should throw InvalidStateError, indicating that ' + | |
63 'the index is marked for deletion, immediately after ' + | |
64 'IDBDatabase.deleteObjectStore() returns'); | |
65 assert_array_equals( | |
66 store.indexNames, [], | |
67 'IDBObjectStore.indexNames should be empty immediately after ' + | |
68 'IDBDatabase.deleteObjectStore() returns'); | |
69 | |
70 transaction.abort(); | |
71 assert_throws( | |
72 'TransactionInactiveError', () => index.get('query'), | |
73 'IDBIndex.get should throw TransactionInactiveError, indicating ' + | |
74 'that the index is no longer marked for deletion, immediately ' + | |
75 'after IDBTransaction.abort() returns'); | |
76 assert_array_equals( | |
77 store.indexNames, ['not_by_author', 'not_by_title'], | |
78 'IDBObjectStore.indexNames should include the deleted indexes ' + | |
79 'immediately after IDBTransaction.abort() returns'); | |
80 })).then(() => { | |
81 assert_throws( | |
82 'TransactionInactiveError', () => index.get('query'), | |
83 'IDBIndex.get should throw TransactionInactiveError, indicating ' + | |
84 'that the index is no longer marked for deletion, after the ' + | |
85 'transaction is aborted'); | |
86 assert_array_equals( | |
87 store.indexNames, ['not_by_author', 'not_by_title'], | |
88 'IDBObjectStore.indexNames should include the deleted indexes ' + | |
89 'after the transaction is aborted'); | |
90 }); | |
91 }, 'Deleted stores get their indexes marked as not-deleted after the ' + | |
92 'transaction that deleted them aborts'); | |
93 | |
94 promise_test(testCase => { | |
95 let store = null, index = null; | |
96 return createDatabase(testCase, (database, transaction) => { | |
97 createBooksStore(testCase, database); | |
98 }).then(database => { | |
99 database.close(); | |
100 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { | |
101 store = createNotBooksStore(testCase, database); | |
102 index = store.index('not_by_author'); | |
103 assert_array_equals( | |
104 store.indexNames, ['not_by_author', 'not_by_title'], | |
105 'IDBObjectStore.indexNames should include newly created indexes ' + | |
106 'before the transaction is aborted'); | |
107 | |
108 database.deleteObjectStore('not_books'); | |
109 assert_throws( | |
110 'InvalidStateError', () => index.get('query'), | |
111 'IDBIndex.get should throw InvalidStateError, indicating that ' + | |
112 'the index is marked for deletion, immediately after ' + | |
113 'IDBDatabase.deleteObjectStore() returns'); | |
114 assert_array_equals( | |
115 store.indexNames, [], | |
116 'IDBObjectStore.indexNames should be empty immediately after ' + | |
117 'IDBDatabase.deleteObjectStore() returns'); | |
118 | |
119 transaction.abort(); | |
120 assert_throws( | |
121 'InvalidStateError', () => index.get('query'), | |
122 'IDBIndex.get should throw InvalidStateError, indicating that ' + | |
123 'the index is still marked for deletion, immediately after ' + | |
124 'IDBTransaction.abort() returns'); | |
125 assert_array_equals( | |
126 store.indexNames, [], | |
127 'IDBObjectStore.indexNames should not include the newly ' + | |
128 'created indexes immediately after IDBTransaction.abort() returns'); | |
129 })).then(() => { | |
130 assert_throws( | |
131 'InvalidStateError', () => index.get('query'), | |
132 'IDBIndex.get should throw InvalidStateError, indicating that ' + | |
133 'the index is still marked for deletion, after the transaction ' + | |
134 'is aborted'); | |
135 assert_array_equals( | |
136 store.indexNames, [], | |
137 'IDBObjectStore.indexNames should not include the newly ' + | |
138 'created indexes after the transaction is aborted'); | |
139 }); | |
140 }, 'Created+deleted stores still have their indexes marked as deleted after ' + | |
141 'the transaction aborts'); | |
142 | |
143 promise_test(testCase => { | |
144 let store = null, index = null; | |
145 return createDatabase(testCase, (database, transaction) => { | |
146 createBooksStore(testCase, database); | |
147 createNotBooksStore(testCase, database); | |
148 }).then(database => { | |
149 database.close(); | |
150 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { | |
151 store = transaction.objectStore('not_books'); | |
152 index = store.createIndex('not_by_isbn', 'isbn'); | |
153 assert_array_equals( | |
154 store.indexNames, ['not_by_author', 'not_by_isbn', 'not_by_title'], | |
155 'IDBObjectStore.indexNames should include newly created indexes ' + | |
156 'before the transaction is aborted'); | |
157 | |
158 transaction.abort(); | |
159 assert_throws( | |
160 'InvalidStateError', () => index.get('query'), | |
161 'IDBIndex.get should throw InvalidStateError, indicating that ' + | |
162 'the index is marked for deletion, immediately after ' + | |
163 'IDBTransaction.abort() returns'); | |
164 assert_array_equals( | |
165 store.indexNames, ['not_by_author', 'not_by_title'], | |
166 'IDBObjectStore.indexNames should stop including the newly ' + | |
167 'created index immediately after IDBTransaction.abort() returns'); | |
168 })).then(() => { | |
169 assert_throws( | |
170 'InvalidStateError', () => index.get('query'), | |
171 'IDBIndex.get should throw InvalidStateError, indicating that ' + | |
172 'the index is marked for deletion, after the transaction is ' + | |
173 'aborted'); | |
174 assert_array_equals( | |
175 store.indexNames, ['not_by_author', 'not_by_title'], | |
176 'IDBObjectStore.indexNames should stop including the newly ' + | |
177 'created index after the transaction is aborted'); | |
178 }); | |
179 }, 'Created indexes get marked as deleted after their transaction aborts'); | |
180 | |
181 promise_test(testCase => { | |
182 let store = null, index = null; | |
183 return createDatabase(testCase, (database, transaction) => { | |
184 createBooksStore(testCase, database); | |
185 createNotBooksStore(testCase, database); | |
186 }).then(database => { | |
187 database.close(); | |
188 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { | |
189 store = transaction.objectStore('not_books'); | |
190 index = store.index('not_by_author'); | |
191 | |
192 store.deleteIndex('not_by_author'); | |
193 assert_throws( | |
194 'InvalidStateError', () => index.get('query'), | |
195 'IDBIndex.get should throw InvalidStateError, indicating that ' + | |
196 'the index is marked for deletion, immediately after ' + | |
197 'IDBObjectStore.deleteIndex() returns'); | |
198 assert_array_equals( | |
199 store.indexNames, ['not_by_title'], | |
200 'IDBObjectStore.indexNames should not include the deleted index ' + | |
201 'immediately after IDBObjectStore.deleteIndex() returns'); | |
202 | |
203 transaction.abort(); | |
204 assert_throws( | |
205 'TransactionInactiveError', () => index.get('query'), | |
206 'IDBIndex.get should throw TransactionInactiveError, indicating ' + | |
207 'that the index is no longer marked for deletion, immediately ' + | |
208 'after IDBTransaction.abort() returns'); | |
209 assert_array_equals( | |
210 store.indexNames, ['not_by_author', 'not_by_title'], | |
211 'IDBObjectStore.indexNames should include the deleted indexes ' + | |
212 'immediately after IDBTransaction.abort() returns'); | |
213 })).then(() => { | |
214 assert_throws( | |
215 'TransactionInactiveError', () => index.get('query'), | |
216 'IDBIndex.get should throw TransactionInactiveError, indicating ' + | |
217 'that the index is no longer marked for deletion, after the ' + | |
218 'transaction is aborted'); | |
219 assert_array_equals( | |
220 store.indexNames, ['not_by_author', 'not_by_title'], | |
221 'IDBObjectStore.indexNames should include the deleted indexes ' + | |
222 'after the transaction is aborted'); | |
223 }); | |
224 }, 'Deleted indexes get marked as not-deleted after the transaction aborts'); | |
225 | |
226 promise_test(testCase => { | |
227 let store = null, index = null; | |
228 return createDatabase(testCase, (database, transaction) => { | |
229 createBooksStore(testCase, database); | |
230 createNotBooksStore(testCase, database); | |
231 }).then(database => { | |
232 database.close(); | |
233 }).then(() => migrateDatabase(testCase, 2, (database, transaction) => { | |
234 store = transaction.objectStore('not_books'); | |
235 index = store.createIndex('not_by_isbn', 'isbn'); | |
236 assert_array_equals( | |
237 store.indexNames, ['not_by_author', 'not_by_isbn', 'not_by_title'], | |
238 'IDBObjectStore.indexNames should include newly created indexes ' + | |
239 'before the transaction is aborted'); | |
240 | |
241 store.deleteIndex('not_by_isbn'); | |
242 assert_throws( | |
243 'InvalidStateError', () => index.get('query'), | |
244 'IDBIndex.get should throw InvalidStateError, indicating that ' + | |
245 'the index is marked for deletion, immediately after ' + | |
246 'IDBObjectStore.deleteIndex() returns'); | |
247 assert_array_equals( | |
248 store.indexNames, ['not_by_author', 'not_by_title'], | |
249 'IDBObjectStore.indexNames should not include the deleted index ' + | |
250 'immediately after IDBObjectStore.deleteIndex() returns'); | |
251 | |
252 transaction.abort(); | |
253 assert_throws( | |
254 'InvalidStateError', () => index.get('query'), | |
255 'IDBIndex.get should throw InvalidStateError, indicating that ' + | |
256 'the index is still marked for deletion, immediately after ' + | |
257 'IDBTransaction.abort() returns'); | |
258 assert_array_equals( | |
259 store.indexNames, ['not_by_author', 'not_by_title'], | |
260 'IDBObjectStore.indexNames should stop including the newly ' + | |
261 'created index immediately after IDBTransaction.abort() returns'); | |
262 })).then(() => { | |
263 assert_throws( | |
264 'InvalidStateError', () => index.get('query'), | |
265 'IDBIndex.get should throw InvalidStateError, indicating that ' + | |
266 'the index is marked for deletion, after the transaction is ' + | |
267 'aborted'); | |
268 assert_array_equals( | |
269 store.indexNames, ['not_by_author', 'not_by_title'], | |
270 'IDBObjectStore.indexNames should stop including the newly ' + | |
271 'created index after the transaction is aborted'); | |
272 }); | |
273 }, 'Created+deleted indexes are still marked as deleted after their ' + | |
274 'transaction aborts'); | |
275 | |
276 </script> | |
OLD | NEW |