diff --git a/src/types/YText.js b/src/types/YText.js index 68a052c1..6f05b6d0 100644 --- a/src/types/YText.js +++ b/src/types/YText.js @@ -1018,15 +1018,7 @@ export class YText extends AbstractType { str = '' } } - // snapshots are merged again after the transaction, so we need to keep the - // transalive until we are done - transact(doc, transaction => { - if (snapshot) { - splitSnapshotAffectedStructs(transaction, snapshot) - } - if (prevSnapshot) { - splitSnapshotAffectedStructs(transaction, prevSnapshot) - } + const computeDelta = () => { while (n !== null) { if (isVisible(n, snapshot) || (prevSnapshot !== undefined && isVisible(n, prevSnapshot))) { switch (n.content.constructor) { @@ -1079,7 +1071,22 @@ export class YText extends AbstractType { n = n.right } packStr() - }, 'cleanup') + } + if (snapshot || prevSnapshot) { + // snapshots are merged again after the transaction, so we need to keep the + // transaction alive until we are done + transact(doc, transaction => { + if (snapshot) { + splitSnapshotAffectedStructs(transaction, snapshot) + } + if (prevSnapshot) { + splitSnapshotAffectedStructs(transaction, prevSnapshot) + } + computeDelta() + }, 'cleanup') + } else { + computeDelta() + } return ops } diff --git a/src/types/YXmlFragment.js b/src/types/YXmlFragment.js index 06b1c0de..b229a4ac 100644 --- a/src/types/YXmlFragment.js +++ b/src/types/YXmlFragment.js @@ -257,8 +257,7 @@ export class YXmlFragment extends AbstractType { * @return {string} The string representation of all children. */ toString () { - // toString can result in many cleanup transactions. We wrap all cleanup transactions here to reduce the work - return transact(/** @type {Doc} */ (this.doc), () => typeListMap(this, xml => xml.toString()).join('')) + return typeListMap(this, xml => xml.toString()).join('') } /** diff --git a/src/utils/Doc.js b/src/utils/Doc.js index 9588d362..d07dd56e 100644 --- a/src/utils/Doc.js +++ b/src/utils/Doc.js @@ -156,13 +156,15 @@ export class Doc extends Observable { * that happened inside of the transaction are sent as one message to the * other peers. * - * @param {function(Transaction):void} f The function that should be executed as a transaction + * @template T + * @param {function(Transaction):T} f The function that should be executed as a transaction * @param {any} [origin] Origin of who started the transaction. Will be stored on transaction.origin + * @return T * * @public */ transact (f, origin = null) { - transact(this, f, origin) + return transact(this, f, origin) } /** diff --git a/tests/doc.tests.js b/tests/doc.tests.js index e2910a1f..60524936 100644 --- a/tests/doc.tests.js +++ b/tests/doc.tests.js @@ -33,7 +33,7 @@ export const testOriginInTransaction = _tc => { doc.on('afterTransaction', (tr) => { origins.push(tr.origin) if (origins.length <= 1) { - ytext.toDelta() + ytext.toDelta(Y.snapshot(doc)) // adding a snapshot forces toDelta to create a cleanup transaction doc.transact(() => { ytext.insert(0, 'a') }, 'nested')