if ( !getState().diffing || getState().diffing.firstSnapshotId !== first.id || getState().diffing.secondSnapshotId !== second.id ) { // If we stopped diffing or stopped and then started diffing a different // pair of snapshots, then just give up with diffing this pair. In the // latter case, a newly spawned task will handle the diffing for the new // pair. return; } display = getState().censusDisplay; filter = getState().filter; dispatch({ type: actions.TAKE_CENSUS_DIFF_START, first, second, filter, display, }); const opts = display.inverted ? { asInvertedTreeNode: true } : { asTreeNode: true }; opts.filter = filter || null; try { ({ delta: report, parentMap } = await heapWorker.takeCensusDiff( first.path, second.path, { breakdown: display.breakdown }, opts )); } catch (error) { reportException("actions/diffing/takeCensusDiff", error); dispatch({ type: actions.DIFFING_ERROR, error }); return; } } while ( filter !== getState().filter || display !== getState().censusDisplay ); dispatch({ type: actions.TAKE_CENSUS_DIFF_END, first, second, report, parentMap, filter, display, }); }; }); /** * Ensure that the current diffing data is up to date with the currently * selected display, filter, etc. If the state is not up-to-date, then a * recompute is triggered. * * @param {HeapAnalysesClient} heapWorker */ const refreshDiffing = (exports.refreshDiffing = function (heapWorker) { return function ({ dispatch, getState }) { if (getState().diffing.secondSnapshotId === null) { return; } assert(getState().diffing.firstSnapshotId, "Should have first snapshot id"); if (getState().diffing.state === diffingState.TAKING_DIFF) { // There is an existing task that will ensure that the diffing data is // up-to-date. return; } const { firstSnapshotId, secondSnapshotId } = getState().diffing; const first = getSnapshot(getState(), firstSnapshotId); const second = getSnapshot(getState(), secondSnapshotId); dispatch(takeCensusDiff(heapWorker, first, second)); }; }); /** * Select the given snapshot for diffing and refresh the diffing data if * necessary (for example, if two snapshots are now selected for diffing). * * @param {HeapAnalysesClient} heapWorker * @param {snapshotModel} snapshot */ exports.selectSnapshotForDiffingAndRefresh = function (heapWorker, snapshot) { return async function ({ dispatch, getState }) { assert( getState().diffing, "If we are selecting for diffing, we must be in diffing mode" ); dispatch(selectSnapshotForDiffing(snapshot)); await dispatch(refreshDiffing(heapWorker)); }; }; /** * Expand the given node in the diffing's census's delta-report. * * @param {CensusTreeNode} node */ exports.expandDiffingCensusNode = function (node) { return { type: actions.EXPAND_DIFFING_CENSUS_NODE, node, }; }; /** * Collapse the given node in the diffing's census's delta-report. * * @param {CensusTreeNode} node */ exports.collapseDiffingCensusNode = function (node) { return { type: actions.COLLAPSE_DIFFING_CENSUS_NODE, node, }; }; /** * Focus the given node in the snapshot's census's report. * * @param {DominatorTreeNode} node */ exports.focusDiffingCensusNode = function (node) { return { type: actions.FOCUS_DIFFING_CENSUS_NODE, node, }; }; PK