Convert a lot of top level consts to const enums

This commit is contained in:
Daniel Imms
2026-05-02 06:44:25 -07:00
parent 5c47e6dd9a
commit 80debafa11
19 changed files with 304 additions and 282 deletions
+5 -3
View File
@@ -12,7 +12,9 @@ import { IBuffer } from 'common/buffer/Types';
import { IInstantiationService } from 'common/services/Services';
import { addDisposableListener } from 'browser/Dom';
const MAX_ROWS_TO_READ = 20;
const enum Constants {
MAX_ROWS_TO_READ = 20
}
const enum BoundaryPosition {
TOP,
@@ -137,7 +139,7 @@ export class AccessibilityManager extends Disposable {
}
private _handleChar(char: string): void {
if (this._liveRegionLineCount < MAX_ROWS_TO_READ + 1) {
if (this._liveRegionLineCount < Constants.MAX_ROWS_TO_READ + 1) {
if (this._charsToConsume.length > 0) {
// Have the screen reader ignore the char if it was just input
const shiftedChar = this._charsToConsume.shift();
@@ -150,7 +152,7 @@ export class AccessibilityManager extends Disposable {
if (char === '\n') {
this._liveRegionLineCount++;
if (this._liveRegionLineCount === MAX_ROWS_TO_READ + 1) {
if (this._liveRegionLineCount === Constants.MAX_ROWS_TO_READ + 1) {
this._liveRegion.textContent = Strings.tooMuchOutput.get();
}
}
+41 -39
View File
@@ -19,13 +19,15 @@ import { Emitter } from 'common/Event';
import { addDisposableListener } from 'browser/Dom';
const TERMINAL_CLASS_PREFIX = 'xterm-dom-renderer-owner-';
const ROW_CONTAINER_CLASS = 'xterm-rows';
const FG_CLASS_PREFIX = 'xterm-fg-';
const BG_CLASS_PREFIX = 'xterm-bg-';
const FOCUS_CLASS = 'xterm-focus';
const SELECTION_CLASS = 'xterm-selection';
const CURSOR_BLINK_IDLE_CLASS = 'xterm-cursor-blink-idle';
const enum Constants {
TERMINAL_CLASS_PREFIX = 'xterm-dom-renderer-owner-',
ROW_CONTAINER_CLASS = 'xterm-rows',
FG_CLASS_PREFIX = 'xterm-fg-',
BG_CLASS_PREFIX = 'xterm-bg-',
FOCUS_CLASS = 'xterm-focus',
SELECTION_CLASS = 'xterm-selection',
CURSOR_BLINK_IDLE_CLASS = 'xterm-cursor-blink-idle'
}
let nextTerminalId = 1;
@@ -76,12 +78,12 @@ export class DomRenderer extends Disposable implements IRenderer {
) {
super();
this._rowContainer = this._document.createElement('div');
this._rowContainer.classList.add(ROW_CONTAINER_CLASS);
this._rowContainer.classList.add(Constants.ROW_CONTAINER_CLASS);
this._rowContainer.style.lineHeight = 'normal';
this._rowContainer.setAttribute('aria-hidden', 'true');
this._refreshRowElements(this._bufferService.cols, this._bufferService.rows);
this._selectionContainer = this._document.createElement('div');
this._selectionContainer.classList.add(SELECTION_CLASS);
this._selectionContainer.classList.add(Constants.SELECTION_CLASS);
this._selectionContainer.setAttribute('aria-hidden', 'true');
this.dimensions = createRenderDimensions();
@@ -93,7 +95,7 @@ export class DomRenderer extends Disposable implements IRenderer {
this._rowFactory = instantiationService.createInstance(DomRendererRowFactory, document);
this._element.classList.add(TERMINAL_CLASS_PREFIX + this._terminalClass);
this._element.classList.add(Constants.TERMINAL_CLASS_PREFIX + this._terminalClass);
this._screenElement.appendChild(this._rowContainer);
this._screenElement.appendChild(this._selectionContainer);
@@ -110,7 +112,7 @@ export class DomRenderer extends Disposable implements IRenderer {
));
this._register(toDisposable(() => {
this._element.classList.remove(TERMINAL_CLASS_PREFIX + this._terminalClass);
this._element.classList.remove(Constants.TERMINAL_CLASS_PREFIX + this._terminalClass);
// Outside influences such as React unmounts may manipulate the DOM before our disposal.
// https://github.com/xtermjs/xterm.js/issues/2960
@@ -160,7 +162,7 @@ export class DomRenderer extends Disposable implements IRenderer {
}
const styles =
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} span {` +
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS} span {` +
` display: inline-block;` + // TODO: find workaround for inline-block (creates ~20% render penalty)
` height: 100%;` +
` vertical-align: top;` +
@@ -181,7 +183,7 @@ export class DomRenderer extends Disposable implements IRenderer {
// Base CSS
let styles =
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} {` +
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS} {` +
// Disabling pointer events circumvents a browser behavior that prevents `click` events from
// being delivered if the target element is replaced during the click. This happened due to
// refresh() being called during the mousedown handler to start a selection.
@@ -189,14 +191,14 @@ export class DomRenderer extends Disposable implements IRenderer {
` color: ${colors.foreground.css};` +
`}`;
styles +=
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}, ${this._terminalSelector} .${ROW_CONTAINER_CLASS} span {` +
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS}, ${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS} span {` +
` font-family: ${this._optionsService.rawOptions.fontFamily};` +
` font-size: ${this._optionsService.rawOptions.fontSize}px;` +
` font-kerning: none;` +
` white-space: pre` +
`}`;
styles +=
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} .xterm-dim {` +
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS} .xterm-dim {` +
` color: ${color.multiplyOpacity(colors.foreground, 0.5).css};` +
`}`;
// Text styles
@@ -242,70 +244,70 @@ export class DomRenderer extends Disposable implements IRenderer {
`}`;
// Cursor
styles +=
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}.${RowCss.CURSOR_STYLE_UNDERLINE_CLASS} {` +
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS}.${Constants.FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}.${RowCss.CURSOR_STYLE_UNDERLINE_CLASS} {` +
` animation: ${blinkAnimationUnderlineId} 1s step-end infinite;` +
`}` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}.${RowCss.CURSOR_STYLE_BAR_CLASS} {` +
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS}.${Constants.FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}.${RowCss.CURSOR_STYLE_BAR_CLASS} {` +
` animation: ${blinkAnimationBarId} 1s step-end infinite;` +
`}` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS} {` +
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS}.${Constants.FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS} {` +
` animation: ${blinkAnimationBlockId} 1s step-end infinite;` +
`}` +
// Disable cursor blinking when idle
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${CURSOR_BLINK_IDLE_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS} {` +
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS}.${Constants.CURSOR_BLINK_IDLE_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS} {` +
` animation: none !important;` +
`}` +
// !important helps fix an issue where the cursor will not render on top of the selection,
// however it's very hard to fix this issue and retain the blink animation without the use of
// !important. So this edge case fails when cursor blink is on.
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS} {` +
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS} {` +
` background-color: ${colors.cursor.css};` +
` color: ${colors.cursorAccent.css};` +
`}` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS}:not(.${RowCss.CURSOR_BLINK_CLASS}) {` +
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS}:not(.${RowCss.CURSOR_BLINK_CLASS}) {` +
` background-color: ${colors.cursor.css} !important;` +
` color: ${colors.cursorAccent.css} !important;` +
`}` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_OUTLINE_CLASS} {` +
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_OUTLINE_CLASS} {` +
` outline: 1px solid ${colors.cursor.css};` +
` outline-offset: -1px;` +
`}` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_BAR_CLASS} {` +
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_BAR_CLASS} {` +
` box-shadow: ${this._optionsService.rawOptions.cursorWidth}px 0 0 ${colors.cursor.css} inset;` +
`}` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_UNDERLINE_CLASS} {` +
`${this._terminalSelector} .${Constants.ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_UNDERLINE_CLASS} {` +
` border-bottom: 1px ${colors.cursor.css};` +
` border-bottom-style: solid;` +
` height: calc(100% - 1px);` +
`}`;
// Selection
styles +=
`${this._terminalSelector} .${SELECTION_CLASS} {` +
`${this._terminalSelector} .${Constants.SELECTION_CLASS} {` +
` position: absolute;` +
` top: 0;` +
` left: 0;` +
` z-index: 1;` +
` pointer-events: none;` +
`}` +
`${this._terminalSelector}.focus .${SELECTION_CLASS} div {` +
`${this._terminalSelector}.focus .${Constants.SELECTION_CLASS} div {` +
` position: absolute;` +
` background-color: ${colors.selectionBackgroundOpaque.css};` +
`}` +
`${this._terminalSelector} .${SELECTION_CLASS} div {` +
`${this._terminalSelector} .${Constants.SELECTION_CLASS} div {` +
` position: absolute;` +
` background-color: ${colors.selectionInactiveBackgroundOpaque.css};` +
`}`;
// Colors
for (const [i, c] of colors.ansi.entries()) {
styles +=
`${this._terminalSelector} .${FG_CLASS_PREFIX}${i} { color: ${c.css}; }` +
`${this._terminalSelector} .${FG_CLASS_PREFIX}${i}.${RowCss.DIM_CLASS} { color: ${color.multiplyOpacity(c, 0.5).css}; }` +
`${this._terminalSelector} .${BG_CLASS_PREFIX}${i} { background-color: ${c.css}; }`;
`${this._terminalSelector} .${Constants.FG_CLASS_PREFIX}${i} { color: ${c.css}; }` +
`${this._terminalSelector} .${Constants.FG_CLASS_PREFIX}${i}.${RowCss.DIM_CLASS} { color: ${color.multiplyOpacity(c, 0.5).css}; }` +
`${this._terminalSelector} .${Constants.BG_CLASS_PREFIX}${i} { background-color: ${c.css}; }`;
}
styles +=
`${this._terminalSelector} .${FG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { color: ${color.opaque(colors.background).css}; }` +
`${this._terminalSelector} .${FG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR}.${RowCss.DIM_CLASS} { color: ${color.multiplyOpacity(color.opaque(colors.background), 0.5).css}; }` +
`${this._terminalSelector} .${BG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { background-color: ${colors.foreground.css}; }`;
`${this._terminalSelector} .${Constants.FG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { color: ${color.opaque(colors.background).css}; }` +
`${this._terminalSelector} .${Constants.FG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR}.${RowCss.DIM_CLASS} { color: ${color.multiplyOpacity(color.opaque(colors.background), 0.5).css}; }` +
`${this._terminalSelector} .${Constants.BG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { background-color: ${colors.foreground.css}; }`;
this._themeStyleElement.textContent = styles;
}
@@ -361,13 +363,13 @@ export class DomRenderer extends Disposable implements IRenderer {
}
public handleBlur(): void {
this._rowContainer.classList.remove(FOCUS_CLASS);
this._rowContainer.classList.remove(Constants.FOCUS_CLASS);
this._cursorBlinkStateManager.pause();
this.renderRows(0, this._bufferService.rows - 1);
}
public handleFocus(): void {
this._rowContainer.classList.add(FOCUS_CLASS);
this._rowContainer.classList.add(Constants.FOCUS_CLASS);
this._cursorBlinkStateManager.resume();
this.renderRows(this._bufferService.buffer.y, this._bufferService.buffer.y);
}
@@ -561,7 +563,7 @@ export class DomRenderer extends Disposable implements IRenderer {
}
private get _terminalSelector(): string {
return `.${TERMINAL_CLASS_PREFIX}${this._terminalClass}`;
return `.${Constants.TERMINAL_CLASS_PREFIX}${this._terminalClass}`;
}
private _handleLinkHover(e: ILinkifierEvent): void {
@@ -667,7 +669,7 @@ class CursorBlinkStateManager {
public restartBlinkAnimation(): void {
if (this._isIdlePaused) {
this._rowContainer.classList.remove(CURSOR_BLINK_IDLE_CLASS);
this._rowContainer.classList.remove(Constants.CURSOR_BLINK_IDLE_CLASS);
}
this._resetIdleTimer();
}
@@ -679,7 +681,7 @@ class CursorBlinkStateManager {
public resume(): void {
this._isIdlePaused = false;
this._rowContainer.classList.remove(CURSOR_BLINK_IDLE_CLASS);
this._rowContainer.classList.remove(Constants.CURSOR_BLINK_IDLE_CLASS);
this._resetIdleTimer();
}
@@ -699,7 +701,7 @@ class CursorBlinkStateManager {
}
private _stopBlinkingDueToIdle(): void {
this._rowContainer.classList.add(CURSOR_BLINK_IDLE_CLASS);
this._rowContainer.classList.add(Constants.CURSOR_BLINK_IDLE_CLASS);
this._isIdlePaused = true;
this._idleTimeout = undefined;
}
+7 -5
View File
@@ -18,8 +18,10 @@ import * as platform from 'common/Platform';
import { INewScrollDimensions, INewScrollPosition, IScrollDimensions, IScrollPosition, IScrollEvent, Scrollable, ScrollbarVisibility } from './scrollable';
// import 'vs/css!./media/scrollbars';
const HIDE_TIMEOUT = 500;
const SCROLL_WHEEL_SENSITIVITY = 50;
const enum Constants {
HIDE_TIMEOUT = 500,
SCROLL_WHEEL_SENSITIVITY = 50
}
class MouseWheelClassifierItem {
public timestamp: number;
@@ -404,12 +406,12 @@ export class SmoothScrollableElement extends Widget {
let desiredScrollPosition: INewScrollPosition = {};
if (deltaY) {
const deltaScrollTop = SCROLL_WHEEL_SENSITIVITY * deltaY;
const deltaScrollTop = Constants.SCROLL_WHEEL_SENSITIVITY * deltaY;
const desiredScrollTop = futureScrollPosition.scrollTop - (deltaScrollTop < 0 ? Math.floor(deltaScrollTop) : Math.ceil(deltaScrollTop));
this._verticalScrollbar.writeScrollPosition(desiredScrollPosition, desiredScrollTop);
}
if (deltaX) {
const deltaScrollLeft = SCROLL_WHEEL_SENSITIVITY * deltaX;
const deltaScrollLeft = Constants.SCROLL_WHEEL_SENSITIVITY * deltaX;
const desiredScrollLeft = futureScrollPosition.scrollLeft - (deltaScrollLeft < 0 ? Math.floor(deltaScrollLeft) : Math.ceil(deltaScrollLeft));
this._horizontalScrollbar.writeScrollPosition(desiredScrollPosition, desiredScrollLeft);
}
@@ -533,7 +535,7 @@ export class SmoothScrollableElement extends Widget {
private _scheduleHide(): void {
if (!this._mouseIsOver && !this._isDragging) {
this._hideTimeout.cancelAndSet(() => this._hide(), HIDE_TIMEOUT);
this._hideTimeout.cancelAndSet(() => this._hide(), Constants.HIDE_TIMEOUT);
}
}
}
+26 -27
View File
@@ -18,27 +18,26 @@ import { IBuffer } from 'common/buffer/Types';
import { IBufferService, ICoreService, IOptionsService } from 'common/services/Services';
import { Emitter } from 'common/Event';
/**
* The number of pixels the mouse needs to be above or below the viewport in
* order to scroll at the maximum speed.
*/
const DRAG_SCROLL_MAX_THRESHOLD = 50;
/**
* The maximum scrolling speed
*/
const DRAG_SCROLL_MAX_SPEED = 15;
/**
* The number of milliseconds between drag scroll updates.
*/
const DRAG_SCROLL_INTERVAL = 50;
/**
* The maximum amount of time that can have elapsed for an alt click to move the
* cursor.
*/
const ALT_CLICK_MOVE_CURSOR_TIME = 500;
const enum Constants {
/**
* The number of pixels the mouse needs to be above or below the viewport in
* order to scroll at the maximum speed.
*/
DRAG_SCROLL_MAX_THRESHOLD = 50,
/**
* The maximum scrolling speed
*/
DRAG_SCROLL_MAX_SPEED = 15,
/**
* The number of milliseconds between drag scroll updates.
*/
DRAG_SCROLL_INTERVAL = 50,
/**
* The maximum amount of time that can have elapsed for an alt click to move the
* cursor.
*/
ALT_CLICK_MOVE_CURSOR_TIME = 500
}
const NON_BREAKING_SPACE_CHAR = String.fromCharCode(160);
const ALL_NON_BREAKING_SPACE_REGEX = new RegExp(NON_BREAKING_SPACE_CHAR, 'g');
@@ -424,9 +423,9 @@ export class SelectionService extends Disposable implements ISelectionService {
offset -= terminalHeight;
}
offset = Math.min(Math.max(offset, -DRAG_SCROLL_MAX_THRESHOLD), DRAG_SCROLL_MAX_THRESHOLD);
offset /= DRAG_SCROLL_MAX_THRESHOLD;
return (offset / Math.abs(offset)) + Math.round(offset * (DRAG_SCROLL_MAX_SPEED - 1));
offset = Math.min(Math.max(offset, -Constants.DRAG_SCROLL_MAX_THRESHOLD), Constants.DRAG_SCROLL_MAX_THRESHOLD);
offset /= Constants.DRAG_SCROLL_MAX_THRESHOLD;
return (offset / Math.abs(offset)) + Math.round(offset * (Constants.DRAG_SCROLL_MAX_SPEED - 1));
}
/**
@@ -500,7 +499,7 @@ export class SelectionService extends Disposable implements ISelectionService {
this._screenElement.ownerDocument.addEventListener('mousemove', this._mouseMoveListener);
this._screenElement.ownerDocument.addEventListener('mouseup', this._mouseUpListener);
}
this._dragScrollIntervalTimer = this._coreBrowserService.window.setInterval(() => this._dragScroll(), DRAG_SCROLL_INTERVAL);
this._dragScrollIntervalTimer = this._coreBrowserService.window.setInterval(() => this._dragScroll(), Constants.DRAG_SCROLL_INTERVAL);
}
/**
@@ -675,7 +674,7 @@ export class SelectionService extends Disposable implements ISelectionService {
}
/**
* The callback that occurs every DRAG_SCROLL_INTERVAL ms that does the
* The callback that occurs every Constants.DRAG_SCROLL_INTERVAL ms that does the
* scrolling of the viewport.
*/
private _dragScroll(): void {
@@ -713,7 +712,7 @@ export class SelectionService extends Disposable implements ISelectionService {
this._removeMouseDownListeners();
if (this.selectionText.length <= 1 && timeElapsed < ALT_CLICK_MOVE_CURSOR_TIME && event.altKey && this._optionsService.rawOptions.altClickMovesCursor) {
if (this.selectionText.length <= 1 && timeElapsed < Constants.ALT_CLICK_MOVE_CURSOR_TIME && event.altKey && this._optionsService.rawOptions.altClickMovesCursor) {
if (this._bufferService.buffer.ybase === this._bufferService.buffer.ydisp) {
const coordinates = this._mouseCoordsService.getCoords(
event,
+3 -3
View File
@@ -24,7 +24,7 @@
import { IInstantiationService, IOptionsService, IBufferService, ILogService, ICharsetService, ICoreService, IMouseStateService, IUnicodeService, LogLevelEnum, ITerminalOptions, IOscLinkService } from 'common/services/Services';
import { InstantiationService } from 'common/services/InstantiationService';
import { LogService } from 'common/services/LogService';
import { BufferService, MINIMUM_COLS, MINIMUM_ROWS } from 'common/services/BufferService';
import { BufferService, BufferServiceConstants } from 'common/services/BufferService';
import { OptionsService } from 'common/services/OptionsService';
import { IDisposable, IAttributeData, ICoreTerminal, IScrollEvent } from 'common/Types';
import { CoreService } from 'common/services/CoreService';
@@ -173,8 +173,8 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
return;
}
x = Math.max(x, MINIMUM_COLS);
y = Math.max(y, MINIMUM_ROWS);
x = Math.max(x, BufferServiceConstants.MINIMUM_COLS);
y = Math.max(y, BufferServiceConstants.MINIMUM_ROWS);
// Flush pending writes before resize to avoid race conditions where async
// writes are processed with incorrect dimensions
+18 -20
View File
@@ -41,12 +41,13 @@ const GLEVEL: { [key: string]: number } = { '(': 0, ')': 1, '*': 2, '+': 3, '-':
/**
* Max length of the UTF32 input buffer. Real memory consumption is 4 times higher.
*/
const MAX_PARSEBUFFER_LENGTH = 131072;
/**
* Limit length of title and icon name stacks.
*/
const STACK_LIMIT = 10;
const enum Constants {
MAX_PARSEBUFFER_LENGTH = 131072,
/** Limit length of title and icon name stacks. */
STACK_LIMIT = 10,
// create a warning log if an async handler takes longer than the limit (in ms)
SLOW_ASYNC_LIMIT = 5000
}
// map params to window option
function paramToWindowOption(n: number, opts: IWindowOptions): boolean {
@@ -85,9 +86,6 @@ export enum WindowsOptionsReportType {
GET_CELL_SIZE_PIXELS = 1
}
// create a warning log if an async handler takes longer than the limit (in ms)
const SLOW_ASYNC_LIMIT = 5000;
// Work variables to avoid garbage collection
let $temp = 0;
@@ -393,7 +391,7 @@ export class InputHandler extends Disposable implements IInputHandler {
if (this._logService.logLevel <= LogLevelEnum.WARN) {
let slowTimeout: ReturnType<typeof setTimeout> | undefined;
const slowPromise = new Promise<never>((_res, rej) => {
slowTimeout = setTimeout(() => rej('#SLOW_TIMEOUT'), SLOW_ASYNC_LIMIT);
slowTimeout = setTimeout(() => rej('#SLOW_TIMEOUT'), Constants.SLOW_ASYNC_LIMIT);
});
Promise.race([p, slowPromise])
.then(() => {
@@ -407,7 +405,7 @@ export class InputHandler extends Disposable implements IInputHandler {
if (err !== '#SLOW_TIMEOUT') {
throw err;
}
console.warn(`async parser handler taking longer than ${SLOW_ASYNC_LIMIT} ms`);
console.warn(`async parser handler taking longer than ${Constants.SLOW_ASYNC_LIMIT} ms`);
});
}
}
@@ -445,8 +443,8 @@ export class InputHandler extends Disposable implements IInputHandler {
cursorStartX = this._parseStack.cursorStartX;
cursorStartY = this._parseStack.cursorStartY;
this._parseStack.paused = false;
if (data.length > MAX_PARSEBUFFER_LENGTH) {
start = this._parseStack.position + MAX_PARSEBUFFER_LENGTH;
if (data.length > Constants.MAX_PARSEBUFFER_LENGTH) {
start = this._parseStack.position + Constants.MAX_PARSEBUFFER_LENGTH;
}
}
@@ -463,8 +461,8 @@ export class InputHandler extends Disposable implements IInputHandler {
// resize input buffer if needed
if (this._parseBuffer.length < data.length) {
if (this._parseBuffer.length < MAX_PARSEBUFFER_LENGTH) {
this._parseBuffer = new Uint32Array(Math.min(data.length, MAX_PARSEBUFFER_LENGTH));
if (this._parseBuffer.length < Constants.MAX_PARSEBUFFER_LENGTH) {
this._parseBuffer = new Uint32Array(Math.min(data.length, Constants.MAX_PARSEBUFFER_LENGTH));
}
}
@@ -475,9 +473,9 @@ export class InputHandler extends Disposable implements IInputHandler {
}
// process big data in smaller chunks
if (data.length > MAX_PARSEBUFFER_LENGTH) {
for (let i = start; i < data.length; i += MAX_PARSEBUFFER_LENGTH) {
const end = i + MAX_PARSEBUFFER_LENGTH < data.length ? i + MAX_PARSEBUFFER_LENGTH : data.length;
if (data.length > Constants.MAX_PARSEBUFFER_LENGTH) {
for (let i = start; i < data.length; i += Constants.MAX_PARSEBUFFER_LENGTH) {
const end = i + Constants.MAX_PARSEBUFFER_LENGTH < data.length ? i + Constants.MAX_PARSEBUFFER_LENGTH : data.length;
const len = (typeof data === 'string')
? this._stringDecoder.decode(data.substring(i, end), this._parseBuffer)
: this._utf8Decoder.decode(data.subarray(i, end), this._parseBuffer);
@@ -2955,13 +2953,13 @@ export class InputHandler extends Disposable implements IInputHandler {
case 22: // PushTitle
if (second === 0 || second === 2) {
this._windowTitleStack.push(this._windowTitle);
if (this._windowTitleStack.length > STACK_LIMIT) {
if (this._windowTitleStack.length > Constants.STACK_LIMIT) {
this._windowTitleStack.shift();
}
}
if (second === 0 || second === 1) {
this._iconNameStack.push(this._iconName);
if (this._iconNameStack.length > STACK_LIMIT) {
if (this._iconNameStack.length > Constants.STACK_LIMIT) {
this._iconNameStack.shift();
}
}
+58 -58
View File
@@ -9,25 +9,20 @@ import { CellData } from 'common/buffer/CellData';
import { Attributes, BgFlags, CHAR_DATA_ATTR_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, Content, NULL_CELL_CHAR, NULL_CELL_CODE, NULL_CELL_WIDTH, WHITESPACE_CELL_CHAR } from 'common/buffer/Constants';
import { stringFromCodePoint } from 'common/input/TextDecoder';
/**
* buffer memory layout:
*
* | uint32_t | uint32_t | uint32_t |
* | `content` | `FG` | `BG` |
* | wcwidth(2) comb(1) codepoint(21) | flags(8) R(8) G(8) B(8) | flags(8) R(8) G(8) B(8) |
*/
/** typed array slots taken by one cell */
const CELL_SIZE = 3;
const enum Constants {
/** The number of 32 bit array indices taken by one cell. */
CELL_INDICIES = 3,
/** Factor when to cleanup underlying array buffer after shrinking. */
CLEANUP_THRESHOLD = 2
}
/**
* Cell member indices.
*
* Direct access:
* `content = data[column * CELL_SIZE + Cell.CONTENT];`
* `fg = data[column * CELL_SIZE + Cell.FG];`
* `bg = data[column * CELL_SIZE + Cell.BG];`
* `content = data[column * Constants.CELL_INDICIES + Cell.CONTENT];`
* `fg = data[column * Constants.CELL_INDICIES + Cell.FG];`
* `bg = data[column * Constants.CELL_INDICIES + Cell.BG];`
*/
const enum Cell {
CONTENT = 0,
@@ -41,9 +36,6 @@ export const DEFAULT_ATTR_DATA = Object.freeze(new AttributeData());
let $startIndex = 0;
const $workCell = new CellData();
/** Factor when to cleanup underlying array buffer after shrinking. */
const CLEANUP_THRESHOLD = 2;
/**
* Typed array based bufferline implementation.
*
@@ -60,13 +52,21 @@ const CLEANUP_THRESHOLD = 2;
* memory allocs / GC pressure can be greatly reduced by reusing the CellData object.
*/
export class BufferLine implements IBufferLine {
/**
* Buffer memory layout:
*
* | uint32_t | uint32_t | uint32_t |
* |----------------------------------------|---------------------------------|---------------------------------|
* | `content` | `FG` | `BG` |
* | `wcwidth(2)` `comb(1)` `codepoint(21)` | `flags(8)` `R(8)` `G(8)` `B(8)` | `flags(8)` `R(8)` `G(8)` `B(8)` |
*/
protected _data: Uint32Array;
protected _combined: {[index: number]: string} = {};
protected _extendedAttrs: {[index: number]: IExtendedAttrs | undefined} = {};
public length: number;
constructor(cols: number, fillCellData?: ICellData, public isWrapped: boolean = false) {
this._data = new Uint32Array(cols * CELL_SIZE);
this._data = new Uint32Array(cols * Constants.CELL_INDICIES);
const cell = fillCellData ?? CellData.fromCharData([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]);
for (let i = 0; i < cols; ++i) {
this.setCell(i, cell);
@@ -79,10 +79,10 @@ export class BufferLine implements IBufferLine {
* @deprecated
*/
public get(index: number): CharData {
const content = this._data[index * CELL_SIZE + Cell.CONTENT];
const content = this._data[index * Constants.CELL_INDICIES + Cell.CONTENT];
const cp = content & Content.CODEPOINT_MASK;
return [
this._data[index * CELL_SIZE + Cell.FG],
this._data[index * Constants.CELL_INDICIES + Cell.FG],
(content & Content.IS_COMBINED_MASK)
? this._combined[index]
: (cp) ? stringFromCodePoint(cp) : '',
@@ -98,12 +98,12 @@ export class BufferLine implements IBufferLine {
* @deprecated
*/
public set(index: number, value: CharData): void {
this._data[index * CELL_SIZE + Cell.FG] = value[CHAR_DATA_ATTR_INDEX];
this._data[index * Constants.CELL_INDICIES + Cell.FG] = value[CHAR_DATA_ATTR_INDEX];
if (value[CHAR_DATA_CHAR_INDEX].length > 1) {
this._combined[index] = value[1];
this._data[index * CELL_SIZE + Cell.CONTENT] = index | Content.IS_COMBINED_MASK | (value[CHAR_DATA_WIDTH_INDEX] << Content.WIDTH_SHIFT);
this._data[index * Constants.CELL_INDICIES + Cell.CONTENT] = index | Content.IS_COMBINED_MASK | (value[CHAR_DATA_WIDTH_INDEX] << Content.WIDTH_SHIFT);
} else {
this._data[index * CELL_SIZE + Cell.CONTENT] = value[CHAR_DATA_CHAR_INDEX].charCodeAt(0) | (value[CHAR_DATA_WIDTH_INDEX] << Content.WIDTH_SHIFT);
this._data[index * Constants.CELL_INDICIES + Cell.CONTENT] = value[CHAR_DATA_CHAR_INDEX].charCodeAt(0) | (value[CHAR_DATA_WIDTH_INDEX] << Content.WIDTH_SHIFT);
}
}
@@ -112,22 +112,22 @@ export class BufferLine implements IBufferLine {
* use these when only one value is needed, otherwise use `loadCell`
*/
public getWidth(index: number): number {
return this._data[index * CELL_SIZE + Cell.CONTENT] >> Content.WIDTH_SHIFT;
return this._data[index * Constants.CELL_INDICIES + Cell.CONTENT] >> Content.WIDTH_SHIFT;
}
/** Test whether content has width. */
public hasWidth(index: number): number {
return this._data[index * CELL_SIZE + Cell.CONTENT] & Content.WIDTH_MASK;
return this._data[index * Constants.CELL_INDICIES + Cell.CONTENT] & Content.WIDTH_MASK;
}
/** Get FG cell component. */
public getFg(index: number): number {
return this._data[index * CELL_SIZE + Cell.FG];
return this._data[index * Constants.CELL_INDICIES + Cell.FG];
}
/** Get BG cell component. */
public getBg(index: number): number {
return this._data[index * CELL_SIZE + Cell.BG];
return this._data[index * Constants.CELL_INDICIES + Cell.BG];
}
/**
@@ -136,7 +136,7 @@ export class BufferLine implements IBufferLine {
* from real empty cells.
*/
public hasContent(index: number): number {
return this._data[index * CELL_SIZE + Cell.CONTENT] & Content.HAS_CONTENT_MASK;
return this._data[index * Constants.CELL_INDICIES + Cell.CONTENT] & Content.HAS_CONTENT_MASK;
}
/**
@@ -145,7 +145,7 @@ export class BufferLine implements IBufferLine {
* a single UTF32 codepoint or the last codepoint of a combined string.
*/
public getCodePoint(index: number): number {
const content = this._data[index * CELL_SIZE + Cell.CONTENT];
const content = this._data[index * Constants.CELL_INDICIES + Cell.CONTENT];
if (content & Content.IS_COMBINED_MASK) {
return this._combined[index].charCodeAt(this._combined[index].length - 1);
}
@@ -154,12 +154,12 @@ export class BufferLine implements IBufferLine {
/** Test whether the cell contains a combined string. */
public isCombined(index: number): number {
return this._data[index * CELL_SIZE + Cell.CONTENT] & Content.IS_COMBINED_MASK;
return this._data[index * Constants.CELL_INDICIES + Cell.CONTENT] & Content.IS_COMBINED_MASK;
}
/** Returns the string content of the cell. */
public getString(index: number): string {
const content = this._data[index * CELL_SIZE + Cell.CONTENT];
const content = this._data[index * Constants.CELL_INDICIES + Cell.CONTENT];
if (content & Content.IS_COMBINED_MASK) {
return this._combined[index];
}
@@ -172,7 +172,7 @@ export class BufferLine implements IBufferLine {
/** Get state of protected flag. */
public isProtected(index: number): number {
return this._data[index * CELL_SIZE + Cell.BG] & BgFlags.PROTECTED;
return this._data[index * Constants.CELL_INDICIES + Cell.BG] & BgFlags.PROTECTED;
}
/**
@@ -180,7 +180,7 @@ export class BufferLine implements IBufferLine {
* to GC as it significantly reduced the amount of new objects/references needed.
*/
public loadCell(index: number, cell: ICellData): ICellData {
$startIndex = index * CELL_SIZE;
$startIndex = index * Constants.CELL_INDICIES;
cell.content = this._data[$startIndex + Cell.CONTENT];
cell.fg = this._data[$startIndex + Cell.FG];
cell.bg = this._data[$startIndex + Cell.BG];
@@ -203,9 +203,9 @@ export class BufferLine implements IBufferLine {
if (cell.bg & BgFlags.HAS_EXTENDED) {
this._extendedAttrs[index] = cell.extended;
}
this._data[index * CELL_SIZE + Cell.CONTENT] = cell.content;
this._data[index * CELL_SIZE + Cell.FG] = cell.fg;
this._data[index * CELL_SIZE + Cell.BG] = cell.bg;
this._data[index * Constants.CELL_INDICIES + Cell.CONTENT] = cell.content;
this._data[index * Constants.CELL_INDICIES + Cell.FG] = cell.fg;
this._data[index * Constants.CELL_INDICIES + Cell.BG] = cell.bg;
}
/**
@@ -217,9 +217,9 @@ export class BufferLine implements IBufferLine {
if (attrs.bg & BgFlags.HAS_EXTENDED) {
this._extendedAttrs[index] = attrs.extended;
}
this._data[index * CELL_SIZE + Cell.CONTENT] = codePoint | (width << Content.WIDTH_SHIFT);
this._data[index * CELL_SIZE + Cell.FG] = attrs.fg;
this._data[index * CELL_SIZE + Cell.BG] = attrs.bg;
this._data[index * Constants.CELL_INDICIES + Cell.CONTENT] = codePoint | (width << Content.WIDTH_SHIFT);
this._data[index * Constants.CELL_INDICIES + Cell.FG] = attrs.fg;
this._data[index * Constants.CELL_INDICIES + Cell.BG] = attrs.bg;
}
/**
@@ -229,7 +229,7 @@ export class BufferLine implements IBufferLine {
* by the previous `setDataFromCodePoint` call, we can omit it here.
*/
public addCodepointToCell(index: number, codePoint: number, width: number): void {
let content = this._data[index * CELL_SIZE + Cell.CONTENT];
let content = this._data[index * Constants.CELL_INDICIES + Cell.CONTENT];
if (content & Content.IS_COMBINED_MASK) {
// we already have a combined string, simply add
this._combined[index] += stringFromCodePoint(codePoint);
@@ -251,7 +251,7 @@ export class BufferLine implements IBufferLine {
content &= ~Content.WIDTH_MASK;
content |= width << Content.WIDTH_SHIFT;
}
this._data[index * CELL_SIZE + Cell.CONTENT] = content;
this._data[index * Constants.CELL_INDICIES + Cell.CONTENT] = content;
}
public insertCells(pos: number, n: number, fillCellData: ICellData): void {
@@ -344,13 +344,13 @@ export class BufferLine implements IBufferLine {
* The underlying array buffer will not change if there is still enough space
* to hold the new buffer line data.
* Returns a boolean indicating, whether a `cleanupMemory` call would free
* excess memory (true after shrinking > CLEANUP_THRESHOLD).
* excess memory (true after shrinking > Constants.CLEANUP_THRESHOLD).
*/
public resize(cols: number, fillCellData: ICellData): boolean {
if (cols === this.length) {
return this._data.length * 4 * CLEANUP_THRESHOLD < this._data.buffer.byteLength;
return this._data.length * 4 * Constants.CLEANUP_THRESHOLD < this._data.buffer.byteLength;
}
const uint32Cells = cols * CELL_SIZE;
const uint32Cells = cols * Constants.CELL_INDICIES;
if (cols > this.length) {
if (this._data.buffer.byteLength >= uint32Cells * 4) {
// optimization: avoid alloc and data copy if buffer has enough room
@@ -385,17 +385,17 @@ export class BufferLine implements IBufferLine {
}
}
this.length = cols;
return uint32Cells * 4 * CLEANUP_THRESHOLD < this._data.buffer.byteLength;
return uint32Cells * 4 * Constants.CLEANUP_THRESHOLD < this._data.buffer.byteLength;
}
/**
* Cleanup underlying array buffer.
* A cleanup will be triggered if the array buffer exceeds the actual used
* memory by a factor of CLEANUP_THRESHOLD.
* memory by a factor of Constants.CLEANUP_THRESHOLD.
* Returns 0 or 1 indicating whether a cleanup happened.
*/
public cleanupMemory(): number {
if (this._data.length * 4 * CLEANUP_THRESHOLD < this._data.buffer.byteLength) {
if (this._data.length * 4 * Constants.CLEANUP_THRESHOLD < this._data.buffer.byteLength) {
const data = new Uint32Array(this._data.length);
data.set(this._data);
this._data = data;
@@ -459,8 +459,8 @@ export class BufferLine implements IBufferLine {
public getTrimmedLength(): number {
for (let i = this.length - 1; i >= 0; --i) {
if ((this._data[i * CELL_SIZE + Cell.CONTENT] & Content.HAS_CONTENT_MASK)) {
return i + (this._data[i * CELL_SIZE + Cell.CONTENT] >> Content.WIDTH_SHIFT);
if ((this._data[i * Constants.CELL_INDICIES + Cell.CONTENT] & Content.HAS_CONTENT_MASK)) {
return i + (this._data[i * Constants.CELL_INDICIES + Cell.CONTENT] >> Content.WIDTH_SHIFT);
}
}
return 0;
@@ -468,8 +468,8 @@ export class BufferLine implements IBufferLine {
public getNoBgTrimmedLength(): number {
for (let i = this.length - 1; i >= 0; --i) {
if ((this._data[i * CELL_SIZE + Cell.CONTENT] & Content.HAS_CONTENT_MASK) || (this._data[i * CELL_SIZE + Cell.BG] & Attributes.CM_MASK)) {
return i + (this._data[i * CELL_SIZE + Cell.CONTENT] >> Content.WIDTH_SHIFT);
if ((this._data[i * Constants.CELL_INDICIES + Cell.CONTENT] & Content.HAS_CONTENT_MASK) || (this._data[i * Constants.CELL_INDICIES + Cell.BG] & Attributes.CM_MASK)) {
return i + (this._data[i * Constants.CELL_INDICIES + Cell.CONTENT] >> Content.WIDTH_SHIFT);
}
}
return 0;
@@ -479,19 +479,19 @@ export class BufferLine implements IBufferLine {
const srcData = src._data;
if (applyInReverse) {
for (let cell = length - 1; cell >= 0; cell--) {
for (let i = 0; i < CELL_SIZE; i++) {
this._data[(destCol + cell) * CELL_SIZE + i] = srcData[(srcCol + cell) * CELL_SIZE + i];
for (let i = 0; i < Constants.CELL_INDICIES; i++) {
this._data[(destCol + cell) * Constants.CELL_INDICIES + i] = srcData[(srcCol + cell) * Constants.CELL_INDICIES + i];
}
if (srcData[(srcCol + cell) * CELL_SIZE + Cell.BG] & BgFlags.HAS_EXTENDED) {
if (srcData[(srcCol + cell) * Constants.CELL_INDICIES + Cell.BG] & BgFlags.HAS_EXTENDED) {
this._extendedAttrs[destCol + cell] = src._extendedAttrs[srcCol + cell];
}
}
} else {
for (let cell = 0; cell < length; cell++) {
for (let i = 0; i < CELL_SIZE; i++) {
this._data[(destCol + cell) * CELL_SIZE + i] = srcData[(srcCol + cell) * CELL_SIZE + i];
for (let i = 0; i < Constants.CELL_INDICIES; i++) {
this._data[(destCol + cell) * Constants.CELL_INDICIES + i] = srcData[(srcCol + cell) * Constants.CELL_INDICIES + i];
}
if (srcData[(srcCol + cell) * CELL_SIZE + Cell.BG] & BgFlags.HAS_EXTENDED) {
if (srcData[(srcCol + cell) * Constants.CELL_INDICIES + Cell.BG] & BgFlags.HAS_EXTENDED) {
this._extendedAttrs[destCol + cell] = src._extendedAttrs[srcCol + cell];
}
}
@@ -531,7 +531,7 @@ export class BufferLine implements IBufferLine {
}
let result = '';
while (startCol < endCol) {
const content = this._data[startCol * CELL_SIZE + Cell.CONTENT];
const content = this._data[startCol * Constants.CELL_INDICIES + Cell.CONTENT];
const cp = content & Content.CODEPOINT_MASK;
const chars = (content & Content.IS_COMBINED_MASK) ? this._combined[startCol] : (cp) ? stringFromCodePoint(cp) : WHITESPACE_CELL_CHAR;
result += chars;
+30 -30
View File
@@ -9,30 +9,30 @@ import { Emitter } from 'common/Event';
declare const setTimeout: (handler: () => void, timeout?: number) => void;
/**
* Safety watermark to avoid memory exhaustion and browser engine crash on fast data input.
* Enable flow control to avoid this limit and make sure that your backend correctly
* propagates this to the underlying pty. (see docs for further instructions)
* Since this limit is meant as a safety parachute to prevent browser crashs,
* it is set to a very high number. Typically xterm.js gets unresponsive with
* a 100 times lower number (>500 kB).
*/
const DISCARD_WATERMARK = 50000000; // ~50 MB
/**
* The max number of ms to spend on writes before allowing the renderer to
* catch up with a 0ms setTimeout. A value of < 33 to keep us close to
* 30fps, and a value of < 16 to try to run at 60fps. Of course, the real FPS
* depends on the time it takes for the renderer to draw the frame.
*/
const WRITE_TIMEOUT_MS = 12;
/**
* Threshold of max held chunks in the write buffer, that were already processed.
* This is a tradeoff between extensive write buffer shifts (bad runtime) and high
* memory consumption by data thats not used anymore.
*/
const WRITE_BUFFER_LENGTH_THRESHOLD = 50;
const enum Constants {
/**
* Safety watermark to avoid memory exhaustion and browser engine crash on fast data input.
* Enable flow control to avoid this limit and make sure that your backend correctly
* propagates this to the underlying pty. (see docs for further instructions)
* Since this limit is meant as a safety parachute to prevent browser crashs,
* it is set to a very high number. Typically xterm.js gets unresponsive with
* a 100 times lower number (>500 kB).
*/
DISCARD_WATERMARK = 50000000, // ~50 MB
/**
* The max number of ms to spend on writes before allowing the renderer to
* catch up with a 0ms setTimeout. A value of < 33 to keep us close to
* 30fps, and a value of < 16 to try to run at 60fps. Of course, the real FPS
* depends on the time it takes for the renderer to draw the frame.
*/
WRITE_TIMEOUT_MS = 12,
/**
* Threshold of max held chunks in the write buffer, that were already processed.
* This is a tradeoff between extensive write buffer shifts (bad runtime) and high
* memory consumption by data thats not used anymore.
*/
WRITE_BUFFER_LENGTH_THRESHOLD = 50
}
export class WriteBuffer extends Disposable {
private _writeBuffer: (string | Uint8Array)[] = [];
@@ -133,7 +133,7 @@ export class WriteBuffer extends Disposable {
}
public write(data: string | Uint8Array, callback?: () => void): void {
if (this._pendingData > DISCARD_WATERMARK) {
if (this._pendingData > Constants.DISCARD_WATERMARK) {
throw new Error('write data discarded, use flow control to avoid losing data');
}
@@ -169,7 +169,7 @@ export class WriteBuffer extends Disposable {
* effectively lowering the redrawing needs, schematically:
*
* macroTask _innerWrite:
* if (performance.now() - (lastTime | 0) < WRITE_TIMEOUT_MS):
* if (performance.now() - (lastTime | 0) < Constants.WRITE_TIMEOUT_MS):
* schedule microTask _innerWrite(lastTime)
* else:
* schedule macroTask _innerWrite(0)
@@ -218,7 +218,7 @@ export class WriteBuffer extends Disposable {
* responsibility to slice hard work), but we can at least schedule a screen update as we
* gain control.
*/
const continuation: (r: boolean) => void = (r: boolean) => performance.now() - startTime >= WRITE_TIMEOUT_MS
const continuation: (r: boolean) => void = (r: boolean) => performance.now() - startTime >= Constants.WRITE_TIMEOUT_MS
? setTimeout(() => this._innerWrite(0, r))
: this._innerWrite(startTime, r);
@@ -235,7 +235,7 @@ export class WriteBuffer extends Disposable {
* current microtask queue (executed before setTimeout).
*/
// const continuation: (r: boolean) => void = performance.now() - startTime >=
// WRITE_TIMEOUT_MS
// Constants.WRITE_TIMEOUT_MS
// ? r => setTimeout(() => this._innerWrite(0, r))
// : r => this._innerWrite(startTime, r);
@@ -255,14 +255,14 @@ export class WriteBuffer extends Disposable {
this._bufferOffset++;
this._pendingData -= data.length;
if (performance.now() - startTime >= WRITE_TIMEOUT_MS) {
if (performance.now() - startTime >= Constants.WRITE_TIMEOUT_MS) {
break;
}
}
if (this._writeBuffer.length > this._bufferOffset) {
// Allow renderer to catch up before processing the next batch
// trim already processed chunks if we are above threshold
if (this._bufferOffset > WRITE_BUFFER_LENGTH_THRESHOLD) {
if (this._bufferOffset > Constants.WRITE_BUFFER_LENGTH_THRESHOLD) {
this._writeBuffer = this._writeBuffer.slice(this._bufferOffset);
this._callbacks = this._callbacks.slice(this._bufferOffset);
this._bufferOffset = 0;
+14 -8
View File
@@ -4,10 +4,16 @@
*/
import { IParams, ParamsArray } from 'common/parser/Types';
// max value supported for a single param/subparam (clamped to positive int32 range)
const MAX_VALUE = 0x7FFFFFFF;
// max allowed subparams for a single sequence (hardcoded limitation)
const MAX_SUBPARAMS = 256;
const enum Constants {
/**
* Max value supported for a single param/subparam (clamped to positive int32 range)
*/
MAX_VALUE = 0x7FFFFFFF,
/**
* Max allowed subparams for a single sequence (hardcoded limitation)
*/
MAX_SUBPARAMS = 256
}
/**
* Params storage class.
@@ -70,7 +76,7 @@ export class Params implements IParams {
* @param maxSubParamsLength max length of storable sub parameters
*/
constructor(public maxLength: number = 32, public maxSubParamsLength: number = 32) {
if (maxSubParamsLength > MAX_SUBPARAMS) {
if (maxSubParamsLength > Constants.MAX_SUBPARAMS) {
throw new Error('maxSubParamsLength must not be greater than 256');
}
this.params = new Int32Array(maxLength);
@@ -159,7 +165,7 @@ export class Params implements IParams {
throw new Error('values lesser than -1 are not allowed');
}
this._subParamsIdx[this.length] = this._subParamsLength << 8 | this._subParamsLength;
this.params[this.length++] = value > MAX_VALUE ? MAX_VALUE : value;
this.params[this.length++] = value > Constants.MAX_VALUE ? Constants.MAX_VALUE : value;
}
/**
@@ -181,7 +187,7 @@ export class Params implements IParams {
if (value < -1) {
throw new Error('values lesser than -1 are not allowed');
}
this._subParams[this._subParamsLength++] = value > MAX_VALUE ? MAX_VALUE : value;
this._subParams[this._subParamsLength++] = value > Constants.MAX_VALUE ? Constants.MAX_VALUE : value;
this._subParamsIdx[this.length - 1]++;
}
@@ -237,6 +243,6 @@ export class Params implements IParams {
const store = this._digitIsSub ? this._subParams : this.params;
const cur = store[length - 1];
store[length - 1] = ~cur ? Math.min(cur * 10 + value, MAX_VALUE) : value;
store[length - 1] = ~cur ? Math.min(cur * 10 + value, Constants.MAX_VALUE) : value;
}
}
+6 -4
View File
@@ -10,8 +10,10 @@ import { IBuffer, IBufferSet } from 'common/buffer/Types';
import { IBufferService, ILogService, IOptionsService, type IBufferResizeEvent } from 'common/services/Services';
import { Emitter } from 'common/Event';
export const MINIMUM_COLS = 2; // Less than 2 can mess with wide chars
export const MINIMUM_ROWS = 1;
export const enum BufferServiceConstants {
MINIMUM_COLS = 2, // Less than 2 can mess with wide chars
MINIMUM_ROWS = 1
}
export class BufferService extends Disposable implements IBufferService {
public serviceBrand: any;
@@ -37,8 +39,8 @@ export class BufferService extends Disposable implements IBufferService {
@ILogService logService: ILogService
) {
super();
this.cols = Math.max(optionsService.rawOptions.cols || 0, MINIMUM_COLS);
this.rows = Math.max(optionsService.rawOptions.rows || 0, MINIMUM_ROWS);
this.cols = Math.max(optionsService.rawOptions.cols || 0, BufferServiceConstants.MINIMUM_COLS);
this.rows = Math.max(optionsService.rawOptions.rows || 0, BufferServiceConstants.MINIMUM_ROWS);
this.buffers = this._register(new BufferSet(optionsService, this, logService));
this._register(this.buffers.onBufferActivate(e => {
this._onScroll.fire(e.activeBuffer.ydisp);
+9 -7
View File
@@ -11,13 +11,15 @@
import { IServiceIdentifier } from 'common/services/Services';
const DI_TARGET = 'di$target';
const DI_DEPENDENCIES = 'di$dependencies';
const enum Constants {
DI_TARGET = 'di$target',
DI_DEPENDENCIES = 'di$dependencies'
}
export const serviceRegistry: Map<string, IServiceIdentifier<any>> = new Map();
export function getServiceDependencies(ctor: any): { id: IServiceIdentifier<any>, index: number, optional: boolean }[] {
return ctor[DI_DEPENDENCIES] || [];
return ctor[Constants.DI_DEPENDENCIES] || [];
}
export function createDecorator<T>(id: string): IServiceIdentifier<T> {
@@ -40,10 +42,10 @@ export function createDecorator<T>(id: string): IServiceIdentifier<T> {
}
function storeServiceDependency(id: Function, target: Function, index: number): void {
if ((target as any)[DI_TARGET] === target) {
(target as any)[DI_DEPENDENCIES].push({ id, index });
if ((target as any)[Constants.DI_TARGET] === target) {
(target as any)[Constants.DI_DEPENDENCIES].push({ id, index });
} else {
(target as any)[DI_DEPENDENCIES] = [{ id, index }];
(target as any)[DI_TARGET] = target;
(target as any)[Constants.DI_DEPENDENCIES] = [{ id, index }];
(target as any)[Constants.DI_TARGET] = target;
}
}