diffing.js (5128B)
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 "use strict"; 5 6 const { 7 immutableUpdate, 8 assert, 9 } = require("resource://devtools/shared/DevToolsUtils.js"); 10 const { 11 actions, 12 diffingState, 13 viewState, 14 } = require("resource://devtools/client/memory/constants.js"); 15 const { 16 snapshotIsDiffable, 17 } = require("resource://devtools/client/memory/utils.js"); 18 19 const handlers = Object.create(null); 20 21 handlers[actions.POP_VIEW] = function (diffing, { previousView }) { 22 if (previousView.state === viewState.DIFFING) { 23 assert(previousView.diffing, "Should have previousView.diffing"); 24 return previousView.diffing; 25 } 26 27 return null; 28 }; 29 30 handlers[actions.CHANGE_VIEW] = function (diffing, { newViewState }) { 31 if (newViewState === viewState.DIFFING) { 32 assert(!diffing, "Should not switch to diffing view when already diffing"); 33 return Object.freeze({ 34 firstSnapshotId: null, 35 secondSnapshotId: null, 36 census: null, 37 state: diffingState.SELECTING, 38 }); 39 } 40 41 return null; 42 }; 43 44 handlers[actions.SELECT_SNAPSHOT_FOR_DIFFING] = function ( 45 diffing, 46 { snapshot } 47 ) { 48 assert( 49 diffing, 50 "Should never select a snapshot for diffing when we aren't diffing " + 51 "anything" 52 ); 53 assert( 54 diffing.state === diffingState.SELECTING, 55 "Can't select when not in SELECTING state" 56 ); 57 assert(snapshotIsDiffable(snapshot), "snapshot must be in a diffable state"); 58 59 if (!diffing.firstSnapshotId) { 60 return immutableUpdate(diffing, { 61 firstSnapshotId: snapshot.id, 62 }); 63 } 64 65 assert( 66 !diffing.secondSnapshotId, 67 "If we aren't selecting the first, then we must be selecting the " + 68 "second" 69 ); 70 71 if (snapshot.id === diffing.firstSnapshotId) { 72 // Ignore requests to select the same snapshot. 73 return diffing; 74 } 75 76 return immutableUpdate(diffing, { 77 secondSnapshotId: snapshot.id, 78 }); 79 }; 80 81 handlers[actions.TAKE_CENSUS_DIFF_START] = function (diffing, action) { 82 assert(diffing, "Should be diffing when starting a census diff"); 83 assert( 84 action.first.id === diffing.firstSnapshotId, 85 "First snapshot's id should match" 86 ); 87 assert( 88 action.second.id === diffing.secondSnapshotId, 89 "Second snapshot's id should match" 90 ); 91 92 return immutableUpdate(diffing, { 93 state: diffingState.TAKING_DIFF, 94 census: { 95 report: null, 96 inverted: action.inverted, 97 filter: action.filter, 98 display: action.display, 99 }, 100 }); 101 }; 102 103 handlers[actions.TAKE_CENSUS_DIFF_END] = function (diffing, action) { 104 assert(diffing, "Should be diffing when ending a census diff"); 105 assert( 106 action.first.id === diffing.firstSnapshotId, 107 "First snapshot's id should match" 108 ); 109 assert( 110 action.second.id === diffing.secondSnapshotId, 111 "Second snapshot's id should match" 112 ); 113 114 return immutableUpdate(diffing, { 115 state: diffingState.TOOK_DIFF, 116 census: { 117 report: action.report, 118 parentMap: action.parentMap, 119 expanded: new Set(), 120 inverted: action.inverted, 121 filter: action.filter, 122 display: action.display, 123 }, 124 }); 125 }; 126 127 handlers[actions.DIFFING_ERROR] = function (diffing, action) { 128 return { 129 state: diffingState.ERROR, 130 error: action.error, 131 }; 132 }; 133 134 handlers[actions.EXPAND_DIFFING_CENSUS_NODE] = function (diffing, { node }) { 135 assert(diffing, "Should be diffing if expanding diffing's census nodes"); 136 assert( 137 diffing.state === diffingState.TOOK_DIFF, 138 "Should have taken the census diff if expanding nodes" 139 ); 140 assert(diffing.census, "Should have a census"); 141 assert(diffing.census.report, "Should have a census report"); 142 assert(diffing.census.expanded, "Should have a census's expanded set"); 143 144 const expanded = new Set(diffing.census.expanded); 145 expanded.add(node.id); 146 const census = immutableUpdate(diffing.census, { expanded }); 147 return immutableUpdate(diffing, { census }); 148 }; 149 150 handlers[actions.COLLAPSE_DIFFING_CENSUS_NODE] = function (diffing, { node }) { 151 assert(diffing, "Should be diffing if expanding diffing's census nodes"); 152 assert( 153 diffing.state === diffingState.TOOK_DIFF, 154 "Should have taken the census diff if expanding nodes" 155 ); 156 assert(diffing.census, "Should have a census"); 157 assert(diffing.census.report, "Should have a census report"); 158 assert(diffing.census.expanded, "Should have a census's expanded set"); 159 160 const expanded = new Set(diffing.census.expanded); 161 expanded.delete(node.id); 162 const census = immutableUpdate(diffing.census, { expanded }); 163 return immutableUpdate(diffing, { census }); 164 }; 165 166 handlers[actions.FOCUS_DIFFING_CENSUS_NODE] = function (diffing, { node }) { 167 assert(diffing, "Should be diffing."); 168 assert(diffing.census, "Should have a census"); 169 const census = immutableUpdate(diffing.census, { focused: node }); 170 return immutableUpdate(diffing, { census }); 171 }; 172 173 module.exports = function (diffing = null, action) { 174 const handler = handlers[action.type]; 175 return handler ? handler(diffing, action) : diffing; 176 };