allow transactions within event handlers having different origins

This commit is contained in:
Kevin Jahns 2022-11-30 12:09:19 +01:00
parent cac9407185
commit 3ece681758
3 changed files with 40 additions and 12 deletions

View File

@ -1064,7 +1064,7 @@ export class YText extends AbstractType {
n = n.right n = n.right
} }
packStr() packStr()
}, splitSnapshotAffectedStructs) }, 'cleanup')
return ops return ops
} }

View File

@ -251,7 +251,6 @@ const cleanupTransactions = (transactionCleanups, i) => {
try { try {
sortAndMergeDeleteSet(ds) sortAndMergeDeleteSet(ds)
transaction.afterState = getStateVector(transaction.doc.store) transaction.afterState = getStateVector(transaction.doc.store)
doc._transaction = null
doc.emit('beforeObserverCalls', [transaction, doc]) doc.emit('beforeObserverCalls', [transaction, doc])
/** /**
* An array of event callbacks. * An array of event callbacks.
@ -398,16 +397,20 @@ export const transact = (doc, f, origin = null, local = true) => {
try { try {
f(doc._transaction) f(doc._transaction)
} finally { } finally {
if (initialCall && transactionCleanups[0] === doc._transaction) { if (initialCall) {
// The first transaction ended, now process observer calls. const finishCleanup = doc._transaction === transactionCleanups[0]
// Observer call may create new transactions for which we need to call the observers and do cleanup. doc._transaction = null
// We don't want to nest these calls, so we execute these calls one after if (finishCleanup) {
// another. // The first transaction ended, now process observer calls.
// Also we need to ensure that all cleanups are called, even if the // Observer call may create new transactions for which we need to call the observers and do cleanup.
// observes throw errors. // We don't want to nest these calls, so we execute these calls one after
// This file is full of hacky try {} finally {} blocks to ensure that an // another.
// event can throw errors and also that the cleanup is called. // Also we need to ensure that all cleanups are called, even if the
cleanupTransactions(transactionCleanups, 0) // observes throw errors.
// This file is full of hacky try {} finally {} blocks to ensure that an
// event can throw errors and also that the cleanup is called.
cleanupTransactions(transactionCleanups, 0)
}
} }
} }
} }

View File

@ -2,6 +2,31 @@
import * as Y from '../src/index.js' import * as Y from '../src/index.js'
import * as t from 'lib0/testing' import * as t from 'lib0/testing'
/**
* @param {t.TestCase} _tc
*/
export const testOriginInTransaction = _tc => {
const doc = new Y.Doc()
const ytext = doc.getText()
/**
* @type {Array<string>}
*/
const origins = []
doc.on('afterTransaction', (tr) => {
origins.push(tr.origin)
if (origins.length <= 1) {
ytext.toDelta()
doc.transact(() => {
ytext.insert(0, 'a')
}, 'nested')
}
})
doc.transact(() => {
ytext.insert(0, '0')
}, 'first')
t.compareArrays(origins, ['first', 'cleanup', 'nested'])
}
/** /**
* Client id should be changed when an instance receives updates from another client using the same client id. * Client id should be changed when an instance receives updates from another client using the same client id.
* *