Files
xterm.js/src/browser/renderer/dom/WidthCache.test.ts
T
Daniel ImmsandCursor 17ad33dc3d Remove TypeScript path mappings in favor of relative imports
Fixes https://github.com/xtermjs/xterm.js/issues/5896

TypeScript path mappings for common/*, browser/*, and headless/*
were not rewritten in emitted JavaScript, which forced webpack resolve
aliases and NODE_PATH workarounds so runtime could resolve modules.
That added build complexity and broke tooling such as ESLint import/no-cycle.

Changes:
- Convert ~750 imports across src/, addons/, and test/ to relative paths
- Remove common/browser/headless paths and src catch-all mappings from tsconfigs
  (keep @xterm/addon-* demo and addon typings paths)
- Remove webpack resolve.alias for common, browser, headless, and vs
- Drop NODE_PATH from unit tests, benchmarks, and VS Code launch config
- Fix addon-image IIPImageStorage to import ./Types after removing catch-all *

Verified: npm run build, esbuild, package, package-headless
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-31 09:16:10 -07:00

143 lines
4.8 KiB
TypeScript

/**
* Copyright (c) 2023 The xterm.js authors. All rights reserved.
* @license MIT
*/
import * as assert from 'assert';
import { IWidthCacheFontVariantCanvas, WidthCache, WidthCacheSettings } from './WidthCache';
class MockWidthCacheFontVariantCanvas implements IWidthCacheFontVariantCanvas {
public widths: { [key: string]: number } = {};
public setFont(_fontFamily: string, _fontSize: number, _fontWeight: unknown, _italic: boolean): void {
}
public measure(c: string): number {
return this.widths[c] ?? 5;
}
}
export class TestWidthCache extends WidthCache {
public get flat(): Float32Array {
return (this as any)._flat;
}
public get holey(): Map<string, number> | undefined {
return (this as any)._holey;
}
public get canvasElements(): MockWidthCacheFontVariantCanvas[] {
return (this as any)._canvasElements;
}
constructor() {
super(() => new MockWidthCacheFontVariantCanvas());
}
public setWidths(widths: { [key: string]: number }): void {
for (const canvas of this.canvasElements) {
canvas.widths = widths;
}
}
}
function castf32(v: number): number {
const buffer = new Float32Array(1);
buffer[0] = v;
return buffer[0];
}
describe('WidthCache', () => {
let wc: TestWidthCache;
beforeEach(() => {
wc = new TestWidthCache();
wc.setFont('monospace', 15, 'normal', 'bold');
});
describe('cache invalidation', () => {
beforeEach(() => {
wc.flat.fill(1.23);
wc.holey?.set('a', 2.34);
});
it('can cache values', () => {
assert.deepStrictEqual(wc.flat[0], castf32(1.23));
assert.deepStrictEqual(wc.holey?.get('a'), 2.34);
assert.deepStrictEqual(wc.holey?.size, 1);
});
it('clear resets cache entries', () => {
wc.clear();
assert.deepStrictEqual(wc.flat[0], castf32(WidthCacheSettings.FLAT_UNSET));
assert.deepStrictEqual(wc.holey?.get('a'), undefined);
assert.deepStrictEqual(wc.holey?.size, 0);
});
it('setFont with changed font name', () => {
wc.setFont('Arial', 15, 'normal', 'bold');
assert.deepStrictEqual(wc.flat[0], castf32(WidthCacheSettings.FLAT_UNSET));
assert.deepStrictEqual(wc.holey?.get('a'), undefined);
assert.deepStrictEqual(wc.holey?.size, 0);
});
it('setFont with changed font size', () => {
wc.setFont('monospace', 14, 'normal', 'bold');
assert.deepStrictEqual(wc.flat[0], castf32(WidthCacheSettings.FLAT_UNSET));
assert.deepStrictEqual(wc.holey?.get('a'), undefined);
assert.deepStrictEqual(wc.holey?.size, 0);
});
it('setFont with changed weight', () => {
wc.setFont('monospace', 15, '100', 'bold');
assert.deepStrictEqual(wc.flat[0], castf32(WidthCacheSettings.FLAT_UNSET));
assert.deepStrictEqual(wc.holey?.get('a'), undefined);
assert.deepStrictEqual(wc.holey?.size, 0);
});
it('setFont with changed weightBold', () => {
wc.setFont('monospace', 15, 'normal', '900');
assert.deepStrictEqual(wc.flat[0], castf32(WidthCacheSettings.FLAT_UNSET));
assert.deepStrictEqual(wc.holey?.get('a'), undefined);
assert.deepStrictEqual(wc.holey?.size, 0);
});
it('setFont with unchanged settings does not cache entries', () => {
wc.setFont('monospace', 15, 'normal', 'bold');
assert.deepStrictEqual(wc.flat[0], castf32(1.23));
assert.deepStrictEqual(wc.holey?.get('a'), 2.34);
assert.deepStrictEqual(wc.holey?.size, 1);
});
});
describe('get', () => {
it('store regular < WidthCacheSettings.FLAT_SIZE in flat', () => {
for (let i = 0; i < WidthCacheSettings.FLAT_SIZE + 10; ++i) {
const width = wc.get(String.fromCharCode(i), false, false);
assert.deepStrictEqual(width, 5);
if (i < WidthCacheSettings.FLAT_SIZE) {
assert.deepStrictEqual(wc.flat[i], 5);
assert.deepStrictEqual(wc.holey?.get(String.fromCharCode(i)), undefined);
} else {
assert.deepStrictEqual(wc.holey?.get(String.fromCharCode(i)), 5);
}
}
});
it('stores bold & italic in holey', () => {
// bold
let width = wc.get('b', true, false);
assert.deepStrictEqual(width, 5);
assert.deepStrictEqual(wc.holey?.get('bB'), 5);
// italic
width = wc.get('i', false, true);
assert.deepStrictEqual(width, 5);
assert.deepStrictEqual(wc.holey?.get('iI'), 5);
// bold&italic
width = wc.get('x', true, true);
assert.deepStrictEqual(width, 5);
assert.deepStrictEqual(wc.holey?.get('xBI'), 5);
});
it('can store any string', () => {
// regular
let width = wc.get('foo', false, false);
assert.deepStrictEqual(width, 5);
assert.deepStrictEqual(wc.holey?.get('foo'), 5);
// bold&italic
width = wc.get('bar&baz', true, true);
assert.deepStrictEqual(width, 5);
assert.deepStrictEqual(wc.holey?.get('bar&bazBI'), 5);
});
});
});