Chromium (bug), Gecko (bug), and WebKit (bug) all make transactions inactive during structured serialization of object values. The spec addresses this in the "clone a value" algorithm (see also structured-clone-transaction-state.any.js).
However, the spec does not consider keys, which can be arbitrarily set using the second argument to put()/add():
const array = [0]
Object.defineProperty(array, '0', {
get() {
// can continue to call `store.put` here
return 0
}
})
store.put({}, array)
This unfortunately leads to a discrepancy in browser behavior, as demonstrated by this minimal repro:
<!doctype html>
<script>
const request = indexedDB.open(Math.random(), 1)
request.onupgradeneeded = (e) => {
const db = e.target.result
db.createObjectStore('store')
}
request.onsuccess = (e) => {
const db = e.target.result
const store = db.transaction('store', 'readwrite')
.objectStore('store')
const array = [0]
Object.defineProperty(array, '0', {
get() {
store.put({}, [1])
return 0
}
})
try {
store.put({}, array)
} catch (err) {
console.log('Error', err)
}
}
</script>
Results:
- Chromium 140:
puts succeed
- GNOME Web 46.5 (WebKit 605.1.15):
puts succeed
- Firefox 143: throws
DOMException: A request was placed against a transaction which is currently not active, or which is finished.
(Note that recursive calls result in a Maximum call stack size exceeded error in both Chromium and WebKit.)
My intuition is that the spec should probably match Firefox's behavior. It seems sensible for both values and keys to throw because the transaction is not currently active.
Chromium (bug), Gecko (bug), and WebKit (bug) all make transactions inactive during structured serialization of object values. The spec addresses this in the "clone a value" algorithm (see also
structured-clone-transaction-state.any.js).However, the spec does not consider keys, which can be arbitrarily set using the second argument to
put()/add():This unfortunately leads to a discrepancy in browser behavior, as demonstrated by this minimal repro:
Results:
puts succeedputssucceedDOMException: A request was placed against a transaction which is currently not active, or which is finished.(Note that recursive calls result in a
Maximum call stack size exceedederror in both Chromium and WebKit.)My intuition is that the spec should probably match Firefox's behavior. It seems sensible for both values and keys to throw because the transaction is not currently active.