# All files / lib/tasks schedule.js

92.59% Statements 75/81
81.81% Branches 9/11
100% Functions 1/1
92.59% Lines 75/81

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
    822x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    235x
    235x
    235x
    235x
    235x
    235x
    235x
    244x
    244x
    244x
    244x
    244x
    244x
    244x
    238x
    238x
    244x
    244x
    244x
    244x
    244x
    1x
    244x
    244x
    244x
    244x

    235x
    235x
    235x
    235x
    235x
    235x
    235x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    6x
    229x
    229x
    229x
    229x
    229x
    229x
    235x
     import { StateCache } from '../util/types';
    import Transaction from '../transaction';

    /**
     * If diffHTML is rendering anywhere asynchronously, we need to wait until it
     * completes before this render can be executed. This sets up the next
     * buffer, if necessary, which serves as a Boolean determination later to
     * `bufferSet`.
     *
     * @param {Transaction} transaction
     * @return {Promise<Boolean> | void}
     */
    export default function schedule(transaction) {
      // The state is a global store which is shared by all like-transactions.
      let { state, state: { isRendering } } = transaction;

      state.measure('schedule');

      // Loop through all existing mounts to ensure we properly wait.
      StateCache.forEach(val => {
        const oldMount = /** @type {HTMLElement} */ (
          val.activeTransaction && val.activeTransaction.mount
        );
        const newMount = /** @type {HTMLElement} */ (transaction.mount);

        // Only consider transactions that have mounts and are rendering.
        if (!oldMount || !newMount || !val.isRendering) {
          return;
        }

        // If the new mount point exists within an existing point that is rendering,
        // then wait for that transaction to finish.
        else if (
          oldMount.contains && oldMount.contains(newMount) ||
          newMount.contains && newMount.contains(oldMount)
        ) {
          state = val;
          isRendering = true;
        }
        // Test if the active transaction is the same as the incoming by looking at
        // the mount. Then look and see if the state is rendering.
        else if (oldMount === newMount) {
          state = val;
          isRendering = true;
        }
      });

      const { activeTransaction, nextTransaction } = state;

      // If there is an in-flight transaction render happening, push this
      // transaction into a queue.
      if (isRendering) {
        const { tasks } = transaction;

        // Pave over the `nextTransaction` to chain off the previous.
        state.nextTransaction = transaction;

        // Abort the remaining tasks (but do not signal completion).
        transaction.abort();

        const promise = nextTransaction && nextTransaction.promise || activeTransaction.promise || Promise.resolve();

        return transaction.promise = promise.then(() => {
          // Mark the transaction as not aborted (we are running it now). This
          // triggers a nested render.
          transaction.aborted = false;
          transaction.state.isRendering = true;
          transaction.state.activeTransaction = transaction;

          state.measure('schedule');

          return Transaction.flow(transaction, tasks.slice(1));
        });
      }

      // Indicate we are now rendering a transaction for this DOM Node.
      state.isRendering = true;
      state.activeTransaction = transaction;

      state.measure('schedule');
    }