Bug 1408182 - remove immutable from requests store
MozReview-Commit-ID: 4ZiOVYqkeU
--- a/devtools/client/netmonitor/src/reducers/requests.js
+++ b/devtools/client/netmonitor/src/reducers/requests.js
@@ -1,31 +1,31 @@
/* 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 I = require("devtools/client/shared/vendor/immutable");
+//const I = require("devtools/client/shared/vendor/immutable");
const {
getUrlDetails,
processNetworkUpdates,
} = require("../utils/request-utils");
const {
ADD_REQUEST,
CLEAR_REQUESTS,
CLONE_SELECTED_REQUEST,
OPEN_NETWORK_DETAILS,
REMOVE_SELECTED_CUSTOM_REQUEST,
SELECT_REQUEST,
SEND_CUSTOM_REQUEST,
TOGGLE_RECORDING,
UPDATE_REQUEST,
} = require("../constants");
-
+/*
const Request = I.Record({
id: null,
// Set to true in case of a request that's being edited as part of "edit and resend"
isCustom: false,
// Request properties - at the beginning, they are unknown and are gradually filled in
startedMillis: undefined,
endedMillis: undefined,
method: undefined,
@@ -56,29 +56,53 @@ const Request = I.Record({
requestCookies: undefined,
requestPostData: undefined,
responseHeaders: undefined,
responseCookies: undefined,
responseContent: undefined,
responseContentAvailable: false,
formDataSections: undefined,
});
+*/
-const Requests = I.Record({
- // The collection of requests (keyed by id)
- requests: I.Map(),
- // Selection state
- selectedId: null,
- preselectedId: null,
- // Auxiliary fields to hold requests stats
- firstStartedMillis: +Infinity,
- lastEndedMillis: -Infinity,
- // Recording state
- recording: true,
-});
+function Requests(wasRecording=true) {
+ let state = {
+ requests: new Map(),
+ // Selection state
+ selectedId: null,
+ preselectedId: null,
+
+ recording: true,
+
+ // Auxiliary fields to hold requests stats
+ firstStartedMillis: +Infinity,
+ lastEndedMillis: -Infinity,
+
+
+ valueSeq() {
+ return [...state.requests.values()];
+ },
+ isEmpty() {
+ return state.requests.size == 0;
+ },
+ get(name) {
+ return state[name];
+ }
+ };
+ state.requests.isEmpty = () => {
+ return state.isEmpty();
+ };
+ state.requests.valueSeq = () => {
+ return state.valueSeq();
+ };
+ state.requests.filter = (...args) => {
+ return [...state.requests.values()].filter(...args);
+ };
+ return state;
+}
/**
* Remove the currently selected custom request.
*/
function closeCustomRequest(state) {
let { requests, selectedId } = state;
if (!selectedId) {
@@ -93,74 +117,117 @@ function closeCustomRequest(state) {
}
return state.withMutations(st => {
st.requests = st.requests.delete(selectedId);
st.selectedId = null;
});
}
-function requestsReducer(state = new Requests(), action) {
+function requestsReducer(state = Requests() , action) {
switch (action.type) {
case ADD_REQUEST: {
- return state.withMutations(st => {
- let newRequest = new Request(Object.assign(
- { id: action.id },
- action.data,
- { urlDetails: getUrlDetails(action.data.url) }
- ));
- st.requests = st.requests.set(newRequest.id, newRequest);
+ let st = Object.assign({}, state);
+
+ let newRequest = Object.assign(
+ { id: action.id },
+ action.data,
+ { urlDetails: getUrlDetails(action.data.url) }
+ );
+ st.requests.set(newRequest.id, newRequest);
+
+ // Update the started/ended timestamps
+ let { startedMillis } = action.data;
+ if (startedMillis < st.firstStartedMillis) {
+ st.firstStartedMillis = startedMillis;
+ }
+ if (startedMillis > st.lastEndedMillis) {
+ st.lastEndedMillis = startedMillis;
+ }
- // Update the started/ended timestamps
- let { startedMillis } = action.data;
- if (startedMillis < st.firstStartedMillis) {
- st.firstStartedMillis = startedMillis;
- }
- if (startedMillis > st.lastEndedMillis) {
- st.lastEndedMillis = startedMillis;
+ // Select the request if it was preselected and there is no other selection
+ if (st.preselectedId && st.preselectedId === action.id) {
+ st.selectedId = st.selectedId || st.preselectedId;
+ st.preselectedId = null;
+ }
+ return st;
+ }
+ case UPDATE_REQUEST: {
+ let { requests, lastEndedMillis } = state;
+
+ let request = requests.get(action.id);
+ if (!request) {
+ return state;
+ }
+ request = Object.assign({}, request);
+ requests.set(action.id, request);
+
+ let st = Object.assign({}, state);
+ for (let [key, value] of Object.entries(action.data)) {
+ if (!UPDATE_PROPS.includes(key)) {
+ continue;
}
- // Select the request if it was preselected and there is no other selection
- if (st.preselectedId && st.preselectedId === action.id) {
- st.selectedId = st.selectedId || st.preselectedId;
- st.preselectedId = null;
+ request[key] = value;
+
+ switch (key) {
+ case "url":
+ // Compute the additional URL details
+ request.urlDetails = getUrlDetails(value);
+ break;
+ case "totalTime":
+ request.endedMillis = request.startedMillis + value;
+ lastEndedMillis = Math.max(lastEndedMillis, request.endedMillis);
+ break;
+ case "requestPostData":
+ request.requestHeadersFromUploadStream = {
+ headers: [],
+ headersSize: 0,
+ };
+ break;
}
- });
+ }
+
+ st.lastEndedMillis = lastEndedMillis;
+ return st;
}
case CLEAR_REQUESTS: {
- return new Requests({
- recording: state.recording
- });
+ return Requests(state.recording);
+ }
+ case SELECT_REQUEST: {
+ let st = Object.assign({}, state);
+ st.selectedId = action.id;
+ return st;
}
case CLONE_SELECTED_REQUEST: {
let { requests, selectedId } = state;
if (!selectedId) {
return state;
}
let clonedRequest = requests.get(selectedId);
if (!clonedRequest) {
return state;
}
+ let st = Object.assign({}, state);
- let newRequest = new Request({
+ let newRequest = {
id: clonedRequest.id + "-clone",
method: clonedRequest.method,
url: clonedRequest.url,
urlDetails: clonedRequest.urlDetails,
requestHeaders: clonedRequest.requestHeaders,
requestPostData: clonedRequest.requestPostData,
isCustom: true
- });
+ };
- return state.withMutations(st => {
- st.requests = requests.set(newRequest.id, newRequest);
- st.selectedId = newRequest.id;
- });
+ requests.set(newRequest.id, newRequest);
+ st.selectedId = newRequest.id;
+ return st;
}
case OPEN_NETWORK_DETAILS: {
if (!action.open) {
return state.set("selectedId", null);
}
if (!state.selectedId && !state.requests.isEmpty()) {
return state.set("selectedId", state.requests.first().id);
@@ -176,35 +243,33 @@ function requestsReducer(state = new Req
}
case SEND_CUSTOM_REQUEST: {
// When a new request with a given id is added in future, select it immediately.
// where we know in advance the ID of the request, at a time when it
// wasn't sent yet.
return closeCustomRequest(state.set("preselectedId", action.id));
}
case TOGGLE_RECORDING: {
- return state.set("recording", !state.recording);
+ let st = Object.assign({}, state);
+ st.recording = !st.recording;
+ return st;
}
- case UPDATE_REQUEST: {
- let { requests, lastEndedMillis } = state;
-
- let updatedRequest = requests.get(action.id);
- if (!updatedRequest) {
- return state;
+ case OPEN_NETWORK_DETAILS: {
+ let st = Object.assign({}, state);
+ if (!action.open) {
+ state.selectedId = null;
+ return st;
}
updatedRequest = updatedRequest.withMutations(request => {
let values = processNetworkUpdates(action.data);
request = Object.assign(request, values);
});
- return state.withMutations(st => {
- st.requests = requests.set(updatedRequest.id, updatedRequest);
- st.lastEndedMillis = lastEndedMillis;
- });
+ return st;
}
default:
return state;
}
}
module.exports = {
--- a/devtools/client/netmonitor/src/selectors/requests.js
+++ b/devtools/client/netmonitor/src/selectors/requests.js
@@ -51,43 +51,43 @@ const getTypeFilterFn = createSelector(
const matchesType = filters.requestFilterTypes.some((enabled, filter) => {
return enabled && Filters[filter] && Filters[filter](r);
});
return matchesType;
}
);
const getSortFn = createSelector(
- state => state.requests.requests,
+ state => state.requests,
state => state.sort,
- (requests, sort) => {
+ ({requests}, sort) => {
const sorter = Sorters[sort.type || "waterfall"];
const ascending = sort.ascending ? +1 : -1;
return (a, b) => ascending * sortWithClones(requests, sorter, a, b);
}
);
const getSortedRequests = createSelector(
- state => state.requests.requests,
+ state => state.requests,
getSortFn,
- (requests, sortFn) => requests.valueSeq().sort(sortFn).toList()
+ ({requests}, sortFn) => requests.valueSeq().sort(sortFn)
);
const getDisplayedRequests = createSelector(
- state => state.requests.requests,
+ state => state.requests,
getFilterFn,
getSortFn,
- (requests, filterFn, sortFn) => requests.valueSeq()
- .filter(filterFn).sort(sortFn).toList()
+ ({requests}, filterFn, sortFn) => requests.valueSeq()
+ .filter(filterFn).sort(sortFn)
);
const getTypeFilteredRequests = createSelector(
- state => state.requests.requests,
+ state => state.requests,
getTypeFilterFn,
- (requests, filterFn) => requests.valueSeq().filter(filterFn).toList()
+ ({requests}, filterFn) => requests.valueSeq().filter(filterFn)
);
const getDisplayedRequestsSummary = createSelector(
getDisplayedRequests,
state => state.requests.lastEndedMillis - state.requests.firstStartedMillis,
(requests, totalMillis) => {
if (requests.size == 0) {
return { count: 0, bytes: 0, millis: 0 };
--- a/devtools/client/netmonitor/src/selectors/ui.js
+++ b/devtools/client/netmonitor/src/selectors/ui.js
@@ -3,17 +3,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { REQUESTS_WATERFALL } = require("../constants");
const { getDisplayedRequests } = require("./requests");
function isNetworkDetailsToggleButtonDisabled(state) {
- return getDisplayedRequests(state).isEmpty();
+ return getDisplayedRequests(state).length == 0;
}
const EPSILON = 0.001;
function getWaterfallScale(state) {
const { requests, timingMarkers, ui } = state;
if (requests.firstStartedMillis === +Infinity || ui.waterfallWidth === null) {