function recomputeStates(computedStates, minInvalidatedStateIndex, reducer, committedState, actionsById, stagedActionIds, skippedActionIds, shouldCatchErrors) {
	  // Optimization: exit early and return the same reference
	  // if we know nothing could have changed.
	  if (!computedStates || minInvalidatedStateIndex === -1 || minInvalidatedStateIndex >= computedStates.length && computedStates.length === stagedActionIds.length) {
	    return computedStates;
	  }

	  var nextComputedStates = computedStates.slice(0, minInvalidatedStateIndex);
	  for (var i = minInvalidatedStateIndex; i < stagedActionIds.length; i++) {
	    var actionId = stagedActionIds[i];
	    var action = actionsById[actionId].action;

	    var previousEntry = nextComputedStates[i - 1];
	    var previousState = previousEntry ? previousEntry.state : committedState;

	    var shouldSkip = skippedActionIds.indexOf(actionId) > -1;
	    var entry = void 0;
	    if (shouldSkip) {
	      entry = previousEntry;
	    } else {
	      if (shouldCatchErrors && previousEntry && previousEntry.error) {
	        entry = {
	          state: previousState,
	          error: 'Interrupted by an error up the chain'
	        };
	      } else {
	        entry = computeNextEntry(reducer, action, previousState, shouldCatchErrors);
	      }
	    }
	    nextComputedStates.push(entry);
	  }

	  return nextComputedStates;
	}
Runs the reducer on invalidated actions to get a fresh computation log.