dead5cd581a5343df7538b5ddd112ef5524303c354732e2213b70753267272b41d77d4d02e56d6bd606b78f8cf5cf75e5ff5bb3bcc92a1e2163767f6babda2 2.1 KB

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