OLD | NEW |
(Empty) | |
| 1 <!doctype html> |
| 2 <meta charset="utf8"> |
| 3 <title>IndexedDB: versionchange transaction lifecycle</title> |
| 4 <!-- These tests cannot yet be upstreamed to WPT because they rely on microtask |
| 5 sequencing, which was not fully specified yet. --> |
| 6 <link rel="help" |
| 7 href="https://w3c.github.io/IndexedDB/#upgrade-transaction-steps"> |
| 8 <link rel="help" |
| 9 href="https://w3c.github.io/IndexedDB/#dom-idbdatabase-createobjectstore"> |
| 10 <link rel="help" |
| 11 href="https://w3c.github.io/IndexedDB/#dom-idbdatabase-deleteobjectstore"> |
| 12 <link rel="author" href="pwnall@chromium.org" title="Victor Costan"> |
| 13 <script src="../../resources/testharness.js"></script> |
| 14 <script src="../../resources/testharnessreport.js"></script> |
| 15 <script src="resources/support-promises.js"></script> |
| 16 <script> |
| 17 'use strict'; |
| 18 |
| 19 promise_test(t => { |
| 20 return createDatabase(t, database => { |
| 21 createBooksStore(t, database); |
| 22 }).then(database => { |
| 23 database.close(); |
| 24 }).then(() => migrateDatabase(t, 2, (database, transaction, request) => { |
| 25 let abortFired = false; |
| 26 const abortPromise = new Promise((resolve, reject) => { |
| 27 transaction.addEventListener('abort', () => { |
| 28 abortFired = true; |
| 29 resolve(); |
| 30 }, false); |
| 31 transaction.objectStore('books').add(BOOKS_RECORD_DATA[0]); |
| 32 transaction._willBeAborted(); |
| 33 }); |
| 34 |
| 35 return Promise.resolve().then(() => { |
| 36 assert_false( |
| 37 abortFired, |
| 38 'The abort event should fire after promises are resolved'); |
| 39 assert_equals( |
| 40 request.transaction, transaction, |
| 41 "The open request's transaction should be reset after onabort"); |
| 42 try { |
| 43 database.createObjectStore('books2'); |
| 44 } catch(e) { |
| 45 assert_false( |
| 46 e, |
| 47 'createObjectStore should not throw an exception, because the ' + |
| 48 'transaction is still active'); |
| 49 } |
| 50 try { |
| 51 database.deleteObjectStore('books'); |
| 52 } catch(e) { |
| 53 assert_false( |
| 54 e, |
| 55 'deleteObjectStore should not throw an exception, because the ' + |
| 56 'transaction is still active'); |
| 57 } |
| 58 }).then(() => abortPromise); |
| 59 })); |
| 60 }, 'in a promise microtask after a failing request is issued, before the ' + |
| 61 'transaction abort event is fired'); |
| 62 |
| 63 promise_test(t => { |
| 64 return createDatabase(t, database => { |
| 65 createBooksStore(t, database); |
| 66 }).then(database => { |
| 67 database.close(); |
| 68 }).then(() => migrateDatabase(t, 2, (database, transaction, request) => { |
| 69 return new Promise((resolve, reject) => { |
| 70 transaction.addEventListener('abort', () => resolve(), false); |
| 71 transaction.objectStore('books').add(BOOKS_RECORD_DATA[0]); |
| 72 transaction._willBeAborted(); |
| 73 }).then(() => { |
| 74 assert_equals( |
| 75 request.transaction, transaction, |
| 76 "The open request's transaction should be reset after onabort " + |
| 77 'microtasks'); |
| 78 assert_throws( |
| 79 'InvalidStateError', |
| 80 () => { database.createObjectStore('books2'); }, |
| 81 'createObjectStore exception should reflect that the transaction ' + |
| 82 'is no longer running'); |
| 83 assert_throws( |
| 84 'InvalidStateError', |
| 85 () => { database.deleteObjectStore('books'); }, |
| 86 'deleteObjectStore exception should reflect that the transaction ' + |
| 87 'is no longer running'); |
| 88 }); |
| 89 })); |
| 90 }, 'in a promise microtask after the abort event is fired for a transaction ' + |
| 91 'aborted due to an unhandled request failure'); |
| 92 |
| 93 promise_test(t => { |
| 94 return createDatabase(t, database => { |
| 95 createBooksStore(t, database); |
| 96 }).then(database => { |
| 97 database.close(); |
| 98 }).then(() => migrateDatabase(t, 2, (database, transaction, request) => { |
| 99 return new Promise((resolve, reject) => { |
| 100 transaction.addEventListener('abort', () => resolve(), false); |
| 101 transaction.abort(); |
| 102 }).then(() => { |
| 103 assert_equals( |
| 104 request.transaction, transaction, |
| 105 "The open request's transaction should be reset after onabort " + |
| 106 'microtasks'); |
| 107 assert_throws( |
| 108 'InvalidStateError', |
| 109 () => { database.createObjectStore('books2'); }, |
| 110 'createObjectStore exception should reflect that the transaction ' + |
| 111 'is no longer running'); |
| 112 assert_throws( |
| 113 'InvalidStateError', |
| 114 () => { database.deleteObjectStore('books'); }, |
| 115 'deleteObjectStore exception should reflect that the transaction ' + |
| 116 'is no longer running'); |
| 117 }); |
| 118 })); |
| 119 }, 'in a promise microtask after the abort event is fired for a transaction ' + |
| 120 'aborted due to an abort() call'); |
| 121 |
| 122 promise_test(t => { |
| 123 return createDatabase(t, database => { |
| 124 createBooksStore(t, database); |
| 125 }).then(database => { |
| 126 database.close(); |
| 127 }).then(() => migrateDatabase(t, 2, (database, transaction, request) => { |
| 128 let completeFired = false; |
| 129 const completePromise = new Promise((resolve, reject) => { |
| 130 transaction.addEventListener('complete', () => { |
| 131 completeFired = true; |
| 132 resolve(); |
| 133 }, false); |
| 134 }); |
| 135 |
| 136 return Promise.resolve().then(() => { |
| 137 assert_false( |
| 138 completeFired, |
| 139 'The complete event should fire after promises are resolved'); |
| 140 assert_equals( |
| 141 request.transaction, transaction, |
| 142 "The open request's transaction should be reset after oncomplete"); |
| 143 try { |
| 144 database.createObjectStore('books2'); |
| 145 } catch(e) { |
| 146 assert_false( |
| 147 e, |
| 148 'createObjectStore should not throw an exception, because the ' + |
| 149 'transaction is still active'); |
| 150 } |
| 151 try { |
| 152 database.deleteObjectStore('books'); |
| 153 } catch(e) { |
| 154 assert_false( |
| 155 e, |
| 156 'deleteObjectStore should not throw an exception, because the ' + |
| 157 'transaction is still active'); |
| 158 } |
| 159 }).then(() => completePromise); |
| 160 })).then(database => { database.close(); }); |
| 161 }, 'in a promise microtask after the transaction requests are performed'); |
| 162 |
| 163 promise_test(t => { |
| 164 return createDatabase(t, database => { |
| 165 createBooksStore(t, database); |
| 166 }).then(database => { |
| 167 database.close(); |
| 168 }).then(() => migrateDatabase(t, 2, (database, transaction, request) => { |
| 169 return new Promise((resolve, reject) => { |
| 170 transaction.addEventListener('complete', () => resolve(), false); |
| 171 }).then(() => { |
| 172 assert_equals( |
| 173 request.transaction, transaction, |
| 174 "The open request's transaction should be reset after oncomplete " + |
| 175 'microtasks'); |
| 176 assert_throws( |
| 177 'InvalidStateError', |
| 178 () => { database.createObjectStore('books2'); }, |
| 179 'createObjectStore exception should reflect that the transaction ' + |
| 180 'is no longer running'); |
| 181 assert_throws( |
| 182 'InvalidStateError', |
| 183 () => { database.deleteObjectStore('books'); }, |
| 184 'deleteObjectStore exception should reflect that the transaction ' + |
| 185 'is no longer running'); |
| 186 }); |
| 187 })).then(database => { database.close(); }); |
| 188 }, 'in a promise microtask after the complete event is fired for a committed ' + |
| 189 'transaction'); |
| 190 |
| 191 </script> |
OLD | NEW |