All files abort.js

100% Statements 84/84
97.22% Branches 35/36
100% Functions 11/11
100% Lines 84/84

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 859x 9x 9x 9x 9x 105x 105x 105x 105x 105x 105x 169x 105x 105x 165x 165x 105x 105x 105x 105x 105x 11x 10x 10x 10x 10x 10x 11x 2x 2x 2x 1x 1x 2x 11x 7x 7x 7x 1x 1x 7x 105x 105x 105x 9x 9x 9x 369x 369x 2x 2x 2x 168x 168x 7x 7x 7x 168x 173x 167x 167x 165x 165x 167x 167x 1x 1x 1x 369x 9x 9x 9x 101x 101x 101x 101x 101x 101x 101x 101x 101x 101x 101x 101x  
// The mini program runtime has no AbortController. createAbortController returns an object with the
// same shape (signal.aborted, signal.addEventListener('abort', fn), abort(reason)). Any standard
// AbortSignal is accepted as well.
 
export function createAbortController() {
  const listeners = [];
  const signal = {
    aborted: false,
    reason: undefined,
    onabort: null,
    addEventListener(type, fn) {
      if (type === 'abort' && typeof fn === 'function' && listeners.indexOf(fn) < 0) listeners.push(fn);
    },
    removeEventListener(type, fn) {
      const i = listeners.indexOf(fn);
      if (type === 'abort' && i >= 0) listeners.splice(i, 1);
    },
  };
  return {
    signal,
    abort(reason) {
      if (signal.aborted) return;
      signal.aborted = true;
      signal.reason = reason;
      const event = { type: 'abort' };
      const all = listeners.slice();
      listeners.length = 0;
      if (typeof signal.onabort === 'function') {
        try {
          signal.onabort(event);
        } catch (e) {
          // listener errors do not stop the abort
        }
      }
      for (let i = 0; i < all.length; i++) {
        try {
          all[i](event);
        } catch (e) {
          // listener errors do not stop the abort
        }
      }
    },
  };
}
 
/** Subscribes to abort of any signal shape. Returns the unsubscribe function. */
export function onAbort(signal, fn) {
  if (!signal || typeof signal !== 'object') return () => {};
  if (signal.aborted) {
    fn();
    return () => {};
  }
  let done = false;
  const handler = () => {
    if (done) return;
    done = true;
    fn();
  };
  if (typeof signal.addEventListener === 'function') {
    signal.addEventListener('abort', handler);
    return () => {
      done = true;
      if (typeof signal.removeEventListener === 'function') signal.removeEventListener('abort', handler);
    };
  }
  return () => {
    done = true;
  };
}
 
/** Signal that aborts when either input signal aborts. */
export function linkSignals(a, b) {
  const ctl = createAbortController();
  const offA = onAbort(a, () => ctl.abort(a && a.reason));
  const offB = onAbort(b, () => ctl.abort(b && b.reason));
  return {
    signal: ctl.signal,
    abort: (r) => ctl.abort(r),
    dispose() {
      offA();
      offB();
    },
  };
}