gecko-dev/devtools/client/performance/components/jit-optimizations-item.js

180 строки
5.9 KiB
JavaScript

/* 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 { LocalizationHelper } = require("devtools/shared/l10n");
const STRINGS_URI = "devtools/client/locales/jit-optimizations.properties";
const L10N = new LocalizationHelper(STRINGS_URI);
const {PluralForm} = require("devtools/shared/plural-form");
const { DOM: dom, PropTypes, createClass, createFactory } = require("devtools/client/shared/vendor/react");
const Frame = createFactory(require("devtools/client/shared/components/frame"));
const PROPNAME_MAX_LENGTH = 4;
// If TREE_ROW_HEIGHT changes, be sure to change `var(--jit-tree-row-height)`
// in `devtools/client/themes/jit-optimizations.css`
const TREE_ROW_HEIGHT = 14;
const OPTIMIZATION_ITEM_TYPES = ["site", "attempts", "types", "attempt", "type",
"observedtype"];
/* eslint-disable no-unused-vars */
/**
* TODO - Re-enable this eslint rule. The JIT tool is a work in progress, and isn't fully
* integrated as of yet.
*/
const {
JITOptimizations, hasSuccessfulOutcome, isSuccessfulOutcome
} = require("devtools/client/performance/modules/logic/jit");
const OPTIMIZATION_FAILURE = L10N.getStr("jit.optimizationFailure");
const JIT_SAMPLES = L10N.getStr("jit.samples");
const JIT_TYPES = L10N.getStr("jit.types");
const JIT_ATTEMPTS = L10N.getStr("jit.attempts");
/* eslint-enable no-unused-vars */
const JITOptimizationsItem = createClass({
displayName: "JITOptimizationsItem",
propTypes: {
onViewSourceInDebugger: PropTypes.func.isRequired,
frameData: PropTypes.object.isRequired,
type: PropTypes.oneOf(OPTIMIZATION_ITEM_TYPES).isRequired,
depth: PropTypes.number.isRequired,
arrow: PropTypes.element.isRequired,
item: PropTypes.object,
focused: PropTypes.bool
},
_renderSite({ item: site, onViewSourceInDebugger, frameData }) {
let attempts = site.data.attempts;
let lastStrategy = attempts[attempts.length - 1].strategy;
let propString = "";
let propertyName = site.data.propertyName;
// Display property name if it exists
if (propertyName) {
if (propertyName.length > PROPNAME_MAX_LENGTH) {
propString = ` (.${propertyName.substr(0, PROPNAME_MAX_LENGTH)}…)`;
} else {
propString = ` (.${propertyName})`;
}
}
let sampleString = PluralForm.get(site.samples, JIT_SAMPLES)
.replace("#1", site.samples);
let text = dom.span(
{ className: "optimization-site-title" },
`${lastStrategy}${propString} – (${sampleString})`
);
let frame = Frame({
onClick: () => onViewSourceInDebugger(frameData.url, site.data.line),
frame: {
source: frameData.url,
line: +site.data.line,
column: site.data.column,
}
});
let children = [text, frame];
if (!hasSuccessfulOutcome(site)) {
children.unshift(dom.span({ className: "opt-icon warning" }));
}
return dom.span({ className: "optimization-site" }, ...children);
},
_renderAttempts({ item: attempts }) {
return dom.span({ className: "optimization-attempts" },
`${JIT_ATTEMPTS} (${attempts.length})`
);
},
_renderTypes({ item: types }) {
return dom.span({ className: "optimization-types" },
`${JIT_TYPES} (${types.length})`
);
},
_renderAttempt({ item: attempt }) {
let success = isSuccessfulOutcome(attempt.outcome);
let { strategy, outcome } = attempt;
return dom.span({ className: "optimization-attempt" },
dom.span({ className: "optimization-strategy" }, strategy),
" → ",
dom.span({ className: `optimization-outcome ${success ? "success" : "failure"}` },
outcome)
);
},
_renderType({ item: type }) {
return dom.span({ className: "optimization-ion-type" },
`${type.site}:${type.mirType}`);
},
_renderObservedType({ onViewSourceInDebugger, item: type }) {
let children = [
dom.span({ className: "optimization-observed-type-keyed" },
`${type.keyedBy}${type.name ? `${type.name}` : ""}`)
];
// If we have a line and location, make a link to the debugger
if (type.location && type.line) {
children.push(
Frame({
onClick: () => onViewSourceInDebugger(type.location, type.line),
frame: {
source: type.location,
line: type.line,
column: type.column,
}
})
);
// Otherwise if we just have a location, it's probably just a memory location.
} else if (type.location) {
children.push(`@${type.location}`);
}
return dom.span({ className: "optimization-observed-type" }, ...children);
},
render() {
/* eslint-disable no-unused-vars */
/**
* TODO - Re-enable this eslint rule. The JIT tool is a work in progress, and these
* undefined variables may represent intended functionality.
*/
let {
depth,
arrow,
type,
// TODO - The following are currently unused.
item,
focused,
frameData,
onViewSourceInDebugger,
} = this.props;
/* eslint-enable no-unused-vars */
let content;
switch (type) {
case "site": content = this._renderSite(this.props); break;
case "attempts": content = this._renderAttempts(this.props); break;
case "types": content = this._renderTypes(this.props); break;
case "attempt": content = this._renderAttempt(this.props); break;
case "type": content = this._renderType(this.props); break;
case "observedtype": content = this._renderObservedType(this.props); break;
}
return dom.div(
{
className: `optimization-tree-item optimization-tree-item-${type}`,
style: { marginInlineStart: depth * TREE_ROW_HEIGHT }
},
arrow,
content
);
},
});
module.exports = JITOptimizationsItem;