Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions addons/xterm-addon-webgl/src/GlyphRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { IRasterizedGlyph, IRenderDimensions, ITextureAtlas } from 'browser/rend
import { Disposable, toDisposable } from 'common/Lifecycle';
import { throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
import { TextureAtlas } from 'browser/renderer/shared/TextureAtlas';
import { ILogService } from 'common/services/Services';
import { traceCall } from 'common/services/LogService';

interface IVertices {
attributes: Float32Array;
Expand Down Expand Up @@ -212,6 +214,7 @@ export class GlyphRenderer extends Disposable {
return this._atlas ? this._atlas.beginFrame() : true;
}

@traceCall
public updateCell(x: number, y: number, code: number, bg: number, fg: number, ext: number, chars: string, lastBg: number): void {
// Since this function is called for every cell (`rows*cols`), it must be very optimized. It
// should not instantiate any variables unless a new glyph is drawn to the cache where the
Expand Down
8 changes: 7 additions & 1 deletion addons/xterm-addon-webgl/src/WebglAddon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import { ITerminal } from 'browser/Types';
import { EventEmitter, forwardEvent } from 'common/EventEmitter';
import { Disposable, toDisposable } from 'common/Lifecycle';
import { getSafariVersion, isSafari } from 'common/Platform';
import { ICoreService, IDecorationService, IOptionsService } from 'common/services/Services';
import { ICoreService, IDecorationService, ILogService, IOptionsService } from 'common/services/Services';
import { ITerminalAddon, Terminal } from 'xterm';
import { WebglRenderer } from './WebglRenderer';
import { setTraceLogger } from 'common/services/LogService';

export class WebglAddon extends Disposable implements ITerminalAddon {
private _terminal?: Terminal;
Expand Down Expand Up @@ -51,8 +52,13 @@ export class WebglAddon extends Disposable implements ITerminalAddon {
const charSizeService: ICharSizeService = unsafeCore._charSizeService;
const coreBrowserService: ICoreBrowserService = unsafeCore._coreBrowserService;
const decorationService: IDecorationService = unsafeCore._decorationService;
const logService: ILogService = unsafeCore._logService;
const themeService: IThemeService = unsafeCore._themeService;

// Set trace logger just in case it hasn't been yet which could happen when the addon is
// bundled separately to the core module
setTraceLogger(logService);

this._renderer = this.register(new WebglRenderer(
terminal,
characterJoinerService,
Expand Down
4 changes: 3 additions & 1 deletion addons/xterm-addon-webgl/src/WebglRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { CellData } from 'common/buffer/CellData';
import { Attributes, Content, NULL_CELL_CHAR, NULL_CELL_CODE } from 'common/buffer/Constants';
import { EventEmitter, forwardEvent } from 'common/EventEmitter';
import { Disposable, getDisposeArrayDisposable, toDisposable } from 'common/Lifecycle';
import { ICoreService, IDecorationService, IOptionsService } from 'common/services/Services';
import { ICoreService, IDecorationService, ILogService, IOptionsService } from 'common/services/Services';
import { CharData, IBufferLine, ICellData } from 'common/Types';
import { IDisposable, Terminal } from 'xterm';
import { GlyphRenderer } from './GlyphRenderer';
Expand All @@ -27,6 +27,7 @@ import { LinkRenderLayer } from './renderLayer/LinkRenderLayer';
import { IRenderLayer } from './renderLayer/Types';
import { COMBINED_CHAR_BIT_MASK, RenderModel, RENDER_MODEL_BG_OFFSET, RENDER_MODEL_EXT_OFFSET, RENDER_MODEL_FG_OFFSET, RENDER_MODEL_INDICIES_PER_CELL } from './RenderModel';
import { IWebGL2RenderingContext } from './Types';
import { traceCall } from 'common/services/LogService';

export class WebglRenderer extends Disposable implements IRenderer {
private _renderLayers: IRenderLayer[];
Expand Down Expand Up @@ -323,6 +324,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
return false;
}

@traceCall
public renderRows(start: number, end: number): void {
if (!this._isAttached) {
if (this._coreBrowserService.window.document.body.contains(this._core.screenElement!) && this._charSizeService.width && this._charSizeService.height) {
Expand Down
1 change: 1 addition & 0 deletions addons/xterm-addon-webgl/src/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
},
"strict": true,
"downlevelIteration": true,
"experimentalDecorators": true,
"types": [
"../../../node_modules/@types/mocha"
]
Expand Down
6 changes: 3 additions & 3 deletions demo/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ function initOptions(term: TerminalType): void {
fontFamily: null,
fontWeight: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'],
fontWeightBold: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'],
logLevel: ['debug', 'info', 'warn', 'error', 'off'],
logLevel: ['trace', 'debug', 'info', 'warn', 'error', 'off'],
theme: ['default', 'xtermjs', 'sapphire', 'light'],
wordSeparator: null
};
Expand Down Expand Up @@ -1227,7 +1227,7 @@ Test BG-colored Erase (BCE):
for all cells to the right.

def 41 42 43 44 45 46 47\x1b[47m
\x1b[m \x1b[41m \x1b[42m \x1b[43m \x1b[44m \x1b[45m \x1b[46m \x1b[47m
\x1b[m \x1b[41m \x1b[42m \x1b[43m \x1b[44m \x1b[45m \x1b[46m \x1b[47m
\x1b[m\x1b[5X\x1b[41m\x1b[5C\x1b[5X\x1b[42m\x1b[5C\x1b[5X\x1b[43m\x1b[5C\x1b[5X\x1b[44m\x1b[5C\x1b[5X\x1b[45m\x1b[5C\x1b[5X\x1b[46m\x1b[5C\x1b[5X\x1b[47m\x1b[5C\x1b[5X\x1b[m
`;
term.write(data.split('\n').join('\r\n'));
Expand Down Expand Up @@ -1263,7 +1263,7 @@ function initImageAddonExposed(): void {
term.write('\r\n');
term.write(new Uint8Array(buffer));
});

const iip_demo = (url: string) => () => fetch(url)
.then(resp => resp.arrayBuffer())
.then(buffer => {
Expand Down
2 changes: 2 additions & 0 deletions src/browser/renderer/shared/TextureAtlas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { IdleTaskQueue } from 'common/TaskQueue';
import { IBoundingBox, ICharAtlasConfig, IRasterizedGlyph, IRequestRedrawEvent, ITextureAtlas } from 'browser/renderer/shared/Types';
import { EventEmitter } from 'common/EventEmitter';
import { IColorContrastCache } from 'browser/Types';
import { traceCall } from 'common/services/LogService';

/**
* A shared object which is used to draw nothing for a particular cell.
Expand Down Expand Up @@ -425,6 +426,7 @@ export class TextureAtlas implements ITextureAtlas {
return this._config.colors.contrastCache;
}

@traceCall
private _drawToCache(codeOrChars: number | string, bg: number, fg: number, ext: number, restrictToCellHeight: boolean = false): IRasterizedGlyph {
const chars = typeof codeOrChars === 'number' ? String.fromCharCode(codeOrChars) : codeOrChars;

Expand Down
1 change: 1 addition & 0 deletions src/common/TestUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export class MockCoreService implements ICoreService {
export class MockLogService implements ILogService {
public serviceBrand: any;
public logLevel = LogLevelEnum.DEBUG;
public trace(message: any, ...optionalParams: any[]): void { }
public debug(message: any, ...optionalParams: any[]): void { }
public info(message: any, ...optionalParams: any[]): void { }
public warn(message: any, ...optionalParams: any[]): void { }
Expand Down
37 changes: 37 additions & 0 deletions src/common/services/LogService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ interface IConsole {
declare const console: IConsole;

const optionsKeyToLogLevel: { [key: string]: LogLevelEnum } = {
trace: LogLevelEnum.TRACE,
debug: LogLevelEnum.DEBUG,
info: LogLevelEnum.INFO,
warn: LogLevelEnum.WARN,
Expand All @@ -42,6 +43,9 @@ export class LogService extends Disposable implements ILogService {
super();
this._updateLogLevel();
this.register(this._optionsService.onSpecificOptionChange('logLevel', () => this._updateLogLevel()));

// For trace logging, assume the latest created log service is valid
traceLogger = this;
}

private _updateLogLevel(): void {
Expand All @@ -61,6 +65,12 @@ export class LogService extends Disposable implements ILogService {
type.call(console, (this._optionsService.options.logger ? '' : LOG_PREFIX) + message, ...optionalParams);
}

public trace(message: string, ...optionalParams: any[]): void {
if (this._logLevel <= LogLevelEnum.TRACE) {
this._log(this._optionsService.options.logger?.trace.bind(this._optionsService.options.logger) ?? console.log, message, optionalParams);
}
}

public debug(message: string, ...optionalParams: any[]): void {
if (this._logLevel <= LogLevelEnum.DEBUG) {
this._log(this._optionsService.options.logger?.debug.bind(this._optionsService.options.logger) ?? console.log, message, optionalParams);
Expand All @@ -85,3 +95,30 @@ export class LogService extends Disposable implements ILogService {
}
}
}

let traceLogger: ILogService;
export function setTraceLogger(logger: ILogService): void {
traceLogger = logger;
}

/**
* A decorator that can be used to automatically log trace calls to the decorated function.
*/
export function traceCall(_target: any, key: string, descriptor: any): any {
if (typeof descriptor.value !== 'function') {
throw new Error('not supported');
}
const fnKey = 'value';
const fn = descriptor.value;
descriptor[fnKey] = function (...args: any[]) {
// Early exit
if (traceLogger.logLevel !== LogLevelEnum.TRACE) {
return fn.apply(this, args);
}

traceLogger.trace(`GlyphRenderer#${fn.name}(${args.map(e => JSON.stringify(e)).join(', ')})`);
const result = fn.apply(this, args);
traceLogger.trace(`GlyphRenderer#${fn.name} return`, result);
return result;
};
}
14 changes: 8 additions & 6 deletions src/common/services/Services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,12 @@ export interface IInstantiationService {
}

export enum LogLevelEnum {
DEBUG = 0,
INFO = 1,
WARN = 2,
ERROR = 3,
OFF = 4
TRACE = 0,
DEBUG = 1,
INFO = 2,
WARN = 3,
ERROR = 4,
OFF = 5
}

export const ILogService = createDecorator<ILogService>('LogService');
Expand All @@ -155,6 +156,7 @@ export interface ILogService {

readonly logLevel: LogLevelEnum;

trace(message: any, ...optionalParams: any[]): void;
debug(message: any, ...optionalParams: any[]): void;
info(message: any, ...optionalParams: any[]): void;
warn(message: any, ...optionalParams: any[]): void;
Expand Down Expand Up @@ -201,7 +203,7 @@ export interface IOptionsService {
}

export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900' | number;
export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'off';
export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'off';

export interface ITerminalOptions {
allowProposedApi?: boolean;
Expand Down
20 changes: 13 additions & 7 deletions typings/xterm-headless.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ declare module 'xterm-headless' {
/**
* A string representing log level.
*/
export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'off';
export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'off';

/**
* An object containing options for the terminal.
Expand Down Expand Up @@ -100,11 +100,12 @@ declare module 'xterm-headless' {
* What log level to use, this will log for all levels below and including
* what is set:
*
* 1. debug
* 2. info (default)
* 3. warn
* 4. error
* 5. off
* 1. trace
* 2. debug
* 3. info (default)
* 4. warn
* 5. error
* 6. off
*/
logLevel?: LogLevel;

Expand Down Expand Up @@ -314,9 +315,14 @@ declare module 'xterm-headless' {
* A replacement logger for `console`.
*/
export interface ILogger {
/**
* Log a trace message, this will only be called if
* {@link ITerminalOptions.logLevel} is set to trace.
*/
trace(message: string, ...args: any[]): void;
/**
* Log a debug message, this will only be called if
* {@link ITerminalOptions.logLevel} is set to debug.
* {@link ITerminalOptions.logLevel} is set to debug or below.
*/
debug(message: string, ...args: any[]): void;
/**
Expand Down
20 changes: 13 additions & 7 deletions typings/xterm.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ declare module 'xterm' {
/**
* A string representing log level.
*/
export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'off';
export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'off';

/**
* An object containing options for the terminal.
Expand Down Expand Up @@ -158,11 +158,12 @@ declare module 'xterm' {
* What log level to use, this will log for all levels below and including
* what is set:
*
* 1. debug
* 2. info (default)
* 3. warn
* 4. error
* 5. off
* 1. trace
* 2. debug
* 3. info (default)
* 4. warn
* 5. error
* 6. off
*/
logLevel?: LogLevel;

Expand Down Expand Up @@ -391,9 +392,14 @@ declare module 'xterm' {
* A replacement logger for `console`.
*/
export interface ILogger {
/**
* Log a trace message, this will only be called if
* {@link ITerminalOptions.logLevel} is set to trace.
*/
trace(message: string, ...args: any[]): void;
/**
* Log a debug message, this will only be called if
* {@link ITerminalOptions.logLevel} is set to debug.
* {@link ITerminalOptions.logLevel} is set to debug or below.
*/
debug(message: string, ...args: any[]): void;
/**
Expand Down