summaryrefslogtreecommitdiffstats
path: root/devtools/client/memory/reducers/diffing.js
blob: 6d4973c8e995b28a84ff20764dc925516868c04e (plain)
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* 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 Immutable = require("devtools/client/shared/vendor/immutable");
const { immutableUpdate, assert } = require("devtools/shared/DevToolsUtils");
const { actions, diffingState, viewState } = require("../constants");
const { snapshotIsDiffable } = require("../utils");

const handlers = Object.create(null);

handlers[actions.POP_VIEW] = function (diffing, { previousView }) {
  if (previousView.state === viewState.DIFFING) {
    assert(previousView.diffing, "Should have previousView.diffing");
    return previousView.diffing;
  }

  return null;
};

handlers[actions.CHANGE_VIEW] = function (diffing, { newViewState }) {
  if (newViewState === viewState.DIFFING) {
    assert(!diffing, "Should not switch to diffing view when already diffing");
    return Object.freeze({
      firstSnapshotId: null,
      secondSnapshotId: null,
      census: null,
      state: diffingState.SELECTING,
    });
  }

  return null;
};

handlers[actions.SELECT_SNAPSHOT_FOR_DIFFING] = function (diffing, { snapshot }) {
  assert(diffing,
         "Should never select a snapshot for diffing when we aren't diffing " +
         "anything");
  assert(diffing.state === diffingState.SELECTING,
         "Can't select when not in SELECTING state");
  assert(snapshotIsDiffable(snapshot),
         "snapshot must be in a diffable state");

  if (!diffing.firstSnapshotId) {
    return immutableUpdate(diffing, {
      firstSnapshotId: snapshot.id
    });
  }

  assert(!diffing.secondSnapshotId,
         "If we aren't selecting the first, then we must be selecting the " +
         "second");

  if (snapshot.id === diffing.firstSnapshotId) {
    // Ignore requests to select the same snapshot.
    return diffing;
  }

  return immutableUpdate(diffing, {
    secondSnapshotId: snapshot.id
  });
};

handlers[actions.TAKE_CENSUS_DIFF_START] = function (diffing, action) {
  assert(diffing, "Should be diffing when starting a census diff");
  assert(action.first.id === diffing.firstSnapshotId,
         "First snapshot's id should match");
  assert(action.second.id === diffing.secondSnapshotId,
         "Second snapshot's id should match");

  return immutableUpdate(diffing, {
    state: diffingState.TAKING_DIFF,
    census: {
      report: null,
      inverted: action.inverted,
      filter: action.filter,
      display: action.display,
    }
  });
};

handlers[actions.TAKE_CENSUS_DIFF_END] = function (diffing, action) {
  assert(diffing, "Should be diffing when ending a census diff");
  assert(action.first.id === diffing.firstSnapshotId,
         "First snapshot's id should match");
  assert(action.second.id === diffing.secondSnapshotId,
         "Second snapshot's id should match");

  return immutableUpdate(diffing, {
    state: diffingState.TOOK_DIFF,
    census: {
      report: action.report,
      parentMap: action.parentMap,
      expanded: Immutable.Set(),
      inverted: action.inverted,
      filter: action.filter,
      display: action.display,
    }
  });
};

handlers[actions.DIFFING_ERROR] = function (diffing, action) {
  return {
    state: diffingState.ERROR,
    error: action.error
  };
};

handlers[actions.EXPAND_DIFFING_CENSUS_NODE] = function (diffing, { node }) {
  assert(diffing, "Should be diffing if expanding diffing's census nodes");
  assert(diffing.state === diffingState.TOOK_DIFF,
         "Should have taken the census diff if expanding nodes");
  assert(diffing.census, "Should have a census");
  assert(diffing.census.report, "Should have a census report");
  assert(diffing.census.expanded, "Should have a census's expanded set");

  const expanded = diffing.census.expanded.add(node.id);
  const census = immutableUpdate(diffing.census, { expanded });
  return immutableUpdate(diffing, { census });
};

handlers[actions.COLLAPSE_DIFFING_CENSUS_NODE] = function (diffing, { node }) {
  assert(diffing, "Should be diffing if expanding diffing's census nodes");
  assert(diffing.state === diffingState.TOOK_DIFF,
         "Should have taken the census diff if expanding nodes");
  assert(diffing.census, "Should have a census");
  assert(diffing.census.report, "Should have a census report");
  assert(diffing.census.expanded, "Should have a census's expanded set");

  const expanded = diffing.census.expanded.delete(node.id);
  const census = immutableUpdate(diffing.census, { expanded });
  return immutableUpdate(diffing, { census });
};

handlers[actions.FOCUS_DIFFING_CENSUS_NODE] = function (diffing, { node }) {
  assert(diffing, "Should be diffing.");
  assert(diffing.census, "Should have a census");
  const census = immutableUpdate(diffing.census, { focused: node });
  return immutableUpdate(diffing, { census });
};

module.exports = function (diffing = null, action) {
  const handler = handlers[action.type];
  return handler ? handler(diffing, action) : diffing;
};