message: Address re-entrancy when playing ops
  When callback is called, we immediately process op synchronously, resulting in re-entrancy and eventually running out of stack (if processing too many ops).
  This problem was avoided in old code path due to using continuations.
diff: @@ -114,6 +114,9 @@ export class DeltaQueue<T> extends EventEmitter implements IDeltaQueue<T> {
  }
  private processDeltas() {
  + // For grouping to work we must process all local messages immediately and in the single turn.
  + // So loop over them until one of the conditions below is false.
  + while (true) {
  // Return early if no messages to process, we have become paused, or are already processing a delta
  if (this.q.length === 0 || this._paused || this.processing || this.error) {
  return;
  @@ -123,7 +126,11 @@ export class DeltaQueue<T> extends EventEmitter implements IDeltaQueue<T> {
  this.processing = true;
  const next = this.q.shift();
  this.emit("pre-op", next);
  - this.worker(next!, (error) => {
  +
  + // Track when callback is called - whether it is called asynchronously or not.
  + let async = false;
  +
  + const callback = (error) => {
  this.processing = false;
  // Signal any pending messages
  @@ -142,8 +149,23 @@ export class DeltaQueue<T> extends EventEmitter implements IDeltaQueue<T> {
  this.q.clear();
  } else {
  this.emit("op", next);
  + // If this callback is called asynchronously, then kick processing of new task
  + // Otherwise (when called synchronously) doing so would result in re-entrancy and stack overflow.
  + // So for synchronously called callback we do nothing here and rely on the loop in processDeltas()
  + // itself to process next message.
  + if (async) {
  this.processDeltas();
  }
  - });
  + }
  + };
  +
  + this.worker(next!, callback);
  +
  + // If callback was not called yet, let it know it is called asynchronously.
  + // In such case loop will terminate, because this.processing is still true and we will kick next task
  + // whenever callback is called.
  + // Otherwise looping over will execute next task.
  + async = true;
  + }
  }
  }
  