tenfourfox/devtools/client/memory/actions/diffing.js
Cameron Kaiser c9b2922b70 hello FPR
2017-04-19 00:56:45 -07:00

155 lines
4.8 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { assert, reportException } = require("devtools/shared/DevToolsUtils");
const { actions, diffingState } = require("../constants");
const {
breakdownEquals,
getSnapshot,
censusIsUpToDate,
snapshotIsDiffable
} = require("../utils");
/**
* Toggle diffing mode on or off.
*/
const toggleDiffing = exports.toggleDiffing = function () {
return { type: actions.TOGGLE_DIFFING };
};
/**
* Select the given snapshot for diffing.
*
* @param {snapshotModel} snapshot
*/
const selectSnapshotForDiffing = exports.selectSnapshotForDiffing = function (snapshot) {
assert(snapshotIsDiffable(snapshot),
"To select a snapshot for diffing, it must be diffable");
return { type: actions.SELECT_SNAPSHOT_FOR_DIFFING, snapshot };
};
/**
* Compute the difference between the first and second snapshots.
*
* @param {HeapAnalysesClient} heapWorker
* @param {snapshotModel} first
* @param {snapshotModel} second
*/
const takeCensusDiff = exports.takeCensusDiff = function (heapWorker, first, second) {
return function*(dispatch, getState) {
assert(snapshotIsDiffable(first),
`First snapshot must be in a diffable state, found ${first.state}`);
assert(snapshotIsDiffable(second),
`Second snapshot must be in a diffable state, found ${second.state}`);
let report;
let inverted = getState().inverted;
let breakdown = getState().breakdown;
let filter = getState().filter;
if (censusIsUpToDate(inverted, filter, breakdown, getState().diffing.census)) {
return;
}
do {
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;
}
inverted = getState().inverted;
breakdown = getState().breakdown;
filter = getState().filter;
dispatch({
type: actions.TAKE_CENSUS_DIFF_START,
first,
second,
inverted,
filter,
breakdown,
});
let opts = inverted ? { asInvertedTreeNode: true } : { asTreeNode: true };
opts.filter = filter || null;
try {
report = yield heapWorker.takeCensusDiff(first.path,
second.path,
{ breakdown },
opts);
} catch (error) {
reportException("actions/diffing/takeCensusDiff", error);
dispatch({ type: actions.DIFFING_ERROR, error });
return;
}
}
while (inverted !== getState().inverted
|| filter !== getState().filter
|| !breakdownEquals(breakdown, getState().breakdown));
dispatch({
type: actions.TAKE_CENSUS_DIFF_END,
first,
second,
report,
inverted,
filter,
breakdown,
});
};
};
/**
* Ensure that the current diffing data is up to date with the currently
* selected breakdown, filter, inversion, 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
*/
const selectSnapshotForDiffingAndRefresh = exports.selectSnapshotForDiffingAndRefresh = function (heapWorker, snapshot) {
return function*(dispatch, getState) {
assert(getState().diffing,
"If we are selecting for diffing, we must be in diffing mode");
dispatch(selectSnapshotForDiffing(snapshot));
yield dispatch(refreshDiffing(heapWorker));
};
};