Merge branch 'master' into buffer_optimizations

This commit is contained in:
Jörg Breitbart
2022-09-28 13:22:16 +02:00
27 changed files with 317 additions and 174 deletions
+20 -20
View File
@@ -99,6 +99,26 @@ The full API for xterm.js is contained within the [TypeScript declaration file](
Note that some APIs are marked *experimental*, these are added to enable experimentation with new ideas without committing to support it like a normal [semver](https://semver.org/) API. Note that these APIs can change radically between versions, so be sure to read release notes if you plan on using experimental APIs.
## Releases
Xterm.js follows a monthly release cycle roughly.
All current and past releases are available on this repo's [Releases page](https://github.com/sourcelair/xterm.js/releases), you can view the [high-level roadmap on the wiki](https://github.com/xtermjs/xterm.js/wiki/Roadmap) and see what we're working on now by looking through [Milestones](https://github.com/sourcelair/xterm.js/milestones).
### Beta builds
Our CI releases beta builds to npm for every change that goes into master. Install the latest beta build with:
```bash
npm install -S xterm@beta
```
These should generally be stable, but some bugs may slip in. We recommend using the beta build primarily to test out new features and to verify bug fixes.
## Contributing
You can read the [guide on the wiki](https://github.com/xtermjs/xterm.js/wiki/Contributing) to learn how to contribute and set up xterm.js for development.
## Real-world uses
Xterm.js is used in several world-class applications to provide great terminal experiences.
@@ -197,26 +217,6 @@ Xterm.js is used in several world-class applications to provide great terminal e
Do you use xterm.js in your application as well? Please [open a Pull Request](https://github.com/sourcelair/xterm.js/pulls) to include it here. We would love to have it on our list. Note: Please add any new contributions to the end of the list only.
## Releases
Xterm.js follows a monthly release cycle roughly.
All current and past releases are available on this repo's [Releases page](https://github.com/sourcelair/xterm.js/releases), you can view the [high-level roadmap on the wiki](https://github.com/xtermjs/xterm.js/wiki/Roadmap) and see what we're working on now by looking through [Milestones](https://github.com/sourcelair/xterm.js/milestones).
### Beta builds
Our CI releases beta builds to npm for every change that goes into master. Install the latest beta build with:
```bash
npm install -S xterm@beta
```
These should generally be stable, but some bugs may slip in. We recommend using the beta build primarily to test out new features and to verify bug fixes.
## Contributing
You can read the [guide on the wiki](https://github.com/xtermjs/xterm.js/wiki/Contributing) to learn how to contribute and set up xterm.js for development.
## License Agreement
If you contribute code to this project, you implicitly allow your code to be distributed under the MIT license. You are also implicitly verifying that all code is your original work.
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "xterm-addon-attach",
"version": "0.6.0",
"version": "0.7.0",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "xterm-addon-canvas",
"version": "0.1.0",
"version": "0.2.0",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "xterm-addon-fit",
"version": "0.5.0",
"version": "0.6.0",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "xterm-addon-ligatures",
"version": "0.5.3",
"version": "0.6.0",
"description": "Add support for programming ligatures to xterm.js",
"author": {
"name": "The xterm.js authors",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "xterm-addon-search",
"version": "0.9.0",
"version": "0.10.0",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "xterm-addon-serialize",
"version": "0.7.0",
"version": "0.8.0",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
@@ -78,7 +78,7 @@ describe('xterm-addon-serialize', () => {
terminal.loadAddon(serializeAddon);
selectionService = new TestSelectionService((terminal as any)._core._bufferService);
cm = new ColorManager(document, false);
cm = new ColorManager();
(terminal as any)._core._colorManager = cm;
(terminal as any)._core._selectionService = selectionService;
});
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "xterm-addon-unicode11",
"version": "0.3.0",
"version": "0.4.0",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "xterm-addon-web-links",
"version": "0.6.0",
"version": "0.7.0",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "xterm-addon-webgl",
"version": "0.12.0",
"version": "0.13.0",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
@@ -16,6 +16,7 @@ import { tryDrawCustomChar } from 'browser/renderer/CustomGlyphs';
import { excludeFromContrastRatioDemands, isPowerlineGlyph, isRestrictedPowerlineGlyph } from 'browser/renderer/RendererUtils';
import { IUnicodeService } from 'common/services/Services';
import { FourKeyMap } from 'common/MultiKeyMap';
import { IdleTaskQueue } from 'common/TaskQueue';
// For debugging purposes, it can be useful to set this to a really tiny value,
// to verify that LRU eviction works.
@@ -110,7 +111,10 @@ export class WebglCharAtlas implements IDisposable {
this._tmpCanvas = document.createElement('canvas');
this._tmpCanvas.width = this._config.scaledCellWidth * 4 + TMP_CANVAS_GLYPH_PADDING * 2;
this._tmpCanvas.height = this._config.scaledCellHeight + TMP_CANVAS_GLYPH_PADDING * 2;
this._tmpCtx = throwIfFalsy(this._tmpCanvas.getContext('2d', { alpha: this._config.allowTransparency }));
this._tmpCtx = throwIfFalsy(this._tmpCanvas.getContext('2d', {
alpha: this._config.allowTransparency,
willReadFrequently: true
}));
}
public dispose(): void {
@@ -127,10 +131,15 @@ export class WebglCharAtlas implements IDisposable {
}
private _doWarmUp(): void {
// Pre-fill with ASCII 33-126
// Pre-fill with ASCII 33-126, this is not urgent and done in idle callbacks
const queue = new IdleTaskQueue();
for (let i = 33; i < 126; i++) {
const rasterizedGlyph = this._drawToCache(i, DEFAULT_COLOR, DEFAULT_COLOR, DEFAULT_EXT);
this._cacheMap.set(i, DEFAULT_COLOR, DEFAULT_COLOR, DEFAULT_EXT, rasterizedGlyph);
queue.enqueue(() => {
if (!this._cacheMap.get(i, DEFAULT_COLOR, DEFAULT_COLOR, DEFAULT_EXT)) {
const rasterizedGlyph = this._drawToCache(i, DEFAULT_COLOR, DEFAULT_COLOR, DEFAULT_EXT);
this._cacheMap.set(i, DEFAULT_COLOR, DEFAULT_COLOR, DEFAULT_EXT, rasterizedGlyph);
}
});
}
}
+2 -7
View File
@@ -98,13 +98,8 @@ function getNextBetaVersion(packageJson) {
process.exit(1);
}
const tag = 'beta';
let nextStableVersion;
if (packageJson.name === 'xterm') {
nextStableVersion = `5.0.0`;
} else {
const stableVersion = packageJson.version.split('.');
nextStableVersion = `${stableVersion[0]}.${parseInt(stableVersion[1]) + 1}.0`;
}
const stableVersion = packageJson.version.split('.');
const nextStableVersion = `${stableVersion[0]}.${parseInt(stableVersion[1]) + 1}.0`;
const publishedVersions = getPublishedVersions(packageJson, nextStableVersion, tag);
if (publishedVersions.length === 0) {
return `${nextStableVersion}-${tag}.1`;
+2 -2
View File
@@ -86,7 +86,7 @@ function startServer() {
return (data) => {
s += data;
if (!sender) {
sender = setTimeout(() => {
sender = queueMicrotask(() => {
socket.send(s);
s = '';
sender = null;
@@ -103,7 +103,7 @@ function startServer() {
buffer.push(data);
length += data.length;
if (!sender) {
sender = setTimeout(() => {
sender = queueMicrotask(() => {
socket.send(Buffer.concat(buffer, length));
buffer = [];
sender = null;
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "xterm",
"description": "Full xterm terminal, in your browser",
"version": "4.19.0",
"version": "5.0.0",
"main": "lib/xterm.js",
"style": "css/xterm.css",
"types": "typings/xterm.d.ts",
+1 -1
View File
@@ -28,7 +28,7 @@ describe('ColorManager', () => {
return {data: [0, 0, 0, 0xFF]};
}
});
cm = new ColorManager(document, false);
cm = new ColorManager();
});
describe('constructor', () => {
+14 -81
View File
@@ -80,22 +80,11 @@ export const DEFAULT_ANSI_COLORS = Object.freeze((() => {
*/
export class ColorManager implements IColorManager {
public colors: IColorSet;
private _ctx: CanvasRenderingContext2D;
private _litmusColor: CanvasGradient;
private _contrastCache: IColorContrastCache;
private _restoreColors!: IRestoreColorSet;
constructor(document: Document, public allowTransparency: boolean) {
const canvas = document.createElement('canvas');
canvas.width = 1;
canvas.height = 1;
const ctx = canvas.getContext('2d');
if (!ctx) {
throw new Error('Could not get rendering context');
}
this._ctx = ctx;
this._ctx.globalCompositeOperation = 'copy';
this._litmusColor = this._ctx.createLinearGradient(0, 0, 1, 1);
constructor() {
this._contrastCache = new ColorContrastCache();
this.colors = {
foreground: DEFAULT_FOREGROUND,
@@ -118,9 +107,6 @@ export class ColorManager implements IColorManager {
case 'minimumContrastRatio':
this._contrastCache.clear();
break;
case 'allowTransparency':
this.allowTransparency = value;
break;
}
}
@@ -132,11 +118,11 @@ export class ColorManager implements IColorManager {
public setTheme(theme: ITheme = {}): void {
this.colors.foreground = this._parseColor(theme.foreground, DEFAULT_FOREGROUND);
this.colors.background = this._parseColor(theme.background, DEFAULT_BACKGROUND);
this.colors.cursor = this._parseColor(theme.cursor, DEFAULT_CURSOR, true);
this.colors.cursorAccent = this._parseColor(theme.cursorAccent, DEFAULT_CURSOR_ACCENT, true);
this.colors.selectionBackgroundTransparent = this._parseColor(theme.selectionBackground, DEFAULT_SELECTION, true);
this.colors.cursor = this._parseColor(theme.cursor, DEFAULT_CURSOR);
this.colors.cursorAccent = this._parseColor(theme.cursorAccent, DEFAULT_CURSOR_ACCENT);
this.colors.selectionBackgroundTransparent = this._parseColor(theme.selectionBackground, DEFAULT_SELECTION);
this.colors.selectionBackgroundOpaque = color.blend(this.colors.background, this.colors.selectionBackgroundTransparent);
this.colors.selectionInactiveBackgroundTransparent = this._parseColor(theme.selectionInactiveBackground, this.colors.selectionBackgroundTransparent, true);
this.colors.selectionInactiveBackgroundTransparent = this._parseColor(theme.selectionInactiveBackground, this.colors.selectionBackgroundTransparent);
this.colors.selectionInactiveBackgroundOpaque = color.blend(this.colors.background, this.colors.selectionInactiveBackgroundTransparent);
const nullColor: IColor = {
css: '',
@@ -220,69 +206,16 @@ export class ColorManager implements IColorManager {
}
private _parseColor(
css: string | undefined,
fallback: IColor,
allowTransparency: boolean = this.allowTransparency
cssString: string | undefined,
fallback: IColor
): IColor {
if (css === undefined) {
return fallback;
}
// If parsing the value results in failure, then it must be ignored, and the attribute must
// retain its previous value.
// -- https://html.spec.whatwg.org/multipage/canvas.html#fill-and-stroke-styles
this._ctx.fillStyle = this._litmusColor;
this._ctx.fillStyle = css;
if (typeof this._ctx.fillStyle !== 'string') {
console.warn(`Color: ${css} is invalid using fallback ${fallback.css}`);
return fallback;
}
this._ctx.fillRect(0, 0, 1, 1);
const data = this._ctx.getImageData(0, 0, 1, 1).data;
// Check if the printed color was transparent
if (data[3] !== 0xFF) {
if (!allowTransparency) {
// Ideally we'd just ignore the alpha channel, but...
//
// Browsers may not give back exactly the same RGB values we put in, because most/all
// convert the color to a pre-multiplied representation. getImageData converts that back to
// a un-premultipled representation, but the precision loss may make the RGB channels unuable
// on their own.
//
// E.g. In Chrome #12345610 turns into #10305010, and in the extreme case, 0xFFFFFF00 turns
// into 0x00000000.
//
// "Note: Due to the lossy nature of converting to and from premultiplied alpha color values,
// pixels that have just been set using putImageData() might be returned to an equivalent
// getImageData() as different values."
// -- https://html.spec.whatwg.org/multipage/canvas.html#pixel-manipulation
//
// So let's just use the fallback color in this case instead.
console.warn(
`Color: ${css} is using transparency, but allowTransparency is false. ` +
`Using fallback ${fallback.css}.`
);
return fallback;
if (cssString !== undefined) {
try {
return css.toColor(cssString);
} catch {
// no-op
}
// https://html.spec.whatwg.org/multipage/canvas.html#serialisation-of-a-color
// the color value has alpha less than 1.0, and the string is the color value in the CSS rgba()
const [r, g, b, a] = this._ctx.fillStyle.substring(5, this._ctx.fillStyle.length - 1).split(',').map(component => Number(component));
const alpha = Math.round(a * 255);
const rgba: number = channels.toRgba(r, g, b, alpha);
return {
rgba,
css
};
}
return {
// https://html.spec.whatwg.org/multipage/canvas.html#serialisation-of-a-color
// if it has alpha equal to 1.0, then the string is a lowercase six-digit hex value, prefixed with a "#" character
css: this._ctx.fillStyle,
rgba: channels.toRgba(data[0], data[1], data[2], data[3])
};
return fallback;
}
}
+1 -1
View File
@@ -502,7 +502,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
this._instantiationService.setService(ICharSizeService, this._charSizeService);
this._theme = this.options.theme || this._theme;
this._colorManager = new ColorManager(document, this.options.allowTransparency);
this._colorManager = new ColorManager();
this.register(this.optionsService.onOptionChange(e => this._colorManager!.onOptionsChange(e, this.optionsService.rawOptions[e])));
this._colorManager.setTheme(this._theme);
+1 -1
View File
@@ -33,7 +33,7 @@ export const blockElementDefinitions: { [index: string]: IBlockVector[] | undefi
'▐': [{ x: 4, y: 0, w: 4, h: 8 }], // RIGHT HALF BLOCK
// Block elements (0x2594-0x2595)
'▔': [{ x: 0, y: 0, w: 9, h: 1 }], // UPPER ONE EIGHTH BLOCK
'▔': [{ x: 0, y: 0, w: 8, h: 1 }], // UPPER ONE EIGHTH BLOCK
'▕': [{ x: 7, y: 0, w: 1, h: 8 }], // RIGHT ONE EIGHTH BLOCK
// Terminal graphic characters (0x2596-0x259F)
@@ -166,7 +166,7 @@ export class DomRendererRowFactory {
if (cell.isUnderline()) {
charElement.classList.add(`${UNDERLINE_CLASS}-${cell.extended.underlineStyle}`);
if (charElement.textContent === ' ') {
charElement.innerHTML = '&nbsp;';
charElement.textContent = '\xa0'; // = &nbsp;
}
if (!cell.isUnderlineColorDefault()) {
if (cell.isUnderlineColorRGB()) {

Some files were not shown because too many files have changed in this diff Show More