store.js (5728B)
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 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 "use strict"; 5 6 // State 7 const { 8 FilterState, 9 } = require("resource://devtools/client/webconsole/reducers/filters.js"); 10 const { 11 PrefState, 12 } = require("resource://devtools/client/webconsole/reducers/prefs.js"); 13 const { 14 UiState, 15 } = require("resource://devtools/client/webconsole/reducers/ui.js"); 16 17 // Redux 18 const { 19 applyMiddleware, 20 compose, 21 createStore, 22 } = require("resource://devtools/client/shared/vendor/redux.js"); 23 24 // Prefs 25 const { PREFS } = require("resource://devtools/client/webconsole/constants.js"); 26 const { 27 getPrefsService, 28 } = require("resource://devtools/client/webconsole/utils/prefs.js"); 29 30 // Reducers 31 const { 32 reducers, 33 } = require("resource://devtools/client/webconsole/reducers/index.js"); 34 35 // Middlewares 36 const { 37 ignore, 38 } = require("resource://devtools/client/shared/redux/middleware/ignore.js"); 39 const eventTelemetry = require("resource://devtools/client/webconsole/middleware/event-telemetry.js"); 40 const historyPersistence = require("resource://devtools/client/webconsole/middleware/history-persistence.js"); 41 const performanceMarker = require("resource://devtools/client/webconsole/middleware/performance-marker.js"); 42 const { 43 thunk, 44 } = require("resource://devtools/client/shared/redux/middleware/thunk.js"); 45 const { 46 visibilityHandlerStore, 47 } = require("resource://devtools/client/shared/redux/visibilityHandlerStore.js"); 48 49 // Enhancers 50 const enableBatching = require("resource://devtools/client/webconsole/enhancers/batching.js"); 51 const enableActorReleaser = require("resource://devtools/client/webconsole/enhancers/actor-releaser.js"); 52 const enableMessagesCacheClearing = require("resource://devtools/client/webconsole/enhancers/message-cache-clearing.js"); 53 54 /** 55 * Create and configure store for the Console panel. This is the place 56 * where various enhancers and middleware can be registered. 57 */ 58 function configureStore(webConsoleUI, options = {}) { 59 const prefsService = getPrefsService(webConsoleUI); 60 const { getBoolPref, getIntPref } = prefsService; 61 62 const logLimit = 63 options.logLimit || Math.max(getIntPref("devtools.hud.loglimit"), 1); 64 const sidebarToggle = getBoolPref(PREFS.FEATURES.SIDEBAR_TOGGLE); 65 const autocomplete = getBoolPref(PREFS.FEATURES.AUTOCOMPLETE); 66 const eagerEvaluation = getBoolPref(PREFS.FEATURES.EAGER_EVALUATION); 67 const groupSimilar = getBoolPref(PREFS.FEATURES.GROUP_SIMILAR_MESSAGES); 68 const historyCount = getIntPref(PREFS.UI.INPUT_HISTORY_COUNT); 69 70 const initialState = { 71 prefs: PrefState({ 72 logLimit, 73 sidebarToggle, 74 autocomplete, 75 eagerEvaluation, 76 historyCount, 77 groupSimilar, 78 }), 79 filters: FilterState({ 80 error: getBoolPref(PREFS.FILTER.ERROR), 81 warn: getBoolPref(PREFS.FILTER.WARN), 82 info: getBoolPref(PREFS.FILTER.INFO), 83 debug: getBoolPref(PREFS.FILTER.DEBUG), 84 log: getBoolPref(PREFS.FILTER.LOG), 85 css: getBoolPref(PREFS.FILTER.CSS), 86 net: getBoolPref(PREFS.FILTER.NET), 87 netxhr: getBoolPref(PREFS.FILTER.NETXHR), 88 }), 89 ui: UiState({ 90 networkMessageActiveTabId: "headers", 91 persistLogs: getBoolPref(PREFS.UI.PERSIST), 92 editor: getBoolPref(PREFS.UI.EDITOR), 93 editorWidth: getIntPref(PREFS.UI.EDITOR_WIDTH), 94 showEditorOnboarding: getBoolPref(PREFS.UI.EDITOR_ONBOARDING), 95 timestampsVisible: getBoolPref(PREFS.UI.MESSAGE_TIMESTAMP), 96 enableNetworkMonitoring: 97 webConsoleUI.isBrowserConsole || webConsoleUI.isBrowserToolboxConsole 98 ? getBoolPref(PREFS.UI.ENABLE_NETWORK_MONITORING) 99 : true, 100 }), 101 }; 102 103 const { toolbox } = options.thunkArgs; 104 const sessionId = (toolbox && toolbox.sessionId) || -1; 105 const middleware = applyMiddleware( 106 performanceMarker(sessionId), 107 ignore, 108 thunk({ 109 prefsService, 110 ...options.thunkArgs, 111 }), 112 historyPersistence.bind(null, webConsoleUI), 113 eventTelemetry.bind(null, options.telemetry) 114 ); 115 116 const store = createStore( 117 createRootReducer(), 118 initialState, 119 compose( 120 middleware, 121 enableActorReleaser(webConsoleUI), 122 enableMessagesCacheClearing(webConsoleUI), 123 // ⚠️ Keep this one last so it will be executed before all the other ones. This is 124 // needed so batched actions can be "unbatched" and handled in the other enhancers. 125 enableBatching() 126 ) 127 ); 128 129 // Also wrap the store in order to pause store update notifications while the panel is hidden. 130 return visibilityHandlerStore(store); 131 } 132 133 function createRootReducer() { 134 return function rootReducer(state, action) { 135 // We want to compute the new state for all properties except 136 // "messages" and "history". These two reducers are handled 137 // separately since they are receiving additional arguments. 138 const newState = Object.entries(reducers).reduce((res, [key, reducer]) => { 139 if (key !== "messages" && key !== "history") { 140 res[key] = reducer(state[key], action); 141 } 142 return res; 143 }, {}); 144 145 // Pass prefs state as additional argument to the history reducer. 146 newState.history = reducers.history(state.history, action, newState.prefs); 147 148 // Specifically pass the updated filters, prefs and ui states as additional arguments. 149 newState.messages = reducers.messages( 150 state.messages, 151 action, 152 newState.filters, 153 newState.prefs, 154 newState.ui 155 ); 156 157 return newState; 158 }; 159 } 160 161 // Provide the store factory for test code so that each test is working with 162 // its own instance. 163 module.exports.configureStore = configureStore;