--- a/devtools/client/netmonitor/components/request-list-column-cause.js
+++ b/devtools/client/netmonitor/components/request-list-column-cause.js
@@ -1,34 +1,38 @@
/* 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 {
+ createClass,
createFactory,
DOM,
+ PropTypes,
} = require("devtools/client/shared/vendor/react");
+const { propertiesEqual } = require("../utils/request-utils");
// Components
const Column = createFactory(require("devtools/client/shared/vendor/react-virtualized").Column);
const RequestListColumnHeader = createFactory(require("./request-list-column-header"));
const { div } = DOM;
+const UPDATED_PROPS = ["cause"];
/**
* Request list cause column component
* Describes the header and cell contents of a table column
*/
function RequestListColumnCause() {
let name = "cause";
return (
Column({
- cellRenderer,
+ cellRenderer: CauseColumnCell,
className: "requests-list-subitem",
dataKey: name,
headerClassName: "requests-list-header",
headerRenderer: (props) => RequestListColumnHeader(props),
label: name,
width: 100,
maxWidth: 100,
minWidth: 45,
@@ -37,41 +41,49 @@ function RequestListColumnCause() {
justifyContent: "center",
},
})
);
}
RequestListColumnCause.displayName = "RequestListColumnCause";
-function cellRenderer({
- cellData,
- dataKey,
- rowData,
- rowIndex,
-}) {
- let { cause } = rowData;
- let causeType = "";
- let causeUri;
- let causeHasStack = false;
+const CauseColumnCell = createFactory(createClass({
+ displayName: "CauseColumnCell",
+
+ propTypes: {
+ rowData: PropTypes.object,
+ },
+
+ shouldComponentUpdate(nextProps) {
+ return !propertiesEqual(UPDATED_PROPS, this.props.rowData, nextProps.rowData);
+ },
+
+ render() {
+ let { rowData } = this.props;
+ let { cause } = rowData;
+ let causeType = "";
+ let causeUri;
+ let causeHasStack = false;
- if (cause) {
- // Legacy server might send a numeric value. Display it as "unknown"
- causeType = typeof cause.type === "string" ? cause.type : "unknown";
- causeUri = cause.loadingDocumentUri;
- causeHasStack = cause.stacktrace && cause.stacktrace.length > 0;
- }
+ if (cause) {
+ // Legacy server might send a numeric value. Display it as "unknown"
+ causeType = typeof cause.type === "string" ? cause.type : "unknown";
+ causeUri = cause.loadingDocumentUri;
+ causeHasStack = cause.stacktrace && cause.stacktrace.length > 0;
+ }
- return (
- div({
- className: "requests-list-subitem requests-list-cause",
- title: causeUri,
- },
+ return (
div({
- className: "requests-list-cause-stack",
- hidden: !causeHasStack,
- }, "JS"),
- div({ className: "subitem-label" }, causeType),
- )
- );
-}
+ className: "requests-list-subitem requests-list-cause",
+ title: causeUri,
+ },
+ div({
+ className: "requests-list-cause-stack",
+ hidden: !causeHasStack,
+ }, "JS"),
+ div({ className: "subitem-label" }, causeType),
+ )
+ );
+ }
+}));
module.exports = RequestListColumnCause;
--- a/devtools/client/netmonitor/components/request-list-column-domain.js
+++ b/devtools/client/netmonitor/components/request-list-column-domain.js
@@ -1,85 +1,103 @@
/* 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 {
+ createClass,
createFactory,
DOM,
+ PropTypes,
} = require("devtools/client/shared/vendor/react");
const { L10N } = require("../utils/l10n");
+const { propertiesEqual } = require("../utils/request-utils");
// Components
const Column = createFactory(require("devtools/client/shared/vendor/react-virtualized").Column);
const RequestListColumnHeader = createFactory(require("./request-list-column-header"));
const { div } = DOM;
+const UPDATED_PROPS = [
+ "remoteAddress",
+ "securityState",
+ "urlDetails",
+];
/**
* Request list domain column component
* Describes the header and cell contents of a table column
*/
function RequestListColumnDomain({
selectDetailsPanelTab,
}) {
let name = "domain";
return (
Column({
- cellRenderer: (props) => cellRenderer(props, selectDetailsPanelTab),
+ cellRenderer: (props) =>
+ DomainColumnCell(Object.assign(props, { selectDetailsPanelTab })),
className: "requests-list-subitem",
dataKey: name,
headerClassName: "requests-list-header",
headerRenderer: (props) => RequestListColumnHeader(props),
label: name,
width: 150,
maxWidth: 220,
minWidth: 75,
style: { display: "flex" },
})
);
}
RequestListColumnDomain.displayName = "RequestListColumnDomain";
-function cellRenderer({
- cellData,
- dataKey,
- rowData,
- rowIndex,
-}, selectDetailsPanelTab) {
- let {
- urlDetails,
- remoteAddress,
- securityState,
- } = rowData;
+const DomainColumnCell = createFactory(createClass({
+ displayName: "DomainColumnCell",
+
+ propTypes: {
+ rowData: PropTypes.object,
+ selectDetailsPanelTab: PropTypes.func.isRequired,
+ },
+
+ shouldComponentUpdate(nextProps) {
+ return !propertiesEqual(UPDATED_PROPS, this.props.rowData, nextProps.rowData);
+ },
+
+ render() {
+ let { rowData, selectDetailsPanelTab } = this.props;
+ let {
+ urlDetails,
+ remoteAddress,
+ securityState,
+ } = rowData;
- let iconClassList = ["requests-domain"];
- let iconTitle;
- if (urlDetails.isLocal) {
- iconClassList.push("security-state-local");
- iconTitle = L10N.getStr("netmonitor.security.state.secure");
- } else if (securityState) {
- iconClassList.push(`security-state-${securityState}`);
- iconTitle = L10N.getStr(`netmonitor.security.state.${securityState}`);
- }
+ let iconClassList = ["requests-domain"];
+ let iconTitle;
+ if (urlDetails.isLocal) {
+ iconClassList.push("security-state-local");
+ iconTitle = L10N.getStr("netmonitor.security.state.secure");
+ } else if (securityState) {
+ iconClassList.push(`security-state-${securityState}`);
+ iconTitle = L10N.getStr(`netmonitor.security.state.${securityState}`);
+ }
- let title = urlDetails.host + (remoteAddress ? ` (${remoteAddress})` : "");
+ let title = urlDetails.host + (remoteAddress ? ` (${remoteAddress})` : "");
- return (
- div({ className: "requests-list-subitem" },
- div({
- className: iconClassList.join(" "),
- title: iconTitle,
- onClick: () => {
- if (securityState && securityState !== "insecure") {
- selectDetailsPanelTab("security");
- }
- },
- }),
- div({ className: "requests-list-domain subitem-label", title }, urlDetails.host),
- )
- );
-}
+ return (
+ div({ className: "requests-list-subitem" },
+ div({
+ className: iconClassList.join(" "),
+ title: iconTitle,
+ onClick: () => {
+ if (securityState && securityState !== "insecure") {
+ selectDetailsPanelTab("security");
+ }
+ },
+ }),
+ div({ className: "requests-list-domain subitem-label", title }, urlDetails.host),
+ )
+ );
+ }
+}));
module.exports = RequestListColumnDomain;
--- a/devtools/client/netmonitor/components/request-list-column-file.js
+++ b/devtools/client/netmonitor/components/request-list-column-file.js
@@ -1,71 +1,86 @@
/* 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 {
+ createClass,
createFactory,
DOM,
+ PropTypes,
} = require("devtools/client/shared/vendor/react");
+const { propertiesEqual } = require("../utils/request-utils");
// Components
const Column = createFactory(require("devtools/client/shared/vendor/react-virtualized").Column);
const RequestListColumnHeader = createFactory(require("./request-list-column-header"));
const { div, img } = DOM;
+const UPDATED_PROPS = [
+ "responseContentDataUri",
+ "urlDetails",
+];
/**
* Request list file column component
* Describes the header and cell contents of a table column
*/
function RequestListColumnFile() {
let name = "file";
return (
Column({
- cellRenderer,
+ cellRenderer: FileColumnCell,
className: "requests-list-subitem",
dataKey: name,
headerClassName: "requests-list-header",
headerRenderer: (props) => RequestListColumnHeader(props),
label: name,
width: 300,
maxWidth: 350,
minWidth: 100,
style: { display: "flex" },
})
);
}
RequestListColumnFile.displayName = "RequestListColumnFile";
-function cellRenderer({
- cellData,
- dataKey,
- rowData,
- rowIndex,
-}) {
- let {
- urlDetails,
- responseContentDataUri,
- } = rowData;
+const FileColumnCell = createFactory(createClass({
+ displayName: "FileColumnCell",
+
+ propTypes: {
+ rowData: PropTypes.object,
+ },
+
+ shouldComponentUpdate(nextProps) {
+ return !propertiesEqual(UPDATED_PROPS, this.props.rowData, nextProps.rowData);
+ },
+
+ render() {
+ let { rowData } = this.props;
+ let {
+ urlDetails,
+ responseContentDataUri,
+ } = rowData;
- return (
- div({ className: "requests-list-file requests-list-subitem" },
- img({
- className: "requests-list-icon",
- src: responseContentDataUri,
- hidden: !responseContentDataUri,
- "data-type": responseContentDataUri ? "thumbnail" : undefined,
- }),
- div({
- className: "requests-list-url subitem-label",
- title: urlDetails.unicodeUrl,
- },
- urlDetails.baseNameWithQuery,
- ),
- )
- );
-}
+ return (
+ div({ className: "requests-list-file requests-list-subitem" },
+ img({
+ className: "requests-list-icon",
+ src: responseContentDataUri,
+ hidden: !responseContentDataUri,
+ "data-type": responseContentDataUri ? "thumbnail" : undefined,
+ }),
+ div({
+ className: "requests-list-url subitem-label",
+ title: urlDetails.unicodeUrl,
+ },
+ urlDetails.baseNameWithQuery,
+ ),
+ )
+ );
+ }
+}));
module.exports = RequestListColumnFile;
--- a/devtools/client/netmonitor/components/request-list-column-method.js
+++ b/devtools/client/netmonitor/components/request-list-column-method.js
@@ -1,34 +1,38 @@
/* 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 {
+ createClass,
createFactory,
DOM,
+ PropTypes,
} = require("devtools/client/shared/vendor/react");
+const { propertiesEqual } = require("../utils/request-utils");
// Components
const Column = createFactory(require("devtools/client/shared/vendor/react-virtualized").Column);
const RequestListColumnHeader = createFactory(require("./request-list-column-header"));
const { div } = DOM;
+const UPDATED_PROPS = ["method"];
/**
* Request list method column component
* Describes the header and cell contents of a table column
*/
function RequestListColumnMethod() {
let name = "method";
return (
Column({
- cellRenderer,
+ cellRenderer: MethodColumnCell,
className: "requests-list-subitem requests-list-method-box",
dataKey: name,
headerClassName: "requests-list-header",
headerRenderer: (props) => RequestListColumnHeader(props),
label: name,
width: 75,
maxWidth: 84,
minWidth: 55,
@@ -37,22 +41,30 @@ function RequestListColumnMethod() {
justifyContent: "center",
},
})
);
}
RequestListColumnMethod.displayName = "RequestListColumnMethod";
-function cellRenderer({
- cellData,
- dataKey,
- rowData,
- rowIndex,
-}) {
- let { method } = rowData;
+const MethodColumnCell = createFactory(createClass({
+ displayName: "MethodColumnCell",
+
+ propTypes: {
+ rowData: PropTypes.object,
+ },
- return (
- div({ className: "subitem-label requests-list-method" }, method)
- );
-}
+ shouldComponentUpdate(nextProps) {
+ return !propertiesEqual(UPDATED_PROPS, this.props.rowData, nextProps.rowData);
+ },
+
+ render() {
+ let { rowData } = this.props;
+ let { method } = rowData;
+
+ return (
+ div({ className: "subitem-label requests-list-method" }, method)
+ );
+ }
+}));
module.exports = RequestListColumnMethod;
--- a/devtools/client/netmonitor/components/request-list-column-size.js
+++ b/devtools/client/netmonitor/components/request-list-column-size.js
@@ -1,35 +1,39 @@
/* 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 {
+ createClass,
createFactory,
DOM,
+ PropTypes,
} = require("devtools/client/shared/vendor/react");
const { getFormattedSize } = require("../utils/format-utils");
+const { propertiesEqual } = require("../utils/request-utils");
// Components
const Column = createFactory(require("devtools/client/shared/vendor/react-virtualized").Column);
const RequestListColumnHeader = createFactory(require("./request-list-column-header"));
const { div } = DOM;
+const UPDATED_PROPS = ["contentSize"];
/**
* Request list size column component
* Describes the header and cell contents of a table column
*/
function RequestListColumnsize() {
let name = "size";
return (
Column({
- cellRenderer,
+ cellRenderer: ContentSizeColumnCell,
className: "requests-list-subitem",
dataKey: name,
headerClassName: "requests-list-header",
headerRenderer: (props) => RequestListColumnHeader(props),
label: name,
width: 72,
maxWidth: 72,
minWidth: 45,
@@ -38,25 +42,33 @@ function RequestListColumnsize() {
justifyContent: "center",
},
})
);
}
RequestListColumnsize.displayName = "RequestListColumnsize";
-function cellRenderer({
- cellData,
- dataKey,
- rowData,
- rowIndex,
-}) {
- let { contentSize } = rowData;
- let title;
+const ContentSizeColumnCell = createFactory(createClass({
+ displayName: "ContentSizeColumnCell",
+
+ propTypes: {
+ rowData: PropTypes.object,
+ },
+
+ shouldComponentUpdate(nextProps) {
+ return !propertiesEqual(UPDATED_PROPS, this.props.rowData, nextProps.rowData);
+ },
- if (typeof contentSize === "number") {
- title = getFormattedSize(contentSize);
+ render() {
+ let { rowData } = this.props;
+ let { contentSize } = rowData;
+ let title;
+
+ if (typeof contentSize === "number") {
+ title = getFormattedSize(contentSize);
+ }
+
+ return div({ className: "requests-list-size subitem-label", title }, title);
}
-
- return div({ className: "requests-list-size subitem-label", title }, title);
-}
+}));
module.exports = RequestListColumnsize;
--- a/devtools/client/netmonitor/components/request-list-column-status.js
+++ b/devtools/client/netmonitor/components/request-list-column-status.js
@@ -1,34 +1,43 @@
/* 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 {
+ createClass,
createFactory,
DOM,
+ PropTypes,
} = require("devtools/client/shared/vendor/react");
+const { propertiesEqual } = require("../utils/request-utils");
// Components
const Column = createFactory(require("devtools/client/shared/vendor/react-virtualized").Column);
const RequestListColumnHeader = createFactory(require("./request-list-column-header"));
const { div } = DOM;
+const UPDATED_PROPS = [
+ "fromCache",
+ "fromServiceWorker",
+ "status",
+ "statusText",
+];
/**
* Request list status column component
* Describes the header and cell contents of a table column
*/
function RequestListColumnStatus() {
let name = "status";
return (
Column({
- cellRenderer,
+ cellRenderer: StatusColumnCell,
className: "requests-list-subitem",
dataKey: name,
disableSort: false,
headerClassName: "requests-list-header",
headerRenderer: (props) => RequestListColumnHeader(props),
label: name + "3",
width: 72,
maxWidth: 72,
@@ -38,46 +47,54 @@ function RequestListColumnStatus() {
justifyContent: "center",
},
})
);
}
RequestListColumnStatus.displayName = "RequestListColumnStatus";
-function cellRenderer({
- cellData,
- dataKey,
- rowData,
- rowIndex,
-}) {
- let { status, statusText, fromCache, fromServiceWorker } = rowData;
- let code, title;
+const StatusColumnCell = createFactory(createClass({
+ displayName: "StatusColumnCell",
+
+ propTypes: {
+ rowData: PropTypes.object,
+ },
+
+ shouldComponentUpdate(nextProps) {
+ return !propertiesEqual(UPDATED_PROPS, this.props.rowData, nextProps.rowData);
+ },
+
+ render() {
+ let { rowData } = this.props;
+ let { status, statusText, fromCache, fromServiceWorker } = rowData;
+ let code, title;
- if (status) {
- if (fromCache) {
- code = "cached";
- } else if (fromServiceWorker) {
- code = "service worker";
- } else {
- code = status;
+ if (status) {
+ if (fromCache) {
+ code = "cached";
+ } else if (fromServiceWorker) {
+ code = "service worker";
+ } else {
+ code = status;
+ }
+
+ if (statusText) {
+ title = `${status} ${statusText}`;
+ if (fromCache) {
+ title += " (cached)";
+ }
+ if (fromServiceWorker) {
+ title += " (service worker)";
+ }
+ }
}
- if (statusText) {
- title = `${status} ${statusText}`;
- if (fromCache) {
- title += " (cached)";
- }
- if (fromServiceWorker) {
- title += " (service worker)";
- }
- }
+ return (
+ div({ className: "requests-list-subitem requests-list-status", title },
+ div({ className: "requests-list-status-icon", "data-code": code }),
+ div({ className: "requests-list-status-code subitem-label" }, status),
+ )
+ );
}
-
- return (
- div({ className: "requests-list-subitem requests-list-status", title },
- div({ className: "requests-list-status-icon", "data-code": code }),
- div({ className: "requests-list-status-code subitem-label" }, status),
- )
- );
-}
+}));
module.exports = RequestListColumnStatus;
--- a/devtools/client/netmonitor/components/request-list-column-transferred.js
+++ b/devtools/client/netmonitor/components/request-list-column-transferred.js
@@ -1,36 +1,44 @@
/* 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 {
+ createClass,
createFactory,
DOM,
+ PropTypes,
} = require("devtools/client/shared/vendor/react");
const { L10N } = require("../utils/l10n");
const { getFormattedSize } = require("../utils/format-utils");
+const { propertiesEqual } = require("../utils/request-utils");
// Components
const Column = createFactory(require("devtools/client/shared/vendor/react-virtualized").Column);
const RequestListColumnHeader = createFactory(require("./request-list-column-header"));
const { div } = DOM;
+const UPDATED_PROPS = [
+ "fromCache",
+ "fromServiceWorker",
+ "transferredSize",
+];
/**
* Request list transferred column component
* Describes the header and cell contents of a table column
*/
function RequestListColumnTransferred() {
let name = "transferred";
return (
Column({
- cellRenderer,
+ cellRenderer: TransferredSizeColumnCell,
className: "requests-list-subitem",
dataKey: name,
headerClassName: "requests-list-header",
headerRenderer: (props) => RequestListColumnHeader(props),
label: name,
width: 96,
maxWidth: 96,
minWidth: 45,
@@ -39,34 +47,42 @@ function RequestListColumnTransferred()
justifyContent: "center",
},
})
);
}
RequestListColumnTransferred.displayName = "RequestListColumnTransferred";
-function cellRenderer({
- cellData,
- dataKey,
- rowData,
- rowIndex,
-}) {
- let { transferredSize, fromCache, fromServiceWorker } = rowData;
+const TransferredSizeColumnCell = createFactory(createClass({
+ displayName: "TransferredSizeColumnCell",
+
+ propTypes: {
+ rowData: PropTypes.object,
+ },
+
+ shouldComponentUpdate(nextProps) {
+ return !propertiesEqual(UPDATED_PROPS, this.props.rowData, nextProps.rowData);
+ },
+
+ render() {
+ let { rowData } = this.props;
+ let { transferredSize, fromCache, fromServiceWorker } = rowData;
- let title;
- let className = "requests-list-transferred subitem-label";
- if (fromCache) {
- title = L10N.getStr("networkMenu.sizeCached");
- className += " theme-comment";
- } else if (fromServiceWorker) {
- title = L10N.getStr("networkMenu.sizeServiceWorker");
- className += " theme-comment";
- } else if (typeof transferredSize == "number") {
- title = getFormattedSize(transferredSize);
- } else if (transferredSize === null) {
- title = L10N.getStr("networkMenu.sizeUnavailable");
+ let title;
+ let className = "requests-list-transferred subitem-label";
+ if (fromCache) {
+ title = L10N.getStr("networkMenu.sizeCached");
+ className += " theme-comment";
+ } else if (fromServiceWorker) {
+ title = L10N.getStr("networkMenu.sizeServiceWorker");
+ className += " theme-comment";
+ } else if (typeof transferredSize == "number") {
+ title = getFormattedSize(transferredSize);
+ } else if (transferredSize === null) {
+ title = L10N.getStr("networkMenu.sizeUnavailable");
+ }
+
+ return div({ className, title }, title);
}
-
- return div({ className, title }, title);
-}
+}));
module.exports = RequestListColumnTransferred;
--- a/devtools/client/netmonitor/components/request-list-column-type.js
+++ b/devtools/client/netmonitor/components/request-list-column-type.js
@@ -1,41 +1,46 @@
/* 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 {
+ createClass,
createFactory,
DOM,
+ PropTypes,
} = require("devtools/client/shared/vendor/react");
-const { getAbbreviatedMimeType } = require("../utils/request-utils");
+const {
+ getAbbreviatedMimeType,
+ propertiesEqual,
+} = require("../utils/request-utils");
// Components
const Column = createFactory(require("devtools/client/shared/vendor/react-virtualized").Column);
const RequestListColumnHeader = createFactory(require("./request-list-column-header"));
const { div } = DOM;
-
const CONTENT_MIME_TYPE_ABBREVIATIONS = {
"ecmascript": "js",
"javascript": "js",
"x-javascript": "js"
};
+const UPDATED_PROPS = ["mimeType"];
/**
* Request list type column component
* Describes the header and cell contents of a table column
*/
function RequestListColumnType() {
let name = "type";
return (
Column({
- cellRenderer,
+ cellRenderer: TypeColumnCell,
className: "requests-list-subitem",
dataKey: name,
headerClassName: "requests-list-header",
headerRenderer: (props) => RequestListColumnHeader(props),
label: name,
width: 72,
maxWidth: 72,
minWidth: 45,
@@ -44,33 +49,41 @@ function RequestListColumnType() {
justifyContent: "center",
},
})
);
}
RequestListColumnType.displayName = "RequestListColumnType";
-function cellRenderer({
- cellData,
- dataKey,
- rowData,
- rowIndex,
-}) {
- let { mimeType } = rowData;
- let abbrevType;
+const TypeColumnCell = createFactory(createClass({
+ displayName: "TypeColumnCell",
+
+ propTypes: {
+ rowData: PropTypes.object,
+ },
+
+ shouldComponentUpdate(nextProps) {
+ return !propertiesEqual(UPDATED_PROPS, this.props.rowData, nextProps.rowData);
+ },
+
+ render() {
+ let { rowData } = this.props;
+ let { mimeType } = rowData;
+ let abbrevType;
- if (mimeType) {
- abbrevType = getAbbreviatedMimeType(mimeType);
- abbrevType = CONTENT_MIME_TYPE_ABBREVIATIONS[abbrevType] || abbrevType;
- }
+ if (mimeType) {
+ abbrevType = getAbbreviatedMimeType(mimeType);
+ abbrevType = CONTENT_MIME_TYPE_ABBREVIATIONS[abbrevType] || abbrevType;
+ }
- return (
- div({
- className: "requests-list-type subitem-label",
- title: mimeType,
- },
- abbrevType
- )
- );
-}
+ return (
+ div({
+ className: "requests-list-type subitem-label",
+ title: mimeType,
+ },
+ abbrevType
+ )
+ );
+ }
+}));
module.exports = RequestListColumnType;
--- a/devtools/client/netmonitor/components/request-list-column-waterfall.js
+++ b/devtools/client/netmonitor/components/request-list-column-waterfall.js
@@ -1,66 +1,86 @@
/* 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 {
+ createClass,
createFactory,
DOM,
+ PropTypes,
} = require("devtools/client/shared/vendor/react");
const { L10N } = require("../utils/l10n");
+const { propertiesEqual } = require("../utils/request-utils");
// Components
const Column = createFactory(require("devtools/client/shared/vendor/react-virtualized").Column);
const RequestListColumnHeader = createFactory(require("./request-list-column-header"));
const { div } = DOM;
+const UPDATED_PROPS = [
+ "eventTimings",
+ "fromCache",
+ "fromServiceWorker",
+ "totalTime",
+];
/**
* Request list waterfall column component
* Describes the header and cell contents of a table column
*/
function RequestListColumnWaterfall(columnData) {
let name = "waterfall";
+ let { firstRequestStartedMillis } = columnData;
return (
Column({
- cellRenderer: (props) => cellRenderer(props, columnData.firstRequestStartedMillis),
+ cellRenderer: (props) =>
+ WaterfallColumnCell(Object.assign(props, { firstRequestStartedMillis })),
className: "requests-list-subitem",
columnData,
dataKey: name,
flexGrow: 1,
headerClassName: "requests-list-header",
headerRenderer: (props) => RequestListColumnHeader(props),
label: name,
width: 300,
})
);
}
RequestListColumnWaterfall.displayName = "RequestListColumnWaterfall";
-function cellRenderer({
- cellData,
- dataKey,
- rowData,
- rowIndex,
-}, firstRequestStartedMillis) {
- return (
- div({
- className: "requests-list-timings",
- style: {
- paddingInlineStart: `${rowData.startedMillis - firstRequestStartedMillis}px`,
+const WaterfallColumnCell = createFactory(createClass({
+ displayName: "WaterfallColumnCell",
+
+ propTypes: {
+ rowData: PropTypes.object,
+ firstRequestStartedMillis: PropTypes.number,
+ },
+
+ shouldComponentUpdate(nextProps) {
+ return !propertiesEqual(UPDATED_PROPS, this.props.rowData, nextProps.rowData);
+ },
+
+ render() {
+ let { rowData, firstRequestStartedMillis } = this.props;
+ return (
+ div({
+ className: "requests-list-timings",
+ style: {
+ paddingInlineStart: `${rowData.startedMillis - firstRequestStartedMillis}px`,
+ },
},
- },
- timingBoxes(rowData),
- )
- );
-}
+ timingBoxes(rowData),
+ )
+ );
+ }
+}));
// List of properties of the timing info we want to create boxes for
const TIMING_KEYS = ["blocked", "dns", "connect", "send", "wait", "receive"];
function timingBoxes(item) {
const { eventTimings, totalTime, fromCache, fromServiceWorker } = item;
let boxes = [];
--- a/devtools/client/netmonitor/utils/request-utils.js
+++ b/devtools/client/netmonitor/utils/request-utils.js
@@ -217,23 +217,31 @@ function parseQueryString(query) {
let param = e.split("=");
return {
name: param[0] ? decodeUnicodeUrl(param[0]) : "",
value: param[1] ? decodeUnicodeUrl(param[1]) : "",
};
});
}
+/**
+ * Compare two objects on a subset of their properties
+ */
+function propertiesEqual(props, item1, item2) {
+ return item1 === item2 || props.every(p => item1[p] === item2[p]);
+}
+
module.exports = {
getFormDataSections,
fetchHeaders,
formDataURI,
writeHeaderText,
decodeUnicodeUrl,
getAbbreviatedMimeType,
getUrlBaseName,
getUrlQuery,
getUrlBaseNameWithQuery,
getUrlHostName,
getUrlHost,
getUrlDetails,
parseQueryString,
+ propertiesEqual,
};