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 110x 110x 110x 110x 110x 110x 174x 110x 110x 170x 170x 110x 110x 110x 110x 110x 11x 10x 10x 10x 10x 10x 11x 2x 2x 2x 1x 1x 2x 11x 7x 7x 7x 1x 1x 7x 110x 110x 110x 9x 9x 9x 384x 384x 2x 2x 2x 173x 173x 7x 7x 7x 173x 178x 172x 172x 170x 170x 172x 172x 1x 1x 1x 384x 9x 9x 9x 106x 106x 106x 106x 106x 106x 106x 106x 106x 106x 106x 106x  
// 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();
    },
  };
}