tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

diffing.js (5786B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 const {
      8  assert,
      9  reportException,
     10 } = require("resource://devtools/shared/DevToolsUtils.js");
     11 const {
     12  actions,
     13  diffingState,
     14  viewState,
     15 } = require("resource://devtools/client/memory/constants.js");
     16 const {
     17  getSnapshot,
     18  censusIsUpToDate,
     19  snapshotIsDiffable,
     20  findSelectedSnapshot,
     21 } = require("resource://devtools/client/memory/utils.js");
     22 
     23 /**
     24 * Toggle diffing mode on or off.
     25 */
     26 exports.toggleDiffing = function () {
     27  return function ({ dispatch, getState }) {
     28    dispatch({
     29      type: actions.CHANGE_VIEW,
     30      newViewState: getState().diffing ? viewState.CENSUS : viewState.DIFFING,
     31      oldDiffing: getState().diffing,
     32      oldSelected: findSelectedSnapshot(getState()),
     33    });
     34  };
     35 };
     36 
     37 /**
     38 * Select the given snapshot for diffing.
     39 *
     40 * @param {snapshotModel} snapshot
     41 */
     42 const selectSnapshotForDiffing = (exports.selectSnapshotForDiffing = function (
     43  snapshot
     44 ) {
     45  assert(
     46    snapshotIsDiffable(snapshot),
     47    "To select a snapshot for diffing, it must be diffable"
     48  );
     49  return { type: actions.SELECT_SNAPSHOT_FOR_DIFFING, snapshot };
     50 });
     51 
     52 /**
     53 * Compute the difference between the first and second snapshots.
     54 *
     55 * @param {HeapAnalysesClient} heapWorker
     56 * @param {snapshotModel} first
     57 * @param {snapshotModel} second
     58 */
     59 const takeCensusDiff = (exports.takeCensusDiff = function (
     60  heapWorker,
     61  first,
     62  second
     63 ) {
     64  return async function ({ dispatch, getState }) {
     65    assert(
     66      snapshotIsDiffable(first),
     67      `First snapshot must be in a diffable state, found ${first.state}`
     68    );
     69    assert(
     70      snapshotIsDiffable(second),
     71      `Second snapshot must be in a diffable state, found ${second.state}`
     72    );
     73 
     74    let report, parentMap;
     75    let display = getState().censusDisplay;
     76    let filter = getState().filter;
     77 
     78    if (censusIsUpToDate(filter, display, getState().diffing.census)) {
     79      return;
     80    }
     81 
     82    do {
     83      if (
     84        !getState().diffing ||
     85        getState().diffing.firstSnapshotId !== first.id ||
     86        getState().diffing.secondSnapshotId !== second.id
     87      ) {
     88        // If we stopped diffing or stopped and then started diffing a different
     89        // pair of snapshots, then just give up with diffing this pair. In the
     90        // latter case, a newly spawned task will handle the diffing for the new
     91        // pair.
     92        return;
     93      }
     94 
     95      display = getState().censusDisplay;
     96      filter = getState().filter;
     97 
     98      dispatch({
     99        type: actions.TAKE_CENSUS_DIFF_START,
    100        first,
    101        second,
    102        filter,
    103        display,
    104      });
    105 
    106      const opts = display.inverted
    107        ? { asInvertedTreeNode: true }
    108        : { asTreeNode: true };
    109      opts.filter = filter || null;
    110 
    111      try {
    112        ({ delta: report, parentMap } = await heapWorker.takeCensusDiff(
    113          first.path,
    114          second.path,
    115          { breakdown: display.breakdown },
    116          opts
    117        ));
    118      } catch (error) {
    119        reportException("actions/diffing/takeCensusDiff", error);
    120        dispatch({ type: actions.DIFFING_ERROR, error });
    121        return;
    122      }
    123    } while (
    124      filter !== getState().filter ||
    125      display !== getState().censusDisplay
    126    );
    127 
    128    dispatch({
    129      type: actions.TAKE_CENSUS_DIFF_END,
    130      first,
    131      second,
    132      report,
    133      parentMap,
    134      filter,
    135      display,
    136    });
    137  };
    138 });
    139 
    140 /**
    141 * Ensure that the current diffing data is up to date with the currently
    142 * selected display, filter, etc. If the state is not up-to-date, then a
    143 * recompute is triggered.
    144 *
    145 * @param {HeapAnalysesClient} heapWorker
    146 */
    147 const refreshDiffing = (exports.refreshDiffing = function (heapWorker) {
    148  return function ({ dispatch, getState }) {
    149    if (getState().diffing.secondSnapshotId === null) {
    150      return;
    151    }
    152 
    153    assert(getState().diffing.firstSnapshotId, "Should have first snapshot id");
    154 
    155    if (getState().diffing.state === diffingState.TAKING_DIFF) {
    156      // There is an existing task that will ensure that the diffing data is
    157      // up-to-date.
    158      return;
    159    }
    160 
    161    const { firstSnapshotId, secondSnapshotId } = getState().diffing;
    162 
    163    const first = getSnapshot(getState(), firstSnapshotId);
    164    const second = getSnapshot(getState(), secondSnapshotId);
    165    dispatch(takeCensusDiff(heapWorker, first, second));
    166  };
    167 });
    168 
    169 /**
    170 * Select the given snapshot for diffing and refresh the diffing data if
    171 * necessary (for example, if two snapshots are now selected for diffing).
    172 *
    173 * @param {HeapAnalysesClient} heapWorker
    174 * @param {snapshotModel} snapshot
    175 */
    176 exports.selectSnapshotForDiffingAndRefresh = function (heapWorker, snapshot) {
    177  return async function ({ dispatch, getState }) {
    178    assert(
    179      getState().diffing,
    180      "If we are selecting for diffing, we must be in diffing mode"
    181    );
    182    dispatch(selectSnapshotForDiffing(snapshot));
    183    await dispatch(refreshDiffing(heapWorker));
    184  };
    185 };
    186 
    187 /**
    188 * Expand the given node in the diffing's census's delta-report.
    189 *
    190 * @param {CensusTreeNode} node
    191 */
    192 exports.expandDiffingCensusNode = function (node) {
    193  return {
    194    type: actions.EXPAND_DIFFING_CENSUS_NODE,
    195    node,
    196  };
    197 };
    198 
    199 /**
    200 * Collapse the given node in the diffing's census's delta-report.
    201 *
    202 * @param {CensusTreeNode} node
    203 */
    204 exports.collapseDiffingCensusNode = function (node) {
    205  return {
    206    type: actions.COLLAPSE_DIFFING_CENSUS_NODE,
    207    node,
    208  };
    209 };
    210 
    211 /**
    212 * Focus the given node in the snapshot's census's report.
    213 *
    214 * @param {DominatorTreeNode} node
    215 */
    216 exports.focusDiffingCensusNode = function (node) {
    217  return {
    218    type: actions.FOCUS_DIFFING_CENSUS_NODE,
    219    node,
    220  };
    221 };