transaction-deactivation-timing.any.js (5138B)
1 // META: title=IndexedDB Transaction Deactivation Timing 2 // META: global=window,worker 3 // META: script=resources/support.js 4 5 // Spec: https://w3c.github.io/IndexedDB/#dom-idbdatabase-transaction 6 7 'use strict'; 8 9 indexeddb_test( 10 (t, db, tx) => { 11 db.createObjectStore('store'); 12 }, 13 (t, db) => { 14 const tx = db.transaction('store', 'readonly'); 15 const release_tx = keep_alive(tx, 'store'); 16 assert_true( 17 is_transaction_active(tx, 'store'), 18 'Transaction should be active after creation'); 19 20 setTimeout( 21 t.step_func(() => { 22 assert_false( 23 is_transaction_active(tx, 'store'), 24 'Transaction should be inactive in next task'); 25 release_tx(); 26 t.done(); 27 }), 28 0); 29 }, 30 'New transactions are deactivated before next task'); 31 32 indexeddb_test( 33 (t, db, tx) => { 34 db.createObjectStore('store'); 35 }, 36 (t, db) => { 37 const tx = db.transaction('store', 'readonly'); 38 const release_tx = keep_alive(tx, 'store'); 39 assert_true( 40 is_transaction_active(tx, 'store'), 41 'Transaction should be active after creation'); 42 43 Promise.resolve().then(t.step_func(() => { 44 assert_true( 45 is_transaction_active(tx, 'store'), 46 'Transaction should be active in microtask checkpoint'); 47 release_tx(); 48 t.done(); 49 })); 50 }, 51 'New transactions are not deactivated until after the microtask checkpoint'); 52 53 indexeddb_test( 54 (t, db, tx) => { 55 db.createObjectStore('store'); 56 }, 57 (t, db) => { 58 let tx; 59 let release_tx; 60 61 Promise.resolve().then(t.step_func(() => { 62 tx = db.transaction('store', 'readonly'); 63 release_tx = keep_alive(tx, 'store'); 64 assert_true( 65 is_transaction_active(tx, 'store'), 66 'Transaction should be active after creation'); 67 })); 68 69 setTimeout( 70 t.step_func(() => { 71 assert_false( 72 is_transaction_active(tx, 'store'), 73 'Transaction should be inactive in next task'); 74 release_tx(); 75 t.done(); 76 }), 77 0); 78 }, 79 'New transactions from microtask are deactivated before next task'); 80 81 indexeddb_test( 82 (t, db, tx) => { 83 db.createObjectStore('store'); 84 }, 85 (t, db) => { 86 let tx; 87 let release_tx; 88 89 Promise.resolve().then(t.step_func(() => { 90 tx = db.transaction('store', 'readonly'); 91 release_tx = keep_alive(tx, 'store'); 92 assert_true( 93 is_transaction_active(tx, 'store'), 94 'Transaction should be active after creation'); 95 })); 96 97 Promise.resolve().then(t.step_func(() => { 98 assert_true( 99 is_transaction_active(tx, 'store'), 100 'Transaction should be active in microtask checkpoint'); 101 release_tx(); 102 t.done(); 103 })); 104 }, 105 'New transactions from microtask are still active through the ' + 106 'microtask checkpoint'); 107 108 109 indexeddb_test( 110 (t, db, tx) => { 111 db.createObjectStore('store'); 112 }, 113 (t, db) => { 114 // This transaction serves as the source of an event seen by multiple 115 // listeners. A DOM event with multiple listeners could be used instead, 116 // but not via dispatchEvent() because (drumroll...) that happens 117 // synchronously so microtasks don't run between steps. 118 const tx = db.transaction('store', 'readonly'); 119 assert_true( 120 is_transaction_active(tx, 'store'), 121 'Transaction should be active after creation'); 122 123 const request = tx.objectStore('store').get(0); 124 let new_tx; 125 let first_listener_ran = false; 126 let microtasks_ran = false; 127 request.addEventListener('success', t.step_func(() => { 128 first_listener_ran = true; 129 assert_true( 130 is_transaction_active(tx, 'store'), 131 'Transaction should be active in callback'); 132 133 // We check to see if t transaction is active across unrelated event 134 // dispatch steps. 135 new_tx = db.transaction('store', 'readonly'); 136 assert_true( 137 is_transaction_active(new_tx, 'store'), 138 'New transaction should be active after creation'); 139 140 Promise.resolve().then(t.step_func(() => { 141 microtasks_ran = true; 142 assert_true( 143 is_transaction_active(new_tx, 'store'), 144 'New transaction is still active in microtask checkpoint'); 145 })); 146 })); 147 request.addEventListener('success', t.step_func(() => { 148 assert_true(first_listener_ran, 'first listener ran first'); 149 assert_true(microtasks_ran, 'microtasks ran before second listener'); 150 assert_true( 151 is_transaction_active(tx, 'store'), 152 'Transaction should be active in callback'); 153 assert_false( 154 is_transaction_active(new_tx, 'store'), 155 'New transaction should be inactive in unrelated callback'); 156 t.done(); 157 })); 158 }, 159 'Deactivation of new transactions happens at end of invocation');