(doc, f, origin = null, local = true)
| 633 | * @function |
| 634 | */ |
| 635 | export const transact = (doc, f, origin = null, local = true) => { |
| 636 | const transactionCleanups = doc._transactionCleanups |
| 637 | let initialCall = false |
| 638 | /** |
| 639 | * @type {any} |
| 640 | */ |
| 641 | let result = null |
| 642 | if (doc._transaction === null) { |
| 643 | initialCall = true |
| 644 | doc._transaction = new Transaction(doc, origin, local) |
| 645 | transactionCleanups.push(doc._transaction) |
| 646 | if (transactionCleanups.length === 1) { |
| 647 | doc.emit('beforeAllTransactions', [doc]) |
| 648 | } |
| 649 | doc.emit('beforeTransaction', [doc._transaction, doc]) |
| 650 | } |
| 651 | try { |
| 652 | result = f(doc._transaction) |
| 653 | } finally { |
| 654 | if (initialCall) { |
| 655 | const finishCleanup = doc._transaction === transactionCleanups[0] |
| 656 | doc._transaction = null |
| 657 | if (finishCleanup) { |
| 658 | // The first transaction ended, now process observer calls. |
| 659 | // Observer call may create new transactions for which we need to call the observers and do cleanup. |
| 660 | // We don't want to nest these calls, so we execute these calls one after |
| 661 | // another. |
| 662 | // Also we need to ensure that all cleanups are called, even if the |
| 663 | // observes throw errors. |
| 664 | // This file is full of hacky try {} finally {} blocks to ensure that an |
| 665 | // event can throw errors and also that the cleanup is called. |
| 666 | cleanupTransactions(transactionCleanups, 0) |
| 667 | } |
| 668 | } |
| 669 | } |
| 670 | return result |
| 671 | } |
no test coverage detected
searching dependent graphs…