Merge remote-tracking branch 'upstream/master' into onSelectionChangeClear

This commit is contained in:
Daniel Imms
2026-01-08 16:51:54 -08:00
77 changed files with 3428 additions and 173 deletions
+12 -2
View File
@@ -636,8 +636,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
// send event to CoreMouseService
function sendEvent(ev: MouseEvent | WheelEvent): boolean {
// get mouse coordinates
const pos = self._mouseService!.getMouseReportCoords(ev, self.screenElement!);
// Get mouse coordinates
const pos = self._mouseService?.getMouseReportCoords(ev, self.screenElement!);
if (!pos) {
return false;
}
@@ -804,6 +804,16 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
// force initial onProtocolChange so we dont miss early mouse requests
this.coreMouseService.activeProtocol = this.coreMouseService.activeProtocol;
// Ensure document-level listeners are removed on dispose
this._register(toDisposable(() => {
if (requestedEvents.mouseup) {
this._document!.removeEventListener('mouseup', requestedEvents.mouseup);
}
if (requestedEvents.mousedrag) {
this._document!.removeEventListener('mousemove', requestedEvents.mousedrag);
}
}));
/**
* "Always on" event listeners.
*/
-4
View File
@@ -103,7 +103,6 @@ export class Terminal extends Disposable implements ITerminalApi {
return this._buffer;
}
public get markers(): ReadonlyArray<IMarker> {
this._checkProposedApi();
return this._core.markers;
}
public get modes(): IModes {
@@ -166,11 +165,9 @@ export class Terminal extends Disposable implements ITerminalApi {
return this._core.registerLinkProvider(linkProvider);
}
public registerCharacterJoiner(handler: (text: string) => [number, number][]): number {
this._checkProposedApi();
return this._core.registerCharacterJoiner(handler);
}
public deregisterCharacterJoiner(joinerId: number): void {
this._checkProposedApi();
this._core.deregisterCharacterJoiner(joinerId);
}
public registerMarker(cursorYOffset: number = 0): IMarker {
@@ -178,7 +175,6 @@ export class Terminal extends Disposable implements ITerminalApi {
return this._core.registerMarker(cursorYOffset);
}
public registerDecoration(decorationOptions: IDecorationOptions): IDecoration | undefined {
this._checkProposedApi();
this._verifyPositiveIntegers(decorationOptions.x ?? 0, decorationOptions.width ?? 0, decorationOptions.height ?? 0);
return this._core.registerDecoration(decorationOptions);
}
+8 -2
View File
@@ -1154,7 +1154,10 @@ export class InputHandler extends Disposable implements IInputHandler {
* @param respectProtect Whether to respect the protection attribute (DECSCA).
*/
private _eraseInBufferLine(y: number, start: number, end: number, clearWrap: boolean = false, respectProtect: boolean = false): void {
const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!;
const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y);
if (!line) {
return;
}
line.replaceCells(
start,
end,
@@ -1224,7 +1227,10 @@ export class InputHandler extends Disposable implements IInputHandler {
this._eraseInBufferLine(j, 0, this._activeBuffer.x + 1, true, respectProtect);
if (this._activeBuffer.x + 1 >= this._bufferService.cols) {
// Deleted entire previous line. This next line can no longer be wrapped.
this._activeBuffer.lines.get(j + 1)!.isWrapped = false;
const nextLine = this._activeBuffer.lines.get(j + 1);
if (nextLine) {
nextLine.isWrapped = false;
}
}
while (j--) {
this._resetBufferLine(j, respectProtect);
+4 -1
View File
@@ -14,7 +14,10 @@ interface INavigator {
declare const navigator: INavigator;
declare const process: unknown;
export const isNode = (typeof process !== 'undefined' && 'title' in (process as any)) ? true : false;
// navigator.userAgent is also checked here because bundling with the process module can cause
// issues otherwise. Note that navigator exists in Node.js 21+ but the userAgent is
// "Node.js/<version>".
export const isNode = (typeof process !== 'undefined' && 'title' in (process as any) && (typeof navigator === 'undefined' || navigator.userAgent.startsWith('Node.js/'))) ? true : false;
const userAgent = (isNode) ? 'node' : navigator.userAgent;
const platform = (isNode) ? 'node' : navigator.platform;
+1 -1
View File
@@ -22,7 +22,7 @@ describe('Headless API Tests', function (): void {
it('Proposed API check', async () => {
term = new Terminal({ allowProposedApi: false });
throws(() => term.markers, (error: any) => error.message === 'You must set the allowProposedApi option to true to use proposed API');
throws(() => term.unicode, (error: any) => error.message === 'You must set the allowProposedApi option to true to use proposed API');
});
it('write', async () => {
-4
View File
@@ -84,7 +84,6 @@ export class Terminal extends Disposable implements ITerminalApi {
public get onWriteParsed(): Event<void> { return this._core.onWriteParsed; }
public get parser(): IParser {
this._checkProposedApi();
if (!this._parser) {
this._parser = new ParserApi(this._core);
}
@@ -97,14 +96,12 @@ export class Terminal extends Disposable implements ITerminalApi {
public get rows(): number { return this._core.rows; }
public get cols(): number { return this._core.cols; }
public get buffer(): IBufferNamespaceApi {
this._checkProposedApi();
if (!this._buffer) {
this._buffer = this._register(new BufferNamespaceApi(this._core));
}
return this._buffer;
}
public get markers(): ReadonlyArray<IMarker> {
this._checkProposedApi();
return this._core.markers;
}
public get modes(): IModes {
@@ -146,7 +143,6 @@ export class Terminal extends Disposable implements ITerminalApi {
this._core.resize(columns, rows);
}
public registerMarker(cursorYOffset: number = 0): IMarker | undefined {
this._checkProposedApi();
this._verifyIntegers(cursorYOffset);
return this._core.addMarker(cursorYOffset);
}