operation_group.js (2154B)
1 import { getHandlers } from "./event.js" 2 3 let operationGroup = null 4 5 export function pushOperation(op) { 6 if (operationGroup) { 7 operationGroup.ops.push(op) 8 } else { 9 op.ownsGroup = operationGroup = { 10 ops: [op], 11 delayedCallbacks: [] 12 } 13 } 14 } 15 16 function fireCallbacksForOps(group) { 17 // Calls delayed callbacks and cursorActivity handlers until no 18 // new ones appear 19 let callbacks = group.delayedCallbacks, i = 0 20 do { 21 for (; i < callbacks.length; i++) 22 callbacks[i].call(null) 23 for (let j = 0; j < group.ops.length; j++) { 24 let op = group.ops[j] 25 if (op.cursorActivityHandlers) 26 while (op.cursorActivityCalled < op.cursorActivityHandlers.length) 27 op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm) 28 } 29 } while (i < callbacks.length) 30 } 31 32 export function finishOperation(op, endCb) { 33 let group = op.ownsGroup 34 if (!group) return 35 36 try { fireCallbacksForOps(group) } 37 finally { 38 operationGroup = null 39 endCb(group) 40 } 41 } 42 43 let orphanDelayedCallbacks = null 44 45 // Often, we want to signal events at a point where we are in the 46 // middle of some work, but don't want the handler to start calling 47 // other methods on the editor, which might be in an inconsistent 48 // state or simply not expect any other events to happen. 49 // signalLater looks whether there are any handlers, and schedules 50 // them to be executed when the last operation ends, or, if no 51 // operation is active, when a timeout fires. 52 export function signalLater(emitter, type /*, values...*/) { 53 let arr = getHandlers(emitter, type) 54 if (!arr.length) return 55 let args = Array.prototype.slice.call(arguments, 2), list 56 if (operationGroup) { 57 list = operationGroup.delayedCallbacks 58 } else if (orphanDelayedCallbacks) { 59 list = orphanDelayedCallbacks 60 } else { 61 list = orphanDelayedCallbacks = [] 62 setTimeout(fireOrphanDelayed, 0) 63 } 64 for (let i = 0; i < arr.length; ++i) 65 list.push(() => arr[i].apply(null, args)) 66 } 67 68 function fireOrphanDelayed() { 69 let delayed = orphanDelayedCallbacks 70 orphanDelayedCallbacks = null 71 for (let i = 0; i < delayed.length; ++i) delayed[i]() 72 }