@quick-game/cli
Version:
Command line interface for rapid qg development
167 lines • 6.04 kB
JavaScript
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import * as i18n from '../../core/i18n/i18n.js';
import * as Platform from '../../core/platform/platform.js';
import * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';
import * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
import { Plugin } from './Plugin.js';
// Defines plugins that show profiling information in the editor
// gutter when available.
const UIStrings = {
/**
*@description The milisecond unit
*/
ms: 'ms',
/**
*@description Unit for data size in DevTools
*/
mb: 'MB',
/**
*@description A unit
*/
kb: 'kB',
};
const str_ = i18n.i18n.registerUIStrings('panels/sources/ProfilePlugin.ts', UIStrings);
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
class MemoryMarker extends CodeMirror.GutterMarker {
value;
constructor(value) {
super();
this.value = value;
}
eq(other) {
return this.value === other.value;
}
toDOM() {
const element = document.createElement('div');
element.className = 'cm-profileMarker';
let value = this.value;
const intensity = Platform.NumberUtilities.clamp(Math.log10(1 + 2e-3 * value) / 5, 0.02, 1);
element.style.backgroundColor = `hsla(217, 100%, 70%, ${intensity.toFixed(3)})`;
value /= 1e3;
let units;
let fractionDigits;
if (value >= 1e3) {
units = i18nString(UIStrings.mb);
value /= 1e3;
fractionDigits = value >= 20 ? 0 : 1;
}
else {
units = i18nString(UIStrings.kb);
fractionDigits = 0;
}
element.textContent = value.toFixed(fractionDigits);
const unitElement = element.appendChild(document.createElement('span'));
unitElement.className = 'cm-units';
unitElement.textContent = units;
return element;
}
}
class PerformanceMarker extends CodeMirror.GutterMarker {
value;
constructor(value) {
super();
this.value = value;
}
eq(other) {
return this.value === other.value;
}
toDOM() {
const element = document.createElement('div');
element.className = 'cm-profileMarker';
const intensity = Platform.NumberUtilities.clamp(Math.log10(1 + 10 * this.value) / 5, 0.02, 1);
element.textContent = this.value.toFixed(1);
element.style.backgroundColor = `hsla(44, 100%, 50%, ${intensity.toFixed(3)})`;
const span = document.createElement('span');
span.className = 'cm-units';
span.textContent = i18nString(UIStrings.ms);
element.appendChild(span);
return element;
}
}
function markersFromProfileData(map, state, type) {
const markerType = type === SourceFrame.SourceFrame.DecoratorType.PERFORMANCE ? PerformanceMarker : MemoryMarker;
const markers = [];
for (const [line, value] of map) {
if (line <= state.doc.lines) {
const { from } = state.doc.line(line);
markers.push(new markerType(value).range(from));
}
}
return CodeMirror.RangeSet.of(markers, true);
}
const makeLineLevelProfilePlugin = (type) => class extends Plugin {
updateEffect = CodeMirror.StateEffect.define();
field;
gutter;
compartment = new CodeMirror.Compartment();
constructor(uiSourceCode) {
super(uiSourceCode);
this.field = CodeMirror.StateField.define({
create() {
return CodeMirror.RangeSet.empty;
},
update: (markers, tr) => {
return tr.effects.reduce((markers, effect) => {
return effect.is(this.updateEffect) ? markersFromProfileData(effect.value, tr.state, type) : markers;
}, markers.map(tr.changes));
},
});
this.gutter = CodeMirror.gutter({
markers: (view) => view.state.field(this.field),
class: `cm-${type}Gutter`,
});
}
static accepts(uiSourceCode) {
return uiSourceCode.contentType().hasScripts();
}
getLineMap() {
return this.uiSourceCode.getDecorationData(type);
}
editorExtension() {
const map = this.getLineMap();
return this.compartment.of(!map ? [] : [this.field.init(state => markersFromProfileData(map, state, type)), this.gutter, theme]);
}
decorationChanged(type, editor) {
const installed = Boolean(editor.state.field(this.field, false));
const map = this.getLineMap();
if (!map) {
if (installed) {
editor.dispatch({ effects: this.compartment.reconfigure([]) });
}
}
else if (!installed) {
editor.dispatch({
effects: this.compartment.reconfigure([this.field.init(state => markersFromProfileData(map, state, type)), this.gutter, theme]),
});
}
else {
editor.dispatch({ effects: this.updateEffect.of(map) });
}
}
};
const theme = CodeMirror.EditorView.baseTheme({
'.cm-performanceGutter': {
width: '60px',
backgroundColor: 'var(--color-background)',
marginLeft: '3px',
},
'.cm-memoryGutter': {
width: '48px',
backgroundColor: 'var(--color-background)',
marginLeft: '3px',
},
'.cm-profileMarker': {
textAlign: 'right',
paddingRight: '3px',
},
'.cm-profileMarker .cm-units': {
color: 'var(--color-text-secondary)',
fontSize: '75%',
marginLeft: '3px',
},
});
export const MemoryProfilePlugin = makeLineLevelProfilePlugin(SourceFrame.SourceFrame.DecoratorType.MEMORY);
export const PerformanceProfilePlugin = makeLineLevelProfilePlugin(SourceFrame.SourceFrame.DecoratorType.PERFORMANCE);
//# sourceMappingURL=ProfilePlugin.js.map