Merge branch 'master' into clusters

This commit is contained in:
Daniel Imms
2023-08-18 15:20:02 -07:00
committed by GitHub
13 changed files with 188 additions and 39 deletions
@@ -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.
@@ -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;
+51 -1
View File
@@ -4,7 +4,8 @@
*/
import { assert } from 'chai';
import { Disposable } from 'common/Lifecycle';
import { Disposable, MutableDisposable } from 'common/Lifecycle';
import { IDisposable } from 'common/Types';
class TestDisposable extends Disposable {
public get isDisposed(): boolean {
@@ -43,3 +44,52 @@ describe('Disposable', () => {
});
});
});
describe('MutableDisposable', () => {
const mutable = new MutableDisposable();
class TrackedDisposable extends Disposable {
public get isDisposed(): boolean { return this._isDisposed; }
}
describe('value', () => {
it('should set the value', () => {
const d1 = new TrackedDisposable();
mutable.value = d1;
assert.strictEqual(mutable.value, d1);
assert.isFalse(d1.isDisposed);
});
it('should dispose of any previous value', () => {
const d1 = new TrackedDisposable();
const d2 = new TrackedDisposable();
mutable.value = d1;
mutable.value = d2;
assert.strictEqual(mutable.value, d2);
assert.isTrue(d1.isDisposed);
assert.isFalse(d2.isDisposed);
});
});
describe('clear', () => {
it('should clear and dispose of the object', () => {
const d1 = new TrackedDisposable();
mutable.value = d1;
mutable.clear();
assert.strictEqual(mutable.value, undefined);
assert.isTrue(d1.isDisposed);
});
});
it('dispose', () => {
it('should dispose of the object', () => {
const d1 = new TrackedDisposable();
mutable.value = d1;
mutable.dispose();
assert.strictEqual(mutable.value, undefined);
assert.isTrue(d1.isDisposed);
});
it('should prevent using the MutableDisposable again', () => {
const d1 = new TrackedDisposable();
mutable.value = d1;
mutable.dispose();
mutable.value = new TrackedDisposable();
assert.strictEqual(mutable.value, undefined);
});
});
});
+36
View File
@@ -50,6 +50,42 @@ export abstract class Disposable implements IDisposable {
}
}
export class MutableDisposable<T extends IDisposable> implements IDisposable {
private _value?: T;
private _isDisposed = false;
/**
* Gets the value if it exists.
*/
public get value(): T | undefined {
return this._isDisposed ? undefined : this._value;
}
/**
* Sets the value, disposing of the old value if it exists.
*/
public set value(value: T | undefined) {
if (this._isDisposed || value === this._value) {
return;
}
this._value?.dispose();
this._value = value;
}
/**
* Resets the stored value and disposes of the previously stored value.
*/
public clear(): void {
this.value = undefined;
}
public dispose(): void {
this._isDisposed = true;
this._value?.dispose();
this._value = undefined;
}
}
/**
* Wrap a function in a disposable.
*/
+1
View File
@@ -105,6 +105,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 { }
+37
View File
@@ -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,
@@ -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 {
@@ -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);
@@ -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;
};
}
+8 -6
View File
@@ -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');
@@ -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;
@@ -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;