From 1ee0422f8220c66421a258036efab01c388cd499 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Tue, 4 Aug 2026 12:11:22 -0400 Subject: [PATCH 1/3] feat(terminal): add an xterm.js emulator backend Adds a second `Emulator` implementation built on `@xterm/headless`, running on an embedded QuickJS interpreter via `rquickjs`. The bundle and its host shim are compiled into the binary, so this adds no runtime dependency on Node or on anything installed on the machine. Two things the seam needed: `Terminal.write()` is asynchronous. It queues the chunk and drains it from a `setTimeout` callback, so the grid is still empty when it returns, while `Emulator::process` has to have the grid ready. The shim collects timers into a queue and drains it to empty before handing control back, which makes writes synchronous and deterministic. `performance.now()` returns a constant so the write loop never takes its 12ms yield and one feed always consumes the whole chunk. Reading a cell is a call into JS, and an 80x30 screen is 2,400 of them with ten property reads each. The shim instead flattens a row span into one NUL-joined string and one flat integer array, so a whole screen crosses the boundary as two values. PTY output is passed as a `Uint8Array` rather than a string so xterm.js's own incremental UTF-8 decoder carries a sequence split across two reads. The backend passes the existing conformance suite unchanged except for `underline_color_outlives_the_underline`, which is narrowed here. xterm.js keeps the underline color in an extended-attribute record whose `isEmpty()` consults only the underline style and hyperlink id, so a cell with a color but no shape drops the record and reports the foreground instead. The test now pins the shape transitions, which every emulator agrees on, and the color only where it is actually drawn. The shim collapses that foreground fallback back to "unset", which is what `underline_color: None` already means, so both backends emit identical cells. xterm.js reports the `blink` attribute, which alacritty parses and discards. It is the first backend to source that part of the vocabulary. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Ayman Bagabas --- Cargo.lock | 90 +++++++ Cargo.toml | 1 + crates/shell-use/Cargo.toml | 1 + crates/shell-use/assets/xterm/LICENSE | 21 ++ crates/shell-use/assets/xterm/shim.js | 145 +++++++++++ .../shell-use/assets/xterm/xterm-headless.js | 2 + crates/shell-use/src/terminal/conformance.rs | 26 +- crates/shell-use/src/terminal/mod.rs | 1 + crates/shell-use/src/terminal/xtermjs.rs | 246 ++++++++++++++++++ 9 files changed, 521 insertions(+), 12 deletions(-) create mode 100644 crates/shell-use/assets/xterm/LICENSE create mode 100644 crates/shell-use/assets/xterm/shim.js create mode 100644 crates/shell-use/assets/xterm/xterm-headless.js create mode 100644 crates/shell-use/src/terminal/xtermjs.rs diff --git a/Cargo.lock b/Cargo.lock index 2b3f15f..fd367c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -42,6 +42,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "anstream" version = "1.0.0" @@ -149,6 +155,16 @@ dependencies = [ "rustversion", ] +[[package]] +name = "cc" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9" +dependencies = [ + "find-msvc-tools", + "shlex", +] + [[package]] name = "cfg-if" version = "1.0.4" @@ -367,6 +383,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "errno" version = "0.3.14" @@ -394,6 +416,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + [[package]] name = "flate2" version = "1.1.9" @@ -404,6 +432,12 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "futures-io" version = "0.3.32" @@ -431,6 +465,17 @@ dependencies = [ "wasi", ] +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + [[package]] name = "heck" version = "0.5.0" @@ -740,6 +785,44 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" +[[package]] +name = "relative-path" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bca40a312222d8ba74837cb474edef44b37f561da5f773981007a10bbaa992b0" +dependencies = [ + "serde", +] + +[[package]] +name = "rquickjs" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e04e4eedfb060b503b5f0a2644abb890b0b3620d3fb674f9455f230014964e4" +dependencies = [ + "rquickjs-core", +] + +[[package]] +name = "rquickjs-core" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e4f499ac5b943d97ee6dbc44f23c2c10426f420f7d2f1793d6318911b6608c" +dependencies = [ + "hashbrown", + "relative-path", + "rquickjs-sys", +] + +[[package]] +name = "rquickjs-sys" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13ac243b86a74120814ef7e9e30ad5a2c1199b7b9963b1cf7c84e4cdc1cad99" +dependencies = [ + "cc", +] + [[package]] name = "rustix" version = "0.38.44" @@ -876,6 +959,7 @@ dependencies = [ "flate2", "portable-pty", "regex", + "rquickjs", "serde", "serde_json", "ttf-parser", @@ -902,6 +986,12 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77" +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + [[package]] name = "signal-hook" version = "0.3.18" diff --git a/Cargo.toml b/Cargo.toml index 7b23491..c76fb8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ flate2 = "1.1.9" interprocess = "2.4.2" portable-pty = "0.9.0" regex = "1.12.4" +rquickjs = { version = "0.12.2", features = ["parallel"] } serde = { version = "1.0.228", features = ["derive"] } serde_json = "1.0.150" sha2 = "0.10.9" diff --git a/crates/shell-use/Cargo.toml b/crates/shell-use/Cargo.toml index a805364..16ad0fb 100644 --- a/crates/shell-use/Cargo.toml +++ b/crates/shell-use/Cargo.toml @@ -20,6 +20,7 @@ dirs.workspace = true flate2.workspace = true portable-pty.workspace = true regex.workspace = true +rquickjs.workspace = true serde.workspace = true serde_json.workspace = true ttf-parser.workspace = true diff --git a/crates/shell-use/assets/xterm/LICENSE b/crates/shell-use/assets/xterm/LICENSE new file mode 100644 index 0000000..4472336 --- /dev/null +++ b/crates/shell-use/assets/xterm/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2017-2019, The xterm.js authors (https://github.com/xtermjs/xterm.js) +Copyright (c) 2014-2016, SourceLair Private Company (https://www.sourcelair.com) +Copyright (c) 2012-2013, Christopher Jeffrey (https://github.com/chjj/) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/crates/shell-use/assets/xterm/shim.js b/crates/shell-use/assets/xterm/shim.js new file mode 100644 index 0000000..bb6d10a --- /dev/null +++ b/crates/shell-use/assets/xterm/shim.js @@ -0,0 +1,145 @@ +// Host shim + Rust-facing glue for the vendored `@xterm/headless` bundle. +// +// Two jobs: +// +// 1. Stand in for the handful of browser/Node globals the bundle reaches for. +// `process.title` is the important one: xterm.js branches on +// `typeof process !== 'undefined' && 'title' in process` to set `isNode`, +// and every `navigator` access sits on the other side of that branch, so +// defining it means no user-agent sniffing ever runs. +// +// 2. Make writing synchronous. `Terminal.write()` is async: it queues the +// chunk and drains it from a `setTimeout` callback, so the grid is still +// empty when it returns. `Emulator::process` has to have the grid ready +// when it returns, so timers are collected into a queue that `feed()` +// drains to empty before it hands control back to Rust. The drain is +// ordinary FIFO, which is all xterm.js needs: it only ever schedules its +// own continuation. +// +// `performance.now()` returning a constant is deliberate, not a stub: the +// write loop yields to a fresh timer once it has spent 12ms on a chunk, and a +// frozen clock means it never does, so one `feed()` always consumes the whole +// chunk instead of leaving a tail for the next drain. + +globalThis.process = { title: 'shell-use' }; +globalThis.performance = { now: function () { return 0; } }; +globalThis.console = { + log: function () {}, warn: function () {}, error: function () {}, + debug: function () {}, info: function () {}, trace: function () {}, +}; + +var __timers = []; +globalThis.setTimeout = function (fn) { return __timers.push(fn); }; +globalThis.clearTimeout = function () {}; +globalThis.setInterval = function () { return 0; }; +globalThis.clearInterval = function () {}; +globalThis.queueMicrotask = function (fn) { __timers.push(fn); }; + +// The bundle is UMD and assigns to `exports`. +globalThis.exports = {}; +globalThis.module = { exports: globalThis.exports }; + +globalThis.__boot = function (cols, rows, scrollback) { + var term = new exports.Terminal({ + cols: cols, + rows: rows, + scrollback: scrollback, + // `getUnderlineStyle`, `getUnderlineColor` and `getNullCell` are proposed + // API; without this every one of them throws. + allowProposedApi: true, + }); + + // Replies the terminal wants sent back up the PTY (DA, CPR, and friends). + var replies = []; + term.onData(function (d) { replies.push(d); }); + + function drain() { + // `_timers` grows while draining, so re-check rather than snapshotting. + // The cap turns a hypothetical self-rescheduling timer into an error + // instead of a hung reader thread. + var guard = 0; + while (__timers.length) { + __timers.shift()(); + if (++guard > 1000000) { throw new Error('xterm.js timer queue did not settle'); } + } + } + + // One reused cell object across the whole grid walk. `getCell(x, cell)` + // fills it in place; the allocating form costs roughly twice as much. + var CELL = term.buffer.active.getNullCell(); + + return { + feed: function (bytes) { term.write(bytes); drain(); }, + + // Joined rather than returned as an array: one string crossing the + // boundary beats one call per pending reply. + takeReplies: function () { var s = replies.join(''); replies.length = 0; return s; }, + + resize: function (cols, rows) { term.resize(cols, rows); drain(); }, + cols: function () { return term.cols; }, + rows: function () { return term.rows; }, + cursorX: function () { return term.buffer.active.cursorX; }, + cursorY: function () { return term.buffer.active.cursorY; }, + + // Row span of the visible screen; `full` prepends the scrollback. + start: function (full) { return full ? 0 : term.buffer.active.baseY; }, + end: function (full) { + var b = term.buffer.active; + return full ? b.length : b.baseY + term.rows; + }, + + // The grid crosses the boundary as exactly two values: every cell's text + // in one NUL-joined string, and six ints per cell in one flat array. NUL + // is safe as a separator because xterm.js reports an empty string, never + // a NUL, for a cell holding nothing. + // + // Per-cell ints are `[width, fg, bg, ulColor, ulStyle, flags]`, with the + // color *modes* packed into `flags` alongside the SGR booleans: a raw + // color of 1 is palette slot 1 or the RGB triple #000001 depending on its + // mode, so the mode has to travel with it. + pack: function (start, end) { + var buf = term.buffer.active, cols = term.cols; + var chars = [], meta = []; + for (var y = start; y < end; y++) { + var line = buf.getLine(y); + for (var x = 0; x < cols; x++) { + if (!line) { chars.push(' '); meta.push(1, 0, 0, 0, 0, 0); continue; } + var c = line.getCell(x, CELL); + chars.push(c.getChars()); + + var fg = c.getFgColor(); + var fgMode = c.isFgPalette() ? 1 : (c.isFgRGB() ? 2 : 0); + var ulColor = c.getUnderlineColor(); + var ulMode = c.isUnderlineColorPalette() ? 1 : (c.isUnderlineColorRGB() ? 2 : 0); + + // xterm.js keeps the underline color in an extended-attribute + // record that it drops whenever the underline style is NONE, and + // both underline-color getters then fall back to reporting the + // foreground. Left alone that shows up as every colored cell + // claiming an underline color it was never given. Collapsing the + // case where the two are identical back to "unset" is exactly the + // vocabulary's own spelling for it: `underline_color: None` already + // means the underline takes the foreground. A cell that really did + // set SGR 58 to its own foreground color lands here too, and draws + // the same either way. + if (ulColor === fg && ulMode === fgMode) { ulMode = 0; } + + var flags = + (c.isBold() ? 1 : 0) | + (c.isDim() ? 2 : 0) | + (c.isItalic() ? 4 : 0) | + (c.isInverse() ? 8 : 0) | + (c.isInvisible() ? 16 : 0) | + (c.isStrikethrough() ? 32 : 0) | + (c.isBlink() ? 64 : 0) | + (fgMode === 1 ? 256 : (fgMode === 2 ? 512 : 0)) | + (c.isBgPalette() ? 1024 : (c.isBgRGB() ? 2048 : 0)) | + (ulMode === 1 ? 4096 : (ulMode === 2 ? 8192 : 0)); + + meta.push(c.getWidth(), fg, c.getBgColor(), ulColor, c.getUnderlineStyle(), flags); + } + } + return [chars.join('\0'), meta]; + }, + }; +}; diff --git a/crates/shell-use/assets/xterm/xterm-headless.js b/crates/shell-use/assets/xterm/xterm-headless.js new file mode 100644 index 0000000..a1a3c01 --- /dev/null +++ b/crates/shell-use/assets/xterm/xterm-headless.js @@ -0,0 +1,2 @@ +(()=>{"use strict";var e={5639:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.CircularList=void 0;const i=s(7150),r=s(802);class n extends i.Disposable{constructor(e){super(),this._maxLength=e,this.onDeleteEmitter=this._register(new r.Emitter),this.onDelete=this.onDeleteEmitter.event,this.onInsertEmitter=this._register(new r.Emitter),this.onInsert=this.onInsertEmitter.event,this.onTrimEmitter=this._register(new r.Emitter),this.onTrim=this.onTrimEmitter.event,this._array=new Array(this._maxLength),this._startIndex=0,this._length=0}get maxLength(){return this._maxLength}set maxLength(e){if(this._maxLength===e)return;const t=new Array(e);for(let s=0;sthis._length)for(let t=this._length;t=e;t--)this._array[this._getCyclicIndex(t+s.length)]=this._array[this._getCyclicIndex(t)];for(let t=0;tthis._maxLength){const e=this._length+s.length-this._maxLength;this._startIndex+=e,this._length=this._maxLength,this.onTrimEmitter.fire(e)}else this._length+=s.length}trimStart(e){e>this._length&&(e=this._length),this._startIndex+=e,this._length-=e,this.onTrimEmitter.fire(e)}shiftElements(e,t,s){if(!(t<=0)){if(e<0||e>=this._length)throw new Error("start argument out of range");if(e+s<0)throw new Error("Cannot shift elements in list beyond index 0");if(s>0){for(let i=t-1;i>=0;i--)this.set(e+i+s,this.get(e+i));const i=e+t+s-this._length;if(i>0)for(this._length+=i;this._length>this._maxLength;)this._length--,this._startIndex++,this.onTrimEmitter.fire(1)}else for(let i=0;i{Object.defineProperty(t,"__esModule",{value:!0}),t.clone=function e(t,s=5){if("object"!=typeof t)return t;const i=Array.isArray(t)?[]:{};for(const r in t)i[r]=s<=1?t[r]:t[r]&&e(t[r],s-1);return i}},5777:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.CoreTerminal=void 0;const i=s(6501),r=s(6025),n=s(7276),o=s(9640),a=s(56),h=s(4071),c=s(7792),l=s(6415),u=s(5746),d=s(5882),f=s(2486),_=s(3562),p=s(8811),g=s(802),v=s(7150);let m=!1;class b extends v.Disposable{get onScroll(){return this._onScrollApi||(this._onScrollApi=this._register(new g.Emitter),this._onScroll.event((e=>{this._onScrollApi?.fire(e.position)}))),this._onScrollApi.event}get cols(){return this._bufferService.cols}get rows(){return this._bufferService.rows}get buffers(){return this._bufferService.buffers}get options(){return this.optionsService.options}set options(e){for(const t in e)this.optionsService.options[t]=e[t]}constructor(e){super(),this._windowsWrappingHeuristics=this._register(new v.MutableDisposable),this._onBinary=this._register(new g.Emitter),this.onBinary=this._onBinary.event,this._onData=this._register(new g.Emitter),this.onData=this._onData.event,this._onLineFeed=this._register(new g.Emitter),this.onLineFeed=this._onLineFeed.event,this._onResize=this._register(new g.Emitter),this.onResize=this._onResize.event,this._onWriteParsed=this._register(new g.Emitter),this.onWriteParsed=this._onWriteParsed.event,this._onScroll=this._register(new g.Emitter),this._instantiationService=new r.InstantiationService,this.optionsService=this._register(new a.OptionsService(e)),this._instantiationService.setService(i.IOptionsService,this.optionsService),this._bufferService=this._register(this._instantiationService.createInstance(o.BufferService)),this._instantiationService.setService(i.IBufferService,this._bufferService),this._logService=this._register(this._instantiationService.createInstance(n.LogService)),this._instantiationService.setService(i.ILogService,this._logService),this.coreService=this._register(this._instantiationService.createInstance(h.CoreService)),this._instantiationService.setService(i.ICoreService,this.coreService),this.coreMouseService=this._register(this._instantiationService.createInstance(c.CoreMouseService)),this._instantiationService.setService(i.ICoreMouseService,this.coreMouseService),this.unicodeService=this._register(this._instantiationService.createInstance(l.UnicodeService)),this._instantiationService.setService(i.IUnicodeService,this.unicodeService),this._charsetService=this._instantiationService.createInstance(u.CharsetService),this._instantiationService.setService(i.ICharsetService,this._charsetService),this._oscLinkService=this._instantiationService.createInstance(p.OscLinkService),this._instantiationService.setService(i.IOscLinkService,this._oscLinkService),this._inputHandler=this._register(new f.InputHandler(this._bufferService,this._charsetService,this.coreService,this._logService,this.optionsService,this._oscLinkService,this.coreMouseService,this.unicodeService)),this._register(g.Event.forward(this._inputHandler.onLineFeed,this._onLineFeed)),this._register(this._inputHandler),this._register(g.Event.forward(this._bufferService.onResize,this._onResize)),this._register(g.Event.forward(this.coreService.onData,this._onData)),this._register(g.Event.forward(this.coreService.onBinary,this._onBinary)),this._register(this.coreService.onRequestScrollToBottom((()=>this.scrollToBottom(!0)))),this._register(this.coreService.onUserInput((()=>this._writeBuffer.handleUserInput()))),this._register(this.optionsService.onMultipleOptionChange(["windowsMode","windowsPty"],(()=>this._handleWindowsPtyOptionChange()))),this._register(this._bufferService.onScroll((()=>{this._onScroll.fire({position:this._bufferService.buffer.ydisp}),this._inputHandler.markRangeDirty(this._bufferService.buffer.scrollTop,this._bufferService.buffer.scrollBottom)}))),this._writeBuffer=this._register(new _.WriteBuffer(((e,t)=>this._inputHandler.parse(e,t)))),this._register(g.Event.forward(this._writeBuffer.onWriteParsed,this._onWriteParsed))}write(e,t){this._writeBuffer.write(e,t)}writeSync(e,t){this._logService.logLevel<=i.LogLevelEnum.WARN&&!m&&(this._logService.warn("writeSync is unreliable and will be removed soon."),m=!0),this._writeBuffer.writeSync(e,t)}input(e,t=!0){this.coreService.triggerDataEvent(e,t)}resize(e,t){isNaN(e)||isNaN(t)||(e=Math.max(e,o.MINIMUM_COLS),t=Math.max(t,o.MINIMUM_ROWS),this._bufferService.resize(e,t))}scroll(e,t=!1){this._bufferService.scroll(e,t)}scrollLines(e,t){this._bufferService.scrollLines(e,t)}scrollPages(e){this.scrollLines(e*(this.rows-1))}scrollToTop(){this.scrollLines(-this._bufferService.buffer.ydisp)}scrollToBottom(e){this.scrollLines(this._bufferService.buffer.ybase-this._bufferService.buffer.ydisp)}scrollToLine(e){const t=e-this._bufferService.buffer.ydisp;0!==t&&this.scrollLines(t)}registerEscHandler(e,t){return this._inputHandler.registerEscHandler(e,t)}registerDcsHandler(e,t){return this._inputHandler.registerDcsHandler(e,t)}registerCsiHandler(e,t){return this._inputHandler.registerCsiHandler(e,t)}registerOscHandler(e,t){return this._inputHandler.registerOscHandler(e,t)}_setup(){this._handleWindowsPtyOptionChange()}reset(){this._inputHandler.reset(),this._bufferService.reset(),this._charsetService.reset(),this.coreService.reset(),this.coreMouseService.reset()}_handleWindowsPtyOptionChange(){let e=!1;const t=this.optionsService.rawOptions.windowsPty;t&&void 0!==t.buildNumber&&void 0!==t.buildNumber?e=!!("conpty"===t.backend&&t.buildNumber<21376):this.optionsService.rawOptions.windowsMode&&(e=!0),e?this._enableWindowsWrappingHeuristics():this._windowsWrappingHeuristics.clear()}_enableWindowsWrappingHeuristics(){if(!this._windowsWrappingHeuristics.value){const e=[];e.push(this.onLineFeed(d.updateWindowsModeWrappedState.bind(null,this._bufferService))),e.push(this.registerCsiHandler({final:"H"},(()=>((0,d.updateWindowsModeWrappedState)(this._bufferService),!1)))),this._windowsWrappingHeuristics.value=(0,v.toDisposable)((()=>{for(const t of e)t.dispose()}))}}}t.CoreTerminal=b},2486:function(e,t,s){var i=this&&this.__decorate||function(e,t,s,i){var r,n=arguments.length,o=n<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,s,o):r(t,s))||o);return n>3&&o&&Object.defineProperty(t,s,o),o},r=this&&this.__param||function(e,t){return function(s,i){t(s,i,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.InputHandler=t.WindowsOptionsReportType=void 0,t.isValidColorIndex=k;const n=s(3534),o=s(6760),a=s(6717),h=s(7150),c=s(726),l=s(6107),u=s(8938),d=s(3055),f=s(5451),_=s(6501),p=s(6415),g=s(1346),v=s(9823),m=s(8693),b=s(802),S={"(":0,")":1,"*":2,"+":3,"-":1,".":2},y=131072;function C(e,t){if(e>24)return t.setWinLines||!1;switch(e){case 1:return!!t.restoreWin;case 2:return!!t.minimizeWin;case 3:return!!t.setWinPosition;case 4:return!!t.setWinSizePixels;case 5:return!!t.raiseWin;case 6:return!!t.lowerWin;case 7:return!!t.refreshWin;case 8:return!!t.setWinSizeChars;case 9:return!!t.maximizeWin;case 10:return!!t.fullscreenWin;case 11:return!!t.getWinState;case 13:return!!t.getWinPosition;case 14:return!!t.getWinSizePixels;case 15:return!!t.getScreenSizePixels;case 16:return!!t.getCellSizePixels;case 18:return!!t.getWinSizeChars;case 19:return!!t.getScreenSizeChars;case 20:return!!t.getIconTitle;case 21:return!!t.getWinTitle;case 22:return!!t.pushTitle;case 23:return!!t.popTitle;case 24:return!!t.setWinLines}return!1}var w;!function(e){e[e.GET_WIN_SIZE_PIXELS=0]="GET_WIN_SIZE_PIXELS",e[e.GET_CELL_SIZE_PIXELS=1]="GET_CELL_SIZE_PIXELS"}(w||(t.WindowsOptionsReportType=w={}));let E=0;class A extends h.Disposable{getAttrData(){return this._curAttrData}constructor(e,t,s,i,r,h,u,d,f=new a.EscapeSequenceParser){super(),this._bufferService=e,this._charsetService=t,this._coreService=s,this._logService=i,this._optionsService=r,this._oscLinkService=h,this._coreMouseService=u,this._unicodeService=d,this._parser=f,this._parseBuffer=new Uint32Array(4096),this._stringDecoder=new c.StringToUtf32,this._utf8Decoder=new c.Utf8ToUtf32,this._windowTitle="",this._iconName="",this._windowTitleStack=[],this._iconNameStack=[],this._curAttrData=l.DEFAULT_ATTR_DATA.clone(),this._eraseAttrDataInternal=l.DEFAULT_ATTR_DATA.clone(),this._onRequestBell=this._register(new b.Emitter),this.onRequestBell=this._onRequestBell.event,this._onRequestRefreshRows=this._register(new b.Emitter),this.onRequestRefreshRows=this._onRequestRefreshRows.event,this._onRequestReset=this._register(new b.Emitter),this.onRequestReset=this._onRequestReset.event,this._onRequestSendFocus=this._register(new b.Emitter),this.onRequestSendFocus=this._onRequestSendFocus.event,this._onRequestSyncScrollBar=this._register(new b.Emitter),this.onRequestSyncScrollBar=this._onRequestSyncScrollBar.event,this._onRequestWindowsOptionsReport=this._register(new b.Emitter),this.onRequestWindowsOptionsReport=this._onRequestWindowsOptionsReport.event,this._onA11yChar=this._register(new b.Emitter),this.onA11yChar=this._onA11yChar.event,this._onA11yTab=this._register(new b.Emitter),this.onA11yTab=this._onA11yTab.event,this._onCursorMove=this._register(new b.Emitter),this.onCursorMove=this._onCursorMove.event,this._onLineFeed=this._register(new b.Emitter),this.onLineFeed=this._onLineFeed.event,this._onScroll=this._register(new b.Emitter),this.onScroll=this._onScroll.event,this._onTitleChange=this._register(new b.Emitter),this.onTitleChange=this._onTitleChange.event,this._onColor=this._register(new b.Emitter),this.onColor=this._onColor.event,this._parseStack={paused:!1,cursorStartX:0,cursorStartY:0,decodedLength:0,position:0},this._specialColors=[256,257,258],this._register(this._parser),this._dirtyRowTracker=new L(this._bufferService),this._activeBuffer=this._bufferService.buffer,this._register(this._bufferService.buffers.onBufferActivate((e=>this._activeBuffer=e.activeBuffer))),this._parser.setCsiHandlerFallback(((e,t)=>{this._logService.debug("Unknown CSI code: ",{identifier:this._parser.identToString(e),params:t.toArray()})})),this._parser.setEscHandlerFallback((e=>{this._logService.debug("Unknown ESC code: ",{identifier:this._parser.identToString(e)})})),this._parser.setExecuteHandlerFallback((e=>{this._logService.debug("Unknown EXECUTE code: ",{code:e})})),this._parser.setOscHandlerFallback(((e,t,s)=>{this._logService.debug("Unknown OSC code: ",{identifier:e,action:t,data:s})})),this._parser.setDcsHandlerFallback(((e,t,s)=>{"HOOK"===t&&(s=s.toArray()),this._logService.debug("Unknown DCS code: ",{identifier:this._parser.identToString(e),action:t,payload:s})})),this._parser.setPrintHandler(((e,t,s)=>this.print(e,t,s))),this._parser.registerCsiHandler({final:"@"},(e=>this.insertChars(e))),this._parser.registerCsiHandler({intermediates:" ",final:"@"},(e=>this.scrollLeft(e))),this._parser.registerCsiHandler({final:"A"},(e=>this.cursorUp(e))),this._parser.registerCsiHandler({intermediates:" ",final:"A"},(e=>this.scrollRight(e))),this._parser.registerCsiHandler({final:"B"},(e=>this.cursorDown(e))),this._parser.registerCsiHandler({final:"C"},(e=>this.cursorForward(e))),this._parser.registerCsiHandler({final:"D"},(e=>this.cursorBackward(e))),this._parser.registerCsiHandler({final:"E"},(e=>this.cursorNextLine(e))),this._parser.registerCsiHandler({final:"F"},(e=>this.cursorPrecedingLine(e))),this._parser.registerCsiHandler({final:"G"},(e=>this.cursorCharAbsolute(e))),this._parser.registerCsiHandler({final:"H"},(e=>this.cursorPosition(e))),this._parser.registerCsiHandler({final:"I"},(e=>this.cursorForwardTab(e))),this._parser.registerCsiHandler({final:"J"},(e=>this.eraseInDisplay(e,!1))),this._parser.registerCsiHandler({prefix:"?",final:"J"},(e=>this.eraseInDisplay(e,!0))),this._parser.registerCsiHandler({final:"K"},(e=>this.eraseInLine(e,!1))),this._parser.registerCsiHandler({prefix:"?",final:"K"},(e=>this.eraseInLine(e,!0))),this._parser.registerCsiHandler({final:"L"},(e=>this.insertLines(e))),this._parser.registerCsiHandler({final:"M"},(e=>this.deleteLines(e))),this._parser.registerCsiHandler({final:"P"},(e=>this.deleteChars(e))),this._parser.registerCsiHandler({final:"S"},(e=>this.scrollUp(e))),this._parser.registerCsiHandler({final:"T"},(e=>this.scrollDown(e))),this._parser.registerCsiHandler({final:"X"},(e=>this.eraseChars(e))),this._parser.registerCsiHandler({final:"Z"},(e=>this.cursorBackwardTab(e))),this._parser.registerCsiHandler({final:"`"},(e=>this.charPosAbsolute(e))),this._parser.registerCsiHandler({final:"a"},(e=>this.hPositionRelative(e))),this._parser.registerCsiHandler({final:"b"},(e=>this.repeatPrecedingCharacter(e))),this._parser.registerCsiHandler({final:"c"},(e=>this.sendDeviceAttributesPrimary(e))),this._parser.registerCsiHandler({prefix:">",final:"c"},(e=>this.sendDeviceAttributesSecondary(e))),this._parser.registerCsiHandler({final:"d"},(e=>this.linePosAbsolute(e))),this._parser.registerCsiHandler({final:"e"},(e=>this.vPositionRelative(e))),this._parser.registerCsiHandler({final:"f"},(e=>this.hVPosition(e))),this._parser.registerCsiHandler({final:"g"},(e=>this.tabClear(e))),this._parser.registerCsiHandler({final:"h"},(e=>this.setMode(e))),this._parser.registerCsiHandler({prefix:"?",final:"h"},(e=>this.setModePrivate(e))),this._parser.registerCsiHandler({final:"l"},(e=>this.resetMode(e))),this._parser.registerCsiHandler({prefix:"?",final:"l"},(e=>this.resetModePrivate(e))),this._parser.registerCsiHandler({final:"m"},(e=>this.charAttributes(e))),this._parser.registerCsiHandler({final:"n"},(e=>this.deviceStatus(e))),this._parser.registerCsiHandler({prefix:"?",final:"n"},(e=>this.deviceStatusPrivate(e))),this._parser.registerCsiHandler({intermediates:"!",final:"p"},(e=>this.softReset(e))),this._parser.registerCsiHandler({intermediates:" ",final:"q"},(e=>this.setCursorStyle(e))),this._parser.registerCsiHandler({final:"r"},(e=>this.setScrollRegion(e))),this._parser.registerCsiHandler({final:"s"},(e=>this.saveCursor(e))),this._parser.registerCsiHandler({final:"t"},(e=>this.windowOptions(e))),this._parser.registerCsiHandler({final:"u"},(e=>this.restoreCursor(e))),this._parser.registerCsiHandler({intermediates:"'",final:"}"},(e=>this.insertColumns(e))),this._parser.registerCsiHandler({intermediates:"'",final:"~"},(e=>this.deleteColumns(e))),this._parser.registerCsiHandler({intermediates:'"',final:"q"},(e=>this.selectProtected(e))),this._parser.registerCsiHandler({intermediates:"$",final:"p"},(e=>this.requestMode(e,!0))),this._parser.registerCsiHandler({prefix:"?",intermediates:"$",final:"p"},(e=>this.requestMode(e,!1))),this._parser.setExecuteHandler(n.C0.BEL,(()=>this.bell())),this._parser.setExecuteHandler(n.C0.LF,(()=>this.lineFeed())),this._parser.setExecuteHandler(n.C0.VT,(()=>this.lineFeed())),this._parser.setExecuteHandler(n.C0.FF,(()=>this.lineFeed())),this._parser.setExecuteHandler(n.C0.CR,(()=>this.carriageReturn())),this._parser.setExecuteHandler(n.C0.BS,(()=>this.backspace())),this._parser.setExecuteHandler(n.C0.HT,(()=>this.tab())),this._parser.setExecuteHandler(n.C0.SO,(()=>this.shiftOut())),this._parser.setExecuteHandler(n.C0.SI,(()=>this.shiftIn())),this._parser.setExecuteHandler(n.C1.IND,(()=>this.index())),this._parser.setExecuteHandler(n.C1.NEL,(()=>this.nextLine())),this._parser.setExecuteHandler(n.C1.HTS,(()=>this.tabSet())),this._parser.registerOscHandler(0,new g.OscHandler((e=>(this.setTitle(e),this.setIconName(e),!0)))),this._parser.registerOscHandler(1,new g.OscHandler((e=>this.setIconName(e)))),this._parser.registerOscHandler(2,new g.OscHandler((e=>this.setTitle(e)))),this._parser.registerOscHandler(4,new g.OscHandler((e=>this.setOrReportIndexedColor(e)))),this._parser.registerOscHandler(8,new g.OscHandler((e=>this.setHyperlink(e)))),this._parser.registerOscHandler(10,new g.OscHandler((e=>this.setOrReportFgColor(e)))),this._parser.registerOscHandler(11,new g.OscHandler((e=>this.setOrReportBgColor(e)))),this._parser.registerOscHandler(12,new g.OscHandler((e=>this.setOrReportCursorColor(e)))),this._parser.registerOscHandler(104,new g.OscHandler((e=>this.restoreIndexedColor(e)))),this._parser.registerOscHandler(110,new g.OscHandler((e=>this.restoreFgColor(e)))),this._parser.registerOscHandler(111,new g.OscHandler((e=>this.restoreBgColor(e)))),this._parser.registerOscHandler(112,new g.OscHandler((e=>this.restoreCursorColor(e)))),this._parser.registerEscHandler({final:"7"},(()=>this.saveCursor())),this._parser.registerEscHandler({final:"8"},(()=>this.restoreCursor())),this._parser.registerEscHandler({final:"D"},(()=>this.index())),this._parser.registerEscHandler({final:"E"},(()=>this.nextLine())),this._parser.registerEscHandler({final:"H"},(()=>this.tabSet())),this._parser.registerEscHandler({final:"M"},(()=>this.reverseIndex())),this._parser.registerEscHandler({final:"="},(()=>this.keypadApplicationMode())),this._parser.registerEscHandler({final:">"},(()=>this.keypadNumericMode())),this._parser.registerEscHandler({final:"c"},(()=>this.fullReset())),this._parser.registerEscHandler({final:"n"},(()=>this.setgLevel(2))),this._parser.registerEscHandler({final:"o"},(()=>this.setgLevel(3))),this._parser.registerEscHandler({final:"|"},(()=>this.setgLevel(3))),this._parser.registerEscHandler({final:"}"},(()=>this.setgLevel(2))),this._parser.registerEscHandler({final:"~"},(()=>this.setgLevel(1))),this._parser.registerEscHandler({intermediates:"%",final:"@"},(()=>this.selectDefaultCharset())),this._parser.registerEscHandler({intermediates:"%",final:"G"},(()=>this.selectDefaultCharset()));for(const e in o.CHARSETS)this._parser.registerEscHandler({intermediates:"(",final:e},(()=>this.selectCharset("("+e))),this._parser.registerEscHandler({intermediates:")",final:e},(()=>this.selectCharset(")"+e))),this._parser.registerEscHandler({intermediates:"*",final:e},(()=>this.selectCharset("*"+e))),this._parser.registerEscHandler({intermediates:"+",final:e},(()=>this.selectCharset("+"+e))),this._parser.registerEscHandler({intermediates:"-",final:e},(()=>this.selectCharset("-"+e))),this._parser.registerEscHandler({intermediates:".",final:e},(()=>this.selectCharset("."+e))),this._parser.registerEscHandler({intermediates:"/",final:e},(()=>this.selectCharset("/"+e)));this._parser.registerEscHandler({intermediates:"#",final:"8"},(()=>this.screenAlignmentPattern())),this._parser.setErrorHandler((e=>(this._logService.error("Parsing error: ",e),e))),this._parser.registerDcsHandler({intermediates:"$",final:"q"},new v.DcsHandler(((e,t)=>this.requestStatusString(e,t))))}_preserveStack(e,t,s,i){this._parseStack.paused=!0,this._parseStack.cursorStartX=e,this._parseStack.cursorStartY=t,this._parseStack.decodedLength=s,this._parseStack.position=i}_logSlowResolvingAsync(e){this._logService.logLevel<=_.LogLevelEnum.WARN&&Promise.race([e,new Promise(((e,t)=>setTimeout((()=>t("#SLOW_TIMEOUT")),5e3)))]).catch((e=>{if("#SLOW_TIMEOUT"!==e)throw e;console.warn("async parser handler taking longer than 5000 ms")}))}_getCurrentLinkId(){return this._curAttrData.extended.urlId}parse(e,t){let s,i=this._activeBuffer.x,r=this._activeBuffer.y,n=0;const o=this._parseStack.paused;if(o){if(s=this._parser.parse(this._parseBuffer,this._parseStack.decodedLength,t))return this._logSlowResolvingAsync(s),s;i=this._parseStack.cursorStartX,r=this._parseStack.cursorStartY,this._parseStack.paused=!1,e.length>y&&(n=this._parseStack.position+y)}if(this._logService.logLevel<=_.LogLevelEnum.DEBUG&&this._logService.debug("parsing data "+("string"==typeof e?` "${e}"`:` "${Array.prototype.map.call(e,(e=>String.fromCharCode(e))).join("")}"`)),this._logService.logLevel===_.LogLevelEnum.TRACE&&this._logService.trace("parsing data (codes)","string"==typeof e?e.split("").map((e=>e.charCodeAt(0))):e),this._parseBuffer.lengthy)for(let t=n;t0&&2===_.getWidth(this._activeBuffer.x-1)&&_.setCellFromCodepoint(this._activeBuffer.x-1,0,1,f);let g=this._parser.precedingJoinState;for(let v=t;va)if(h){const e=_;let t=this._activeBuffer.x-m;for(this._activeBuffer.x=m,this._activeBuffer.y++,this._activeBuffer.y===this._activeBuffer.scrollBottom+1?(this._activeBuffer.y--,this._bufferService.scroll(this._eraseAttrData(),!0)):(this._activeBuffer.y>=this._bufferService.rows&&(this._activeBuffer.y=this._bufferService.rows-1),this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y).isWrapped=!0),_=this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y),m>0&&_ instanceof l.BufferLine&&_.copyCellsFrom(e,t,0,m,!1);t=0;)_.setCellFromCodepoint(this._activeBuffer.x++,0,0,f)}else if(d&&(_.insertCells(this._activeBuffer.x,r-m,this._activeBuffer.getNullCell(f)),2===_.getWidth(a-1)&&_.setCellFromCodepoint(a-1,u.NULL_CELL_CODE,u.NULL_CELL_WIDTH,f)),_.setCellFromCodepoint(this._activeBuffer.x++,i,r,f),r>0)for(;--r;)_.setCellFromCodepoint(this._activeBuffer.x++,0,0,f)}this._parser.precedingJoinState=g,this._activeBuffer.x0&&0===_.getWidth(this._activeBuffer.x)&&!_.hasContent(this._activeBuffer.x)&&_.setCellFromCodepoint(this._activeBuffer.x,0,1,f),this._dirtyRowTracker.markDirty(this._activeBuffer.y)}registerCsiHandler(e,t){return"t"!==e.final||e.prefix||e.intermediates?this._parser.registerCsiHandler(e,t):this._parser.registerCsiHandler(e,(e=>!C(e.params[0],this._optionsService.rawOptions.windowOptions)||t(e)))}registerDcsHandler(e,t){return this._parser.registerDcsHandler(e,new v.DcsHandler(t))}registerEscHandler(e,t){return this._parser.registerEscHandler(e,t)}registerOscHandler(e,t){return this._parser.registerOscHandler(e,new g.OscHandler(t))}bell(){return this._onRequestBell.fire(),!0}lineFeed(){return this._dirtyRowTracker.markDirty(this._activeBuffer.y),this._optionsService.rawOptions.convertEol&&(this._activeBuffer.x=0),this._activeBuffer.y++,this._activeBuffer.y===this._activeBuffer.scrollBottom+1?(this._activeBuffer.y--,this._bufferService.scroll(this._eraseAttrData())):this._activeBuffer.y>=this._bufferService.rows?this._activeBuffer.y=this._bufferService.rows-1:this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y).isWrapped=!1,this._activeBuffer.x>=this._bufferService.cols&&this._activeBuffer.x--,this._dirtyRowTracker.markDirty(this._activeBuffer.y),this._onLineFeed.fire(),!0}carriageReturn(){return this._activeBuffer.x=0,!0}backspace(){if(!this._coreService.decPrivateModes.reverseWraparound)return this._restrictCursor(),this._activeBuffer.x>0&&this._activeBuffer.x--,!0;if(this._restrictCursor(this._bufferService.cols),this._activeBuffer.x>0)this._activeBuffer.x--;else if(0===this._activeBuffer.x&&this._activeBuffer.y>this._activeBuffer.scrollTop&&this._activeBuffer.y<=this._activeBuffer.scrollBottom&&this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y)?.isWrapped){this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y).isWrapped=!1,this._activeBuffer.y--,this._activeBuffer.x=this._bufferService.cols-1;const e=this._activeBuffer.lines.get(this._activeBuffer.ybase+this._activeBuffer.y);e.hasWidth(this._activeBuffer.x)&&!e.hasContent(this._activeBuffer.x)&&this._activeBuffer.x--}return this._restrictCursor(),!0}tab(){if(this._activeBuffer.x>=this._bufferService.cols)return!0;const e=this._activeBuffer.x;return this._activeBuffer.x=this._activeBuffer.nextStop(),this._optionsService.rawOptions.screenReaderMode&&this._onA11yTab.fire(this._activeBuffer.x-e),!0}shiftOut(){return this._charsetService.setgLevel(1),!0}shiftIn(){return this._charsetService.setgLevel(0),!0}_restrictCursor(e=this._bufferService.cols-1){this._activeBuffer.x=Math.min(e,Math.max(0,this._activeBuffer.x)),this._activeBuffer.y=this._coreService.decPrivateModes.origin?Math.min(this._activeBuffer.scrollBottom,Math.max(this._activeBuffer.scrollTop,this._activeBuffer.y)):Math.min(this._bufferService.rows-1,Math.max(0,this._activeBuffer.y)),this._dirtyRowTracker.markDirty(this._activeBuffer.y)}_setCursor(e,t){this._dirtyRowTracker.markDirty(this._activeBuffer.y),this._coreService.decPrivateModes.origin?(this._activeBuffer.x=e,this._activeBuffer.y=this._activeBuffer.scrollTop+t):(this._activeBuffer.x=e,this._activeBuffer.y=t),this._restrictCursor(),this._dirtyRowTracker.markDirty(this._activeBuffer.y)}_moveCursor(e,t){this._restrictCursor(),this._setCursor(this._activeBuffer.x+e,this._activeBuffer.y+t)}cursorUp(e){const t=this._activeBuffer.y-this._activeBuffer.scrollTop;return t>=0?this._moveCursor(0,-Math.min(t,e.params[0]||1)):this._moveCursor(0,-(e.params[0]||1)),!0}cursorDown(e){const t=this._activeBuffer.scrollBottom-this._activeBuffer.y;return t>=0?this._moveCursor(0,Math.min(t,e.params[0]||1)):this._moveCursor(0,e.params[0]||1),!0}cursorForward(e){return this._moveCursor(e.params[0]||1,0),!0}cursorBackward(e){return this._moveCursor(-(e.params[0]||1),0),!0}cursorNextLine(e){return this.cursorDown(e),this._activeBuffer.x=0,!0}cursorPrecedingLine(e){return this.cursorUp(e),this._activeBuffer.x=0,!0}cursorCharAbsolute(e){return this._setCursor((e.params[0]||1)-1,this._activeBuffer.y),!0}cursorPosition(e){return this._setCursor(e.length>=2?(e.params[1]||1)-1:0,(e.params[0]||1)-1),!0}charPosAbsolute(e){return this._setCursor((e.params[0]||1)-1,this._activeBuffer.y),!0}hPositionRelative(e){return this._moveCursor(e.params[0]||1,0),!0}linePosAbsolute(e){return this._setCursor(this._activeBuffer.x,(e.params[0]||1)-1),!0}vPositionRelative(e){return this._moveCursor(0,e.params[0]||1),!0}hVPosition(e){return this.cursorPosition(e),!0}tabClear(e){const t=e.params[0];return 0===t?delete this._activeBuffer.tabs[this._activeBuffer.x]:3===t&&(this._activeBuffer.tabs={}),!0}cursorForwardTab(e){if(this._activeBuffer.x>=this._bufferService.cols)return!0;let t=e.params[0]||1;for(;t--;)this._activeBuffer.x=this._activeBuffer.nextStop();return!0}cursorBackwardTab(e){if(this._activeBuffer.x>=this._bufferService.cols)return!0;let t=e.params[0]||1;for(;t--;)this._activeBuffer.x=this._activeBuffer.prevStop();return!0}selectProtected(e){const t=e.params[0];return 1===t&&(this._curAttrData.bg|=536870912),2!==t&&0!==t||(this._curAttrData.bg&=-536870913),!0}_eraseInBufferLine(e,t,s,i=!1,r=!1){const n=this._activeBuffer.lines.get(this._activeBuffer.ybase+e);n.replaceCells(t,s,this._activeBuffer.getNullCell(this._eraseAttrData()),r),i&&(n.isWrapped=!1)}_resetBufferLine(e,t=!1){const s=this._activeBuffer.lines.get(this._activeBuffer.ybase+e);s&&(s.fill(this._activeBuffer.getNullCell(this._eraseAttrData()),t),this._bufferService.buffer.clearMarkers(this._activeBuffer.ybase+e),s.isWrapped=!1)}eraseInDisplay(e,t=!1){let s;switch(this._restrictCursor(this._bufferService.cols),e.params[0]){case 0:for(s=this._activeBuffer.y,this._dirtyRowTracker.markDirty(s),this._eraseInBufferLine(s++,this._activeBuffer.x,this._bufferService.cols,0===this._activeBuffer.x,t);s=this._bufferService.cols&&(this._activeBuffer.lines.get(s+1).isWrapped=!1);s--;)this._resetBufferLine(s,t);this._dirtyRowTracker.markDirty(0);break;case 2:if(this._optionsService.rawOptions.scrollOnEraseInDisplay){for(s=this._bufferService.rows,this._dirtyRowTracker.markRangeDirty(0,s-1);s--;){const e=this._activeBuffer.lines.get(this._activeBuffer.ybase+s);if(e?.getTrimmedLength())break}for(;s>=0;s--)this._bufferService.scroll(this._eraseAttrData())}else{for(s=this._bufferService.rows,this._dirtyRowTracker.markDirty(s-1);s--;)this._resetBufferLine(s,t);this._dirtyRowTracker.markDirty(0)}break;case 3:const e=this._activeBuffer.lines.length-this._bufferService.rows;e>0&&(this._activeBuffer.lines.trimStart(e),this._activeBuffer.ybase=Math.max(this._activeBuffer.ybase-e,0),this._activeBuffer.ydisp=Math.max(this._activeBuffer.ydisp-e,0),this._onScroll.fire(0))}return!0}eraseInLine(e,t=!1){switch(this._restrictCursor(this._bufferService.cols),e.params[0]){case 0:this._eraseInBufferLine(this._activeBuffer.y,this._activeBuffer.x,this._bufferService.cols,0===this._activeBuffer.x,t);break;case 1:this._eraseInBufferLine(this._activeBuffer.y,0,this._activeBuffer.x+1,!1,t);break;case 2:this._eraseInBufferLine(this._activeBuffer.y,0,this._bufferService.cols,!0,t)}return this._dirtyRowTracker.markDirty(this._activeBuffer.y),!0}insertLines(e){this._restrictCursor();let t=e.params[0]||1;if(this._activeBuffer.y>this._activeBuffer.scrollBottom||this._activeBuffer.ythis._activeBuffer.scrollBottom||this._activeBuffer.ythis._activeBuffer.scrollBottom||this._activeBuffer.ythis._activeBuffer.scrollBottom||this._activeBuffer.ythis._activeBuffer.scrollBottom||this._activeBuffer.ythis._activeBuffer.scrollBottom||this._activeBuffer.y65535?2:1}let h=a;for(let e=1;e0||(this._is("xterm")||this._is("rxvt-unicode")||this._is("screen")?this._coreService.triggerDataEvent(n.C0.ESC+"[?1;2c"):this._is("linux")&&this._coreService.triggerDataEvent(n.C0.ESC+"[?6c")),!0}sendDeviceAttributesSecondary(e){return e.params[0]>0||(this._is("xterm")?this._coreService.triggerDataEvent(n.C0.ESC+"[>0;276;0c"):this._is("rxvt-unicode")?this._coreService.triggerDataEvent(n.C0.ESC+"[>85;95;0c"):this._is("linux")?this._coreService.triggerDataEvent(e.params[0]+"c"):this._is("screen")&&this._coreService.triggerDataEvent(n.C0.ESC+"[>83;40003;0c")),!0}_is(e){return 0===(this._optionsService.rawOptions.termName+"").indexOf(e)}setMode(e){for(let t=0;te?1:2,f=e.params[0];return _=f,p=t?2===f?4:4===f?d(o.modes.insertMode):12===f?3:20===f?d(u.convertEol):0:1===f?d(s.applicationCursorKeys):3===f?u.windowOptions.setWinLines?80===h?2:132===h?1:0:0:6===f?d(s.origin):7===f?d(s.wraparound):8===f?3:9===f?d("X10"===i):12===f?d(u.cursorBlink):25===f?d(!o.isCursorHidden):45===f?d(s.reverseWraparound):66===f?d(s.applicationKeypad):67===f?4:1e3===f?d("VT200"===i):1002===f?d("DRAG"===i):1003===f?d("ANY"===i):1004===f?d(s.sendFocus):1005===f?4:1006===f?d("SGR"===r):1015===f?4:1016===f?d("SGR_PIXELS"===r):1048===f?1:47===f||1047===f||1049===f?d(c===l):2004===f?d(s.bracketedPasteMode):2026===f?d(s.synchronizedOutput):0,o.triggerDataEvent(`${n.C0.ESC}[${t?"":"?"}${_};${p}$y`),!0;var _,p}_updateAttrColor(e,t,s,i,r){return 2===t?(e|=50331648,e&=-16777216,e|=f.AttributeData.fromColorRGB([s,i,r])):5===t&&(e&=-50331904,e|=33554432|255&s),e}_extractColor(e,t,s){const i=[0,0,-1,0,0,0];let r=0,n=0;do{if(i[n+r]=e.params[t+n],e.hasSubParams(t+n)){const s=e.getSubParams(t+n);let o=0;do{5===i[1]&&(r=1),i[n+o+1+r]=s[o]}while(++o=2||2===i[1]&&n+r>=5)break;i[1]&&(r=1)}while(++n+t5)&&(e=1),t.extended.underlineStyle=e,t.fg|=268435456,0===e&&(t.fg&=-268435457),t.updateExtended()}_processSGR0(e){e.fg=l.DEFAULT_ATTR_DATA.fg,e.bg=l.DEFAULT_ATTR_DATA.bg,e.extended=e.extended.clone(),e.extended.underlineStyle=0,e.extended.underlineColor&=-67108864,e.updateExtended()}charAttributes(e){if(1===e.length&&0===e.params[0])return this._processSGR0(this._curAttrData),!0;const t=e.length;let s;const i=this._curAttrData;for(let r=0;r=30&&s<=37?(i.fg&=-50331904,i.fg|=16777216|s-30):s>=40&&s<=47?(i.bg&=-50331904,i.bg|=16777216|s-40):s>=90&&s<=97?(i.fg&=-50331904,i.fg|=16777224|s-90):s>=100&&s<=107?(i.bg&=-50331904,i.bg|=16777224|s-100):0===s?this._processSGR0(i):1===s?i.fg|=134217728:3===s?i.bg|=67108864:4===s?(i.fg|=268435456,this._processUnderline(e.hasSubParams(r)?e.getSubParams(r)[0]:1,i)):5===s?i.fg|=536870912:7===s?i.fg|=67108864:8===s?i.fg|=1073741824:9===s?i.fg|=2147483648:2===s?i.bg|=134217728:21===s?this._processUnderline(2,i):22===s?(i.fg&=-134217729,i.bg&=-134217729):23===s?i.bg&=-67108865:24===s?(i.fg&=-268435457,this._processUnderline(0,i)):25===s?i.fg&=-536870913:27===s?i.fg&=-67108865:28===s?i.fg&=-1073741825:29===s?i.fg&=2147483647:39===s?(i.fg&=-67108864,i.fg|=16777215&l.DEFAULT_ATTR_DATA.fg):49===s?(i.bg&=-67108864,i.bg|=16777215&l.DEFAULT_ATTR_DATA.bg):38===s||48===s||58===s?r+=this._extractColor(e,r,i):53===s?i.bg|=1073741824:55===s?i.bg&=-1073741825:59===s?(i.extended=i.extended.clone(),i.extended.underlineColor=-1,i.updateExtended()):100===s?(i.fg&=-67108864,i.fg|=16777215&l.DEFAULT_ATTR_DATA.fg,i.bg&=-67108864,i.bg|=16777215&l.DEFAULT_ATTR_DATA.bg):this._logService.debug("Unknown SGR attribute: %d.",s);return!0}deviceStatus(e){switch(e.params[0]){case 5:this._coreService.triggerDataEvent(`${n.C0.ESC}[0n`);break;case 6:const e=this._activeBuffer.y+1,t=this._activeBuffer.x+1;this._coreService.triggerDataEvent(`${n.C0.ESC}[${e};${t}R`)}return!0}deviceStatusPrivate(e){if(6===e.params[0]){const e=this._activeBuffer.y+1,t=this._activeBuffer.x+1;this._coreService.triggerDataEvent(`${n.C0.ESC}[?${e};${t}R`)}return!0}softReset(e){return this._coreService.isCursorHidden=!1,this._onRequestSyncScrollBar.fire(),this._activeBuffer.scrollTop=0,this._activeBuffer.scrollBottom=this._bufferService.rows-1,this._curAttrData=l.DEFAULT_ATTR_DATA.clone(),this._coreService.reset(),this._charsetService.reset(),this._activeBuffer.savedX=0,this._activeBuffer.savedY=this._activeBuffer.ybase,this._activeBuffer.savedCurAttrData.fg=this._curAttrData.fg,this._activeBuffer.savedCurAttrData.bg=this._curAttrData.bg,this._activeBuffer.savedCharset=this._charsetService.charset,this._coreService.decPrivateModes.origin=!1,!0}setCursorStyle(e){const t=0===e.length?1:e.params[0];if(0===t)this._coreService.decPrivateModes.cursorStyle=void 0,this._coreService.decPrivateModes.cursorBlink=void 0;else{switch(t){case 1:case 2:this._coreService.decPrivateModes.cursorStyle="block";break;case 3:case 4:this._coreService.decPrivateModes.cursorStyle="underline";break;case 5:case 6:this._coreService.decPrivateModes.cursorStyle="bar"}const e=t%2==1;this._coreService.decPrivateModes.cursorBlink=e}return!0}setScrollRegion(e){const t=e.params[0]||1;let s;return(e.length<2||(s=e.params[1])>this._bufferService.rows||0===s)&&(s=this._bufferService.rows),s>t&&(this._activeBuffer.scrollTop=t-1,this._activeBuffer.scrollBottom=s-1,this._setCursor(0,0)),!0}windowOptions(e){if(!C(e.params[0],this._optionsService.rawOptions.windowOptions))return!0;const t=e.length>1?e.params[1]:0;switch(e.params[0]){case 14:2!==t&&this._onRequestWindowsOptionsReport.fire(w.GET_WIN_SIZE_PIXELS);break;case 16:this._onRequestWindowsOptionsReport.fire(w.GET_CELL_SIZE_PIXELS);break;case 18:this._bufferService&&this._coreService.triggerDataEvent(`${n.C0.ESC}[8;${this._bufferService.rows};${this._bufferService.cols}t`);break;case 22:0!==t&&2!==t||(this._windowTitleStack.push(this._windowTitle),this._windowTitleStack.length>10&&this._windowTitleStack.shift()),0!==t&&1!==t||(this._iconNameStack.push(this._iconName),this._iconNameStack.length>10&&this._iconNameStack.shift());break;case 23:0!==t&&2!==t||this._windowTitleStack.length&&this.setTitle(this._windowTitleStack.pop()),0!==t&&1!==t||this._iconNameStack.length&&this.setIconName(this._iconNameStack.pop())}return!0}saveCursor(e){return this._activeBuffer.savedX=this._activeBuffer.x,this._activeBuffer.savedY=this._activeBuffer.ybase+this._activeBuffer.y,this._activeBuffer.savedCurAttrData.fg=this._curAttrData.fg,this._activeBuffer.savedCurAttrData.bg=this._curAttrData.bg,this._activeBuffer.savedCharset=this._charsetService.charset,!0}restoreCursor(e){return this._activeBuffer.x=this._activeBuffer.savedX||0,this._activeBuffer.y=Math.max(this._activeBuffer.savedY-this._activeBuffer.ybase,0),this._curAttrData.fg=this._activeBuffer.savedCurAttrData.fg,this._curAttrData.bg=this._activeBuffer.savedCurAttrData.bg,this._charsetService.charset=this._savedCharset,this._activeBuffer.savedCharset&&(this._charsetService.charset=this._activeBuffer.savedCharset),this._restrictCursor(),!0}setTitle(e){return this._windowTitle=e,this._onTitleChange.fire(e),!0}setIconName(e){return this._iconName=e,!0}setOrReportIndexedColor(e){const t=[],s=e.split(";");for(;s.length>1;){const e=s.shift(),i=s.shift();if(/^\d+$/.exec(e)){const s=parseInt(e);if(k(s))if("?"===i)t.push({type:0,index:s});else{const e=(0,m.parseColor)(i);e&&t.push({type:1,index:s,color:e})}}}return t.length&&this._onColor.fire(t),!0}setHyperlink(e){const t=e.indexOf(";");if(-1===t)return!0;const s=e.slice(0,t).trim(),i=e.slice(t+1);return i?this._createHyperlink(s,i):!s.trim()&&this._finishHyperlink()}_createHyperlink(e,t){this._getCurrentLinkId()&&this._finishHyperlink();const s=e.split(":");let i;const r=s.findIndex((e=>e.startsWith("id=")));return-1!==r&&(i=s[r].slice(3)||void 0),this._curAttrData.extended=this._curAttrData.extended.clone(),this._curAttrData.extended.urlId=this._oscLinkService.registerLink({id:i,uri:t}),this._curAttrData.updateExtended(),!0}_finishHyperlink(){return this._curAttrData.extended=this._curAttrData.extended.clone(),this._curAttrData.extended.urlId=0,this._curAttrData.updateExtended(),!0}_setOrReportSpecialColor(e,t){const s=e.split(";");for(let e=0;e=this._specialColors.length);++e,++t)if("?"===s[e])this._onColor.fire([{type:0,index:this._specialColors[t]}]);else{const i=(0,m.parseColor)(s[e]);i&&this._onColor.fire([{type:1,index:this._specialColors[t],color:i}])}return!0}setOrReportFgColor(e){return this._setOrReportSpecialColor(e,0)}setOrReportBgColor(e){return this._setOrReportSpecialColor(e,1)}setOrReportCursorColor(e){return this._setOrReportSpecialColor(e,2)}restoreIndexedColor(e){if(!e)return this._onColor.fire([{type:2}]),!0;const t=[],s=e.split(";");for(let e=0;e=this._bufferService.rows&&(this._activeBuffer.y=this._bufferService.rows-1),this._restrictCursor(),!0}tabSet(){return this._activeBuffer.tabs[this._activeBuffer.x]=!0,!0}reverseIndex(){if(this._restrictCursor(),this._activeBuffer.y===this._activeBuffer.scrollTop){const e=this._activeBuffer.scrollBottom-this._activeBuffer.scrollTop;this._activeBuffer.lines.shiftElements(this._activeBuffer.ybase+this._activeBuffer.y,e,1),this._activeBuffer.lines.set(this._activeBuffer.ybase+this._activeBuffer.y,this._activeBuffer.getBlankLine(this._eraseAttrData())),this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop,this._activeBuffer.scrollBottom)}else this._activeBuffer.y--,this._restrictCursor();return!0}fullReset(){return this._parser.reset(),this._onRequestReset.fire(),!0}reset(){this._curAttrData=l.DEFAULT_ATTR_DATA.clone(),this._eraseAttrDataInternal=l.DEFAULT_ATTR_DATA.clone()}_eraseAttrData(){return this._eraseAttrDataInternal.bg&=-67108864,this._eraseAttrDataInternal.bg|=67108863&this._curAttrData.bg,this._eraseAttrDataInternal}setgLevel(e){return this._charsetService.setgLevel(e),!0}screenAlignmentPattern(){const e=new d.CellData;e.content=1<<22|"E".charCodeAt(0),e.fg=this._curAttrData.fg,e.bg=this._curAttrData.bg,this._setCursor(0,0);for(let t=0;t(this._coreService.triggerDataEvent(`${n.C0.ESC}${e}${n.C0.ESC}\\`),!0))('"q'===e?`P1$r${this._curAttrData.isProtected()?1:0}"q`:'"p'===e?'P1$r61;1"p':"r"===e?`P1$r${s.scrollTop+1};${s.scrollBottom+1}r`:"m"===e?"P1$r0m":" q"===e?`P1$r${{block:2,underline:4,bar:6}[i.cursorStyle]-(i.cursorBlink?1:0)} q`:"P0$r")}markRangeDirty(e,t){this._dirtyRowTracker.markRangeDirty(e,t)}}t.InputHandler=A;let L=class{constructor(e){this._bufferService=e,this.clearRange()}clearRange(){this.start=this._bufferService.buffer.y,this.end=this._bufferService.buffer.y}markDirty(e){ethis.end&&(this.end=e)}markRangeDirty(e,t){e>t&&(E=e,e=t,t=E),ethis.end&&(this.end=t)}markAllDirty(){this.markRangeDirty(0,this._bufferService.rows-1)}};function k(e){return 0<=e&&e<256}L=i([r(0,_.IBufferService)],L)},701:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.isChromeOS=t.isLinux=t.isWindows=t.isIphone=t.isIpad=t.isMac=t.isSafari=t.isLegacyEdge=t.isFirefox=t.isNode=void 0,t.getSafariVersion=function(){if(!t.isSafari)return 0;const e=s.match(/Version\/(\d+)/);return null===e||e.length<2?0:parseInt(e[1])},t.isNode="undefined"!=typeof process&&"title"in process;const s=t.isNode?"node":navigator.userAgent,i=t.isNode?"node":navigator.platform;t.isFirefox=s.includes("Firefox"),t.isLegacyEdge=s.includes("Edge"),t.isSafari=/^((?!chrome|android).)*safari/i.test(s),t.isMac=["Macintosh","MacIntel","MacPPC","Mac68K"].includes(i),t.isIpad="iPad"===i,t.isIphone="iPhone"===i,t.isWindows=["Windows","Win16","Win32","WinCE"].includes(i),t.isLinux=i.indexOf("Linux")>=0,t.isChromeOS=/\bCrOS\b/.test(s)},6168:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.DebouncedIdleTask=t.IdleTaskQueue=t.PriorityTaskQueue=void 0;const i=s(701);class r{constructor(){this._tasks=[],this._i=0}enqueue(e){this._tasks.push(e),this._start()}flush(){for(;this._ir)return i-t<-20&&console.warn(`task queue exceeded allotted deadline by ${Math.abs(Math.round(i-t))}ms`),void this._start();i=r}this.clear()}}class n extends r{_requestCallback(e){return setTimeout((()=>e(this._createDeadline(16))))}_cancelCallback(e){clearTimeout(e)}_createDeadline(e){const t=performance.now()+e;return{timeRemaining:()=>Math.max(0,t-performance.now())}}}t.PriorityTaskQueue=n,t.IdleTaskQueue=!i.isNode&&"requestIdleCallback"in window?class extends r{_requestCallback(e){return requestIdleCallback(e)}_cancelCallback(e){cancelIdleCallback(e)}}:n,t.DebouncedIdleTask=class{constructor(){this._queue=new t.IdleTaskQueue}set(e){this._queue.clear(),this._queue.enqueue(e)}flush(){this._queue.flush()}}},5882:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.updateWindowsModeWrappedState=function(e){const t=e.buffer.lines.get(e.buffer.ybase+e.buffer.y-1),s=t?.get(e.cols-1),r=e.buffer.lines.get(e.buffer.ybase+e.buffer.y);r&&s&&(r.isWrapped=s[i.CHAR_DATA_CODE_INDEX]!==i.NULL_CELL_CODE&&s[i.CHAR_DATA_CODE_INDEX]!==i.WHITESPACE_CELL_CODE)};const i=s(8938)},5451:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ExtendedAttrs=t.AttributeData=void 0;class s{constructor(){this.fg=0,this.bg=0,this.extended=new i}static toColorRGB(e){return[e>>>16&255,e>>>8&255,255&e]}static fromColorRGB(e){return(255&e[0])<<16|(255&e[1])<<8|255&e[2]}clone(){const e=new s;return e.fg=this.fg,e.bg=this.bg,e.extended=this.extended.clone(),e}isInverse(){return 67108864&this.fg}isBold(){return 134217728&this.fg}isUnderline(){return this.hasExtendedAttrs()&&0!==this.extended.underlineStyle?1:268435456&this.fg}isBlink(){return 536870912&this.fg}isInvisible(){return 1073741824&this.fg}isItalic(){return 67108864&this.bg}isDim(){return 134217728&this.bg}isStrikethrough(){return 2147483648&this.fg}isProtected(){return 536870912&this.bg}isOverline(){return 1073741824&this.bg}getFgColorMode(){return 50331648&this.fg}getBgColorMode(){return 50331648&this.bg}isFgRGB(){return!(50331648&~this.fg)}isBgRGB(){return!(50331648&~this.bg)}isFgPalette(){return 16777216==(50331648&this.fg)||33554432==(50331648&this.fg)}isBgPalette(){return 16777216==(50331648&this.bg)||33554432==(50331648&this.bg)}isFgDefault(){return!(50331648&this.fg)}isBgDefault(){return!(50331648&this.bg)}isAttributeDefault(){return 0===this.fg&&0===this.bg}getFgColor(){switch(50331648&this.fg){case 16777216:case 33554432:return 255&this.fg;case 50331648:return 16777215&this.fg;default:return-1}}getBgColor(){switch(50331648&this.bg){case 16777216:case 33554432:return 255&this.bg;case 50331648:return 16777215&this.bg;default:return-1}}hasExtendedAttrs(){return 268435456&this.bg}updateExtended(){this.extended.isEmpty()?this.bg&=-268435457:this.bg|=268435456}getUnderlineColor(){if(268435456&this.bg&&~this.extended.underlineColor)switch(50331648&this.extended.underlineColor){case 16777216:case 33554432:return 255&this.extended.underlineColor;case 50331648:return 16777215&this.extended.underlineColor;default:return this.getFgColor()}return this.getFgColor()}getUnderlineColorMode(){return 268435456&this.bg&&~this.extended.underlineColor?50331648&this.extended.underlineColor:this.getFgColorMode()}isUnderlineColorRGB(){return 268435456&this.bg&&~this.extended.underlineColor?!(50331648&~this.extended.underlineColor):this.isFgRGB()}isUnderlineColorPalette(){return 268435456&this.bg&&~this.extended.underlineColor?16777216==(50331648&this.extended.underlineColor)||33554432==(50331648&this.extended.underlineColor):this.isFgPalette()}isUnderlineColorDefault(){return 268435456&this.bg&&~this.extended.underlineColor?!(50331648&this.extended.underlineColor):this.isFgDefault()}getUnderlineStyle(){return 268435456&this.fg?268435456&this.bg?this.extended.underlineStyle:1:0}getUnderlineVariantOffset(){return this.extended.underlineVariantOffset}}t.AttributeData=s;class i{get ext(){return this._urlId?-469762049&this._ext|this.underlineStyle<<26:this._ext}set ext(e){this._ext=e}get underlineStyle(){return this._urlId?5:(469762048&this._ext)>>26}set underlineStyle(e){this._ext&=-469762049,this._ext|=e<<26&469762048}get underlineColor(){return 67108863&this._ext}set underlineColor(e){this._ext&=-67108864,this._ext|=67108863&e}get urlId(){return this._urlId}set urlId(e){this._urlId=e}get underlineVariantOffset(){const e=(3758096384&this._ext)>>29;return e<0?4294967288^e:e}set underlineVariantOffset(e){this._ext&=536870911,this._ext|=e<<29&3758096384}constructor(e=0,t=0){this._ext=0,this._urlId=0,this._ext=e,this._urlId=t}clone(){return new i(this._ext,this._urlId)}isEmpty(){return 0===this.underlineStyle&&0===this._urlId}}t.ExtendedAttrs=i},1073:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Buffer=t.MAX_BUFFER_SIZE=void 0;const i=s(5639),r=s(6168),n=s(5451),o=s(6107),a=s(732),h=s(3055),c=s(8938),l=s(8158),u=s(6760);t.MAX_BUFFER_SIZE=4294967295,t.Buffer=class{constructor(e,t,s){this._hasScrollback=e,this._optionsService=t,this._bufferService=s,this.ydisp=0,this.ybase=0,this.y=0,this.x=0,this.tabs={},this.savedY=0,this.savedX=0,this.savedCurAttrData=o.DEFAULT_ATTR_DATA.clone(),this.savedCharset=u.DEFAULT_CHARSET,this.markers=[],this._nullCell=h.CellData.fromCharData([0,c.NULL_CELL_CHAR,c.NULL_CELL_WIDTH,c.NULL_CELL_CODE]),this._whitespaceCell=h.CellData.fromCharData([0,c.WHITESPACE_CELL_CHAR,c.WHITESPACE_CELL_WIDTH,c.WHITESPACE_CELL_CODE]),this._isClearing=!1,this._memoryCleanupQueue=new r.IdleTaskQueue,this._memoryCleanupPosition=0,this._cols=this._bufferService.cols,this._rows=this._bufferService.rows,this.lines=new i.CircularList(this._getCorrectBufferLength(this._rows)),this.scrollTop=0,this.scrollBottom=this._rows-1,this.setupTabStops()}getNullCell(e){return e?(this._nullCell.fg=e.fg,this._nullCell.bg=e.bg,this._nullCell.extended=e.extended):(this._nullCell.fg=0,this._nullCell.bg=0,this._nullCell.extended=new n.ExtendedAttrs),this._nullCell}getWhitespaceCell(e){return e?(this._whitespaceCell.fg=e.fg,this._whitespaceCell.bg=e.bg,this._whitespaceCell.extended=e.extended):(this._whitespaceCell.fg=0,this._whitespaceCell.bg=0,this._whitespaceCell.extended=new n.ExtendedAttrs),this._whitespaceCell}getBlankLine(e,t){return new o.BufferLine(this._bufferService.cols,this.getNullCell(e),t)}get hasScrollback(){return this._hasScrollback&&this.lines.maxLength>this._rows}get isCursorInViewport(){const e=this.ybase+this.y-this.ydisp;return e>=0&&et.MAX_BUFFER_SIZE?t.MAX_BUFFER_SIZE:s}fillViewportRows(e){if(0===this.lines.length){void 0===e&&(e=o.DEFAULT_ATTR_DATA);let t=this._rows;for(;t--;)this.lines.push(this.getBlankLine(e))}}clear(){this.ydisp=0,this.ybase=0,this.y=0,this.x=0,this.lines=new i.CircularList(this._getCorrectBufferLength(this._rows)),this.scrollTop=0,this.scrollBottom=this._rows-1,this.setupTabStops()}resize(e,t){const s=this.getNullCell(o.DEFAULT_ATTR_DATA);let i=0;const r=this._getCorrectBufferLength(t);if(r>this.lines.maxLength&&(this.lines.maxLength=r),this.lines.length>0){if(this._cols0&&this.lines.length<=this.ybase+this.y+n+1?(this.ybase--,n++,this.ydisp>0&&this.ydisp--):this.lines.push(new o.BufferLine(e,s)));else for(let e=this._rows;e>t;e--)this.lines.length>t+this.ybase&&(this.lines.length>this.ybase+this.y+1?this.lines.pop():(this.ybase++,this.ydisp++));if(r0&&(this.lines.trimStart(e),this.ybase=Math.max(this.ybase-e,0),this.ydisp=Math.max(this.ydisp-e,0),this.savedY=Math.max(this.savedY-e,0)),this.lines.maxLength=r}this.x=Math.min(this.x,e-1),this.y=Math.min(this.y,t-1),n&&(this.y+=n),this.savedX=Math.min(this.savedX,e-1),this.scrollTop=0}if(this.scrollBottom=t-1,this._isReflowEnabled&&(this._reflow(e,t),this._cols>e))for(let t=0;t.1*this.lines.length&&(this._memoryCleanupPosition=0,this._memoryCleanupQueue.enqueue((()=>this._batchedMemoryCleanup())))}_batchedMemoryCleanup(){let e=!0;this._memoryCleanupPosition>=this.lines.length&&(this._memoryCleanupPosition=0,e=!1);let t=0;for(;this._memoryCleanupPosition100)return!0;return e}get _isReflowEnabled(){const e=this._optionsService.rawOptions.windowsPty;return e&&e.buildNumber?this._hasScrollback&&"conpty"===e.backend&&e.buildNumber>=21376:this._hasScrollback&&!this._optionsService.rawOptions.windowsMode}_reflow(e,t){this._cols!==e&&(e>this._cols?this._reflowLarger(e,t):this._reflowSmaller(e,t))}_reflowLarger(e,t){const s=this._optionsService.rawOptions.reflowCursorLine,i=(0,a.reflowLargerGetLinesToRemove)(this.lines,this._cols,e,this.ybase+this.y,this.getNullCell(o.DEFAULT_ATTR_DATA),s);if(i.length>0){const s=(0,a.reflowLargerCreateNewLayout)(this.lines,i);(0,a.reflowLargerApplyNewLayout)(this.lines,s.layout),this._reflowLargerAdjustViewport(e,t,s.countRemoved)}}_reflowLargerAdjustViewport(e,t,s){const i=this.getNullCell(o.DEFAULT_ATTR_DATA);let r=s;for(;r-- >0;)0===this.ybase?(this.y>0&&this.y--,this.lines.length=0;h--){let c=this.lines.get(h);if(!c||!c.isWrapped&&c.getTrimmedLength()<=e)continue;const l=[c];for(;c.isWrapped&&h>0;)c=this.lines.get(--h),l.unshift(c);if(!s){const e=this.ybase+this.y;if(e>=h&&e0&&(r.push({start:h+l.length+n,newLines:p}),n+=p.length),l.push(...p);let g=d.length-1,v=d[g];0===v&&(g--,v=d[g]);let m=l.length-f-1,b=u;for(;m>=0;){const e=Math.min(b,v);if(void 0===l[g])break;if(l[g].copyCellsFrom(l[m],b-e,v-e,e,!0),v-=e,0===v&&(g--,v=d[g]),b-=e,0===b){m--;const e=Math.max(m,0);b=(0,a.getWrappedLineTrimmedLength)(l,e,this._cols)}}for(let t=0;t0;)0===this.ybase?this.y0){const e=[],t=[];for(let e=0;e=0;c--)if(a&&a.start>i+h){for(let e=a.newLines.length-1;e>=0;e--)this.lines.set(c--,a.newLines[e]);c++,e.push({index:i+1,amount:a.newLines.length}),h+=a.newLines.length,a=r[++o]}else this.lines.set(c,t[i--]);let c=0;for(let t=e.length-1;t>=0;t--)e[t].index+=c,this.lines.onInsertEmitter.fire(e[t]),c+=e[t].amount;const l=Math.max(0,s+n-this.lines.maxLength);l>0&&this.lines.onTrimEmitter.fire(l)}}translateBufferLineToString(e,t,s=0,i){const r=this.lines.get(e);return r?r.translateToString(t,s,i):""}getWrappedRangeForLine(e){let t=e,s=e;for(;t>0&&this.lines.get(t).isWrapped;)t--;for(;s+10;);return e>=this._cols?this._cols-1:e<0?0:e}nextStop(e){for(null==e&&(e=this.x);!this.tabs[++e]&&e=this._cols?this._cols-1:e<0?0:e}clearMarkers(e){this._isClearing=!0;for(let t=0;t{t.line-=e,t.line<0&&t.dispose()}))),t.register(this.lines.onInsert((e=>{t.line>=e.index&&(t.line+=e.amount)}))),t.register(this.lines.onDelete((e=>{t.line>=e.index&&t.linee.index&&(t.line-=e.amount)}))),t.register(t.onDispose((()=>this._removeMarker(t)))),t}_removeMarker(e){this._isClearing||this.markers.splice(this.markers.indexOf(e),1)}}},6107:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.BufferLine=t.DEFAULT_ATTR_DATA=void 0;const i=s(5451),r=s(3055),n=s(8938),o=s(726);t.DEFAULT_ATTR_DATA=Object.freeze(new i.AttributeData);let a=0;class h{constructor(e,t,s=!1){this.isWrapped=s,this._combined={},this._extendedAttrs={},this._data=new Uint32Array(3*e);const i=t||r.CellData.fromCharData([0,n.NULL_CELL_CHAR,n.NULL_CELL_WIDTH,n.NULL_CELL_CODE]);for(let t=0;t>22,2097152&t?this._combined[e].charCodeAt(this._combined[e].length-1):s]}set(e,t){this._data[3*e+1]=t[n.CHAR_DATA_ATTR_INDEX],t[n.CHAR_DATA_CHAR_INDEX].length>1?(this._combined[e]=t[1],this._data[3*e+0]=2097152|e|t[n.CHAR_DATA_WIDTH_INDEX]<<22):this._data[3*e+0]=t[n.CHAR_DATA_CHAR_INDEX].charCodeAt(0)|t[n.CHAR_DATA_WIDTH_INDEX]<<22}getWidth(e){return this._data[3*e+0]>>22}hasWidth(e){return 12582912&this._data[3*e+0]}getFg(e){return this._data[3*e+1]}getBg(e){return this._data[3*e+2]}hasContent(e){return 4194303&this._data[3*e+0]}getCodePoint(e){const t=this._data[3*e+0];return 2097152&t?this._combined[e].charCodeAt(this._combined[e].length-1):2097151&t}isCombined(e){return 2097152&this._data[3*e+0]}getString(e){const t=this._data[3*e+0];return 2097152&t?this._combined[e]:2097151&t?(0,o.stringFromCodePoint)(2097151&t):""}isProtected(e){return 536870912&this._data[3*e+2]}loadCell(e,t){return a=3*e,t.content=this._data[a+0],t.fg=this._data[a+1],t.bg=this._data[a+2],2097152&t.content&&(t.combinedData=this._combined[e]),268435456&t.bg&&(t.extended=this._extendedAttrs[e]),t}setCell(e,t){2097152&t.content&&(this._combined[e]=t.combinedData),268435456&t.bg&&(this._extendedAttrs[e]=t.extended),this._data[3*e+0]=t.content,this._data[3*e+1]=t.fg,this._data[3*e+2]=t.bg}setCellFromCodepoint(e,t,s,i){268435456&i.bg&&(this._extendedAttrs[e]=i.extended),this._data[3*e+0]=t|s<<22,this._data[3*e+1]=i.fg,this._data[3*e+2]=i.bg}addCodepointToCell(e,t,s){let i=this._data[3*e+0];2097152&i?this._combined[e]+=(0,o.stringFromCodePoint)(t):2097151&i?(this._combined[e]=(0,o.stringFromCodePoint)(2097151&i)+(0,o.stringFromCodePoint)(t),i&=-2097152,i|=2097152):i=t|1<<22,s&&(i&=-12582913,i|=s<<22),this._data[3*e+0]=i}insertCells(e,t,s){if((e%=this.length)&&2===this.getWidth(e-1)&&this.setCellFromCodepoint(e-1,0,1,s),t=0;--s)this.setCell(e+t+s,this.loadCell(e+s,i));for(let i=0;ithis.length){if(this._data.buffer.byteLength>=4*s)this._data=new Uint32Array(this._data.buffer,0,s);else{const e=new Uint32Array(s);e.set(this._data),this._data=e}for(let s=this.length;s=e&&delete this._combined[i]}const i=Object.keys(this._extendedAttrs);for(let t=0;t=e&&delete this._extendedAttrs[s]}}return this.length=e,4*s*2=0;--e)if(4194303&this._data[3*e+0])return e+(this._data[3*e+0]>>22);return 0}getNoBgTrimmedLength(){for(let e=this.length-1;e>=0;--e)if(4194303&this._data[3*e+0]||50331648&this._data[3*e+2])return e+(this._data[3*e+0]>>22);return 0}copyCellsFrom(e,t,s,i,r){const n=e._data;if(r)for(let r=i-1;r>=0;r--){for(let e=0;e<3;e++)this._data[3*(s+r)+e]=n[3*(t+r)+e];268435456&n[3*(t+r)+2]&&(this._extendedAttrs[s+r]=e._extendedAttrs[t+r])}else for(let r=0;r=t&&(this._combined[r-t+s]=e._combined[r])}}translateToString(e,t,s,i){t=t??0,s=s??this.length,e&&(s=Math.min(s,this.getTrimmedLength())),i&&(i.length=0);let r="";for(;t>22||1}return i&&i.push(t),r}}t.BufferLine=h},732:(e,t)=>{function s(e,t,s){if(t===e.length-1)return e[t].getTrimmedLength();const i=!e[t].hasContent(s-1)&&1===e[t].getWidth(s-1),r=2===e[t+1].getWidth(0);return i&&r?s-1:s}Object.defineProperty(t,"__esModule",{value:!0}),t.reflowLargerGetLinesToRemove=function(e,t,i,r,n,o){const a=[];for(let h=0;h=h&&r0&&(e>d||0===u[e].getTrimmedLength());e--)g++;g>0&&(a.push(h+u.length-g),a.push(g)),h+=u.length-1}return a},t.reflowLargerCreateNewLayout=function(e,t){const s=[];let i=0,r=t[i],n=0;for(let o=0;os(e,r,t))).reduce(((e,t)=>e+t));let o=0,a=0,h=0;for(;hc&&(o-=c,a++);const l=2===e[a].getWidth(o-1);l&&o--;const u=l?i-1:i;r.push(u),h+=u}return r},t.getWrappedLineTrimmedLength=s},4097:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.BufferSet=void 0;const i=s(7150),r=s(1073),n=s(802);class o extends i.Disposable{constructor(e,t){super(),this._optionsService=e,this._bufferService=t,this._onBufferActivate=this._register(new n.Emitter),this.onBufferActivate=this._onBufferActivate.event,this.reset(),this._register(this._optionsService.onSpecificOptionChange("scrollback",(()=>this.resize(this._bufferService.cols,this._bufferService.rows)))),this._register(this._optionsService.onSpecificOptionChange("tabStopWidth",(()=>this.setupTabStops())))}reset(){this._normal=new r.Buffer(!0,this._optionsService,this._bufferService),this._normal.fillViewportRows(),this._alt=new r.Buffer(!1,this._optionsService,this._bufferService),this._activeBuffer=this._normal,this._onBufferActivate.fire({activeBuffer:this._normal,inactiveBuffer:this._alt}),this.setupTabStops()}get alt(){return this._alt}get active(){return this._activeBuffer}get normal(){return this._normal}activateNormalBuffer(){this._activeBuffer!==this._normal&&(this._normal.x=this._alt.x,this._normal.y=this._alt.y,this._alt.clearAllMarkers(),this._alt.clear(),this._activeBuffer=this._normal,this._onBufferActivate.fire({activeBuffer:this._normal,inactiveBuffer:this._alt}))}activateAltBuffer(e){this._activeBuffer!==this._alt&&(this._alt.fillViewportRows(e),this._alt.x=this._normal.x,this._alt.y=this._normal.y,this._activeBuffer=this._alt,this._onBufferActivate.fire({activeBuffer:this._alt,inactiveBuffer:this._normal}))}resize(e,t){this._normal.resize(e,t),this._alt.resize(e,t),this.setupTabStops(e)}setupTabStops(e){this._normal.setupTabStops(e),this._alt.setupTabStops(e)}}t.BufferSet=o},3055:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.CellData=void 0;const i=s(726),r=s(8938),n=s(5451);class o extends n.AttributeData{constructor(){super(...arguments),this.content=0,this.fg=0,this.bg=0,this.extended=new n.ExtendedAttrs,this.combinedData=""}static fromCharData(e){const t=new o;return t.setFromCharData(e),t}isCombined(){return 2097152&this.content}getWidth(){return this.content>>22}getChars(){return 2097152&this.content?this.combinedData:2097151&this.content?(0,i.stringFromCodePoint)(2097151&this.content):""}getCode(){return this.isCombined()?this.combinedData.charCodeAt(this.combinedData.length-1):2097151&this.content}setFromCharData(e){this.fg=e[r.CHAR_DATA_ATTR_INDEX],this.bg=0;let t=!1;if(e[r.CHAR_DATA_CHAR_INDEX].length>2)t=!0;else if(2===e[r.CHAR_DATA_CHAR_INDEX].length){const s=e[r.CHAR_DATA_CHAR_INDEX].charCodeAt(0);if(55296<=s&&s<=56319){const i=e[r.CHAR_DATA_CHAR_INDEX].charCodeAt(1);56320<=i&&i<=57343?this.content=1024*(s-55296)+i-56320+65536|e[r.CHAR_DATA_WIDTH_INDEX]<<22:t=!0}else t=!0}else this.content=e[r.CHAR_DATA_CHAR_INDEX].charCodeAt(0)|e[r.CHAR_DATA_WIDTH_INDEX]<<22;t&&(this.combinedData=e[r.CHAR_DATA_CHAR_INDEX],this.content=2097152|e[r.CHAR_DATA_WIDTH_INDEX]<<22)}getAsCharData(){return[this.fg,this.getChars(),this.getWidth(),this.getCode()]}}t.CellData=o},8938:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.WHITESPACE_CELL_CODE=t.WHITESPACE_CELL_WIDTH=t.WHITESPACE_CELL_CHAR=t.NULL_CELL_CODE=t.NULL_CELL_WIDTH=t.NULL_CELL_CHAR=t.CHAR_DATA_CODE_INDEX=t.CHAR_DATA_WIDTH_INDEX=t.CHAR_DATA_CHAR_INDEX=t.CHAR_DATA_ATTR_INDEX=t.DEFAULT_EXT=t.DEFAULT_ATTR=t.DEFAULT_COLOR=void 0,t.DEFAULT_COLOR=0,t.DEFAULT_ATTR=t.DEFAULT_COLOR<<9|256,t.DEFAULT_EXT=0,t.CHAR_DATA_ATTR_INDEX=0,t.CHAR_DATA_CHAR_INDEX=1,t.CHAR_DATA_WIDTH_INDEX=2,t.CHAR_DATA_CODE_INDEX=3,t.NULL_CELL_CHAR="",t.NULL_CELL_WIDTH=1,t.NULL_CELL_CODE=0,t.WHITESPACE_CELL_CHAR=" ",t.WHITESPACE_CELL_WIDTH=1,t.WHITESPACE_CELL_CODE=32},8158:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Marker=void 0;const i=s(802),r=s(7150);class n{get id(){return this._id}constructor(e){this.line=e,this.isDisposed=!1,this._disposables=[],this._id=n._nextId++,this._onDispose=this.register(new i.Emitter),this.onDispose=this._onDispose.event}dispose(){this.isDisposed||(this.isDisposed=!0,this.line=-1,this._onDispose.fire(),(0,r.dispose)(this._disposables),this._disposables.length=0)}register(e){return this._disposables.push(e),e}}t.Marker=n,n._nextId=1},6760:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.DEFAULT_CHARSET=t.CHARSETS=void 0,t.CHARSETS={},t.DEFAULT_CHARSET=t.CHARSETS.B,t.CHARSETS[0]={"`":"◆",a:"▒",b:"␉",c:"␌",d:"␍",e:"␊",f:"°",g:"±",h:"␤",i:"␋",j:"┘",k:"┐",l:"┌",m:"└",n:"┼",o:"⎺",p:"⎻",q:"─",r:"⎼",s:"⎽",t:"├",u:"┤",v:"┴",w:"┬",x:"│",y:"≤",z:"≥","{":"π","|":"≠","}":"£","~":"·"},t.CHARSETS.A={"#":"£"},t.CHARSETS.B=void 0,t.CHARSETS[4]={"#":"£","@":"¾","[":"ij","\\":"½","]":"|","{":"¨","|":"f","}":"¼","~":"´"},t.CHARSETS.C=t.CHARSETS[5]={"[":"Ä","\\":"Ö","]":"Å","^":"Ü","`":"é","{":"ä","|":"ö","}":"å","~":"ü"},t.CHARSETS.R={"#":"£","@":"à","[":"°","\\":"ç","]":"§","{":"é","|":"ù","}":"è","~":"¨"},t.CHARSETS.Q={"@":"à","[":"â","\\":"ç","]":"ê","^":"î","`":"ô","{":"é","|":"ù","}":"è","~":"û"},t.CHARSETS.K={"@":"§","[":"Ä","\\":"Ö","]":"Ü","{":"ä","|":"ö","}":"ü","~":"ß"},t.CHARSETS.Y={"#":"£","@":"§","[":"°","\\":"ç","]":"é","`":"ù","{":"à","|":"ò","}":"è","~":"ì"},t.CHARSETS.E=t.CHARSETS[6]={"@":"Ä","[":"Æ","\\":"Ø","]":"Å","^":"Ü","`":"ä","{":"æ","|":"ø","}":"å","~":"ü"},t.CHARSETS.Z={"#":"£","@":"§","[":"¡","\\":"Ñ","]":"¿","{":"°","|":"ñ","}":"ç"},t.CHARSETS.H=t.CHARSETS[7]={"@":"É","[":"Ä","\\":"Ö","]":"Å","^":"Ü","`":"é","{":"ä","|":"ö","}":"å","~":"ü"},t.CHARSETS["="]={"#":"ù","@":"à","[":"é","\\":"ç","]":"ê","^":"î",_:"è","`":"ô","{":"ä","|":"ö","}":"ü","~":"û"}},3534:(e,t)=>{var s,i,r;Object.defineProperty(t,"__esModule",{value:!0}),t.C1_ESCAPED=t.C1=t.C0=void 0,function(e){e.NUL="\0",e.SOH="",e.STX="",e.ETX="",e.EOT="",e.ENQ="",e.ACK="",e.BEL="",e.BS="\b",e.HT="\t",e.LF="\n",e.VT="\v",e.FF="\f",e.CR="\r",e.SO="",e.SI="",e.DLE="",e.DC1="",e.DC2="",e.DC3="",e.DC4="",e.NAK="",e.SYN="",e.ETB="",e.CAN="",e.EM="",e.SUB="",e.ESC="",e.FS="",e.GS="",e.RS="",e.US="",e.SP=" ",e.DEL=""}(s||(t.C0=s={})),function(e){e.PAD="€",e.HOP="",e.BPH="‚",e.NBH="ƒ",e.IND="„",e.NEL="…",e.SSA="†",e.ESA="‡",e.HTS="ˆ",e.HTJ="‰",e.VTS="Š",e.PLD="‹",e.PLU="Œ",e.RI="",e.SS2="Ž",e.SS3="",e.DCS="",e.PU1="‘",e.PU2="’",e.STS="“",e.CCH="”",e.MW="•",e.SPA="–",e.EPA="—",e.SOS="˜",e.SGCI="™",e.SCI="š",e.CSI="›",e.ST="œ",e.OSC="",e.PM="ž",e.APC="Ÿ"}(i||(t.C1=i={})),function(e){e.ST=`${s.ESC}\\`}(r||(t.C1_ESCAPED=r={}))},726:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Utf8ToUtf32=t.StringToUtf32=void 0,t.stringFromCodePoint=function(e){return e>65535?(e-=65536,String.fromCharCode(55296+(e>>10))+String.fromCharCode(e%1024+56320)):String.fromCharCode(e)},t.utf32ToString=function(e,t=0,s=e.length){let i="";for(let r=t;r65535?(t-=65536,i+=String.fromCharCode(55296+(t>>10))+String.fromCharCode(t%1024+56320)):i+=String.fromCharCode(t)}return i},t.StringToUtf32=class{constructor(){this._interim=0}clear(){this._interim=0}decode(e,t){const s=e.length;if(!s)return 0;let i=0,r=0;if(this._interim){const s=e.charCodeAt(r++);56320<=s&&s<=57343?t[i++]=1024*(this._interim-55296)+s-56320+65536:(t[i++]=this._interim,t[i++]=s),this._interim=0}for(let n=r;n=s)return this._interim=r,i;const o=e.charCodeAt(n);56320<=o&&o<=57343?t[i++]=1024*(r-55296)+o-56320+65536:(t[i++]=r,t[i++]=o)}else 65279!==r&&(t[i++]=r)}return i}},t.Utf8ToUtf32=class{constructor(){this.interim=new Uint8Array(3)}clear(){this.interim.fill(0)}decode(e,t){const s=e.length;if(!s)return 0;let i,r,n,o,a=0,h=0,c=0;if(this.interim[0]){let i=!1,r=this.interim[0];r&=192==(224&r)?31:224==(240&r)?15:7;let n,o=0;for(;(n=63&this.interim[++o])&&o<4;)r<<=6,r|=n;const h=192==(224&this.interim[0])?2:224==(240&this.interim[0])?3:4,l=h-o;for(;c=s)return 0;if(n=e[c++],128!=(192&n)){c--,i=!0;break}this.interim[o++]=n,r<<=6,r|=63&n}i||(2===h?r<128?c--:t[a++]=r:3===h?r<2048||r>=55296&&r<=57343||65279===r||(t[a++]=r):r<65536||r>1114111||(t[a++]=r)),this.interim.fill(0)}const l=s-4;let u=c;for(;u=s)return this.interim[0]=i,a;if(r=e[u++],128!=(192&r)){u--;continue}if(h=(31&i)<<6|63&r,h<128){u--;continue}t[a++]=h}else if(224==(240&i)){if(u>=s)return this.interim[0]=i,a;if(r=e[u++],128!=(192&r)){u--;continue}if(u>=s)return this.interim[0]=i,this.interim[1]=r,a;if(n=e[u++],128!=(192&n)){u--;continue}if(h=(15&i)<<12|(63&r)<<6|63&n,h<2048||h>=55296&&h<=57343||65279===h)continue;t[a++]=h}else if(240==(248&i)){if(u>=s)return this.interim[0]=i,a;if(r=e[u++],128!=(192&r)){u--;continue}if(u>=s)return this.interim[0]=i,this.interim[1]=r,a;if(n=e[u++],128!=(192&n)){u--;continue}if(u>=s)return this.interim[0]=i,this.interim[1]=r,this.interim[2]=n,a;if(o=e[u++],128!=(192&o)){u--;continue}if(h=(7&i)<<18|(63&r)<<12|(63&n)<<6|63&o,h<65536||h>1114111)continue;t[a++]=h}}return a}}},7428:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeV6=void 0;const i=s(6415),r=[[768,879],[1155,1158],[1160,1161],[1425,1469],[1471,1471],[1473,1474],[1476,1477],[1479,1479],[1536,1539],[1552,1557],[1611,1630],[1648,1648],[1750,1764],[1767,1768],[1770,1773],[1807,1807],[1809,1809],[1840,1866],[1958,1968],[2027,2035],[2305,2306],[2364,2364],[2369,2376],[2381,2381],[2385,2388],[2402,2403],[2433,2433],[2492,2492],[2497,2500],[2509,2509],[2530,2531],[2561,2562],[2620,2620],[2625,2626],[2631,2632],[2635,2637],[2672,2673],[2689,2690],[2748,2748],[2753,2757],[2759,2760],[2765,2765],[2786,2787],[2817,2817],[2876,2876],[2879,2879],[2881,2883],[2893,2893],[2902,2902],[2946,2946],[3008,3008],[3021,3021],[3134,3136],[3142,3144],[3146,3149],[3157,3158],[3260,3260],[3263,3263],[3270,3270],[3276,3277],[3298,3299],[3393,3395],[3405,3405],[3530,3530],[3538,3540],[3542,3542],[3633,3633],[3636,3642],[3655,3662],[3761,3761],[3764,3769],[3771,3772],[3784,3789],[3864,3865],[3893,3893],[3895,3895],[3897,3897],[3953,3966],[3968,3972],[3974,3975],[3984,3991],[3993,4028],[4038,4038],[4141,4144],[4146,4146],[4150,4151],[4153,4153],[4184,4185],[4448,4607],[4959,4959],[5906,5908],[5938,5940],[5970,5971],[6002,6003],[6068,6069],[6071,6077],[6086,6086],[6089,6099],[6109,6109],[6155,6157],[6313,6313],[6432,6434],[6439,6440],[6450,6450],[6457,6459],[6679,6680],[6912,6915],[6964,6964],[6966,6970],[6972,6972],[6978,6978],[7019,7027],[7616,7626],[7678,7679],[8203,8207],[8234,8238],[8288,8291],[8298,8303],[8400,8431],[12330,12335],[12441,12442],[43014,43014],[43019,43019],[43045,43046],[64286,64286],[65024,65039],[65056,65059],[65279,65279],[65529,65531]],n=[[68097,68099],[68101,68102],[68108,68111],[68152,68154],[68159,68159],[119143,119145],[119155,119170],[119173,119179],[119210,119213],[119362,119364],[917505,917505],[917536,917631],[917760,917999]];let o;t.UnicodeV6=class{constructor(){if(this.version="6",!o){o=new Uint8Array(65536),o.fill(1),o[0]=0,o.fill(0,1,32),o.fill(0,127,160),o.fill(2,4352,4448),o[9001]=2,o[9002]=2,o.fill(2,11904,42192),o[12351]=1,o.fill(2,44032,55204),o.fill(2,63744,64256),o.fill(2,65040,65050),o.fill(2,65072,65136),o.fill(2,65280,65377),o.fill(2,65504,65511);for(let e=0;et[r][1])return!1;for(;r>=i;)if(s=i+r>>1,e>t[s][1])i=s+1;else{if(!(e=131072&&e<=196605||e>=196608&&e<=262141?2:1}charProperties(e,t){let s=this.wcwidth(e),r=0===s&&0!==t;if(r){const e=i.UnicodeService.extractWidth(t);0===e?r=!1:e>s&&(s=e)}return i.UnicodeService.createPropertyValue(0,s,r)}}},3562:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.WriteBuffer=void 0;const i=s(7150),r=s(802);class n extends i.Disposable{constructor(e){super(),this._action=e,this._writeBuffer=[],this._callbacks=[],this._pendingData=0,this._bufferOffset=0,this._isSyncWriting=!1,this._syncCalls=0,this._didUserInput=!1,this._onWriteParsed=this._register(new r.Emitter),this.onWriteParsed=this._onWriteParsed.event}handleUserInput(){this._didUserInput=!0}writeSync(e,t){if(void 0!==t&&this._syncCalls>t)return void(this._syncCalls=0);if(this._pendingData+=e.length,this._writeBuffer.push(e),this._callbacks.push(void 0),this._syncCalls++,this._isSyncWriting)return;let s;for(this._isSyncWriting=!0;s=this._writeBuffer.shift();){this._action(s);const e=this._callbacks.shift();e&&e()}this._pendingData=0,this._bufferOffset=2147483647,this._isSyncWriting=!1,this._syncCalls=0}write(e,t){if(this._pendingData>5e7)throw new Error("write data discarded, use flow control to avoid losing data");if(!this._writeBuffer.length){if(this._bufferOffset=0,this._didUserInput)return this._didUserInput=!1,this._pendingData+=e.length,this._writeBuffer.push(e),this._callbacks.push(t),void this._innerWrite();setTimeout((()=>this._innerWrite()))}this._pendingData+=e.length,this._writeBuffer.push(e),this._callbacks.push(t)}_innerWrite(e=0,t=!0){const s=e||performance.now();for(;this._writeBuffer.length>this._bufferOffset;){const e=this._writeBuffer[this._bufferOffset],i=this._action(e,t);if(i){const e=e=>performance.now()-s>=12?setTimeout((()=>this._innerWrite(0,e))):this._innerWrite(s,e);return void i.catch((e=>(queueMicrotask((()=>{throw e})),Promise.resolve(!1)))).then(e)}const r=this._callbacks[this._bufferOffset];if(r&&r(),this._bufferOffset++,this._pendingData-=e.length,performance.now()-s>=12)break}this._writeBuffer.length>this._bufferOffset?(this._bufferOffset>50&&(this._writeBuffer=this._writeBuffer.slice(this._bufferOffset),this._callbacks=this._callbacks.slice(this._bufferOffset),this._bufferOffset=0),setTimeout((()=>this._innerWrite()))):(this._writeBuffer.length=0,this._callbacks.length=0,this._pendingData=0,this._bufferOffset=0),this._onWriteParsed.fire()}}t.WriteBuffer=n},8693:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.parseColor=function(e){if(!e)return;let t=e.toLowerCase();if(0===t.indexOf("rgb:")){t=t.slice(4);const e=s.exec(t);if(e){const t=e[1]?15:e[4]?255:e[7]?4095:65535;return[Math.round(parseInt(e[1]||e[4]||e[7]||e[10],16)/t*255),Math.round(parseInt(e[2]||e[5]||e[8]||e[11],16)/t*255),Math.round(parseInt(e[3]||e[6]||e[9]||e[12],16)/t*255)]}}else if(0===t.indexOf("#")&&(t=t.slice(1),i.exec(t)&&[3,6,9,12].includes(t.length))){const e=t.length/3,s=[0,0,0];for(let i=0;i<3;++i){const r=parseInt(t.slice(e*i,e*i+e),16);s[i]=1===e?r<<4:2===e?r:3===e?r>>4:r>>8}return s}},t.toRgbString=function(e,t=16){const[s,i,n]=e;return`rgb:${r(s,t)}/${r(i,t)}/${r(n,t)}`};const s=/^([\da-f])\/([\da-f])\/([\da-f])$|^([\da-f]{2})\/([\da-f]{2})\/([\da-f]{2})$|^([\da-f]{3})\/([\da-f]{3})\/([\da-f]{3})$|^([\da-f]{4})\/([\da-f]{4})\/([\da-f]{4})$/,i=/^[\da-f]+$/;function r(e,t){const s=e.toString(16),i=s.length<2?"0"+s:s;switch(t){case 4:return s[0];case 8:return i;case 12:return(i+i).slice(0,3);default:return i+i}}},1263:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.PAYLOAD_LIMIT=void 0,t.PAYLOAD_LIMIT=1e7},9823:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.DcsHandler=t.DcsParser=void 0;const i=s(726),r=s(7262),n=s(1263),o=[];t.DcsParser=class{constructor(){this._handlers=Object.create(null),this._active=o,this._ident=0,this._handlerFb=()=>{},this._stack={paused:!1,loopPosition:0,fallThrough:!1}}dispose(){this._handlers=Object.create(null),this._handlerFb=()=>{},this._active=o}registerHandler(e,t){void 0===this._handlers[e]&&(this._handlers[e]=[]);const s=this._handlers[e];return s.push(t),{dispose:()=>{const e=s.indexOf(t);-1!==e&&s.splice(e,1)}}}clearHandler(e){this._handlers[e]&&delete this._handlers[e]}setHandlerFallback(e){this._handlerFb=e}reset(){if(this._active.length)for(let e=this._stack.paused?this._stack.loopPosition-1:this._active.length-1;e>=0;--e)this._active[e].unhook(!1);this._stack.paused=!1,this._active=o,this._ident=0}hook(e,t){if(this.reset(),this._ident=e,this._active=this._handlers[e]||o,this._active.length)for(let e=this._active.length-1;e>=0;e--)this._active[e].hook(t);else this._handlerFb(this._ident,"HOOK",t)}put(e,t,s){if(this._active.length)for(let i=this._active.length-1;i>=0;i--)this._active[i].put(e,t,s);else this._handlerFb(this._ident,"PUT",(0,i.utf32ToString)(e,t,s))}unhook(e,t=!0){if(this._active.length){let s=!1,i=this._active.length-1,r=!1;if(this._stack.paused&&(i=this._stack.loopPosition-1,s=t,r=this._stack.fallThrough,this._stack.paused=!1),!r&&!1===s){for(;i>=0&&(s=this._active[i].unhook(e),!0!==s);i--)if(s instanceof Promise)return this._stack.paused=!0,this._stack.loopPosition=i,this._stack.fallThrough=!1,s;i--}for(;i>=0;i--)if(s=this._active[i].unhook(!1),s instanceof Promise)return this._stack.paused=!0,this._stack.loopPosition=i,this._stack.fallThrough=!0,s}else this._handlerFb(this._ident,"UNHOOK",e);this._active=o,this._ident=0}};const a=new r.Params;a.addParam(0),t.DcsHandler=class{constructor(e){this._handler=e,this._data="",this._params=a,this._hitLimit=!1}hook(e){this._params=e.length>1||e.params[0]?e.clone():a,this._data="",this._hitLimit=!1}put(e,t,s){this._hitLimit||(this._data+=(0,i.utf32ToString)(e,t,s),this._data.length>n.PAYLOAD_LIMIT&&(this._data="",this._hitLimit=!0))}unhook(e){let t=!1;if(this._hitLimit)t=!1;else if(e&&(t=this._handler(this._data,this._params),t instanceof Promise))return t.then((e=>(this._params=a,this._data="",this._hitLimit=!1,e)));return this._params=a,this._data="",this._hitLimit=!1,t}}},6717:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.EscapeSequenceParser=t.VT500_TRANSITION_TABLE=t.TransitionTable=void 0;const i=s(7150),r=s(7262),n=s(1346),o=s(9823);class a{constructor(e){this.table=new Uint8Array(e)}setDefault(e,t){this.table.fill(e<<4|t)}add(e,t,s,i){this.table[t<<8|e]=s<<4|i}addMany(e,t,s,i){for(let r=0;rt)),s=(e,s)=>t.slice(e,s),i=s(32,127),r=s(0,24);r.push(25),r.push.apply(r,s(28,32));const n=s(0,14);let o;for(o in e.setDefault(1,0),e.addMany(i,0,2,0),n)e.addMany([24,26,153,154],o,3,0),e.addMany(s(128,144),o,3,0),e.addMany(s(144,152),o,3,0),e.add(156,o,0,0),e.add(27,o,11,1),e.add(157,o,4,8),e.addMany([152,158,159],o,0,7),e.add(155,o,11,3),e.add(144,o,11,9);return e.addMany(r,0,3,0),e.addMany(r,1,3,1),e.add(127,1,0,1),e.addMany(r,8,0,8),e.addMany(r,3,3,3),e.add(127,3,0,3),e.addMany(r,4,3,4),e.add(127,4,0,4),e.addMany(r,6,3,6),e.addMany(r,5,3,5),e.add(127,5,0,5),e.addMany(r,2,3,2),e.add(127,2,0,2),e.add(93,1,4,8),e.addMany(i,8,5,8),e.add(127,8,5,8),e.addMany([156,27,24,26,7],8,6,0),e.addMany(s(28,32),8,0,8),e.addMany([88,94,95],1,0,7),e.addMany(i,7,0,7),e.addMany(r,7,0,7),e.add(156,7,0,0),e.add(127,7,0,7),e.add(91,1,11,3),e.addMany(s(64,127),3,7,0),e.addMany(s(48,60),3,8,4),e.addMany([60,61,62,63],3,9,4),e.addMany(s(48,60),4,8,4),e.addMany(s(64,127),4,7,0),e.addMany([60,61,62,63],4,0,6),e.addMany(s(32,64),6,0,6),e.add(127,6,0,6),e.addMany(s(64,127),6,0,0),e.addMany(s(32,48),3,9,5),e.addMany(s(32,48),5,9,5),e.addMany(s(48,64),5,0,6),e.addMany(s(64,127),5,7,0),e.addMany(s(32,48),4,9,5),e.addMany(s(32,48),1,9,2),e.addMany(s(32,48),2,9,2),e.addMany(s(48,127),2,10,0),e.addMany(s(48,80),1,10,0),e.addMany(s(81,88),1,10,0),e.addMany([89,90,92],1,10,0),e.addMany(s(96,127),1,10,0),e.add(80,1,11,9),e.addMany(r,9,0,9),e.add(127,9,0,9),e.addMany(s(28,32),9,0,9),e.addMany(s(32,48),9,9,12),e.addMany(s(48,60),9,8,10),e.addMany([60,61,62,63],9,9,10),e.addMany(r,11,0,11),e.addMany(s(32,128),11,0,11),e.addMany(s(28,32),11,0,11),e.addMany(r,10,0,10),e.add(127,10,0,10),e.addMany(s(28,32),10,0,10),e.addMany(s(48,60),10,8,10),e.addMany([60,61,62,63],10,0,11),e.addMany(s(32,48),10,9,12),e.addMany(r,12,0,12),e.add(127,12,0,12),e.addMany(s(28,32),12,0,12),e.addMany(s(32,48),12,9,12),e.addMany(s(48,64),12,0,11),e.addMany(s(64,127),12,12,13),e.addMany(s(64,127),10,12,13),e.addMany(s(64,127),9,12,13),e.addMany(r,13,13,13),e.addMany(i,13,13,13),e.add(127,13,0,13),e.addMany([27,156,24,26],13,14,0),e.add(h,0,2,0),e.add(h,8,5,8),e.add(h,6,0,6),e.add(h,11,0,11),e.add(h,13,13,13),e}();class c extends i.Disposable{constructor(e=t.VT500_TRANSITION_TABLE){super(),this._transitions=e,this._parseStack={state:0,handlers:[],handlerPos:0,transition:0,chunkPos:0},this.initialState=0,this.currentState=this.initialState,this._params=new r.Params,this._params.addParam(0),this._collect=0,this.precedingJoinState=0,this._printHandlerFb=(e,t,s)=>{},this._executeHandlerFb=e=>{},this._csiHandlerFb=(e,t)=>{},this._escHandlerFb=e=>{},this._errorHandlerFb=e=>e,this._printHandler=this._printHandlerFb,this._executeHandlers=Object.create(null),this._csiHandlers=Object.create(null),this._escHandlers=Object.create(null),this._register((0,i.toDisposable)((()=>{this._csiHandlers=Object.create(null),this._executeHandlers=Object.create(null),this._escHandlers=Object.create(null)}))),this._oscParser=this._register(new n.OscParser),this._dcsParser=this._register(new o.DcsParser),this._errorHandler=this._errorHandlerFb,this.registerEscHandler({final:"\\"},(()=>!0))}_identifier(e,t=[64,126]){let s=0;if(e.prefix){if(e.prefix.length>1)throw new Error("only one byte as prefix supported");if(s=e.prefix.charCodeAt(0),s&&60>s||s>63)throw new Error("prefix must be in range 0x3c .. 0x3f")}if(e.intermediates){if(e.intermediates.length>2)throw new Error("only two bytes as intermediates are supported");for(let t=0;ti||i>47)throw new Error("intermediate must be in range 0x20 .. 0x2f");s<<=8,s|=i}}if(1!==e.final.length)throw new Error("final must be a single byte");const i=e.final.charCodeAt(0);if(t[0]>i||i>t[1])throw new Error(`final must be in range ${t[0]} .. ${t[1]}`);return s<<=8,s|=i,s}identToString(e){const t=[];for(;e;)t.push(String.fromCharCode(255&e)),e>>=8;return t.reverse().join("")}setPrintHandler(e){this._printHandler=e}clearPrintHandler(){this._printHandler=this._printHandlerFb}registerEscHandler(e,t){const s=this._identifier(e,[48,126]);void 0===this._escHandlers[s]&&(this._escHandlers[s]=[]);const i=this._escHandlers[s];return i.push(t),{dispose:()=>{const e=i.indexOf(t);-1!==e&&i.splice(e,1)}}}clearEscHandler(e){this._escHandlers[this._identifier(e,[48,126])]&&delete this._escHandlers[this._identifier(e,[48,126])]}setEscHandlerFallback(e){this._escHandlerFb=e}setExecuteHandler(e,t){this._executeHandlers[e.charCodeAt(0)]=t}clearExecuteHandler(e){this._executeHandlers[e.charCodeAt(0)]&&delete this._executeHandlers[e.charCodeAt(0)]}setExecuteHandlerFallback(e){this._executeHandlerFb=e}registerCsiHandler(e,t){const s=this._identifier(e);void 0===this._csiHandlers[s]&&(this._csiHandlers[s]=[]);const i=this._csiHandlers[s];return i.push(t),{dispose:()=>{const e=i.indexOf(t);-1!==e&&i.splice(e,1)}}}clearCsiHandler(e){this._csiHandlers[this._identifier(e)]&&delete this._csiHandlers[this._identifier(e)]}setCsiHandlerFallback(e){this._csiHandlerFb=e}registerDcsHandler(e,t){return this._dcsParser.registerHandler(this._identifier(e),t)}clearDcsHandler(e){this._dcsParser.clearHandler(this._identifier(e))}setDcsHandlerFallback(e){this._dcsParser.setHandlerFallback(e)}registerOscHandler(e,t){return this._oscParser.registerHandler(e,t)}clearOscHandler(e){this._oscParser.clearHandler(e)}setOscHandlerFallback(e){this._oscParser.setHandlerFallback(e)}setErrorHandler(e){this._errorHandler=e}clearErrorHandler(){this._errorHandler=this._errorHandlerFb}reset(){this.currentState=this.initialState,this._oscParser.reset(),this._dcsParser.reset(),this._params.reset(),this._params.addParam(0),this._collect=0,this.precedingJoinState=0,0!==this._parseStack.state&&(this._parseStack.state=2,this._parseStack.handlers=[])}_preserveStack(e,t,s,i,r){this._parseStack.state=e,this._parseStack.handlers=t,this._parseStack.handlerPos=s,this._parseStack.transition=i,this._parseStack.chunkPos=r}parse(e,t,s){let i,r=0,n=0,o=0;if(this._parseStack.state)if(2===this._parseStack.state)this._parseStack.state=0,o=this._parseStack.chunkPos+1;else{if(void 0===s||1===this._parseStack.state)throw this._parseStack.state=1,new Error("improper continuation due to previous async handler, giving up parsing");const t=this._parseStack.handlers;let n=this._parseStack.handlerPos-1;switch(this._parseStack.state){case 3:if(!1===s&&n>-1)for(;n>=0&&(i=t[n](this._params),!0!==i);n--)if(i instanceof Promise)return this._parseStack.handlerPos=n,i;this._parseStack.handlers=[];break;case 4:if(!1===s&&n>-1)for(;n>=0&&(i=t[n](),!0!==i);n--)if(i instanceof Promise)return this._parseStack.handlerPos=n,i;this._parseStack.handlers=[];break;case 6:if(r=e[this._parseStack.chunkPos],i=this._dcsParser.unhook(24!==r&&26!==r,s),i)return i;27===r&&(this._parseStack.transition|=1),this._params.reset(),this._params.addParam(0),this._collect=0;break;case 5:if(r=e[this._parseStack.chunkPos],i=this._oscParser.end(24!==r&&26!==r,s),i)return i;27===r&&(this._parseStack.transition|=1),this._params.reset(),this._params.addParam(0),this._collect=0}this._parseStack.state=0,o=this._parseStack.chunkPos+1,this.precedingJoinState=0,this.currentState=15&this._parseStack.transition}for(let s=o;s>4){case 2:for(let i=s+1;;++i){if(i>=t||(r=e[i])<32||r>126&&r=t||(r=e[i])<32||r>126&&r=t||(r=e[i])<32||r>126&&r=t||(r=e[i])<32||r>126&&r=0&&(i=o[a](this._params),!0!==i);a--)if(i instanceof Promise)return this._preserveStack(3,o,a,n,s),i;a<0&&this._csiHandlerFb(this._collect<<8|r,this._params),this.precedingJoinState=0;break;case 8:do{switch(r){case 59:this._params.addParam(0);break;case 58:this._params.addSubParam(-1);break;default:this._params.addDigit(r-48)}}while(++s47&&r<60);s--;break;case 9:this._collect<<=8,this._collect|=r;break;case 10:const c=this._escHandlers[this._collect<<8|r];let l=c?c.length-1:-1;for(;l>=0&&(i=c[l](),!0!==i);l--)if(i instanceof Promise)return this._preserveStack(4,c,l,n,s),i;l<0&&this._escHandlerFb(this._collect<<8|r),this.precedingJoinState=0;break;case 11:this._params.reset(),this._params.addParam(0),this._collect=0;break;case 12:this._dcsParser.hook(this._collect<<8|r,this._params);break;case 13:for(let i=s+1;;++i)if(i>=t||24===(r=e[i])||26===r||27===r||r>127&&r=t||(r=e[i])<32||r>127&&r{Object.defineProperty(t,"__esModule",{value:!0}),t.OscHandler=t.OscParser=void 0;const i=s(1263),r=s(726),n=[];t.OscParser=class{constructor(){this._state=0,this._active=n,this._id=-1,this._handlers=Object.create(null),this._handlerFb=()=>{},this._stack={paused:!1,loopPosition:0,fallThrough:!1}}registerHandler(e,t){void 0===this._handlers[e]&&(this._handlers[e]=[]);const s=this._handlers[e];return s.push(t),{dispose:()=>{const e=s.indexOf(t);-1!==e&&s.splice(e,1)}}}clearHandler(e){this._handlers[e]&&delete this._handlers[e]}setHandlerFallback(e){this._handlerFb=e}dispose(){this._handlers=Object.create(null),this._handlerFb=()=>{},this._active=n}reset(){if(2===this._state)for(let e=this._stack.paused?this._stack.loopPosition-1:this._active.length-1;e>=0;--e)this._active[e].end(!1);this._stack.paused=!1,this._active=n,this._id=-1,this._state=0}_start(){if(this._active=this._handlers[this._id]||n,this._active.length)for(let e=this._active.length-1;e>=0;e--)this._active[e].start();else this._handlerFb(this._id,"START")}_put(e,t,s){if(this._active.length)for(let i=this._active.length-1;i>=0;i--)this._active[i].put(e,t,s);else this._handlerFb(this._id,"PUT",(0,r.utf32ToString)(e,t,s))}start(){this.reset(),this._state=1}put(e,t,s){if(3!==this._state){if(1===this._state)for(;t0&&this._put(e,t,s)}}end(e,t=!0){if(0!==this._state){if(3!==this._state)if(1===this._state&&this._start(),this._active.length){let s=!1,i=this._active.length-1,r=!1;if(this._stack.paused&&(i=this._stack.loopPosition-1,s=t,r=this._stack.fallThrough,this._stack.paused=!1),!r&&!1===s){for(;i>=0&&(s=this._active[i].end(e),!0!==s);i--)if(s instanceof Promise)return this._stack.paused=!0,this._stack.loopPosition=i,this._stack.fallThrough=!1,s;i--}for(;i>=0;i--)if(s=this._active[i].end(!1),s instanceof Promise)return this._stack.paused=!0,this._stack.loopPosition=i,this._stack.fallThrough=!0,s}else this._handlerFb(this._id,"END",e);this._active=n,this._id=-1,this._state=0}}},t.OscHandler=class{constructor(e){this._handler=e,this._data="",this._hitLimit=!1}start(){this._data="",this._hitLimit=!1}put(e,t,s){this._hitLimit||(this._data+=(0,r.utf32ToString)(e,t,s),this._data.length>i.PAYLOAD_LIMIT&&(this._data="",this._hitLimit=!0))}end(e){let t=!1;if(this._hitLimit)t=!1;else if(e&&(t=this._handler(this._data),t instanceof Promise))return t.then((e=>(this._data="",this._hitLimit=!1,e)));return this._data="",this._hitLimit=!1,t}}},7262:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Params=void 0;const s=2147483647;class i{static fromArray(e){const t=new i;if(!e.length)return t;for(let s=Array.isArray(e[0])?1:0;s256)throw new Error("maxSubParamsLength must not be greater than 256");this.params=new Int32Array(e),this.length=0,this._subParams=new Int32Array(t),this._subParamsLength=0,this._subParamsIdx=new Uint16Array(e),this._rejectDigits=!1,this._rejectSubDigits=!1,this._digitIsSub=!1}clone(){const e=new i(this.maxLength,this.maxSubParamsLength);return e.params.set(this.params),e.length=this.length,e._subParams.set(this._subParams),e._subParamsLength=this._subParamsLength,e._subParamsIdx.set(this._subParamsIdx),e._rejectDigits=this._rejectDigits,e._rejectSubDigits=this._rejectSubDigits,e._digitIsSub=this._digitIsSub,e}toArray(){const e=[];for(let t=0;t>8,i=255&this._subParamsIdx[t];i-s>0&&e.push(Array.prototype.slice.call(this._subParams,s,i))}return e}reset(){this.length=0,this._subParamsLength=0,this._rejectDigits=!1,this._rejectSubDigits=!1,this._digitIsSub=!1}addParam(e){if(this._digitIsSub=!1,this.length>=this.maxLength)this._rejectDigits=!0;else{if(e<-1)throw new Error("values lesser than -1 are not allowed");this._subParamsIdx[this.length]=this._subParamsLength<<8|this._subParamsLength,this.params[this.length++]=e>s?s:e}}addSubParam(e){if(this._digitIsSub=!0,this.length)if(this._rejectDigits||this._subParamsLength>=this.maxSubParamsLength)this._rejectSubDigits=!0;else{if(e<-1)throw new Error("values lesser than -1 are not allowed");this._subParams[this._subParamsLength++]=e>s?s:e,this._subParamsIdx[this.length-1]++}}hasSubParams(e){return(255&this._subParamsIdx[e])-(this._subParamsIdx[e]>>8)>0}getSubParams(e){const t=this._subParamsIdx[e]>>8,s=255&this._subParamsIdx[e];return s-t>0?this._subParams.subarray(t,s):null}getSubParamsAll(){const e={};for(let t=0;t>8,i=255&this._subParamsIdx[t];i-s>0&&(e[t]=this._subParams.slice(s,i))}return e}addDigit(e){let t;if(this._rejectDigits||!(t=this._digitIsSub?this._subParamsLength:this.length)||this._digitIsSub&&this._rejectSubDigits)return;const i=this._digitIsSub?this._subParams:this.params,r=i[t-1];i[t-1]=~r?Math.min(10*r+e,s):e}}t.Params=i},3027:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.AddonManager=void 0,t.AddonManager=class{constructor(){this._addons=[]}dispose(){for(let e=this._addons.length-1;e>=0;e--)this._addons[e].instance.dispose()}loadAddon(e,t){const s={instance:t,dispose:t.dispose,isDisposed:!1};this._addons.push(s),t.dispose=()=>this._wrappedAddonDispose(s),t.activate(e)}_wrappedAddonDispose(e){if(e.isDisposed)return;let t=-1;for(let s=0;s{Object.defineProperty(t,"__esModule",{value:!0}),t.BufferApiView=void 0;const i=s(793),r=s(3055);t.BufferApiView=class{constructor(e,t){this._buffer=e,this.type=t}init(e){return this._buffer=e,this}get cursorY(){return this._buffer.y}get cursorX(){return this._buffer.x}get viewportY(){return this._buffer.ydisp}get baseY(){return this._buffer.ybase}get length(){return this._buffer.lines.length}getLine(e){const t=this._buffer.lines.get(e);if(t)return new i.BufferLineApiView(t)}getNullCell(){return new r.CellData}}},793:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.BufferLineApiView=void 0;const i=s(3055);t.BufferLineApiView=class{constructor(e){this._line=e}get isWrapped(){return this._line.isWrapped}get length(){return this._line.length}getCell(e,t){if(!(e<0||e>=this._line.length))return t?(this._line.loadCell(e,t),t):this._line.loadCell(e,new i.CellData)}translateToString(e,t,s){return this._line.translateToString(e,t,s)}}},5101:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.BufferNamespaceApi=void 0;const i=s(3235),r=s(7150),n=s(802);class o extends r.Disposable{constructor(e){super(),this._core=e,this._onBufferChange=this._register(new n.Emitter),this.onBufferChange=this._onBufferChange.event,this._normal=new i.BufferApiView(this._core.buffers.normal,"normal"),this._alternate=new i.BufferApiView(this._core.buffers.alt,"alternate"),this._core.buffers.onBufferActivate((()=>this._onBufferChange.fire(this.active)))}get active(){if(this._core.buffers.active===this._core.buffers.normal)return this.normal;if(this._core.buffers.active===this._core.buffers.alt)return this.alternate;throw new Error("Active buffer is neither normal nor alternate")}get normal(){return this._normal.init(this._core.buffers.normal)}get alternate(){return this._alternate.init(this._core.buffers.alt)}}t.BufferNamespaceApi=o},6097:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ParserApi=void 0,t.ParserApi=class{constructor(e){this._core=e}registerCsiHandler(e,t){return this._core.registerCsiHandler(e,(e=>t(e.toArray())))}addCsiHandler(e,t){return this.registerCsiHandler(e,t)}registerDcsHandler(e,t){return this._core.registerDcsHandler(e,((e,s)=>t(e,s.toArray())))}addDcsHandler(e,t){return this.registerDcsHandler(e,t)}registerEscHandler(e,t){return this._core.registerEscHandler(e,t)}addEscHandler(e,t){return this.registerEscHandler(e,t)}registerOscHandler(e,t){return this._core.registerOscHandler(e,t)}addOscHandler(e,t){return this.registerOscHandler(e,t)}}},4335:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeApi=void 0,t.UnicodeApi=class{constructor(e){this._core=e}register(e){this._core.unicodeService.register(e)}get versions(){return this._core.unicodeService.versions}get activeVersion(){return this._core.unicodeService.activeVersion}set activeVersion(e){this._core.unicodeService.activeVersion=e}}},9640:function(e,t,s){var i=this&&this.__decorate||function(e,t,s,i){var r,n=arguments.length,o=n<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,s,o):r(t,s))||o);return n>3&&o&&Object.defineProperty(t,s,o),o},r=this&&this.__param||function(e,t){return function(s,i){t(s,i,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.BufferService=t.MINIMUM_ROWS=t.MINIMUM_COLS=void 0;const n=s(7150),o=s(4097),a=s(6501),h=s(802);t.MINIMUM_COLS=2,t.MINIMUM_ROWS=1;let c=class extends n.Disposable{get buffer(){return this.buffers.active}constructor(e){super(),this.isUserScrolling=!1,this._onResize=this._register(new h.Emitter),this.onResize=this._onResize.event,this._onScroll=this._register(new h.Emitter),this.onScroll=this._onScroll.event,this.cols=Math.max(e.rawOptions.cols||0,t.MINIMUM_COLS),this.rows=Math.max(e.rawOptions.rows||0,t.MINIMUM_ROWS),this.buffers=this._register(new o.BufferSet(e,this)),this._register(this.buffers.onBufferActivate((e=>{this._onScroll.fire(e.activeBuffer.ydisp)})))}resize(e,t){const s=this.cols!==e,i=this.rows!==t;this.cols=e,this.rows=t,this.buffers.resize(e,t),this._onResize.fire({cols:e,rows:t,colsChanged:s,rowsChanged:i})}reset(){this.buffers.reset(),this.isUserScrolling=!1}scroll(e,t=!1){const s=this.buffer;let i;i=this._cachedBlankLine,i&&i.length===this.cols&&i.getFg(0)===e.fg&&i.getBg(0)===e.bg||(i=s.getBlankLine(e,t),this._cachedBlankLine=i),i.isWrapped=t;const r=s.ybase+s.scrollTop,n=s.ybase+s.scrollBottom;if(0===s.scrollTop){const e=s.lines.isFull;n===s.lines.length-1?e?s.lines.recycle().copyFrom(i):s.lines.push(i.clone()):s.lines.splice(n+1,0,i.clone()),e?this.isUserScrolling&&(s.ydisp=Math.max(s.ydisp-1,0)):(s.ybase++,this.isUserScrolling||s.ydisp++)}else{const e=n-r+1;s.lines.shiftElements(r+1,e-1,-1),s.lines.set(n,i.clone())}this.isUserScrolling||(s.ydisp=s.ybase),this._onScroll.fire(s.ydisp)}scrollLines(e,t){const s=this.buffer;if(e<0){if(0===s.ydisp)return;this.isUserScrolling=!0}else e+s.ydisp>=s.ybase&&(this.isUserScrolling=!1);const i=s.ydisp;s.ydisp=Math.max(Math.min(s.ydisp+e,s.ybase),0),i!==s.ydisp&&(t||this._onScroll.fire(s.ydisp))}};t.BufferService=c,t.BufferService=c=i([r(0,a.IOptionsService)],c)},5746:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.CharsetService=void 0,t.CharsetService=class{constructor(){this.glevel=0,this._charsets=[]}reset(){this.charset=void 0,this._charsets=[],this.glevel=0}setgLevel(e){this.glevel=e,this.charset=this._charsets[e]}setgCharset(e,t){this._charsets[e]=t,this.glevel===e&&(this.charset=t)}}},7792:function(e,t,s){var i=this&&this.__decorate||function(e,t,s,i){var r,n=arguments.length,o=n<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,s,o):r(t,s))||o);return n>3&&o&&Object.defineProperty(t,s,o),o},r=this&&this.__param||function(e,t){return function(s,i){t(s,i,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.CoreMouseService=void 0;const n=s(6501),o=s(7150),a=s(802),h={NONE:{events:0,restrict:()=>!1},X10:{events:1,restrict:e=>4!==e.button&&1===e.action&&(e.ctrl=!1,e.alt=!1,e.shift=!1,!0)},VT200:{events:19,restrict:e=>32!==e.action},DRAG:{events:23,restrict:e=>32!==e.action||3!==e.button},ANY:{events:31,restrict:e=>!0}};function c(e,t){let s=(e.ctrl?16:0)|(e.shift?4:0)|(e.alt?8:0);return 4===e.button?(s|=64,s|=e.action):(s|=3&e.button,4&e.button&&(s|=64),8&e.button&&(s|=128),32===e.action?s|=32:0!==e.action||t||(s|=3)),s}const l=String.fromCharCode,u={DEFAULT:e=>{const t=[c(e,!1)+32,e.col+32,e.row+32];return t[0]>255||t[1]>255||t[2]>255?"":`${l(t[0])}${l(t[1])}${l(t[2])}`},SGR:e=>{const t=0===e.action&&4!==e.button?"m":"M";return`[<${c(e,!0)};${e.col};${e.row}${t}`},SGR_PIXELS:e=>{const t=0===e.action&&4!==e.button?"m":"M";return`[<${c(e,!0)};${e.x};${e.y}${t}`}};let d=class extends o.Disposable{constructor(e,t,s){super(),this._bufferService=e,this._coreService=t,this._optionsService=s,this._protocols={},this._encodings={},this._activeProtocol="",this._activeEncoding="",this._lastEvent=null,this._wheelPartialScroll=0,this._onProtocolChange=this._register(new a.Emitter),this.onProtocolChange=this._onProtocolChange.event;for(const e of Object.keys(h))this.addProtocol(e,h[e]);for(const e of Object.keys(u))this.addEncoding(e,u[e]);this.reset()}addProtocol(e,t){this._protocols[e]=t}addEncoding(e,t){this._encodings[e]=t}get activeProtocol(){return this._activeProtocol}get areMouseEventsActive(){return 0!==this._protocols[this._activeProtocol].events}set activeProtocol(e){if(!this._protocols[e])throw new Error(`unknown protocol "${e}"`);this._activeProtocol=e,this._onProtocolChange.fire(this._protocols[e].events)}get activeEncoding(){return this._activeEncoding}set activeEncoding(e){if(!this._encodings[e])throw new Error(`unknown encoding "${e}"`);this._activeEncoding=e}reset(){this.activeProtocol="NONE",this.activeEncoding="DEFAULT",this._lastEvent=null,this._wheelPartialScroll=0}consumeWheelEvent(e,t,s){if(0===e.deltaY||e.shiftKey)return 0;if(void 0===t||void 0===s)return 0;const i=t/s;let r=this._applyScrollModifier(e.deltaY,e);return e.deltaMode===WheelEvent.DOM_DELTA_PIXEL?(r/=i+0,Math.abs(e.deltaY)<50&&(r*=.3),this._wheelPartialScroll+=r,r=Math.floor(Math.abs(this._wheelPartialScroll))*(this._wheelPartialScroll>0?1:-1),this._wheelPartialScroll%=1):e.deltaMode===WheelEvent.DOM_DELTA_PAGE&&(r*=this._bufferService.rows),r}_applyScrollModifier(e,t){return t.altKey||t.ctrlKey||t.shiftKey?e*this._optionsService.rawOptions.fastScrollSensitivity*this._optionsService.rawOptions.scrollSensitivity:e*this._optionsService.rawOptions.scrollSensitivity}triggerMouseEvent(e){if(e.col<0||e.col>=this._bufferService.cols||e.row<0||e.row>=this._bufferService.rows)return!1;if(4===e.button&&32===e.action)return!1;if(3===e.button&&32!==e.action)return!1;if(4!==e.button&&(2===e.action||3===e.action))return!1;if(e.col++,e.row++,32===e.action&&this._lastEvent&&this._equalEvents(this._lastEvent,e,"SGR_PIXELS"===this._activeEncoding))return!1;if(!this._protocols[this._activeProtocol].restrict(e))return!1;const t=this._encodings[this._activeEncoding](e);return t&&("DEFAULT"===this._activeEncoding?this._coreService.triggerBinaryEvent(t):this._coreService.triggerDataEvent(t,!0)),this._lastEvent=e,!0}explainEvents(e){return{down:!!(1&e),up:!!(2&e),drag:!!(4&e),move:!!(8&e),wheel:!!(16&e)}}_equalEvents(e,t,s){if(s){if(e.x!==t.x)return!1;if(e.y!==t.y)return!1}else{if(e.col!==t.col)return!1;if(e.row!==t.row)return!1}return e.button===t.button&&e.action===t.action&&e.ctrl===t.ctrl&&e.alt===t.alt&&e.shift===t.shift}};t.CoreMouseService=d,t.CoreMouseService=d=i([r(0,n.IBufferService),r(1,n.ICoreService),r(2,n.IOptionsService)],d)},4071:function(e,t,s){var i=this&&this.__decorate||function(e,t,s,i){var r,n=arguments.length,o=n<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,s,o):r(t,s))||o);return n>3&&o&&Object.defineProperty(t,s,o),o},r=this&&this.__param||function(e,t){return function(s,i){t(s,i,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.CoreService=void 0;const n=s(7453),o=s(7150),a=s(6501),h=s(802),c=Object.freeze({insertMode:!1}),l=Object.freeze({applicationCursorKeys:!1,applicationKeypad:!1,bracketedPasteMode:!1,cursorBlink:void 0,cursorStyle:void 0,origin:!1,reverseWraparound:!1,sendFocus:!1,synchronizedOutput:!1,wraparound:!0});let u=class extends o.Disposable{constructor(e,t,s){super(),this._bufferService=e,this._logService=t,this._optionsService=s,this.isCursorInitialized=!1,this.isCursorHidden=!1,this._onData=this._register(new h.Emitter),this.onData=this._onData.event,this._onUserInput=this._register(new h.Emitter),this.onUserInput=this._onUserInput.event,this._onBinary=this._register(new h.Emitter),this.onBinary=this._onBinary.event,this._onRequestScrollToBottom=this._register(new h.Emitter),this.onRequestScrollToBottom=this._onRequestScrollToBottom.event,this.modes=(0,n.clone)(c),this.decPrivateModes=(0,n.clone)(l)}reset(){this.modes=(0,n.clone)(c),this.decPrivateModes=(0,n.clone)(l)}triggerDataEvent(e,t=!1){if(this._optionsService.rawOptions.disableStdin)return;const s=this._bufferService.buffer;t&&this._optionsService.rawOptions.scrollOnUserInput&&s.ybase!==s.ydisp&&this._onRequestScrollToBottom.fire(),t&&this._onUserInput.fire(),this._logService.debug(`sending data "${e}"`),this._logService.trace("sending data (codes)",(()=>e.split("").map((e=>e.charCodeAt(0))))),this._onData.fire(e)}triggerBinaryEvent(e){this._optionsService.rawOptions.disableStdin||(this._logService.debug(`sending binary "${e}"`),this._logService.trace("sending binary (codes)",(()=>e.split("").map((e=>e.charCodeAt(0))))),this._onBinary.fire(e))}};t.CoreService=u,t.CoreService=u=i([r(0,a.IBufferService),r(1,a.ILogService),r(2,a.IOptionsService)],u)},6025:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.InstantiationService=t.ServiceCollection=void 0;const i=s(6501),r=s(6201);class n{constructor(...e){this._entries=new Map;for(const[t,s]of e)this.set(t,s)}set(e,t){const s=this._entries.get(e);return this._entries.set(e,t),s}forEach(e){for(const[t,s]of this._entries.entries())e(t,s)}has(e){return this._entries.has(e)}get(e){return this._entries.get(e)}}t.ServiceCollection=n,t.InstantiationService=class{constructor(){this._services=new n,this._services.set(i.IInstantiationService,this)}setService(e,t){this._services.set(e,t)}getService(e){return this._services.get(e)}createInstance(e,...t){const s=(0,r.getServiceDependencies)(e).sort(((e,t)=>e.index-t.index)),i=[];for(const t of s){const s=this._services.get(t.id);if(!s)throw new Error(`[createInstance] ${e.name} depends on UNKNOWN service ${t.id._id}.`);i.push(s)}const n=s.length>0?s[0].index:t.length;if(t.length!==n)throw new Error(`[createInstance] First service dependency of ${e.name} at position ${n+1} conflicts with ${t.length} static arguments`);return new e(...[...t,...i])}}},7276:function(e,t,s){var i=this&&this.__decorate||function(e,t,s,i){var r,n=arguments.length,o=n<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,s,o):r(t,s))||o);return n>3&&o&&Object.defineProperty(t,s,o),o},r=this&&this.__param||function(e,t){return function(s,i){t(s,i,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.LogService=void 0,t.setTraceLogger=function(e){h=e},t.traceCall=function(e,t,s){if("function"!=typeof s.value)throw new Error("not supported");const i=s.value;s.value=function(...e){if(h.logLevel!==o.LogLevelEnum.TRACE)return i.apply(this,e);h.trace(`GlyphRenderer#${i.name}(${e.map((e=>JSON.stringify(e))).join(", ")})`);const t=i.apply(this,e);return h.trace(`GlyphRenderer#${i.name} return`,t),t}};const n=s(7150),o=s(6501),a={trace:o.LogLevelEnum.TRACE,debug:o.LogLevelEnum.DEBUG,info:o.LogLevelEnum.INFO,warn:o.LogLevelEnum.WARN,error:o.LogLevelEnum.ERROR,off:o.LogLevelEnum.OFF};let h,c=class extends n.Disposable{get logLevel(){return this._logLevel}constructor(e){super(),this._optionsService=e,this._logLevel=o.LogLevelEnum.OFF,this._updateLogLevel(),this._register(this._optionsService.onSpecificOptionChange("logLevel",(()=>this._updateLogLevel()))),h=this}_updateLogLevel(){this._logLevel=a[this._optionsService.rawOptions.logLevel]}_evalLazyOptionalParams(e){for(let t=0;t{Object.defineProperty(t,"__esModule",{value:!0}),t.OptionsService=t.DEFAULT_OPTIONS=void 0;const i=s(7150),r=s(701),n=s(802);t.DEFAULT_OPTIONS={cols:80,rows:24,cursorBlink:!1,cursorStyle:"block",cursorWidth:1,cursorInactiveStyle:"outline",customGlyphs:!0,drawBoldTextInBrightColors:!0,documentOverride:null,fastScrollModifier:"alt",fastScrollSensitivity:5,fontFamily:"monospace",fontSize:15,fontWeight:"normal",fontWeightBold:"bold",ignoreBracketedPasteMode:!1,lineHeight:1,letterSpacing:0,linkHandler:null,logLevel:"info",logger:null,scrollback:1e3,scrollOnEraseInDisplay:!1,scrollOnUserInput:!0,scrollSensitivity:1,screenReaderMode:!1,smoothScrollDuration:0,macOptionIsMeta:!1,macOptionClickForcesSelection:!1,minimumContrastRatio:1,disableStdin:!1,allowProposedApi:!1,allowTransparency:!1,tabStopWidth:8,theme:{},reflowCursorLine:!1,rescaleOverlappingGlyphs:!1,rightClickSelectsWord:r.isMac,windowOptions:{},windowsMode:!1,windowsPty:{},wordSeparator:" ()[]{}',\"`",altClickMovesCursor:!0,convertEol:!1,termName:"xterm",cancelEvents:!1,overviewRuler:{}};const o=["normal","bold","100","200","300","400","500","600","700","800","900"];class a extends i.Disposable{constructor(e){super(),this._onOptionChange=this._register(new n.Emitter),this.onOptionChange=this._onOptionChange.event;const s={...t.DEFAULT_OPTIONS};for(const t in e)if(t in s)try{const i=e[t];s[t]=this._sanitizeAndValidateOption(t,i)}catch(e){console.error(e)}this.rawOptions=s,this.options={...s},this._setupOptions(),this._register((0,i.toDisposable)((()=>{this.rawOptions.linkHandler=null,this.rawOptions.documentOverride=null})))}onSpecificOptionChange(e,t){return this.onOptionChange((s=>{s===e&&t(this.rawOptions[e])}))}onMultipleOptionChange(e,t){return this.onOptionChange((s=>{-1!==e.indexOf(s)&&t()}))}_setupOptions(){const e=e=>{if(!(e in t.DEFAULT_OPTIONS))throw new Error(`No option with key "${e}"`);return this.rawOptions[e]},s=(e,s)=>{if(!(e in t.DEFAULT_OPTIONS))throw new Error(`No option with key "${e}"`);s=this._sanitizeAndValidateOption(e,s),this.rawOptions[e]!==s&&(this.rawOptions[e]=s,this._onOptionChange.fire(e))};for(const t in this.rawOptions){const i={get:e.bind(this,t),set:s.bind(this,t)};Object.defineProperty(this.options,t,i)}}_sanitizeAndValidateOption(e,s){switch(e){case"cursorStyle":if(s||(s=t.DEFAULT_OPTIONS[e]),!function(e){return"block"===e||"underline"===e||"bar"===e}(s))throw new Error(`"${s}" is not a valid value for ${e}`);break;case"wordSeparator":s||(s=t.DEFAULT_OPTIONS[e]);break;case"fontWeight":case"fontWeightBold":if("number"==typeof s&&1<=s&&s<=1e3)break;s=o.includes(s)?s:t.DEFAULT_OPTIONS[e];break;case"cursorWidth":s=Math.floor(s);case"lineHeight":case"tabStopWidth":if(s<1)throw new Error(`${e} cannot be less than 1, value: ${s}`);break;case"minimumContrastRatio":s=Math.max(1,Math.min(21,Math.round(10*s)/10));break;case"scrollback":if((s=Math.min(s,4294967295))<0)throw new Error(`${e} cannot be less than 0, value: ${s}`);break;case"fastScrollSensitivity":case"scrollSensitivity":if(s<=0)throw new Error(`${e} cannot be less than or equal to 0, value: ${s}`);break;case"rows":case"cols":if(!s&&0!==s)throw new Error(`${e} must be numeric, value: ${s}`);break;case"windowsPty":s=s??{}}return s}}t.OptionsService=a},8811:function(e,t,s){var i=this&&this.__decorate||function(e,t,s,i){var r,n=arguments.length,o=n<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,s,o):r(t,s))||o);return n>3&&o&&Object.defineProperty(t,s,o),o},r=this&&this.__param||function(e,t){return function(s,i){t(s,i,e)}};Object.defineProperty(t,"__esModule",{value:!0}),t.OscLinkService=void 0;const n=s(6501);let o=class{constructor(e){this._bufferService=e,this._nextId=1,this._entriesWithId=new Map,this._dataByLinkId=new Map}registerLink(e){const t=this._bufferService.buffer;if(void 0===e.id){const s=t.addMarker(t.ybase+t.y),i={data:e,id:this._nextId++,lines:[s]};return s.onDispose((()=>this._removeMarkerFromLink(i,s))),this._dataByLinkId.set(i.id,i),i.id}const s=e,i=this._getEntryIdKey(s),r=this._entriesWithId.get(i);if(r)return this.addLineToLink(r.id,t.ybase+t.y),r.id;const n=t.addMarker(t.ybase+t.y),o={id:this._nextId++,key:this._getEntryIdKey(s),data:s,lines:[n]};return n.onDispose((()=>this._removeMarkerFromLink(o,n))),this._entriesWithId.set(o.key,o),this._dataByLinkId.set(o.id,o),o.id}addLineToLink(e,t){const s=this._dataByLinkId.get(e);if(s&&s.lines.every((e=>e.line!==t))){const e=this._bufferService.buffer.addMarker(t);s.lines.push(e),e.onDispose((()=>this._removeMarkerFromLink(s,e)))}}getLinkData(e){return this._dataByLinkId.get(e)?.data}_getEntryIdKey(e){return`${e.id};;${e.uri}`}_removeMarkerFromLink(e,t){const s=e.lines.indexOf(t);-1!==s&&(e.lines.splice(s,1),0===e.lines.length&&(void 0!==e.data.id&&this._entriesWithId.delete(e.key),this._dataByLinkId.delete(e.id)))}};t.OscLinkService=o,t.OscLinkService=o=i([r(0,n.IBufferService)],o)},6201:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.serviceRegistry=void 0,t.getServiceDependencies=function(e){return e[i]||[]},t.createDecorator=function(e){if(t.serviceRegistry.has(e))return t.serviceRegistry.get(e);const r=function(e,t,n){if(3!==arguments.length)throw new Error("@IServiceName-decorator can only be used to decorate a parameter");!function(e,t,r){t[s]===t?t[i].push({id:e,index:r}):(t[i]=[{id:e,index:r}],t[s]=t)}(r,e,n)};return r._id=e,t.serviceRegistry.set(e,r),r};const s="di$target",i="di$dependencies";t.serviceRegistry=new Map},6501:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.IDecorationService=t.IUnicodeService=t.IOscLinkService=t.IOptionsService=t.ILogService=t.LogLevelEnum=t.IInstantiationService=t.ICharsetService=t.ICoreService=t.ICoreMouseService=t.IBufferService=void 0;const i=s(6201);var r;t.IBufferService=(0,i.createDecorator)("BufferService"),t.ICoreMouseService=(0,i.createDecorator)("CoreMouseService"),t.ICoreService=(0,i.createDecorator)("CoreService"),t.ICharsetService=(0,i.createDecorator)("CharsetService"),t.IInstantiationService=(0,i.createDecorator)("InstantiationService"),function(e){e[e.TRACE=0]="TRACE",e[e.DEBUG=1]="DEBUG",e[e.INFO=2]="INFO",e[e.WARN=3]="WARN",e[e.ERROR=4]="ERROR",e[e.OFF=5]="OFF"}(r||(t.LogLevelEnum=r={})),t.ILogService=(0,i.createDecorator)("LogService"),t.IOptionsService=(0,i.createDecorator)("OptionsService"),t.IOscLinkService=(0,i.createDecorator)("OscLinkService"),t.IUnicodeService=(0,i.createDecorator)("UnicodeService"),t.IDecorationService=(0,i.createDecorator)("DecorationService")},6415:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeService=void 0;const i=s(7428),r=s(802);class n{static extractShouldJoin(e){return!!(1&e)}static extractWidth(e){return e>>1&3}static extractCharKind(e){return e>>3}static createPropertyValue(e,t,s=!1){return(16777215&e)<<3|(3&t)<<1|(s?1:0)}constructor(){this._providers=Object.create(null),this._active="",this._onChange=new r.Emitter,this.onChange=this._onChange.event;const e=new i.UnicodeV6;this.register(e),this._active=e.version,this._activeProvider=e}dispose(){this._onChange.dispose()}get versions(){return Object.keys(this._providers)}get activeVersion(){return this._active}set activeVersion(e){if(!this._providers[e])throw new Error(`unknown Unicode version "${e}"`);this._active=e,this._activeProvider=this._providers[e],this._onChange.fire(e)}register(e){this._providers[e.version]=e}wcwidth(e){return this._activeProvider.wcwidth(e)}getStringCellWidth(e){let t=0,s=0;const i=e.length;for(let r=0;r=i)return t+this.wcwidth(o);const s=e.charCodeAt(r);56320<=s&&s<=57343?o=1024*(o-55296)+s-56320+65536:t+=this.wcwidth(s)}const a=this.charProperties(o,s);let h=n.extractWidth(a);n.extractShouldJoin(a)&&(h-=n.extractWidth(s)),t+=h,s=a}return t}charProperties(e,t){return this._activeProvider.charProperties(e,t)}}t.UnicodeService=n},5856:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Terminal=void 0;const i=s(6107),r=s(5777),n=s(802);class o extends r.CoreTerminal{constructor(e={}){super(e),this._onBell=this._register(new n.Emitter),this.onBell=this._onBell.event,this._onCursorMove=this._register(new n.Emitter),this.onCursorMove=this._onCursorMove.event,this._onTitleChange=this._register(new n.Emitter),this.onTitleChange=this._onTitleChange.event,this._onA11yCharEmitter=this._register(new n.Emitter),this.onA11yChar=this._onA11yCharEmitter.event,this._onA11yTabEmitter=this._register(new n.Emitter),this.onA11yTab=this._onA11yTabEmitter.event,this._setup(),this._register(this._inputHandler.onRequestBell((()=>this.bell()))),this._register(this._inputHandler.onRequestReset((()=>this.reset()))),this._register(n.Event.forward(this._inputHandler.onCursorMove,this._onCursorMove)),this._register(n.Event.forward(this._inputHandler.onTitleChange,this._onTitleChange)),this._register(n.Event.forward(this._inputHandler.onA11yChar,this._onA11yCharEmitter)),this._register(n.Event.forward(this._inputHandler.onA11yTab,this._onA11yTabEmitter))}get buffer(){return this.buffers.active}get markers(){return this.buffer.markers}addMarker(e){if(this.buffer===this.buffers.normal)return this.buffer.addMarker(this.buffer.ybase+this.buffer.y+e)}bell(){this._onBell.fire()}input(e,t=!0){this.coreService.triggerDataEvent(e,t)}resize(e,t){e===this.cols&&t===this.rows||super.resize(e,t)}clear(){if(0!==this.buffer.ybase||0!==this.buffer.y){this.buffer.lines.set(0,this.buffer.lines.get(this.buffer.ybase+this.buffer.y)),this.buffer.lines.length=1,this.buffer.ydisp=0,this.buffer.ybase=0,this.buffer.y=0;for(let e=1;e{Object.defineProperty(t,"__esModule",{value:!0}),t.Permutation=t.CallbackIterable=t.ArrayQueue=t.booleanComparator=t.numberComparator=t.CompareResult=void 0,t.tail=function(e,t=0){return e[e.length-(1+t)]},t.tail2=function(e){if(0===e.length)throw new Error("Invalid tail call");return[e.slice(0,e.length-1),e[e.length-1]]},t.equals=function(e,t,s=(e,t)=>e===t){if(e===t)return!0;if(!e||!t)return!1;if(e.length!==t.length)return!1;for(let i=0,r=e.length;is(e[i],t)))},t.binarySearch2=n,t.quickSelect=function e(t,s,i){if((t|=0)>=s.length)throw new TypeError("invalid index");const r=s[Math.floor(s.length*Math.random())],n=[],o=[],a=[];for(const e of s){const t=i(e,r);t<0?n.push(e):t>0?o.push(e):a.push(e)}return t{(async()=>{const o=e.length,h=e.slice(0,s).sort(t);for(let c=s,l=Math.min(s+r,o);cs&&await new Promise((e=>setTimeout(e))),n&&n.isCancellationRequested)throw new i.CancellationError;a(e,t,h,c,l)}return h})().then(o,h)}))},t.coalesce=function(e){return e.filter((e=>!!e))},t.coalesceInPlace=function(e){let t=0;for(let s=0;s0},t.distinct=function(e,t=e=>e){const s=new Set;return e.filter((e=>{const i=t(e);return!s.has(i)&&(s.add(i),!0)}))},t.uniqueFilter=function(e){const t=new Set;return s=>{const i=e(s);return!t.has(i)&&(t.add(i),!0)}},t.firstOrDefault=function(e,t){return e.length>0?e[0]:t},t.lastOrDefault=function(e,t){return e.length>0?e[e.length-1]:t},t.commonPrefixLength=function(e,t,s=(e,t)=>e===t){let i=0;for(let r=0,n=Math.min(e.length,t.length);rt;e--)i.push(e);return i},t.index=function(e,t,s){return e.reduce(((e,i)=>(e[t(i)]=s?s(i):i,e)),Object.create(null))},t.insert=function(e,t){return e.push(t),()=>h(e,t)},t.remove=h,t.arrayInsert=function(e,t,s){const i=e.slice(0,t),r=e.slice(t);return i.concat(s,r)},t.shuffle=function(e,t){let s;if("number"==typeof t){let e=t;s=()=>{const t=179426549*Math.sin(e++);return t-Math.floor(t)}}else s=Math.random;for(let t=e.length-1;t>0;t-=1){const i=Math.floor(s()*(t+1)),r=e[t];e[t]=e[i],e[i]=r}},t.pushToStart=function(e,t){const s=e.indexOf(t);s>-1&&(e.splice(s,1),e.unshift(t))},t.pushToEnd=function(e,t){const s=e.indexOf(t);s>-1&&(e.splice(s,1),e.push(t))},t.pushMany=function(e,t){for(const s of t)e.push(s)},t.mapArrayOrNot=function(e,t){return Array.isArray(e)?e.map(t):t(e)},t.asArray=function(e){return Array.isArray(e)?e:[e]},t.getRandomElement=function(e){return e[Math.floor(Math.random()*e.length)]},t.insertInto=c,t.splice=function(e,t,s,i){const r=l(e,t);let n=e.splice(r,s);return void 0===n&&(n=[]),c(e,r,i),n},t.compareBy=function(e,t){return(s,i)=>t(e(s),e(i))},t.tieBreakComparators=function(...e){return(t,s)=>{for(const i of e){const e=i(t,s);if(!u.isNeitherLessOrGreaterThan(e))return e}return u.neitherLessOrGreaterThan}},t.reverseOrder=function(e){return(t,s)=>-e(t,s)};const i=s(9807),r=s(8297);function n(e,t){let s=0,i=e-1;for(;s<=i;){const e=(s+i)/2|0,r=t(e);if(r<0)s=e+1;else{if(!(r>0))return e;i=e-1}}return-(s+1)}function o(e,t,s){const i=[];function r(e,t,s){if(0===t&&0===s.length)return;const r=i[i.length-1];r&&r.start+r.deleteCount===e?(r.deleteCount+=t,r.toInsert.push(...s)):i.push({start:e,deleteCount:t,toInsert:s})}let n=0,o=0;for(;;){if(n===e.length){r(n,0,t.slice(o));break}if(o===t.length){r(n,e.length-n,[]);break}const i=e[n],a=t[o],h=s(i,a);0===h?(n+=1,o+=1):h<0?(r(n,1,[]),n+=1):h>0&&(r(n,0,[a]),o+=1)}return i}function a(e,t,s,i,n){for(const o=s.length;it(n,e)<0));s.splice(e,0,n)}}}function h(e,t){const s=e.indexOf(t);if(s>-1)return e.splice(s,1),t}function c(e,t,s){const i=l(e,t),r=e.length,n=s.length;e.length=r+n;for(let t=r-1;t>=i;t--)e[t+n]=e[t];for(let t=0;t0},e.isNeitherLessOrGreaterThan=function(e){return 0===e},e.greaterThan=1,e.lessThan=-1,e.neitherLessOrGreaterThan=0}(u||(t.CompareResult=u={})),t.numberComparator=(e,t)=>e-t,t.booleanComparator=(e,s)=>(0,t.numberComparator)(e?1:0,s?1:0),t.ArrayQueue=class{constructor(e){this.items=e,this.firstIdx=0,this.lastIdx=this.items.length-1}get length(){return this.lastIdx-this.firstIdx+1}takeWhile(e){let t=this.firstIdx;for(;t=0&&e(this.items[t]);)t--;const s=t===this.lastIdx?null:this.items.slice(t+1,this.lastIdx+1);return this.lastIdx=t,s}peek(){if(0!==this.length)return this.items[this.firstIdx]}peekLast(){if(0!==this.length)return this.items[this.lastIdx]}dequeue(){const e=this.items[this.firstIdx];return this.firstIdx++,e}removeLast(){const e=this.items[this.lastIdx];return this.lastIdx--,e}takeCount(e){const t=this.items.slice(this.firstIdx,this.firstIdx+e);return this.firstIdx+=e,t}};class d{static{this.empty=new d((e=>{}))}constructor(e){this.iterate=e}forEach(e){this.iterate((t=>(e(t),!0)))}toArray(){const e=[];return this.iterate((t=>(e.push(t),!0))),e}filter(e){return new d((t=>this.iterate((s=>!e(s)||t(s)))))}map(e){return new d((t=>this.iterate((s=>t(e(s))))))}some(e){let t=!1;return this.iterate((s=>(t=e(s),!t))),t}findFirst(e){let t;return this.iterate((s=>!e(s)||(t=s,!1))),t}findLast(e){let t;return this.iterate((s=>(e(s)&&(t=s),!0))),t}findLastMaxBy(e){let t,s=!0;return this.iterate((i=>((s||u.isGreaterThan(e(i,t)))&&(s=!1,t=i),!0))),t}}t.CallbackIterable=d;class f{constructor(e){this._indexMap=e}static createSortPermutation(e,t){const s=Array.from(e.keys()).sort(((s,i)=>t(e[s],e[i])));return new f(s)}apply(e){return e.map(((t,s)=>e[this._indexMap[s]]))}inverse(){const e=this._indexMap.slice();for(let t=0;t{function s(e,t,s=e.length-1){for(let i=s;i>=0;i--)if(t(e[i]))return i;return-1}function i(e,t,s=0,i=e.length){let r=s,n=i;for(;r=0&&(s=r)}return s},t.findFirstMin=function(e,t){return o(e,((e,s)=>-t(e,s)))},t.findMaxIdx=function(e,t){if(0===e.length)return-1;let s=0;for(let i=1;i0&&(s=i);return s},t.mapFindFirst=function(e,t){for(const s of e){const e=t(s);if(void 0!==e)return e}};class n{static{this.assertInvariants=!1}constructor(e){this._array=e,this._findLastMonotonousLastIdx=0}findLastMonotonous(e){if(n.assertInvariants){if(this._prevFindLastPredicate)for(const t of this._array)if(this._prevFindLastPredicate(t)&&!e(t))throw new Error("MonotonousArray: current predicate must be weaker than (or equal to) the previous predicate.");this._prevFindLastPredicate=e}const t=i(this._array,e,this._findLastMonotonousLastIdx);return this._findLastMonotonousLastIdx=t+1,-1===t?void 0:this._array[t]}}function o(e,t){if(0===e.length)return;let s=e[0];for(let i=1;i0&&(s=r)}return s}t.MonotonousArray=n},9087:(e,t)=>{var s;Object.defineProperty(t,"__esModule",{value:!0}),t.SetWithKey=void 0,t.groupBy=function(e,t){const s=Object.create(null);for(const i of e){const e=t(i);let r=s[e];r||(r=s[e]=[]),r.push(i)}return s},t.diffSets=function(e,t){const s=[],i=[];for(const i of e)t.has(i)||s.push(i);for(const s of t)e.has(s)||i.push(s);return{removed:s,added:i}},t.diffMaps=function(e,t){const s=[],i=[];for(const[i,r]of e)t.has(i)||s.push(r);for(const[s,r]of t)e.has(s)||i.push(r);return{removed:s,added:i}},t.intersection=function(e,t){const s=new Set;for(const i of t)e.has(i)&&s.add(i);return s};class i{static{s=Symbol.toStringTag}constructor(e,t){this.toKey=t,this._map=new Map,this[s]="SetWithKey";for(const t of e)this.add(t)}get size(){return this._map.size}add(e){const t=this.toKey(e);return this._map.set(t,e),this}delete(e){return this._map.delete(this.toKey(e))}has(e){return this._map.has(this.toKey(e))}*entries(){for(const e of this._map.values())yield[e,e]}keys(){return this.values()}*values(){for(const e of this._map.values())yield e}clear(){this._map.clear()}forEach(e,t){this._map.forEach((s=>e.call(t,s,s,this)))}[Symbol.iterator](){return this.values()}}t.SetWithKey=i},9807:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.BugIndicatingError=t.ErrorNoTelemetry=t.ExpectedError=t.NotSupportedError=t.NotImplementedError=t.ReadonlyError=t.CancellationError=t.errorHandler=t.ErrorHandler=void 0,t.setUnexpectedErrorHandler=function(e){t.errorHandler.setUnexpectedErrorHandler(e)},t.isSigPipeError=function(e){if(!e||"object"!=typeof e)return!1;const t=e;return"EPIPE"===t.code&&"WRITE"===t.syscall?.toUpperCase()},t.onUnexpectedError=function(e){r(e)||t.errorHandler.onUnexpectedError(e)},t.onUnexpectedExternalError=function(e){r(e)||t.errorHandler.onUnexpectedExternalError(e)},t.transformErrorForSerialization=function(e){if(e instanceof Error){const{name:t,message:s}=e;return{$isError:!0,name:t,message:s,stack:e.stacktrace||e.stack,noTelemetry:l.isErrorNoTelemetry(e)}}return e},t.transformErrorFromSerialization=function(e){let t;return e.noTelemetry?t=new l:(t=new Error,t.name=e.name),t.message=e.message,t.stack=e.stack,t},t.isCancellationError=r,t.canceled=function(){const e=new Error(i);return e.name=e.message,e},t.illegalArgument=function(e){return e?new Error(`Illegal argument: ${e}`):new Error("Illegal argument")},t.illegalState=function(e){return e?new Error(`Illegal state: ${e}`):new Error("Illegal state")},t.getErrorMessage=function(e){return e?e.message?e.message:e.stack?e.stack.split("\n")[0]:String(e):"Error"};class s{constructor(){this.listeners=[],this.unexpectedErrorHandler=function(e){setTimeout((()=>{if(e.stack){if(l.isErrorNoTelemetry(e))throw new l(e.message+"\n\n"+e.stack);throw new Error(e.message+"\n\n"+e.stack)}throw e}),0)}}addListener(e){return this.listeners.push(e),()=>{this._removeListener(e)}}emit(e){this.listeners.forEach((t=>{t(e)}))}_removeListener(e){this.listeners.splice(this.listeners.indexOf(e),1)}setUnexpectedErrorHandler(e){this.unexpectedErrorHandler=e}getUnexpectedErrorHandler(){return this.unexpectedErrorHandler}onUnexpectedError(e){this.unexpectedErrorHandler(e),this.emit(e)}onUnexpectedExternalError(e){this.unexpectedErrorHandler(e)}}t.ErrorHandler=s,t.errorHandler=new s;const i="Canceled";function r(e){return e instanceof n||e instanceof Error&&e.name===i&&e.message===i}class n extends Error{constructor(){super(i),this.name=this.message}}t.CancellationError=n;class o extends TypeError{constructor(e){super(e?`${e} is read-only and cannot be changed`:"Cannot change read-only property")}}t.ReadonlyError=o;class a extends Error{constructor(e){super("NotImplemented"),e&&(this.message=e)}}t.NotImplementedError=a;class h extends Error{constructor(e){super("NotSupported"),e&&(this.message=e)}}t.NotSupportedError=h;class c extends Error{constructor(){super(...arguments),this.isExpected=!0}}t.ExpectedError=c;class l extends Error{constructor(e){super(e),this.name="CodeExpectedError"}static fromError(e){if(e instanceof l)return e;const t=new l;return t.message=e.message,t.stack=e.stack,t}static isErrorNoTelemetry(e){return"CodeExpectedError"===e.name}}t.ErrorNoTelemetry=l;class u extends Error{constructor(e){super(e||"An unexpected bug occurred."),Object.setPrototypeOf(this,u.prototype)}}t.BugIndicatingError=u},802:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ValueWithChangeEvent=t.Relay=t.EventBufferer=t.DynamicListEventMultiplexer=t.EventMultiplexer=t.MicrotaskEmitter=t.DebounceEmitter=t.PauseableEmitter=t.AsyncEmitter=t.createEventDeliveryQueue=t.Emitter=t.ListenerRefusalError=t.ListenerLeakError=t.EventProfiling=t.Event=void 0,t.setGlobalLeakWarningThreshold=function(e){const t=l;return l=e,{dispose(){l=t}}};const i=s(9807),r=s(8841),n=s(7150),o=s(6317),a=s(9725);var h;!function(e){function t(e){return(t,s=null,i)=>{let r,n=!1;return r=e((e=>{if(!n)return r?r.dispose():n=!0,t.call(s,e)}),null,i),n&&r.dispose(),r}}function s(e,t,s){return r(((s,i=null,r)=>e((e=>s.call(i,t(e))),null,r)),s)}function i(e,t,s){return r(((s,i=null,r)=>e((e=>t(e)&&s.call(i,e)),null,r)),s)}function r(e,t){let s;const i=new v({onWillAddFirstListener(){s=e(i.fire,i)},onDidRemoveLastListener(){s?.dispose()}});return t?.add(i),i.event}function o(e,t,s=100,i=!1,r=!1,n,o){let a,h,c,l,u=0;const d=new v({leakWarningThreshold:n,onWillAddFirstListener(){a=e((e=>{u++,h=t(h,e),i&&!c&&(d.fire(h),h=void 0),l=()=>{const e=h;h=void 0,c=void 0,(!i||u>1)&&d.fire(e),u=0},"number"==typeof s?(clearTimeout(c),c=setTimeout(l,s)):void 0===c&&(c=0,queueMicrotask(l))}))},onWillRemoveListener(){r&&u>0&&l?.()},onDidRemoveLastListener(){l=void 0,a.dispose()}});return o?.add(d),d.event}e.None=()=>n.Disposable.None,e.defer=function(e,t){return o(e,(()=>{}),0,void 0,!0,void 0,t)},e.once=t,e.map=s,e.forEach=function(e,t,s){return r(((s,i=null,r)=>e((e=>{t(e),s.call(i,e)}),null,r)),s)},e.filter=i,e.signal=function(e){return e},e.any=function(...e){return(t,s=null,i)=>{return r=(0,n.combinedDisposable)(...e.map((e=>e((e=>t.call(s,e)))))),(o=i)instanceof Array?o.push(r):o&&o.add(r),r;var r,o}},e.reduce=function(e,t,i,r){let n=i;return s(e,(e=>(n=t(n,e),n)),r)},e.debounce=o,e.accumulate=function(t,s=0,i){return e.debounce(t,((e,t)=>e?(e.push(t),e):[t]),s,void 0,!0,void 0,i)},e.latch=function(e,t=(e,t)=>e===t,s){let r,n=!0;return i(e,(e=>{const s=n||!t(e,r);return n=!1,r=e,s}),s)},e.split=function(t,s,i){return[e.filter(t,s,i),e.filter(t,(e=>!s(e)),i)]},e.buffer=function(e,t=!1,s=[],i){let r=s.slice(),n=e((e=>{r?r.push(e):a.fire(e)}));i&&i.add(n);const o=()=>{r?.forEach((e=>a.fire(e))),r=null},a=new v({onWillAddFirstListener(){n||(n=e((e=>a.fire(e))),i&&i.add(n))},onDidAddFirstListener(){r&&(t?setTimeout(o):o())},onDidRemoveLastListener(){n&&n.dispose(),n=null}});return i&&i.add(a),a.event},e.chain=function(e,t){return(s,i,r)=>{const n=t(new h);return e((function(e){const t=n.evaluate(e);t!==a&&s.call(i,t)}),void 0,r)}};const a=Symbol("HaltChainable");class h{constructor(){this.steps=[]}map(e){return this.steps.push(e),this}forEach(e){return this.steps.push((t=>(e(t),t))),this}filter(e){return this.steps.push((t=>e(t)?t:a)),this}reduce(e,t){let s=t;return this.steps.push((t=>(s=e(s,t),s))),this}latch(e=(e,t)=>e===t){let t,s=!0;return this.steps.push((i=>{const r=s||!e(i,t);return s=!1,t=i,r?i:a})),this}evaluate(e){for(const t of this.steps)if((e=t(e))===a)break;return e}}e.fromNodeEventEmitter=function(e,t,s=e=>e){const i=(...e)=>r.fire(s(...e)),r=new v({onWillAddFirstListener:()=>e.on(t,i),onDidRemoveLastListener:()=>e.removeListener(t,i)});return r.event},e.fromDOMEventEmitter=function(e,t,s=e=>e){const i=(...e)=>r.fire(s(...e)),r=new v({onWillAddFirstListener:()=>e.addEventListener(t,i),onDidRemoveLastListener:()=>e.removeEventListener(t,i)});return r.event},e.toPromise=function(e){return new Promise((s=>t(e)(s)))},e.fromPromise=function(e){const t=new v;return e.then((e=>{t.fire(e)}),(()=>{t.fire(void 0)})).finally((()=>{t.dispose()})),t.event},e.forward=function(e,t){return e((e=>t.fire(e)))},e.runAndSubscribe=function(e,t,s){return t(s),e((e=>t(e)))};class c{constructor(e,t){this._observable=e,this._counter=0,this._hasChanged=!1;const s={onWillAddFirstListener:()=>{e.addObserver(this)},onDidRemoveLastListener:()=>{e.removeObserver(this)}};this.emitter=new v(s),t&&t.add(this.emitter)}beginUpdate(e){this._counter++}handlePossibleChange(e){}handleChange(e,t){this._hasChanged=!0}endUpdate(e){this._counter--,0===this._counter&&(this._observable.reportChanges(),this._hasChanged&&(this._hasChanged=!1,this.emitter.fire(this._observable.get())))}}e.fromObservable=function(e,t){return new c(e,t).emitter.event},e.fromObservableLight=function(e){return(t,s,i)=>{let r=0,o=!1;const a={beginUpdate(){r++},endUpdate(){r--,0===r&&(e.reportChanges(),o&&(o=!1,t.call(s)))},handlePossibleChange(){},handleChange(){o=!0}};e.addObserver(a),e.reportChanges();const h={dispose(){e.removeObserver(a)}};return i instanceof n.DisposableStore?i.add(h):Array.isArray(i)&&i.push(h),h}}}(h||(t.Event=h={}));class c{static{this.all=new Set}static{this._idPool=0}constructor(e){this.listenerCount=0,this.invocationCount=0,this.elapsedOverall=0,this.durations=[],this.name=`${e}_${c._idPool++}`,c.all.add(this)}start(e){this._stopWatch=new a.StopWatch,this.listenerCount=e}stop(){if(this._stopWatch){const e=this._stopWatch.elapsed();this.durations.push(e),this.elapsedOverall+=e,this.invocationCount+=1,this._stopWatch=void 0}}}t.EventProfiling=c;let l=-1;class u{static{this._idPool=1}constructor(e,t,s=(u._idPool++).toString(16).padStart(3,"0")){this._errorHandler=e,this.threshold=t,this.name=s,this._warnCountdown=0}dispose(){this._stacks?.clear()}check(e,t){const s=this.threshold;if(s<=0||t{const t=this._stacks.get(e.value)||0;this._stacks.set(e.value,t-1)}}getMostFrequentStack(){if(!this._stacks)return;let e,t=0;for(const[s,i]of this._stacks)(!e||t0||this._options?.leakWarningThreshold?new u(e?.onListenerError??i.onUnexpectedError,this._options?.leakWarningThreshold??l):void 0,this._perfMon=this._options?._profName?new c(this._options._profName):void 0,this._deliveryQueue=this._options?.deliveryQueue}dispose(){this._disposed||(this._disposed=!0,this._deliveryQueue?.current===this&&this._deliveryQueue.reset(),this._listeners&&(this._listeners=void 0,this._size=0),this._options?.onDidRemoveLastListener?.(),this._leakageMon?.dispose())}get event(){return this._event??=(e,t,s)=>{if(this._leakageMon&&this._size>this._leakageMon.threshold**2){const e=`[${this._leakageMon.name}] REFUSES to accept new listeners because it exceeded its threshold by far (${this._size} vs ${this._leakageMon.threshold})`;console.warn(e);const t=this._leakageMon.getMostFrequentStack()??["UNKNOWN stack",-1],s=new _(`${e}. HINT: Stack shows most frequent listener (${t[1]}-times)`,t[0]);return(this._options?.onListenerError||i.onUnexpectedError)(s),n.Disposable.None}if(this._disposed)return n.Disposable.None;t&&(e=e.bind(t));const r=new g(e);let o;this._leakageMon&&this._size>=Math.ceil(.2*this._leakageMon.threshold)&&(r.stack=d.create(),o=this._leakageMon.check(r.stack,this._size+1)),this._listeners?this._listeners instanceof g?(this._deliveryQueue??=new m,this._listeners=[this._listeners,r]):this._listeners.push(r):(this._options?.onWillAddFirstListener?.(this),this._listeners=r,this._options?.onDidAddFirstListener?.(this)),this._size++;const a=(0,n.toDisposable)((()=>{o?.(),this._removeListener(r)}));return s instanceof n.DisposableStore?s.add(a):Array.isArray(s)&&s.push(a),a},this._event}_removeListener(e){if(this._options?.onWillRemoveListener?.(this),!this._listeners)return;if(1===this._size)return this._listeners=void 0,this._options?.onDidRemoveLastListener?.(this),void(this._size=0);const t=this._listeners,s=t.indexOf(e);if(-1===s)throw console.log("disposed?",this._disposed),console.log("size?",this._size),console.log("arr?",JSON.stringify(this._listeners)),new Error("Attempted to dispose unknown listener");this._size--,t[s]=void 0;const i=this._deliveryQueue.current===this;if(2*this._size<=t.length){let e=0;for(let s=0;s0}}t.Emitter=v,t.createEventDeliveryQueue=()=>new m;class m{constructor(){this.i=-1,this.end=0}enqueue(e,t,s){this.i=0,this.end=s,this.current=e,this.value=t}reset(){this.i=this.end,this.current=void 0,this.value=void 0}}t.AsyncEmitter=class extends v{async fireAsync(e,t,s){if(this._listeners)for(this._asyncDeliveryQueue||(this._asyncDeliveryQueue=new o.LinkedList),((e,t)=>{if(e instanceof g)t(e);else for(let s=0;sthis._asyncDeliveryQueue.push([t.value,e])));this._asyncDeliveryQueue.size>0&&!t.isCancellationRequested;){const[e,r]=this._asyncDeliveryQueue.shift(),n=[],o={...r,token:t,waitUntil:t=>{if(Object.isFrozen(n))throw new Error("waitUntil can NOT be called asynchronous");s&&(t=s(t,e)),n.push(t)}};try{e(o)}catch(e){(0,i.onUnexpectedError)(e);continue}Object.freeze(n),await Promise.allSettled(n).then((e=>{for(const t of e)"rejected"===t.status&&(0,i.onUnexpectedError)(t.reason)}))}}};class b extends v{get isPaused(){return 0!==this._isPaused}constructor(e){super(e),this._isPaused=0,this._eventQueue=new o.LinkedList,this._mergeFn=e?.merge}pause(){this._isPaused++}resume(){if(0!==this._isPaused&&0==--this._isPaused)if(this._mergeFn){if(this._eventQueue.size>0){const e=Array.from(this._eventQueue);this._eventQueue.clear(),super.fire(this._mergeFn(e))}}else for(;!this._isPaused&&0!==this._eventQueue.size;)super.fire(this._eventQueue.shift())}fire(e){this._size&&(0!==this._isPaused?this._eventQueue.push(e):super.fire(e))}}t.PauseableEmitter=b,t.DebounceEmitter=class extends b{constructor(e){super(e),this._delay=e.delay??100}fire(e){this._handle||(this.pause(),this._handle=setTimeout((()=>{this._handle=void 0,this.resume()}),this._delay)),super.fire(e)}},t.MicrotaskEmitter=class extends v{constructor(e){super(e),this._queuedEvents=[],this._mergeFn=e?.merge}fire(e){this.hasListeners()&&(this._queuedEvents.push(e),1===this._queuedEvents.length&&queueMicrotask((()=>{this._mergeFn?super.fire(this._mergeFn(this._queuedEvents)):this._queuedEvents.forEach((e=>super.fire(e))),this._queuedEvents=[]})))}};class S{constructor(){this.hasListeners=!1,this.events=[],this.emitter=new v({onWillAddFirstListener:()=>this.onFirstListenerAdd(),onDidRemoveLastListener:()=>this.onLastListenerRemove()})}get event(){return this.emitter.event}add(e){const t={event:e,listener:null};return this.events.push(t),this.hasListeners&&this.hook(t),(0,n.toDisposable)((0,r.createSingleCallFunction)((()=>{this.hasListeners&&this.unhook(t);const e=this.events.indexOf(t);this.events.splice(e,1)})))}onFirstListenerAdd(){this.hasListeners=!0,this.events.forEach((e=>this.hook(e)))}onLastListenerRemove(){this.hasListeners=!1,this.events.forEach((e=>this.unhook(e)))}hook(e){e.listener=e.event((e=>this.emitter.fire(e)))}unhook(e){e.listener?.dispose(),e.listener=null}dispose(){this.emitter.dispose();for(const e of this.events)e.listener?.dispose();this.events=[]}}t.EventMultiplexer=S,t.DynamicListEventMultiplexer=class{constructor(e,t,s,i){this._store=new n.DisposableStore;const r=this._store.add(new S),o=this._store.add(new n.DisposableMap);function a(e){o.set(e,r.add(i(e)))}for(const t of e)a(t);this._store.add(t((e=>{a(e)}))),this._store.add(s((e=>{o.deleteAndDispose(e)}))),this.event=r.event}dispose(){this._store.dispose()}},t.EventBufferer=class{constructor(){this.data=[]}wrapEvent(e,t,s){return(i,r,n)=>e((e=>{const n=this.data[this.data.length-1];if(!t)return void(n?n.buffers.push((()=>i.call(r,e))):i.call(r,e));const o=n;o?(o.items??=[],o.items.push(e),0===o.buffers.length&&n.buffers.push((()=>{o.reducedResult??=s?o.items.reduce(t,s):o.items.reduce(t),i.call(r,o.reducedResult)}))):i.call(r,t(s,e))}),void 0,n)}bufferEvents(e){const t={buffers:new Array};this.data.push(t);const s=e();return this.data.pop(),t.buffers.forEach((e=>e())),s}},t.Relay=class{constructor(){this.listening=!1,this.inputEvent=h.None,this.inputEventListener=n.Disposable.None,this.emitter=new v({onDidAddFirstListener:()=>{this.listening=!0,this.inputEventListener=this.inputEvent(this.emitter.fire,this.emitter)},onDidRemoveLastListener:()=>{this.listening=!1,this.inputEventListener.dispose()}}),this.event=this.emitter.event}set input(e){this.inputEvent=e,this.listening&&(this.inputEventListener.dispose(),this.inputEventListener=e(this.emitter.fire,this.emitter))}dispose(){this.inputEventListener.dispose(),this.emitter.dispose()}},t.ValueWithChangeEvent=class{static const(e){return new y(e)}constructor(e){this._value=e,this._onDidChange=new v,this.onDidChange=this._onDidChange.event}get value(){return this._value}set value(e){e!==this._value&&(this._value=e,this._onDidChange.fire(void 0))}};class y{constructor(e){this.value=e,this.onDidChange=h.None}}},8841:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.createSingleCallFunction=function(e,t){const s=this;let i,r=!1;return function(){if(r)return i;if(r=!0,t)try{i=e.apply(s,arguments)}finally{t()}else i=e.apply(s,arguments);return i}}},4218:(e,t)=>{var s;Object.defineProperty(t,"__esModule",{value:!0}),t.Iterable=void 0,function(e){function t(e){return e&&"object"==typeof e&&"function"==typeof e[Symbol.iterator]}e.is=t;const s=Object.freeze([]);function*i(e){yield e}e.empty=function(){return s},e.single=i,e.wrap=function(e){return t(e)?e:i(e)},e.from=function(e){return e||s},e.reverse=function*(e){for(let t=e.length-1;t>=0;t--)yield e[t]},e.isEmpty=function(e){return!e||!0===e[Symbol.iterator]().next().done},e.first=function(e){return e[Symbol.iterator]().next().value},e.some=function(e,t){let s=0;for(const i of e)if(t(i,s++))return!0;return!1},e.find=function(e,t){for(const s of e)if(t(s))return s},e.filter=function*(e,t){for(const s of e)t(s)&&(yield s)},e.map=function*(e,t){let s=0;for(const i of e)yield t(i,s++)},e.flatMap=function*(e,t){let s=0;for(const i of e)yield*t(i,s++)},e.concat=function*(...e){for(const t of e)yield*t},e.reduce=function(e,t,s){let i=s;for(const s of e)i=t(i,s);return i},e.slice=function*(e,t,s=e.length){for(t<0&&(t+=e.length),s<0?s+=e.length:s>e.length&&(s=e.length);tr}]},e.asyncToArray=async function(e){const t=[];for await(const s of e)t.push(s);return Promise.resolve(t)}}(s||(t.Iterable=s={}))},7150:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.DisposableMap=t.ImmortalReference=t.AsyncReferenceCollection=t.ReferenceCollection=t.SafeDisposable=t.RefCountedDisposable=t.MandatoryMutableDisposable=t.MutableDisposable=t.Disposable=t.DisposableStore=t.DisposableTracker=void 0,t.setDisposableTracker=function(e){h=e},t.trackDisposable=l,t.markAsDisposed=u,t.markAsSingleton=function(e){return h?.markAsSingleton(e),e},t.isDisposable=f,t.dispose=_,t.disposeIfDisposable=function(e){for(const t of e)f(t)&&t.dispose();return[]},t.combinedDisposable=function(...e){const t=p((()=>_(e)));return function(e,t){if(h)for(const s of e)h.setParent(s,t)}(e,t),t},t.toDisposable=p,t.disposeOnReturn=function(e){const t=new g;try{e(t)}finally{t.dispose()}};const i=s(3058),r=s(9087),n=s(2608),o=s(8841),a=s(4218);let h=null;class c{constructor(){this.livingDisposables=new Map}static{this.idx=0}getDisposableData(e){let t=this.livingDisposables.get(e);return t||(t={parent:null,source:null,isSingleton:!1,value:e,idx:c.idx++},this.livingDisposables.set(e,t)),t}trackDisposable(e){const t=this.getDisposableData(e);t.source||(t.source=(new Error).stack)}setParent(e,t){this.getDisposableData(e).parent=t}markAsDisposed(e){this.livingDisposables.delete(e)}markAsSingleton(e){this.getDisposableData(e).isSingleton=!0}getRootParent(e,t){const s=t.get(e);if(s)return s;const i=e.parent?this.getRootParent(this.getDisposableData(e.parent),t):e;return t.set(e,i),i}getTrackedDisposables(){const e=new Map;return[...this.livingDisposables.entries()].filter((([,t])=>null!==t.source&&!this.getRootParent(t,e).isSingleton)).flatMap((([e])=>e))}computeLeakingDisposables(e=10,t){let s;if(t)s=t;else{const e=new Map,t=[...this.livingDisposables.values()].filter((t=>null!==t.source&&!this.getRootParent(t,e).isSingleton));if(0===t.length)return;const i=new Set(t.map((e=>e.value)));if(s=t.filter((e=>!(e.parent&&i.has(e.parent)))),0===s.length)throw new Error("There are cyclic diposable chains!")}if(!s)return;function o(e){const t=e.source.split("\n").map((e=>e.trim().replace("at ",""))).filter((e=>""!==e));return function(e,t){for(;e.length>0&&t.some((t=>"string"==typeof t?t===e[0]:e[0].match(t)));)e.shift()}(t,["Error",/^trackDisposable \(.*\)$/,/^DisposableTracker.trackDisposable \(.*\)$/]),t.reverse()}const a=new n.SetMap;for(const e of s){const t=o(e);for(let s=0;s<=t.length;s++)a.add(t.slice(0,s).join("\n"),e)}s.sort((0,i.compareBy)((e=>e.idx),i.numberComparator));let h="",c=0;for(const t of s.slice(0,e)){c++;const e=o(t),i=[];for(let t=0;to(e)[t])),(e=>e));delete c[e[t]];for(const[e,t]of Object.entries(c))i.unshift(` - stacktraces of ${t.length} other leaks continue with ${e}`);i.unshift(n)}h+=`\n\n\n==================== Leaking disposable ${c}/${s.length}: ${t.value.constructor.name} ====================\n${i.join("\n")}\n============================================================\n\n`}return s.length>e&&(h+=`\n\n\n... and ${s.length-e} more leaking disposables\n\n`),{leaks:s,details:h}}}function l(e){return h?.trackDisposable(e),e}function u(e){h?.markAsDisposed(e)}function d(e,t){h?.setParent(e,t)}function f(e){return"object"==typeof e&&null!==e&&"function"==typeof e.dispose&&0===e.dispose.length}function _(e){if(a.Iterable.is(e)){const t=[];for(const s of e)if(s)try{s.dispose()}catch(e){t.push(e)}if(1===t.length)throw t[0];if(t.length>1)throw new AggregateError(t,"Encountered errors while disposing of store");return Array.isArray(e)?[]:e}if(e)return e.dispose(),e}function p(e){const t=l({dispose:(0,o.createSingleCallFunction)((()=>{u(t),e()}))});return t}t.DisposableTracker=c;class g{static{this.DISABLE_DISPOSED_WARNING=!1}constructor(){this._toDispose=new Set,this._isDisposed=!1,l(this)}dispose(){this._isDisposed||(u(this),this._isDisposed=!0,this.clear())}get isDisposed(){return this._isDisposed}clear(){if(0!==this._toDispose.size)try{_(this._toDispose)}finally{this._toDispose.clear()}}add(e){if(!e)return e;if(e===this)throw new Error("Cannot register a disposable on itself!");return d(e,this),this._isDisposed?g.DISABLE_DISPOSED_WARNING||console.warn(new Error("Trying to add a disposable to a DisposableStore that has already been disposed of. The added object will be leaked!").stack):this._toDispose.add(e),e}delete(e){if(e){if(e===this)throw new Error("Cannot dispose a disposable on itself!");this._toDispose.delete(e),e.dispose()}}deleteAndLeak(e){e&&this._toDispose.has(e)&&(this._toDispose.delete(e),d(e,null))}}t.DisposableStore=g;class v{static{this.None=Object.freeze({dispose(){}})}constructor(){this._store=new g,l(this),d(this._store,this)}dispose(){u(this),this._store.dispose()}_register(e){if(e===this)throw new Error("Cannot register a disposable on itself!");return this._store.add(e)}}t.Disposable=v;class m{constructor(){this._isDisposed=!1,l(this)}get value(){return this._isDisposed?void 0:this._value}set value(e){this._isDisposed||e===this._value||(this._value?.dispose(),e&&d(e,this),this._value=e)}clear(){this.value=void 0}dispose(){this._isDisposed=!0,u(this),this._value?.dispose(),this._value=void 0}clearAndLeak(){const e=this._value;return this._value=void 0,e&&d(e,null),e}}t.MutableDisposable=m,t.MandatoryMutableDisposable=class{constructor(e){this._disposable=new m,this._isDisposed=!1,this._disposable.value=e}get value(){return this._disposable.value}set value(e){this._isDisposed||e===this._disposable.value||(this._disposable.value=e)}dispose(){this._isDisposed=!0,this._disposable.dispose()}},t.RefCountedDisposable=class{constructor(e){this._disposable=e,this._counter=1}acquire(){return this._counter++,this}release(){return 0==--this._counter&&this._disposable.dispose(),this}},t.SafeDisposable=class{constructor(){this.dispose=()=>{},this.unset=()=>{},this.isset=()=>!1,l(this)}set(e){let t=e;return this.unset=()=>t=void 0,this.isset=()=>void 0!==t,this.dispose=()=>{t&&(t(),t=void 0,u(this))},this}},t.ReferenceCollection=class{constructor(){this.references=new Map}acquire(e,...t){let s=this.references.get(e);s||(s={counter:0,object:this.createReferencedObject(e,...t)},this.references.set(e,s));const{object:i}=s,r=(0,o.createSingleCallFunction)((()=>{0==--s.counter&&(this.destroyReferencedObject(e,s.object),this.references.delete(e))}));return s.counter++,{object:i,dispose:r}}},t.AsyncReferenceCollection=class{constructor(e){this.referenceCollection=e}async acquire(e,...t){const s=this.referenceCollection.acquire(e,...t);try{return{object:await s.object,dispose:()=>s.dispose()}}catch(e){throw s.dispose(),e}}},t.ImmortalReference=class{constructor(e){this.object=e}dispose(){}};class b{constructor(){this._store=new Map,this._isDisposed=!1,l(this)}dispose(){u(this),this._isDisposed=!0,this.clearAndDisposeAll()}clearAndDisposeAll(){if(this._store.size)try{_(this._store.values())}finally{this._store.clear()}}has(e){return this._store.has(e)}get size(){return this._store.size}get(e){return this._store.get(e)}set(e,t,s=!1){this._isDisposed&&console.warn(new Error("Trying to add a disposable to a DisposableMap that has already been disposed of. The added object will be leaked!").stack),s||this._store.get(e)?.dispose(),this._store.set(e,t)}deleteAndDispose(e){this._store.get(e)?.dispose(),this._store.delete(e)}deleteAndLeak(e){const t=this._store.get(e);return this._store.delete(e),t}keys(){return this._store.keys()}values(){return this._store.values()}[Symbol.iterator](){return this._store[Symbol.iterator]()}}t.DisposableMap=b},6317:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.LinkedList=void 0;class s{static{this.Undefined=new s(void 0)}constructor(e){this.element=e,this.next=s.Undefined,this.prev=s.Undefined}}class i{constructor(){this._first=s.Undefined,this._last=s.Undefined,this._size=0}get size(){return this._size}isEmpty(){return this._first===s.Undefined}clear(){let e=this._first;for(;e!==s.Undefined;){const t=e.next;e.prev=s.Undefined,e.next=s.Undefined,e=t}this._first=s.Undefined,this._last=s.Undefined,this._size=0}unshift(e){return this._insert(e,!1)}push(e){return this._insert(e,!0)}_insert(e,t){const i=new s(e);if(this._first===s.Undefined)this._first=i,this._last=i;else if(t){const e=this._last;this._last=i,i.prev=e,e.next=i}else{const e=this._first;this._first=i,i.next=e,e.prev=i}this._size+=1;let r=!1;return()=>{r||(r=!0,this._remove(i))}}shift(){if(this._first!==s.Undefined){const e=this._first.element;return this._remove(this._first),e}}pop(){if(this._last!==s.Undefined){const e=this._last.element;return this._remove(this._last),e}}_remove(e){if(e.prev!==s.Undefined&&e.next!==s.Undefined){const t=e.prev;t.next=e.next,e.next.prev=t}else e.prev===s.Undefined&&e.next===s.Undefined?(this._first=s.Undefined,this._last=s.Undefined):e.next===s.Undefined?(this._last=this._last.prev,this._last.next=s.Undefined):e.prev===s.Undefined&&(this._first=this._first.next,this._first.prev=s.Undefined);this._size-=1}*[Symbol.iterator](){let e=this._first;for(;e!==s.Undefined;)yield e.element,e=e.next}}t.LinkedList=i},2608:(e,t)=>{var s;Object.defineProperty(t,"__esModule",{value:!0}),t.SetMap=t.BidirectionalMap=t.CounterSet=t.Touch=void 0,t.getOrSet=function(e,t,s){let i=e.get(t);return void 0===i&&(i=s,e.set(t,i)),i},t.mapToString=function(e){const t=[];return e.forEach(((e,s)=>{t.push(`${s} => ${e}`)})),`Map(${e.size}) {${t.join(", ")}}`},t.setToString=function(e){const t=[];return e.forEach((e=>{t.push(e)})),`Set(${e.size}) {${t.join(", ")}}`},t.mapsStrictEqualIgnoreOrder=function(e,t){if(e===t)return!0;if(e.size!==t.size)return!1;for(const[s,i]of e)if(!t.has(s)||t.get(s)!==i)return!1;for(const[s]of t)if(!e.has(s))return!1;return!0},function(e){e[e.None=0]="None",e[e.AsOld=1]="AsOld",e[e.AsNew=2]="AsNew"}(s||(t.Touch=s={})),t.CounterSet=class{constructor(){this.map=new Map}add(e){return this.map.set(e,(this.map.get(e)||0)+1),this}delete(e){let t=this.map.get(e)||0;return 0!==t&&(t--,0===t?this.map.delete(e):this.map.set(e,t),!0)}has(e){return this.map.has(e)}},t.BidirectionalMap=class{constructor(e){if(this._m1=new Map,this._m2=new Map,e)for(const[t,s]of e)this.set(t,s)}clear(){this._m1.clear(),this._m2.clear()}set(e,t){this._m1.set(e,t),this._m2.set(t,e)}get(e){return this._m1.get(e)}getKey(e){return this._m2.get(e)}delete(e){const t=this._m1.get(e);return void 0!==t&&(this._m1.delete(e),this._m2.delete(t),!0)}forEach(e,t){this._m1.forEach(((s,i)=>{e.call(t,s,i,this)}))}keys(){return this._m1.keys()}values(){return this._m1.values()}},t.SetMap=class{constructor(){this.map=new Map}add(e,t){let s=this.map.get(e);s||(s=new Set,this.map.set(e,s)),s.add(t)}delete(e,t){const s=this.map.get(e);s&&(s.delete(t),0===s.size&&this.map.delete(e))}forEach(e,t){const s=this.map.get(e);s&&s.forEach(t)}get(e){return this.map.get(e)||new Set}}},9725:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.StopWatch=void 0;const s=globalThis.performance&&"function"==typeof globalThis.performance.now;class i{static create(e){return new i(e)}constructor(e){this._now=s&&!1===e?Date.now:globalThis.performance.now.bind(globalThis.performance),this._startTime=this._now(),this._stopTime=-1}stop(){this._stopTime=this._now()}reset(){this._startTime=this._now(),this._stopTime=-1}elapsed(){return-1!==this._stopTime?this._stopTime-this._startTime:this._now()-this._startTime}}t.StopWatch=i}},t={};function s(i){var r=t[i];if(void 0!==r)return r.exports;var n=t[i]={exports:{}};return e[i].call(n.exports,n,n.exports,s),n.exports}var i={};(()=>{var e=i;Object.defineProperty(e,"__esModule",{value:!0}),e.Terminal=void 0;const t=s(5101),r=s(6097),n=s(4335),o=s(5856),a=s(3027),h=s(7150),c=["cols","rows"];class l extends h.Disposable{constructor(e){super(),this._core=this._register(new o.Terminal(e)),this._addonManager=this._register(new a.AddonManager),this._publicOptions={...this._core.options};const t=e=>this._core.options[e],s=(e,t)=>{this._checkReadonlyOptions(e),this._core.options[e]=t};for(const e in this._core.options){Object.defineProperty(this._publicOptions,e,{get:()=>this._core.options[e],set:t=>{this._checkReadonlyOptions(e),this._core.options[e]=t}});const i={get:t.bind(this,e),set:s.bind(this,e)};Object.defineProperty(this._publicOptions,e,i)}}_checkReadonlyOptions(e){if(c.includes(e))throw new Error(`Option "${e}" can only be set in the constructor`)}_checkProposedApi(){if(!this._core.optionsService.options.allowProposedApi)throw new Error("You must set the allowProposedApi option to true to use proposed API")}get onBell(){return this._core.onBell}get onBinary(){return this._core.onBinary}get onCursorMove(){return this._core.onCursorMove}get onData(){return this._core.onData}get onLineFeed(){return this._core.onLineFeed}get onResize(){return this._core.onResize}get onScroll(){return this._core.onScroll}get onTitleChange(){return this._core.onTitleChange}get onWriteParsed(){return this._core.onWriteParsed}get parser(){return this._checkProposedApi(),this._parser||(this._parser=new r.ParserApi(this._core)),this._parser}get unicode(){return this._checkProposedApi(),new n.UnicodeApi(this._core)}get rows(){return this._core.rows}get cols(){return this._core.cols}get buffer(){return this._checkProposedApi(),this._buffer||(this._buffer=this._register(new t.BufferNamespaceApi(this._core))),this._buffer}get markers(){return this._checkProposedApi(),this._core.markers}get modes(){const e=this._core.coreService.decPrivateModes;let t="none";switch(this._core.coreMouseService.activeProtocol){case"X10":t="x10";break;case"VT200":t="vt200";break;case"DRAG":t="drag";break;case"ANY":t="any"}return{applicationCursorKeysMode:e.applicationCursorKeys,applicationKeypadMode:e.applicationKeypad,bracketedPasteMode:e.bracketedPasteMode,insertMode:this._core.coreService.modes.insertMode,mouseTrackingMode:t,originMode:e.origin,reverseWraparoundMode:e.reverseWraparound,sendFocusMode:e.sendFocus,synchronizedOutputMode:e.synchronizedOutput,wraparoundMode:e.wraparound}}get options(){return this._publicOptions}set options(e){for(const t in e)this._publicOptions[t]=e[t]}input(e,t=!0){this._core.input(e,t)}resize(e,t){this._verifyIntegers(e,t),this._core.resize(e,t)}registerMarker(e=0){return this._checkProposedApi(),this._verifyIntegers(e),this._core.addMarker(e)}addMarker(e){return this.registerMarker(e)}dispose(){super.dispose()}scrollLines(e){this._verifyIntegers(e),this._core.scrollLines(e)}scrollPages(e){this._verifyIntegers(e),this._core.scrollPages(e)}scrollToTop(){this._core.scrollToTop()}scrollToBottom(){this._core.scrollToBottom()}scrollToLine(e){this._verifyIntegers(e),this._core.scrollToLine(e)}clear(){this._core.clear()}write(e,t){this._core.write(e,t)}writeln(e,t){this._core.write(e),this._core.write("\r\n",t)}reset(){this._core.reset()}loadAddon(e){this._addonManager.loadAddon(this,e)}_verifyIntegers(...e){for(const t of e)if(t===1/0||isNaN(t)||t%1!=0)throw new Error("This API only accepts integers")}}e.Terminal=l})();var r=exports;for(var n in i)r[n]=i[n];i.__esModule&&Object.defineProperty(r,"__esModule",{value:!0})})(); +//# sourceMappingURL=xterm-headless.js.map \ No newline at end of file diff --git a/crates/shell-use/src/terminal/conformance.rs b/crates/shell-use/src/terminal/conformance.rs index bee931a..98c734d 100644 --- a/crates/shell-use/src/terminal/conformance.rs +++ b/crates/shell-use/src/terminal/conformance.rs @@ -211,9 +211,17 @@ macro_rules! emulator_conformance_tests { ); } - /// The underline's color is tracked separately from its shape, so - /// SGR 58 survives a cell that is not underlined and SGR 24 leaves it - /// alone. Only a full reset clears both. + /// The underline's shape and its color are tracked separately: SGR 58 + /// sets a color without drawing anything, SGR 24 clears the shape, and + /// SGR 0 clears both. + /// + /// Whether the *color* outlives a cell that is not underlined is + /// genuinely divergent. alacritty stores it unconditionally, but + /// xterm.js keeps it in an extended-attribute record whose `isEmpty()` + /// consults only the underline style and hyperlink id, so a cell with + /// a color but no shape drops the record and reports the foreground + /// instead. This therefore pins the shape transitions, which every + /// emulator agrees on, and the color only where it is actually drawn. #[test] fn conformance_underline_color_outlives_the_underline() { use $crate::terminal::cell::{Color, UnderlineStyle as U}; @@ -222,19 +230,13 @@ macro_rules! emulator_conformance_tests { let rows = e.viewable_rows(); assert_eq!(rows[0][0].underline, U::None, "58 alone does not underline"); - assert_eq!( - rows[0][0].underline_color, - Some(Color::from_index(33)), - "but its color is still tracked" - ); assert_eq!(rows[0][1].underline, U::Single, "4 turns it on"); - assert_eq!(rows[0][1].underline_color, Some(Color::from_index(33))); - assert_eq!(rows[0][2].underline, U::None, "24 turns it off"); assert_eq!( - rows[0][2].underline_color, + rows[0][1].underline_color, Some(Color::from_index(33)), - "24 clears the shape, not the color" + "an underlined cell carries the color 58 set" ); + assert_eq!(rows[0][2].underline, U::None, "24 turns it off"); assert_eq!(rows[0][3].underline, U::None, "0 resets everything"); assert_eq!(rows[0][3].underline_color, None); } diff --git a/crates/shell-use/src/terminal/mod.rs b/crates/shell-use/src/terminal/mod.rs index a451e81..10e000e 100644 --- a/crates/shell-use/src/terminal/mod.rs +++ b/crates/shell-use/src/terminal/mod.rs @@ -6,3 +6,4 @@ pub mod emu; pub mod integration; pub mod locator; pub mod pty; +pub mod xtermjs; diff --git a/crates/shell-use/src/terminal/xtermjs.rs b/crates/shell-use/src/terminal/xtermjs.rs new file mode 100644 index 0000000..cfbd860 --- /dev/null +++ b/crates/shell-use/src/terminal/xtermjs.rs @@ -0,0 +1,246 @@ +//! [`Emulator`] backend built on `@xterm/headless` running in QuickJS. +//! +//! The bundle and its host shim are embedded in the binary and evaluated into +//! a fresh QuickJS context per session, so this backend adds no runtime +//! dependency on Node or on anything installed on the machine. +//! +//! # Why the grid crosses the boundary packed +//! +//! Reading a cell means a call into JS, and an 80x30 screen is 2,400 of them +//! with ten property reads each. Walking the grid that way costs milliseconds +//! per poll. Instead [`shim.js`](../../../assets/xterm/shim.js) flattens a row +//! span into one string and one integer array, so a whole screen crosses in +//! two values and this module's job is decoding rather than traversal. +//! +//! # Threading +//! +//! [`Emulator`] is `Send` and the daemon moves the emulator between its reader +//! and request threads. `rquickjs`'s `parallel` feature makes `Runtime` and +//! `Context` `Send + Sync`, which is what lets this type be `Send` without +//! confining the interpreter to a thread of its own. It is emphatically not +//! `Sync`-in-spirit: every entry point below takes `&mut self`, so the daemon's +//! existing mutex is still what serializes access. + +use compact_str::{CompactString, ToCompactString}; +use rquickjs::{Context, Function, Object, Runtime}; + +use crate::terminal::cell::{Attrs, Color, EmuCell, UnderlineStyle, CONTINUATION}; +use crate::terminal::emu::Emulator; + +const XTERM_BUNDLE: &str = include_str!("../../assets/xterm/xterm-headless.js"); +const SHIM: &str = include_str!("../../assets/xterm/shim.js"); + +/// Ints per cell in the packed `meta` array, mirroring `pack()` in the shim. +const STRIDE: usize = 6; + +/// Color-mode bits, packed alongside the SGR booleans in the `flags` int. +const FG_PALETTE: i32 = 256; +const FG_RGB: i32 = 512; +const BG_PALETTE: i32 = 1024; +const BG_RGB: i32 = 2048; +const UL_PALETTE: i32 = 4096; +const UL_RGB: i32 = 8192; + +/// Decode one color slot. `mode` is the pair of bits that says how to read +/// `raw`; with neither set the cell uses the terminal default, which the cell +/// vocabulary spells as `None`. +fn color(raw: i32, flags: i32, palette_bit: i32, rgb_bit: i32) -> Option { + if flags & palette_bit != 0 { + Some(Color::from_index(raw as u8)) + } else if flags & rgb_bit != 0 { + Some(Color::Rgb( + ((raw >> 16) & 0xff) as u8, + ((raw >> 8) & 0xff) as u8, + (raw & 0xff) as u8, + )) + } else { + None + } +} + +/// xterm.js's `UnderlineStyle`, which already folds "not underlined" into +/// `NONE` and a bare `SGR 4` into `SINGLE`, so no separate underline flag has +/// to be consulted here. +fn underline(raw: i32) -> UnderlineStyle { + match raw { + 1 => UnderlineStyle::Single, + 2 => UnderlineStyle::Double, + 3 => UnderlineStyle::Curly, + 4 => UnderlineStyle::Dotted, + 5 => UnderlineStyle::Dashed, + _ => UnderlineStyle::None, + } +} + +fn attrs(flags: i32) -> Attrs { + let mut a = Attrs::empty(); + for (bit, attr) in [ + (1, Attrs::BOLD), + (2, Attrs::DIM), + (4, Attrs::ITALIC), + (8, Attrs::INVERSE), + (16, Attrs::INVISIBLE), + (32, Attrs::STRIKE), + (64, Attrs::BLINK), + ] { + a.set(attr, flags & bit != 0); + } + a +} + +pub struct XtermJsEmu { + // Held to keep the interpreter alive for as long as the context that runs + // in it; nothing calls through it directly. + _runtime: Runtime, + ctx: Context, + cols: u16, + rows: u16, +} + +impl XtermJsEmu { + pub fn new(cols: u16, rows: u16, scrollback: usize) -> anyhow::Result { + let runtime = Runtime::new()?; + let ctx = Context::full(&runtime)?; + + ctx.with(|ctx| -> anyhow::Result<()> { + // Shim first: the bundle reads `process`/`exports` while it + // evaluates, not just when the terminal is constructed. + ctx.eval::<(), _>(SHIM)?; + ctx.eval::<(), _>(XTERM_BUNDLE)?; + let boot: Function = ctx.globals().get("__boot")?; + let emu: Object = boot.call((cols, rows, scrollback as u32))?; + ctx.globals().set("__emu", emu)?; + Ok(()) + })?; + + Ok(XtermJsEmu { + _runtime: runtime, + ctx, + cols, + rows, + }) + } + + /// Call a zero-argument method on the shim's emulator object. + /// + /// No `this` is threaded through: every method the shim returns is a + /// closure over its own `term`, so the receiver is unused, and rquickjs + /// would otherwise pass a `This` wrapper as the first positional argument. + fn call(&self, method: &str) -> R + where + R: for<'js> rquickjs::FromJs<'js> + Default, + { + self.ctx + .with(|ctx| -> rquickjs::Result { + let emu: Object = ctx.globals().get("__emu")?; + emu.get::<_, Function>(method)?.call(()) + }) + .unwrap_or_default() + } + + fn rows_in_range(&self, full: bool) -> Vec> { + let cols = self.cols as usize; + let packed = self + .ctx + .with(|ctx| -> rquickjs::Result<(String, Vec)> { + let emu: Object = ctx.globals().get("__emu")?; + let start: i32 = emu.get::<_, Function>("start")?.call((full,))?; + let end: i32 = emu.get::<_, Function>("end")?.call((full,))?; + let packed: rquickjs::Array = emu.get::<_, Function>("pack")?.call((start, end))?; + Ok((packed.get(0)?, packed.get(1)?)) + }); + + let (chars, meta) = match packed { + Ok(p) => p, + Err(_) => return Vec::new(), + }; + + let mut cells = chars.split('\0'); + let mut out = Vec::with_capacity(meta.len() / STRIDE / cols.max(1)); + let mut row = Vec::with_capacity(cols); + for (i, m) in meta.chunks_exact(STRIDE).enumerate() { + let ch = cells.next().unwrap_or(" "); + let (width, fg, bg, ul_color, ul_style, flags) = (m[0], m[1], m[2], m[3], m[4], m[5]); + + // A zero-width cell is the second column of a double-width + // character. Everything else owns its column, so an empty string + // there is a cell nothing has been printed to and renders blank. + let ch = if width == 0 { + CompactString::const_new(CONTINUATION) + } else if ch.is_empty() { + CompactString::const_new(" ") + } else { + ch.to_compact_string() + }; + + row.push(EmuCell { + ch, + fg: color(fg, flags, FG_PALETTE, FG_RGB), + bg: color(bg, flags, BG_PALETTE, BG_RGB), + underline: underline(ul_style), + underline_color: color(ul_color, flags, UL_PALETTE, UL_RGB), + attrs: attrs(flags), + }); + + if (i + 1) % cols == 0 { + out.push(std::mem::replace(&mut row, Vec::with_capacity(cols))); + } + } + out + } +} + +impl Emulator for XtermJsEmu { + fn process(&mut self, bytes: &[u8]) { + // Fed as bytes rather than as a string on purpose: xterm.js runs its + // own incremental UTF-8 decoder over a byte array and carries a + // partial sequence across calls, which is what keeps a multi-byte + // character split across two PTY reads from being corrupted. + let _ = self.ctx.with(|ctx| -> rquickjs::Result<()> { + let emu: Object = ctx.globals().get("__emu")?; + let buf = rquickjs::TypedArray::::new(ctx.clone(), bytes)?; + emu.get::<_, Function>("feed")?.call((buf,)) + }); + } + + fn take_pending_writes(&mut self) -> Vec { + self.call::("takeReplies").into_bytes() + } + + fn resize(&mut self, cols: u16, rows: u16) { + let _ = self.ctx.with(|ctx| -> rquickjs::Result<()> { + let emu: Object = ctx.globals().get("__emu")?; + emu.get::<_, Function>("resize")?.call((cols, rows)) + }); + self.cols = cols; + self.rows = rows; + } + + fn size(&self) -> (u16, u16) { + (self.cols, self.rows) + } + + fn cursor(&self) -> (u16, u16) { + let x = self.call::("cursorX").max(0) as u16; + let y = self.call::("cursorY").max(0) as u16; + ( + x.min(self.cols.saturating_sub(1)), + y.min(self.rows.saturating_sub(1)), + ) + } + + fn viewable_rows(&self) -> Vec> { + self.rows_in_range(false) + } + + fn full_rows(&self) -> Vec> { + self.rows_in_range(true) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + crate::emulator_conformance_tests!(|c, r, s| Box::new(XtermJsEmu::new(c, r, s).unwrap())); +} From f65018068ab89d40b54c0e5e1ab36235e8135ce5 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Tue, 4 Aug 2026 12:12:04 -0400 Subject: [PATCH 2/3] feat(session): let a session choose its terminal backend Adds `Backend`, threaded from the wire protocol through `Session::open` to the single place an emulator was constructed. `--backend` is accepted on `open` and `run`, and as a `backend` option in the JS and Python bindings; `state` reports the backend in use so a client can confirm what it got. The field is optional everywhere and defaults to alacritty, so clients released before backend selection existed keep deserializing and keep getting the emulator they already had. The emulator is built before the PTY is spawned: a backend that cannot start is then a plain error rather than a live child process to clean up. Only the xtermjs path is covered by a new end-to-end test, since every other test in that file already runs a session on the default backend and each one spawns a real daemon. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Ayman Bagabas --- README.md | 29 ++++- SKILL.md | 13 +- bindings/js/src/client.ts | 6 + bindings/js/src/index.ts | 1 + bindings/js/src/types.ts | 23 +++- bindings/python/src/shell_use/client.py | 6 + crates/shell-use-cli/src/cli.rs | 24 ++++ crates/shell-use-cli/src/main.rs | 4 + .../shell-use-cli/tests/session_lifecycle.rs | 39 ++++++ crates/shell-use/src/engine.rs | 19 ++- crates/shell-use/src/protocol.rs | 22 ++++ crates/shell-use/src/session.rs | 19 ++- crates/shell-use/src/terminal/backend.rs | 122 ++++++++++++++++++ crates/shell-use/src/terminal/mod.rs | 1 + 14 files changed, 315 insertions(+), 13 deletions(-) create mode 100644 crates/shell-use/src/terminal/backend.rs diff --git a/README.md b/README.md index a6cc424..f463210 100644 --- a/README.md +++ b/README.md @@ -161,7 +161,7 @@ prints a session's effective timeouts. | Command | Description | | ------------------------------------------------------------ | ------------------------------------------- | -| `open [--shell S] [--cols N --rows N] [--cwd D] [--env K=V] [--timeout- MS]` | Spawn a shell session. | +| `open [--shell S] [--backend B] [--cols N --rows N] [--cwd D] [--env K=V] [--timeout- MS]` | Spawn a shell session. | | `run [args...]` | Spawn a session running a program directly. | | `sessions` | List active sessions. | | `close [--all]` | Close the current session (or all). | @@ -306,12 +306,37 @@ With `--json`, failures also carry a `"kind"` field (`assertion`/`usage`/`no_ses - nushell - cmd +## Terminal backends + +A session runs on one of two emulators, chosen at open time with `--backend`: + +| Backend | Notes | +| ------------------ | ---------------------------------------------------------------------- | +| `alacritty` | Default. Native, no interpreter. | +| `xtermjs` | `@xterm/headless` on an embedded QuickJS. Matches what VS Code's terminal shows. | + +```bash +shell-use open --backend xtermjs +shell-use run --backend xtermjs -- htop +``` + +Both backends pass the same conformance suite, so `expect`, `snapshot`, and the +SVG renderer behave identically on either. Pick `xtermjs` when the question is +specifically "does this look right in VS Code". Neither backend needs Node +installed: the xterm.js bundle is embedded in the binary. + +Two differences are inherent to the emulators rather than to this wiring: + +- Only `xtermjs` reports the `blink` attribute; alacritty parses SGR 5 and + discards it. +- Only `alacritty` keeps an underline color on a cell it is not underlining. + ## Comparison | | shell-use | [tui-use](https://github.com/onesuper/tui-use) | [terminal-use](https://github.com/flipbit03/terminal-use) | | ------------------------------------ | ------------------------------------------------ | ---------------------------------------------- | --------------------------------------------------------- | | Language | Rust | TypeScript/Node | Rust | -| Emulator | alacritty | xterm (headless) | alacritty | +| Emulator | alacritty or xterm.js, per session | xterm (headless) | alacritty | | Shell command tracking | ✅ command boundaries, exit codes, cwd | ❌ | ❌ | | Testing / snapshots | ✅ `expect` text / output / exit-code / snapshot | ❌ | ❌ | | Color & per-cell attributes | ✅ fg/bg, ANSI-256/hex/rgb, `cells` | ❌ plain text (+ highlights) | via PNG | diff --git a/SKILL.md b/SKILL.md index 717ba02..a0499cc 100644 --- a/SKILL.md +++ b/SKILL.md @@ -60,7 +60,7 @@ without parsing text: | Command | Description | | --- | --- | -| `open [--shell S] [--cols N] [--rows N] [--cwd D] [--env K=V]...` | Spawn a shell session (auto-starts the daemon). `--env` is repeatable. | +| `open [--shell S] [--backend B] [--cols N] [--rows N] [--cwd D] [--env K=V]...` | Spawn a shell session (auto-starts the daemon). `--env` is repeatable. | | `run [args...] [--cols N] [--rows N] [--cwd D] [--env K=V]...` | Spawn a session running a program directly (no shell). | | `sessions` | List active sessions. | | `close [--all]` | Close the current session (or every session with `--all`). | @@ -299,6 +299,17 @@ of `ShellUseError`. On its first call a client also checks that the daemon's version matches the package and raises `VersionMismatchError` if they differ; stop the daemon (`daemon_stop`) so it restarts on the matching binary. +## Terminal backends + +`--backend B` picks the emulator a session runs on, on both `open` and `run`: +`alacritty` (default, native) or `xtermjs` (`@xterm/headless` on an embedded +QuickJS, matching VS Code's terminal). Node is not required for either. + +Both pass the same conformance suite, so assertions and screenshots behave the +same on either. Two emulator-level differences remain: only `xtermjs` reports +`blink`, and only `alacritty` keeps an underline color on a cell it is not +underlining. `state` reports the backend in use. + ## Supported shells & integration `open --shell S` accepts: `bash`, `zsh`, `fish`, `powershell`, `pwsh`, `cmd`, diff --git a/bindings/js/src/client.ts b/bindings/js/src/client.ts index f88b8ee..a69090f 100644 --- a/bindings/js/src/client.ts +++ b/bindings/js/src/client.ts @@ -296,6 +296,9 @@ export class ShellUse { cwd: opts.cwd ?? null, env: envPairs(opts.env), }; + if (opts.backend !== undefined) { + payload.backend = opts.backend; + } if (opts.waitReady !== undefined) { payload.wait_ready = opts.waitReady; } @@ -316,6 +319,9 @@ export class ShellUse { cwd: opts.cwd ?? null, env: envPairs(opts.env), }; + if (opts.backend !== undefined) { + payload.backend = opts.backend; + } if (opts.waitReady !== undefined) { payload.wait_ready = opts.waitReady; } diff --git a/bindings/js/src/index.ts b/bindings/js/src/index.ts index 3340719..e38a261 100644 --- a/bindings/js/src/index.ts +++ b/bindings/js/src/index.ts @@ -25,6 +25,7 @@ export type { ErrorKind } from "./errors.js"; export { VERSION } from "./version.js"; export type { ArtifactOptions, + Backend, Cell, ClientOptions, Color, diff --git a/bindings/js/src/types.ts b/bindings/js/src/types.ts index 9c5dfc5..cc2df5b 100644 --- a/bindings/js/src/types.ts +++ b/bindings/js/src/types.ts @@ -20,6 +20,14 @@ export type Shell = | "elvish" | "nushell"; +/** + * The terminal emulator a session runs on. Both pass the same conformance + * suite, so this selects whose reading of an ambiguous sequence you see, not + * which features you get. Pick `"xtermjs"` to match what VS Code's terminal + * would show. Defaults to `"alacritty"`. + */ +export type Backend = "alacritty" | "xtermjs"; + export interface Cursor { x: number; y: number; @@ -43,21 +51,26 @@ export interface Cell { inverse: boolean; invisible: boolean; strike: boolean; - /** Always `false` from the alacritty backend, which cannot report blink. */ + /** Only the `xtermjs` backend reports blink; `alacritty` always says `false`. */ blink: boolean; /** Shorthand for `underline_style !== "none"`. */ underline: boolean; underline_style: UnderlineStyle; /** - * `"default"` means the underline follows the text color. Tracked - * independently of `underline_style`, so a cell that set SGR 58 without an - * underline still reports the color it would use. + * `"default"` means the underline follows the text color. + * + * On the `alacritty` backend this is tracked independently of + * `underline_style`, so a cell that set SGR 58 without an underline still + * reports the color it would use. The `xtermjs` backend discards the color + * for a cell it is not drawing an underline on, and reports `"default"`. */ underline_color: Color; } export interface State { session_shell: string | null; + /** The emulator this session is running on. */ + backend: Backend; cols: number; rows: number; cursor: Cursor; @@ -104,6 +117,8 @@ export interface SpawnOptions { waitReady?: boolean; retries?: number; timeouts?: Timeouts; + /** Emulator to run the session on; defaults to `"alacritty"`. */ + backend?: Backend; } export interface Timeouts { diff --git a/bindings/python/src/shell_use/client.py b/bindings/python/src/shell_use/client.py index 2dd4c99..adc42e3 100644 --- a/bindings/python/src/shell_use/client.py +++ b/bindings/python/src/shell_use/client.py @@ -251,6 +251,7 @@ async def open( self, *, shell: Optional[str] = None, + backend: Optional[str] = None, cols: int = cfg.DEFAULT_COLS, rows: int = cfg.DEFAULT_ROWS, cwd: Optional[str] = None, @@ -268,6 +269,8 @@ async def open( "cwd": cwd, "env": env_pairs(env), } # type: Dict[str, Any] + if backend is not None: + payload["backend"] = backend if wait_ready is not None: payload["wait_ready"] = wait_ready session_timeouts = cfg.session_timeouts_payload(timeouts) @@ -279,6 +282,7 @@ async def run( self, program: str, *args: str, + backend: Optional[str] = None, cols: int = cfg.DEFAULT_COLS, rows: int = cfg.DEFAULT_ROWS, cwd: Optional[str] = None, @@ -296,6 +300,8 @@ async def run( "cwd": cwd, "env": env_pairs(env), } # type: Dict[str, Any] + if backend is not None: + payload["backend"] = backend if wait_ready is not None: payload["wait_ready"] = wait_ready session_timeouts = cfg.session_timeouts_payload(timeouts) diff --git a/crates/shell-use-cli/src/cli.rs b/crates/shell-use-cli/src/cli.rs index e7198d9..8bfa765 100644 --- a/crates/shell-use-cli/src/cli.rs +++ b/crates/shell-use-cli/src/cli.rs @@ -3,6 +3,24 @@ use clap::{Args, Parser, Subcommand}; use shell_use::config::{DEFAULT_COLS, DEFAULT_ROWS}; use shell_use::protocol::TimeoutDefaults; use shell_use::shell::Shell; +use shell_use::terminal::backend::Backend; + +#[derive(Clone, Copy, clap::ValueEnum)] +#[clap(rename_all = "lowercase")] +pub enum BackendArg { + Alacritty, + #[clap(name = "xtermjs", alias = "xterm.js")] + XtermJs, +} + +impl From for Backend { + fn from(backend: BackendArg) -> Self { + match backend { + BackendArg::Alacritty => Backend::Alacritty, + BackendArg::XtermJs => Backend::XtermJs, + } + } +} #[derive(Clone, Copy, clap::ValueEnum)] #[clap(rename_all = "lowercase")] @@ -94,6 +112,9 @@ pub enum Command { /// Shell to launch (defaults to the platform shell). #[arg(long, value_enum)] shell: Option, + /// Terminal emulator to run the session on (defaults to alacritty). + #[arg(long, value_enum)] + backend: Option, /// Terminal width in columns. #[arg(long, default_value_t = DEFAULT_COLS)] cols: u16, @@ -123,6 +144,9 @@ pub enum Command { /// Arguments passed to the program. #[arg(trailing_var_arg = true, allow_hyphen_values = true)] args: Vec, + /// Terminal emulator to run the session on (defaults to alacritty). + #[arg(long, value_enum)] + backend: Option, /// Terminal width in columns. #[arg(long, default_value_t = DEFAULT_COLS)] cols: u16, diff --git a/crates/shell-use-cli/src/main.rs b/crates/shell-use-cli/src/main.rs index 554af0e..123de7b 100644 --- a/crates/shell-use-cli/src/main.rs +++ b/crates/shell-use-cli/src/main.rs @@ -126,6 +126,7 @@ fn build_request(command: Command) -> anyhow::Result { let req = match command { Command::Open { shell, + backend, cols, rows, cwd, @@ -136,6 +137,7 @@ fn build_request(command: Command) -> anyhow::Result { } => Request::Open { shell: shell.map(Into::into), program: None, + backend: backend.map(Into::into), cols, rows, cwd, @@ -146,6 +148,7 @@ fn build_request(command: Command) -> anyhow::Result { Command::Run { program, args, + backend, cols, rows, cwd, @@ -159,6 +162,7 @@ fn build_request(command: Command) -> anyhow::Result { Request::Open { shell: None, program: Some(prog), + backend: backend.map(Into::into), cols, rows, cwd, diff --git a/crates/shell-use-cli/tests/session_lifecycle.rs b/crates/shell-use-cli/tests/session_lifecycle.rs index e67633d..975cbc7 100644 --- a/crates/shell-use-cli/tests/session_lifecycle.rs +++ b/crates/shell-use-cli/tests/session_lifecycle.rs @@ -273,6 +273,45 @@ fn state_reports_effective_timeouts() { ); } +/// A session runs on the backend it was opened with, and that backend drives a +/// real shell to the same visible result. The daemon is the only place the +/// selection is acted on, so a CLI flag that never reached `Session::open` +/// would still look correct everywhere else. +/// +/// Only `xtermjs` is exercised here: it is the path this flag adds, and every +/// other test in this file already runs a session on the default backend. +#[test] +fn a_session_runs_on_the_backend_it_asked_for() { + let sandbox = Sandbox::new("backend-select"); + sandbox.ok(&["open", "--backend", "xtermjs"]); + + let state = sandbox.ok(&["--json", "state"]); + assert!( + state.contains("\"backend\":\"xtermjs\""), + "state should report the xtermjs backend: {state}" + ); + + sandbox.ok(&["submit", "echo backend-ok"]); + sandbox.ok(&["wait", "command"]); + let text = sandbox.ok(&["text"]); + assert!( + text.contains("backend-ok"), + "the xtermjs backend should show the command's output: {text}" + ); +} + +/// An unknown backend is rejected at the CLI rather than silently falling +/// back to the default, which would hide the typo behind a passing run. +#[test] +fn an_unknown_backend_is_rejected() { + let sandbox = Sandbox::new("backend-unknown"); + let out = sandbox.run(&["open", "--backend", "ghostty"]); + assert!( + !out.status.success(), + "an unknown backend must not open a session" + ); +} + #[test] fn open_reports_the_daemon_pid_the_child_and_readiness() { let sandbox = Sandbox::new("open-payload"); diff --git a/crates/shell-use/src/engine.rs b/crates/shell-use/src/engine.rs index be5175b..95b2433 100644 --- a/crates/shell-use/src/engine.rs +++ b/crates/shell-use/src/engine.rs @@ -47,6 +47,7 @@ fn req_summary(req: &Request) -> String { Request::Open { shell, program, + backend, cols, rows, cwd, @@ -54,7 +55,7 @@ fn req_summary(req: &Request) -> String { wait_ready, timeouts, } => format!( - "Open {{ shell: {shell:?}, program: {program:?}, {cols}x{rows}, cwd: {cwd:?}, wait_ready: {wait_ready:?}, timeouts: {timeouts:?}, env: <{} vars> }}", + "Open {{ shell: {shell:?}, program: {program:?}, backend: {backend:?}, {cols}x{rows}, cwd: {cwd:?}, wait_ready: {wait_ready:?}, timeouts: {timeouts:?}, env: <{} vars> }}", env.len() ), other => format!("{other:?}"), @@ -82,6 +83,7 @@ impl Engine { Request::Open { shell, program, + backend, cols, rows, cwd, @@ -89,7 +91,17 @@ impl Engine { wait_ready, timeouts, } => ( - self.open(shell, program, cols, rows, cwd, env, wait_ready, timeouts), + self.open( + shell, + program, + backend.unwrap_or_default(), + cols, + rows, + cwd, + env, + wait_ready, + timeouts, + ), false, ), Request::Close => { @@ -109,6 +121,7 @@ impl Engine { &self, shell: Option, program: Option>, + backend: crate::terminal::backend::Backend, cols: u16, rows: u16, cwd: Option, @@ -119,6 +132,7 @@ impl Engine { match Session::open( shell, program.clone(), + backend, cols, rows, cwd, @@ -365,6 +379,7 @@ fn state(s: &Session) -> Response { let text = text_of(&st.emu.viewable_rows()); Response::with(json!({ "session_shell": s.shell.map(|sh| sh.as_str()), + "backend": s.backend.as_str(), "cols": cols, "rows": rows, "cursor": { "x": cx, "y": cy }, diff --git a/crates/shell-use/src/protocol.rs b/crates/shell-use/src/protocol.rs index 7865e10..8c2ebbb 100644 --- a/crates/shell-use/src/protocol.rs +++ b/crates/shell-use/src/protocol.rs @@ -35,6 +35,9 @@ pub enum Request { Open { shell: Option, program: Option>, + /// Which emulator to run the session on; `None` keeps the default. + #[serde(default)] + backend: Option, cols: u16, rows: u16, cwd: Option, @@ -293,6 +296,7 @@ mod tests { Request::Open { shell: None, program: None, + backend: None, cols: 80, rows: 30, cwd: None, @@ -311,11 +315,16 @@ mod tests { match req { Request::Open { wait_ready, + backend, cols, timeouts, .. } => { assert_eq!(wait_ready, None); + assert_eq!( + backend, None, + "a client that predates backend selection gets the default" + ); assert_eq!(cols, 80); assert_eq!( timeouts, @@ -327,6 +336,19 @@ mod tests { } } + /// The backend travels by its wire name, so a client can ask for one. + #[test] + fn open_carries_a_requested_backend() { + let raw = r#"{"kind":"open","shell":null,"program":null,"backend":"xtermjs", + "cols":80,"rows":30,"cwd":null,"env":[]}"#; + match serde_json::from_str::(raw).expect("deserialize open") { + Request::Open { backend, .. } => { + assert_eq!(backend, Some(crate::terminal::backend::Backend::XtermJs)) + } + other => panic!("expected Open, got {other:?}"), + } + } + /// Older clients' concrete `timeout_ms` must remain an explicit override. #[test] fn waits_accept_a_concrete_timeout_from_older_clients() { diff --git a/crates/shell-use/src/session.rs b/crates/shell-use/src/session.rs index 41cbd35..36f26c8 100644 --- a/crates/shell-use/src/session.rs +++ b/crates/shell-use/src/session.rs @@ -8,7 +8,7 @@ use std::time::Instant; use crate::logger::Logger; use crate::shell::{self, Shell}; -use crate::terminal::alacritty::AlacrittyEmu; +use crate::terminal::backend::Backend; use crate::terminal::emu::Emulator; use crate::terminal::integration::CommandTracker; use crate::terminal::pty::{Pty, SpawnOptions}; @@ -26,6 +26,7 @@ pub struct TermState { pub struct Session { pub shell: Option, + pub backend: Backend, pub cols: u16, pub rows: u16, /// Per-class timeout defaults for the lifetime of this session. @@ -49,6 +50,7 @@ impl Session { pub fn open( shell: Option, program: Option>, + backend: Backend, cols: u16, rows: u16, cwd: Option, @@ -57,6 +59,10 @@ impl Session { logger: Arc, recording_path: PathBuf, ) -> anyhow::Result { + // Built before the PTY is spawned: a backend that cannot start is a + // plain error here, rather than a live child process to clean up. + let emu = backend.build(cols, rows)?; + let (pty, reader) = if let Some(program) = &program { let (target, args) = program .split_first() @@ -76,7 +82,7 @@ impl Session { }; let state = Arc::new(Mutex::new(TermState { - emu: Box::new(AlacrittyEmu::new(cols, rows, 5_000)), + emu, tracker: CommandTracker::new(), last_change: Instant::now(), awaiting_start: None, @@ -133,12 +139,17 @@ impl Session { }); logger.event(&format!( - "session open shell={:?} program={:?} {}x{}", - shell, program, cols, rows + "session open shell={:?} program={:?} backend={} {}x{}", + shell, + program, + backend.as_str(), + cols, + rows )); Ok(Session { shell, + backend, cols, rows, timeouts, diff --git a/crates/shell-use/src/terminal/backend.rs b/crates/shell-use/src/terminal/backend.rs new file mode 100644 index 0000000..65d0280 --- /dev/null +++ b/crates/shell-use/src/terminal/backend.rs @@ -0,0 +1,122 @@ +//! Backend selection: which terminal emulator a session runs on. + +use serde::{Deserialize, Serialize}; + +use crate::terminal::alacritty::AlacrittyEmu; +use crate::terminal::emu::Emulator; +use crate::terminal::xtermjs::XtermJsEmu; + +/// Scrollback retained by every session, in rows. +pub const SCROLLBACK: usize = 5_000; + +/// The emulator a session drives its PTY output through. +/// +/// Both backends pass the same conformance suite, so this picks which +/// emulator's interpretation of an ambiguous sequence a session sees, not +/// which features it gets. It exists because "does my TUI look right in +/// VS Code's terminal" is a question only xterm.js can answer. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum Backend { + #[default] + Alacritty, + #[serde(rename = "xtermjs", alias = "xterm.js", alias = "xterm")] + XtermJs, +} + +impl Backend { + pub fn as_str(self) -> &'static str { + match self { + Backend::Alacritty => "alacritty", + Backend::XtermJs => "xtermjs", + } + } + + pub const ALL: [Backend; 2] = [Backend::Alacritty, Backend::XtermJs]; + + pub fn build(self, cols: u16, rows: u16) -> anyhow::Result> { + Ok(match self { + Backend::Alacritty => Box::new(AlacrittyEmu::new(cols, rows, SCROLLBACK)), + Backend::XtermJs => Box::new(XtermJsEmu::new(cols, rows, SCROLLBACK)?), + }) + } +} + +impl std::str::FromStr for Backend { + type Err = String; + + fn from_str(s: &str) -> Result { + match s.trim().to_ascii_lowercase().as_str() { + "alacritty" => Ok(Backend::Alacritty), + "xtermjs" | "xterm.js" | "xterm" => Ok(Backend::XtermJs), + other => Err(format!( + "unknown backend {other:?}; expected one of: alacritty, xtermjs" + )), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn backend_names_round_trip() { + for b in Backend::ALL { + assert_eq!(b.as_str().parse::(), Ok(b)); + } + } + + #[test] + fn xtermjs_accepts_the_spellings_people_actually_type() { + for s in ["xtermjs", "xterm.js", "xterm", "XtermJS", " xterm.js "] { + assert_eq!(s.parse::(), Ok(Backend::XtermJs), "parsing {s:?}"); + } + } + + #[test] + fn an_unknown_backend_names_the_valid_ones() { + let err = "ghostty".parse::().unwrap_err(); + assert!( + err.contains("alacritty") && err.contains("xtermjs"), + "{err}" + ); + } + + #[test] + fn the_default_is_alacritty_so_existing_sessions_are_unchanged() { + assert_eq!(Backend::default(), Backend::Alacritty); + } + + /// The wire spelling is what clients send; a rename would silently break + /// every already-published binding. + #[test] + fn backends_serialize_to_their_wire_names() { + assert_eq!( + serde_json::to_string(&Backend::XtermJs).unwrap(), + "\"xtermjs\"" + ); + assert_eq!( + serde_json::to_string(&Backend::Alacritty).unwrap(), + "\"alacritty\"" + ); + assert_eq!( + serde_json::from_str::("\"xterm.js\"").unwrap(), + Backend::XtermJs + ); + } + + /// Both backends must actually construct; a typo in the JS shim would + /// otherwise only surface when someone opened a session. + #[test] + fn every_backend_builds_a_working_emulator() { + for b in Backend::ALL { + let mut emu = b + .build(20, 3) + .unwrap_or_else(|e| panic!("{}: {e}", b.as_str())); + emu.process(b"hi"); + assert_eq!(emu.size(), (20, 3), "{}", b.as_str()); + assert_eq!(emu.viewable_rows()[0][0].ch, "h", "{}", b.as_str()); + } + } +} diff --git a/crates/shell-use/src/terminal/mod.rs b/crates/shell-use/src/terminal/mod.rs index 10e000e..c49f915 100644 --- a/crates/shell-use/src/terminal/mod.rs +++ b/crates/shell-use/src/terminal/mod.rs @@ -1,4 +1,5 @@ pub mod alacritty; +pub mod backend; pub mod cell; #[cfg(test)] pub mod conformance; From 7b1c56f2da139ff385bcb6642c52dc504df5e597 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Tue, 4 Aug 2026 13:49:57 -0400 Subject: [PATCH 3/3] fix(terminal): correct xterm.js cell mapping and bound its grid reads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four independent reviews of the new backend turned up defects that a passing conformance suite did not catch, because the suite did not yet pin the contracts they broke. Each fix below has a new conformance case, so both backends are now held to it. Cell mapping: Width alone does not identify a wide-char continuation. xterm.js also reports width 0 for a genuine zero-width grapheme that had no base character to combine with — a lone combining mark, ZWSP, ZWJ, or a variation selector at the start of a row. Reading width alone discarded the grapheme and, because a continuation serializes to nothing, left the row one column short of the grid, shifting every snapshot and screenshot after it. Two bytes were enough to trigger it. A continuation is now the cell that is both zero-width and empty. SGR 59 does not clear xterm.js's underline-color record: it stores a sentinel that reads back through the public getters as RGB white, so resetting the underline color painted one. The sentinel is indistinguishable from a real `58;2;255;255;255` at that layer, so the common case wins and the shim collapses it to unset. The headless bundle ships only the Unicode 6 width tables, which measure astral emoji as one column where alacritty measures two, moving the reported column of everything after an emoji on the line. It now loads the Unicode 11 provider, which was chosen by measurement rather than by recency: of the four available width tables it is the only one that agrees with alacritty on emoji, ZWJ sequences, skin-tone modifiers, flags, and CJK alike. The vendored assets grew a README recording that comparison so the next person does not "upgrade" it to a worse match. Grid reads: `pack` built one JS array of six boxed numbers per cell, which at the 5,000-row scrollback is 2.4 million of them per call — large enough to cost tens of megabytes and small enough that QuickJS did not collect it, so `expect --full` grew the daemon by hundreds of megabytes as it polled. Rows are now read in batches, and cells whose attributes are all default take one getter call instead of nineteen. A ten-call full-scrollback read goes from +376 MB to +27 MB, alongside alacritty's +21 MB, and from 389 ms to 144 ms per call. Sizes: xterm.js clamps to a 2x1 minimum while the backend cached the size it had asked for, so the decoder chunked the packed grid by the wrong width and returned twice as many rows as the terminal had — with `size()` reporting the size that did not exist. It now reads the applied size back. At zero columns the same code divided by zero, which kills the daemon outright since requests are served on its main thread. Since alacritty panics on a zero-width resize too, in its own grid arithmetic, the size is clamped once at the seam so neither backend is asked for a grid it cannot represent and both report the same clamped result. Also aligns `--backend xterm`, which the wire accepted and the CLI rejected, and adds the missing `backend` field to the Python `State`. The TypeScript one becomes optional, since a newer client may be talking to a daemon that predates it. Two divergences are documented rather than fixed, both in README and in the conformance cases that stop short of pinning them: narrowing a session reflows on alacritty and truncates on xterm.js, and a combining mark with no base is dropped by one and given a column by the other. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Ayman Bagabas --- README.md | 11 +- bindings/js/src/types.ts | 4 +- bindings/python/src/shell_use/types.py | 3 + crates/shell-use-cli/src/cli.rs | 2 +- crates/shell-use/assets/xterm/README.md | 40 +++++ .../shell-use/assets/xterm/addon-unicode11.js | 2 + crates/shell-use/assets/xterm/shim.js | 30 +++- crates/shell-use/src/terminal/alacritty.rs | 3 + crates/shell-use/src/terminal/backend.rs | 17 ++ crates/shell-use/src/terminal/conformance.rs | 153 +++++++++++++++++ crates/shell-use/src/terminal/xtermjs.rs | 154 ++++++++++++------ 11 files changed, 368 insertions(+), 51 deletions(-) create mode 100644 crates/shell-use/assets/xterm/README.md create mode 100644 crates/shell-use/assets/xterm/addon-unicode11.js diff --git a/README.md b/README.md index f463210..a35bdd5 100644 --- a/README.md +++ b/README.md @@ -325,11 +325,20 @@ SVG renderer behave identically on either. Pick `xtermjs` when the question is specifically "does this look right in VS Code". Neither backend needs Node installed: the xterm.js bundle is embedded in the binary. -Two differences are inherent to the emulators rather than to this wiring: +Differences that are inherent to the emulators rather than to this wiring: - Only `xtermjs` reports the `blink` attribute; alacritty parses SGR 5 and discards it. - Only `alacritty` keeps an underline color on a cell it is not underlining. +- **Narrowing a session reflows on `alacritty` and truncates on `xtermjs`.** + Resizing `abcdefghijklmnop` from 10 columns to 6 gives `abcdef/ghijkl/mnop` + on alacritty and `abcdef/klmnop` on xterm.js, which drops what no longer + fits. Avoid narrowing a session you still need the scrollback of. +- Reading the full scrollback (`--full`) is roughly 10x slower on `xtermjs`, + since every cell crosses a JS boundary. The visible screen is unaffected. + +`--cols 0` is not a usable size on either emulator, so any request below 2x1 is +clamped to it and reported back at the clamped size. ## Comparison diff --git a/bindings/js/src/types.ts b/bindings/js/src/types.ts index cc2df5b..67d911a 100644 --- a/bindings/js/src/types.ts +++ b/bindings/js/src/types.ts @@ -69,8 +69,8 @@ export interface Cell { export interface State { session_shell: string | null; - /** The emulator this session is running on. */ - backend: Backend; + /** The emulator this session is running on; absent from older daemons. */ + backend?: Backend; cols: number; rows: number; cursor: Cursor; diff --git a/bindings/python/src/shell_use/types.py b/bindings/python/src/shell_use/types.py index 59fecf2..2a8aa7c 100644 --- a/bindings/python/src/shell_use/types.py +++ b/bindings/python/src/shell_use/types.py @@ -57,6 +57,7 @@ class State: ready: bool text: str session_shell: Optional[str] + backend: str @classmethod def from_dict(cls, d: Dict[str, Any]) -> "State": @@ -71,4 +72,6 @@ def from_dict(cls, d: Dict[str, Any]) -> "State": ready=d.get("ready", False), text=d.get("text", ""), session_shell=d.get("session_shell"), + # Absent when talking to a daemon that predates backend selection. + backend=d.get("backend", "alacritty"), ) diff --git a/crates/shell-use-cli/src/cli.rs b/crates/shell-use-cli/src/cli.rs index 8bfa765..de71ff0 100644 --- a/crates/shell-use-cli/src/cli.rs +++ b/crates/shell-use-cli/src/cli.rs @@ -9,7 +9,7 @@ use shell_use::terminal::backend::Backend; #[clap(rename_all = "lowercase")] pub enum BackendArg { Alacritty, - #[clap(name = "xtermjs", alias = "xterm.js")] + #[clap(name = "xtermjs", alias = "xterm.js", alias = "xterm")] XtermJs, } diff --git a/crates/shell-use/assets/xterm/README.md b/crates/shell-use/assets/xterm/README.md new file mode 100644 index 0000000..281175a --- /dev/null +++ b/crates/shell-use/assets/xterm/README.md @@ -0,0 +1,40 @@ +# Vendored xterm.js assets + +Compiled into the `shell-use` binary by `crates/shell-use/src/terminal/xtermjs.rs` +so the xterm.js backend needs no Node.js at runtime. + +| File | Source | Version | License | +| ---- | ------ | ------- | ------- | +| `xterm-headless.js` | [`@xterm/headless`](https://www.npmjs.com/package/@xterm/headless) | 6.0.0 | MIT | +| `addon-unicode11.js` | [`@xterm/addon-unicode11`](https://www.npmjs.com/package/@xterm/addon-unicode11) | 0.9.0 | MIT | +| `LICENSE` | xterm.js | — | MIT | + +`shim.js` is shell-use's own code, not vendored. + +## Why the unicode11 addon + +The headless bundle ships only the Unicode 6 width tables, which measure astral +emoji as one column. alacritty measures them as two, so without this a line +containing an emoji reports every following cell in a different column on the +two backends. Unicode 11 restores the pair. + +Newer is not better here. Measured cursor column after each sequence: + +| Input | alacritty | v6 | **v11** | v15 | v15-graphemes | +| ----- | --------- | -- | ------- | --- | ------------- | +| `🙂X` | 3 | 2 | **3** | 3 | 3 | +| `👨‍👩X` | 5 | 3 | **5** | 6 | 3 | +| `👍🏽X` | 5 | 3 | **5** | 5 | 3 | +| `🇺🇸X` | 3 | 3 | **3** | 3 | 3 | +| `你X` | 3 | 3 | **3** | 3 | 3 | + +Only v11 agrees with alacritty on every case. `@xterm/addon-unicode-graphemes` +(v15 / v15-graphemes) is also marked experimental by its own package +description, and needs an `atob` the QuickJS host does not have. + +## Updating + +Re-download the bundle and the addon at the pinned versions and drop them in +unchanged. Then run `cargo test -p shell-use conformance`, which checks both +backends against the same contract, and re-measure the table above before +changing a version. diff --git a/crates/shell-use/assets/xterm/addon-unicode11.js b/crates/shell-use/assets/xterm/addon-unicode11.js new file mode 100644 index 0000000..941130a --- /dev/null +++ b/crates/shell-use/assets/xterm/addon-unicode11.js @@ -0,0 +1,2 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Unicode11Addon=t():e.Unicode11Addon=t()}(globalThis,(()=>(()=>{"use strict";var e={384:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeV11=void 0;const r=s(765),n=[[768,879],[1155,1161],[1425,1469],[1471,1471],[1473,1474],[1476,1477],[1479,1479],[1536,1541],[1552,1562],[1564,1564],[1611,1631],[1648,1648],[1750,1757],[1759,1764],[1767,1768],[1770,1773],[1807,1807],[1809,1809],[1840,1866],[1958,1968],[2027,2035],[2045,2045],[2070,2073],[2075,2083],[2085,2087],[2089,2093],[2137,2139],[2259,2306],[2362,2362],[2364,2364],[2369,2376],[2381,2381],[2385,2391],[2402,2403],[2433,2433],[2492,2492],[2497,2500],[2509,2509],[2530,2531],[2558,2558],[2561,2562],[2620,2620],[2625,2626],[2631,2632],[2635,2637],[2641,2641],[2672,2673],[2677,2677],[2689,2690],[2748,2748],[2753,2757],[2759,2760],[2765,2765],[2786,2787],[2810,2815],[2817,2817],[2876,2876],[2879,2879],[2881,2884],[2893,2893],[2902,2902],[2914,2915],[2946,2946],[3008,3008],[3021,3021],[3072,3072],[3076,3076],[3134,3136],[3142,3144],[3146,3149],[3157,3158],[3170,3171],[3201,3201],[3260,3260],[3263,3263],[3270,3270],[3276,3277],[3298,3299],[3328,3329],[3387,3388],[3393,3396],[3405,3405],[3426,3427],[3530,3530],[3538,3540],[3542,3542],[3633,3633],[3636,3642],[3655,3662],[3761,3761],[3764,3772],[3784,3789],[3864,3865],[3893,3893],[3895,3895],[3897,3897],[3953,3966],[3968,3972],[3974,3975],[3981,3991],[3993,4028],[4038,4038],[4141,4144],[4146,4151],[4153,4154],[4157,4158],[4184,4185],[4190,4192],[4209,4212],[4226,4226],[4229,4230],[4237,4237],[4253,4253],[4448,4607],[4957,4959],[5906,5908],[5938,5940],[5970,5971],[6002,6003],[6068,6069],[6071,6077],[6086,6086],[6089,6099],[6109,6109],[6155,6158],[6277,6278],[6313,6313],[6432,6434],[6439,6440],[6450,6450],[6457,6459],[6679,6680],[6683,6683],[6742,6742],[6744,6750],[6752,6752],[6754,6754],[6757,6764],[6771,6780],[6783,6783],[6832,6846],[6912,6915],[6964,6964],[6966,6970],[6972,6972],[6978,6978],[7019,7027],[7040,7041],[7074,7077],[7080,7081],[7083,7085],[7142,7142],[7144,7145],[7149,7149],[7151,7153],[7212,7219],[7222,7223],[7376,7378],[7380,7392],[7394,7400],[7405,7405],[7412,7412],[7416,7417],[7616,7673],[7675,7679],[8203,8207],[8234,8238],[8288,8292],[8294,8303],[8400,8432],[11503,11505],[11647,11647],[11744,11775],[12330,12333],[12441,12442],[42607,42610],[42612,42621],[42654,42655],[42736,42737],[43010,43010],[43014,43014],[43019,43019],[43045,43046],[43204,43205],[43232,43249],[43263,43263],[43302,43309],[43335,43345],[43392,43394],[43443,43443],[43446,43449],[43452,43453],[43493,43493],[43561,43566],[43569,43570],[43573,43574],[43587,43587],[43596,43596],[43644,43644],[43696,43696],[43698,43700],[43703,43704],[43710,43711],[43713,43713],[43756,43757],[43766,43766],[44005,44005],[44008,44008],[44013,44013],[64286,64286],[65024,65039],[65056,65071],[65279,65279],[65529,65531]],i=[[66045,66045],[66272,66272],[66422,66426],[68097,68099],[68101,68102],[68108,68111],[68152,68154],[68159,68159],[68325,68326],[68900,68903],[69446,69456],[69633,69633],[69688,69702],[69759,69761],[69811,69814],[69817,69818],[69821,69821],[69837,69837],[69888,69890],[69927,69931],[69933,69940],[70003,70003],[70016,70017],[70070,70078],[70089,70092],[70191,70193],[70196,70196],[70198,70199],[70206,70206],[70367,70367],[70371,70378],[70400,70401],[70459,70460],[70464,70464],[70502,70508],[70512,70516],[70712,70719],[70722,70724],[70726,70726],[70750,70750],[70835,70840],[70842,70842],[70847,70848],[70850,70851],[71090,71093],[71100,71101],[71103,71104],[71132,71133],[71219,71226],[71229,71229],[71231,71232],[71339,71339],[71341,71341],[71344,71349],[71351,71351],[71453,71455],[71458,71461],[71463,71467],[71727,71735],[71737,71738],[72148,72151],[72154,72155],[72160,72160],[72193,72202],[72243,72248],[72251,72254],[72263,72263],[72273,72278],[72281,72283],[72330,72342],[72344,72345],[72752,72758],[72760,72765],[72767,72767],[72850,72871],[72874,72880],[72882,72883],[72885,72886],[73009,73014],[73018,73018],[73020,73021],[73023,73029],[73031,73031],[73104,73105],[73109,73109],[73111,73111],[73459,73460],[78896,78904],[92912,92916],[92976,92982],[94031,94031],[94095,94098],[113821,113822],[113824,113827],[119143,119145],[119155,119170],[119173,119179],[119210,119213],[119362,119364],[121344,121398],[121403,121452],[121461,121461],[121476,121476],[121499,121503],[121505,121519],[122880,122886],[122888,122904],[122907,122913],[122915,122916],[122918,122922],[123184,123190],[123628,123631],[125136,125142],[125252,125258],[917505,917505],[917536,917631],[917760,917999]],o=[[4352,4447],[8986,8987],[9001,9002],[9193,9196],[9200,9200],[9203,9203],[9725,9726],[9748,9749],[9800,9811],[9855,9855],[9875,9875],[9889,9889],[9898,9899],[9917,9918],[9924,9925],[9934,9934],[9940,9940],[9962,9962],[9970,9971],[9973,9973],[9978,9978],[9981,9981],[9989,9989],[9994,9995],[10024,10024],[10060,10060],[10062,10062],[10067,10069],[10071,10071],[10133,10135],[10160,10160],[10175,10175],[11035,11036],[11088,11088],[11093,11093],[11904,11929],[11931,12019],[12032,12245],[12272,12283],[12288,12329],[12334,12350],[12353,12438],[12443,12543],[12549,12591],[12593,12686],[12688,12730],[12736,12771],[12784,12830],[12832,12871],[12880,19903],[19968,42124],[42128,42182],[43360,43388],[44032,55203],[63744,64255],[65040,65049],[65072,65106],[65108,65126],[65128,65131],[65281,65376],[65504,65510]],a=[[94176,94179],[94208,100343],[100352,101106],[110592,110878],[110928,110930],[110948,110951],[110960,111355],[126980,126980],[127183,127183],[127374,127374],[127377,127386],[127488,127490],[127504,127547],[127552,127560],[127568,127569],[127584,127589],[127744,127776],[127789,127797],[127799,127868],[127870,127891],[127904,127946],[127951,127955],[127968,127984],[127988,127988],[127992,128062],[128064,128064],[128066,128252],[128255,128317],[128331,128334],[128336,128359],[128378,128378],[128405,128406],[128420,128420],[128507,128591],[128640,128709],[128716,128716],[128720,128722],[128725,128725],[128747,128748],[128756,128762],[128992,129003],[129293,129393],[129395,129398],[129402,129442],[129445,129450],[129454,129482],[129485,129535],[129648,129651],[129656,129658],[129664,129666],[129680,129685],[131072,196605],[196608,262141]];let l;function c(e,t){let s,r=0,n=t.length-1;if(et[n][1])return!1;for(;n>=r;)if(s=r+n>>1,e>t[s][1])r=s+1;else{if(!(es&&(s=e)}return r.UnicodeService.createPropertyValue(0,s,n)}}},546:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeV6=void 0;const r=s(765),n=[[768,879],[1155,1158],[1160,1161],[1425,1469],[1471,1471],[1473,1474],[1476,1477],[1479,1479],[1536,1539],[1552,1557],[1611,1630],[1648,1648],[1750,1764],[1767,1768],[1770,1773],[1807,1807],[1809,1809],[1840,1866],[1958,1968],[2027,2035],[2305,2306],[2364,2364],[2369,2376],[2381,2381],[2385,2388],[2402,2403],[2433,2433],[2492,2492],[2497,2500],[2509,2509],[2530,2531],[2561,2562],[2620,2620],[2625,2626],[2631,2632],[2635,2637],[2672,2673],[2689,2690],[2748,2748],[2753,2757],[2759,2760],[2765,2765],[2786,2787],[2817,2817],[2876,2876],[2879,2879],[2881,2883],[2893,2893],[2902,2902],[2946,2946],[3008,3008],[3021,3021],[3134,3136],[3142,3144],[3146,3149],[3157,3158],[3260,3260],[3263,3263],[3270,3270],[3276,3277],[3298,3299],[3393,3395],[3405,3405],[3530,3530],[3538,3540],[3542,3542],[3633,3633],[3636,3642],[3655,3662],[3761,3761],[3764,3769],[3771,3772],[3784,3789],[3864,3865],[3893,3893],[3895,3895],[3897,3897],[3953,3966],[3968,3972],[3974,3975],[3984,3991],[3993,4028],[4038,4038],[4141,4144],[4146,4146],[4150,4151],[4153,4153],[4184,4185],[4448,4607],[4959,4959],[5906,5908],[5938,5940],[5970,5971],[6002,6003],[6068,6069],[6071,6077],[6086,6086],[6089,6099],[6109,6109],[6155,6157],[6313,6313],[6432,6434],[6439,6440],[6450,6450],[6457,6459],[6679,6680],[6912,6915],[6964,6964],[6966,6970],[6972,6972],[6978,6978],[7019,7027],[7616,7626],[7678,7679],[8203,8207],[8234,8238],[8288,8291],[8298,8303],[8400,8431],[12330,12335],[12441,12442],[43014,43014],[43019,43019],[43045,43046],[64286,64286],[65024,65039],[65056,65059],[65279,65279],[65529,65531]],i=[[68097,68099],[68101,68102],[68108,68111],[68152,68154],[68159,68159],[119143,119145],[119155,119170],[119173,119179],[119210,119213],[119362,119364],[917505,917505],[917536,917631],[917760,917999]];let o;t.UnicodeV6=class{constructor(){if(this.version="6",!o){o=new Uint8Array(65536),o.fill(1),o[0]=0,o.fill(0,1,32),o.fill(0,127,160),o.fill(2,4352,4448),o[9001]=2,o[9002]=2,o.fill(2,11904,42192),o[12351]=1,o.fill(2,44032,55204),o.fill(2,63744,64256),o.fill(2,65040,65050),o.fill(2,65072,65136),o.fill(2,65280,65377),o.fill(2,65504,65511);for(let e=0;et[n][1])return!1;for(;n>=r;)if(s=r+n>>1,e>t[s][1])r=s+1;else{if(!(e=131072&&e<=196605||e>=196608&&e<=262141?2:1}charProperties(e,t){let s=this.wcwidth(e),n=0===s&&0!==t;if(n){const e=r.UnicodeService.extractWidth(t);0===e?n=!1:e>s&&(s=e)}return r.UnicodeService.createPropertyValue(0,s,n)}}},765:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeService=void 0;const r=s(546),n=s(276);class i{static extractShouldJoin(e){return!!(1&e)}static extractWidth(e){return e>>1&3}static extractCharKind(e){return e>>3}static createPropertyValue(e,t,s=!1){return(16777215&e)<<3|(3&t)<<1|(s?1:0)}constructor(){this._providers=Object.create(null),this._active="",this._onChange=new n.Emitter,this.onChange=this._onChange.event;const e=new r.UnicodeV6;this.register(e),this._active=e.version,this._activeProvider=e}dispose(){this._onChange.dispose()}get versions(){return Object.keys(this._providers)}get activeVersion(){return this._active}set activeVersion(e){if(!this._providers[e])throw new Error(`unknown Unicode version "${e}"`);this._active=e,this._activeProvider=this._providers[e],this._onChange.fire(e)}register(e){this._providers[e.version]=e}wcwidth(e){return this._activeProvider.wcwidth(e)}getStringCellWidth(e){let t=0,s=0;const r=e.length;for(let n=0;n=r)return t+this.wcwidth(o);const s=e.charCodeAt(n);56320<=s&&s<=57343?o=1024*(o-55296)+s-56320+65536:t+=this.wcwidth(s)}const a=this.charProperties(o,s);let l=i.extractWidth(a);i.extractShouldJoin(a)&&(l-=i.extractWidth(s)),t+=l,s=a}return t}charProperties(e,t){return this._activeProvider.charProperties(e,t)}}t.UnicodeService=i},732:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Permutation=t.CallbackIterable=t.ArrayQueue=t.booleanComparator=t.numberComparator=t.CompareResult=void 0,t.tail=function(e,t=0){return e[e.length-(1+t)]},t.tail2=function(e){if(0===e.length)throw new Error("Invalid tail call");return[e.slice(0,e.length-1),e[e.length-1]]},t.equals=function(e,t,s=(e,t)=>e===t){if(e===t)return!0;if(!e||!t)return!1;if(e.length!==t.length)return!1;for(let r=0,n=e.length;rs(e[r],t)))},t.binarySearch2=i,t.quickSelect=function e(t,s,r){if((t|=0)>=s.length)throw new TypeError("invalid index");const n=s[Math.floor(s.length*Math.random())],i=[],o=[],a=[];for(const e of s){const t=r(e,n);t<0?i.push(e):t>0?o.push(e):a.push(e)}return t{(async()=>{const o=e.length,l=e.slice(0,s).sort(t);for(let c=s,h=Math.min(s+n,o);cs&&await new Promise((e=>setTimeout(e))),i&&i.isCancellationRequested)throw new r.CancellationError;a(e,t,l,c,h)}return l})().then(o,l)}))},t.coalesce=function(e){return e.filter((e=>!!e))},t.coalesceInPlace=function(e){let t=0;for(let s=0;s0},t.distinct=function(e,t=e=>e){const s=new Set;return e.filter((e=>{const r=t(e);return!s.has(r)&&(s.add(r),!0)}))},t.uniqueFilter=function(e){const t=new Set;return s=>{const r=e(s);return!t.has(r)&&(t.add(r),!0)}},t.firstOrDefault=function(e,t){return e.length>0?e[0]:t},t.lastOrDefault=function(e,t){return e.length>0?e[e.length-1]:t},t.commonPrefixLength=function(e,t,s=(e,t)=>e===t){let r=0;for(let n=0,i=Math.min(e.length,t.length);nt;e--)r.push(e);return r},t.index=function(e,t,s){return e.reduce(((e,r)=>(e[t(r)]=s?s(r):r,e)),Object.create(null))},t.insert=function(e,t){return e.push(t),()=>l(e,t)},t.remove=l,t.arrayInsert=function(e,t,s){const r=e.slice(0,t),n=e.slice(t);return r.concat(s,n)},t.shuffle=function(e,t){let s;if("number"==typeof t){let e=t;s=()=>{const t=179426549*Math.sin(e++);return t-Math.floor(t)}}else s=Math.random;for(let t=e.length-1;t>0;t-=1){const r=Math.floor(s()*(t+1)),n=e[t];e[t]=e[r],e[r]=n}},t.pushToStart=function(e,t){const s=e.indexOf(t);s>-1&&(e.splice(s,1),e.unshift(t))},t.pushToEnd=function(e,t){const s=e.indexOf(t);s>-1&&(e.splice(s,1),e.push(t))},t.pushMany=function(e,t){for(const s of t)e.push(s)},t.mapArrayOrNot=function(e,t){return Array.isArray(e)?e.map(t):t(e)},t.asArray=function(e){return Array.isArray(e)?e:[e]},t.getRandomElement=function(e){return e[Math.floor(Math.random()*e.length)]},t.insertInto=c,t.splice=function(e,t,s,r){const n=h(e,t);let i=e.splice(n,s);return void 0===i&&(i=[]),c(e,n,r),i},t.compareBy=function(e,t){return(s,r)=>t(e(s),e(r))},t.tieBreakComparators=function(...e){return(t,s)=>{for(const r of e){const e=r(t,s);if(!u.isNeitherLessOrGreaterThan(e))return e}return u.neitherLessOrGreaterThan}},t.reverseOrder=function(e){return(t,s)=>-e(t,s)};const r=s(577),n=s(411);function i(e,t){let s=0,r=e-1;for(;s<=r;){const e=(s+r)/2|0,n=t(e);if(n<0)s=e+1;else{if(!(n>0))return e;r=e-1}}return-(s+1)}function o(e,t,s){const r=[];function n(e,t,s){if(0===t&&0===s.length)return;const n=r[r.length-1];n&&n.start+n.deleteCount===e?(n.deleteCount+=t,n.toInsert.push(...s)):r.push({start:e,deleteCount:t,toInsert:s})}let i=0,o=0;for(;;){if(i===e.length){n(i,0,t.slice(o));break}if(o===t.length){n(i,e.length-i,[]);break}const r=e[i],a=t[o],l=s(r,a);0===l?(i+=1,o+=1):l<0?(n(i,1,[]),i+=1):l>0&&(n(i,0,[a]),o+=1)}return r}function a(e,t,s,r,i){for(const o=s.length;rt(i,e)<0));s.splice(e,0,i)}}}function l(e,t){const s=e.indexOf(t);if(s>-1)return e.splice(s,1),t}function c(e,t,s){const r=h(e,t),n=e.length,i=s.length;e.length=n+i;for(let t=n-1;t>=r;t--)e[t+i]=e[t];for(let t=0;t0},e.isNeitherLessOrGreaterThan=function(e){return 0===e},e.greaterThan=1,e.lessThan=-1,e.neitherLessOrGreaterThan=0}(u||(t.CompareResult=u={})),t.numberComparator=(e,t)=>e-t,t.booleanComparator=(e,s)=>(0,t.numberComparator)(e?1:0,s?1:0),t.ArrayQueue=class{constructor(e){this.items=e,this.firstIdx=0,this.lastIdx=this.items.length-1}get length(){return this.lastIdx-this.firstIdx+1}takeWhile(e){let t=this.firstIdx;for(;t=0&&e(this.items[t]);)t--;const s=t===this.lastIdx?null:this.items.slice(t+1,this.lastIdx+1);return this.lastIdx=t,s}peek(){if(0!==this.length)return this.items[this.firstIdx]}peekLast(){if(0!==this.length)return this.items[this.lastIdx]}dequeue(){const e=this.items[this.firstIdx];return this.firstIdx++,e}removeLast(){const e=this.items[this.lastIdx];return this.lastIdx--,e}takeCount(e){const t=this.items.slice(this.firstIdx,this.firstIdx+e);return this.firstIdx+=e,t}};class d{static{this.empty=new d((e=>{}))}constructor(e){this.iterate=e}forEach(e){this.iterate((t=>(e(t),!0)))}toArray(){const e=[];return this.iterate((t=>(e.push(t),!0))),e}filter(e){return new d((t=>this.iterate((s=>!e(s)||t(s)))))}map(e){return new d((t=>this.iterate((s=>t(e(s))))))}some(e){let t=!1;return this.iterate((s=>(t=e(s),!t))),t}findFirst(e){let t;return this.iterate((s=>!e(s)||(t=s,!1))),t}findLast(e){let t;return this.iterate((s=>(e(s)&&(t=s),!0))),t}findLastMaxBy(e){let t,s=!0;return this.iterate((r=>((s||u.isGreaterThan(e(r,t)))&&(s=!1,t=r),!0))),t}}t.CallbackIterable=d;class f{constructor(e){this._indexMap=e}static createSortPermutation(e,t){const s=Array.from(e.keys()).sort(((s,r)=>t(e[s],e[r])));return new f(s)}apply(e){return e.map(((t,s)=>e[this._indexMap[s]]))}inverse(){const e=this._indexMap.slice();for(let t=0;t{function s(e,t,s=e.length-1){for(let r=s;r>=0;r--)if(t(e[r]))return r;return-1}function r(e,t,s=0,r=e.length){let n=s,i=r;for(;n=0&&(s=n)}return s},t.findFirstMin=function(e,t){return o(e,((e,s)=>-t(e,s)))},t.findMaxIdx=function(e,t){if(0===e.length)return-1;let s=0;for(let r=1;r0&&(s=r);return s},t.mapFindFirst=function(e,t){for(const s of e){const e=t(s);if(void 0!==e)return e}};class i{static{this.assertInvariants=!1}constructor(e){this._array=e,this._findLastMonotonousLastIdx=0}findLastMonotonous(e){if(i.assertInvariants){if(this._prevFindLastPredicate)for(const t of this._array)if(this._prevFindLastPredicate(t)&&!e(t))throw new Error("MonotonousArray: current predicate must be weaker than (or equal to) the previous predicate.");this._prevFindLastPredicate=e}const t=r(this._array,e,this._findLastMonotonousLastIdx);return this._findLastMonotonousLastIdx=t+1,-1===t?void 0:this._array[t]}}function o(e,t){if(0===e.length)return;let s=e[0];for(let r=1;r0&&(s=n)}return s}t.MonotonousArray=i},33:(e,t)=>{var s;Object.defineProperty(t,"__esModule",{value:!0}),t.SetWithKey=void 0,t.groupBy=function(e,t){const s=Object.create(null);for(const r of e){const e=t(r);let n=s[e];n||(n=s[e]=[]),n.push(r)}return s},t.diffSets=function(e,t){const s=[],r=[];for(const r of e)t.has(r)||s.push(r);for(const s of t)e.has(s)||r.push(s);return{removed:s,added:r}},t.diffMaps=function(e,t){const s=[],r=[];for(const[r,n]of e)t.has(r)||s.push(n);for(const[s,n]of t)e.has(s)||r.push(n);return{removed:s,added:r}},t.intersection=function(e,t){const s=new Set;for(const r of t)e.has(r)&&s.add(r);return s};class r{static{s=Symbol.toStringTag}constructor(e,t){this.toKey=t,this._map=new Map,this[s]="SetWithKey";for(const t of e)this.add(t)}get size(){return this._map.size}add(e){const t=this.toKey(e);return this._map.set(t,e),this}delete(e){return this._map.delete(this.toKey(e))}has(e){return this._map.has(this.toKey(e))}*entries(){for(const e of this._map.values())yield[e,e]}keys(){return this.values()}*values(){for(const e of this._map.values())yield e}clear(){this._map.clear()}forEach(e,t){this._map.forEach((s=>e.call(t,s,s,this)))}[Symbol.iterator](){return this.values()}}t.SetWithKey=r},577:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.BugIndicatingError=t.ErrorNoTelemetry=t.ExpectedError=t.NotSupportedError=t.NotImplementedError=t.ReadonlyError=t.CancellationError=t.errorHandler=t.ErrorHandler=void 0,t.setUnexpectedErrorHandler=function(e){t.errorHandler.setUnexpectedErrorHandler(e)},t.isSigPipeError=function(e){if(!e||"object"!=typeof e)return!1;const t=e;return"EPIPE"===t.code&&"WRITE"===t.syscall?.toUpperCase()},t.onUnexpectedError=function(e){n(e)||t.errorHandler.onUnexpectedError(e)},t.onUnexpectedExternalError=function(e){n(e)||t.errorHandler.onUnexpectedExternalError(e)},t.transformErrorForSerialization=function(e){if(e instanceof Error){const{name:t,message:s}=e;return{$isError:!0,name:t,message:s,stack:e.stacktrace||e.stack,noTelemetry:h.isErrorNoTelemetry(e)}}return e},t.transformErrorFromSerialization=function(e){let t;return e.noTelemetry?t=new h:(t=new Error,t.name=e.name),t.message=e.message,t.stack=e.stack,t},t.isCancellationError=n,t.canceled=function(){const e=new Error(r);return e.name=e.message,e},t.illegalArgument=function(e){return e?new Error(`Illegal argument: ${e}`):new Error("Illegal argument")},t.illegalState=function(e){return e?new Error(`Illegal state: ${e}`):new Error("Illegal state")},t.getErrorMessage=function(e){return e?e.message?e.message:e.stack?e.stack.split("\n")[0]:String(e):"Error"};class s{constructor(){this.listeners=[],this.unexpectedErrorHandler=function(e){setTimeout((()=>{if(e.stack){if(h.isErrorNoTelemetry(e))throw new h(e.message+"\n\n"+e.stack);throw new Error(e.message+"\n\n"+e.stack)}throw e}),0)}}addListener(e){return this.listeners.push(e),()=>{this._removeListener(e)}}emit(e){this.listeners.forEach((t=>{t(e)}))}_removeListener(e){this.listeners.splice(this.listeners.indexOf(e),1)}setUnexpectedErrorHandler(e){this.unexpectedErrorHandler=e}getUnexpectedErrorHandler(){return this.unexpectedErrorHandler}onUnexpectedError(e){this.unexpectedErrorHandler(e),this.emit(e)}onUnexpectedExternalError(e){this.unexpectedErrorHandler(e)}}t.ErrorHandler=s,t.errorHandler=new s;const r="Canceled";function n(e){return e instanceof i||e instanceof Error&&e.name===r&&e.message===r}class i extends Error{constructor(){super(r),this.name=this.message}}t.CancellationError=i;class o extends TypeError{constructor(e){super(e?`${e} is read-only and cannot be changed`:"Cannot change read-only property")}}t.ReadonlyError=o;class a extends Error{constructor(e){super("NotImplemented"),e&&(this.message=e)}}t.NotImplementedError=a;class l extends Error{constructor(e){super("NotSupported"),e&&(this.message=e)}}t.NotSupportedError=l;class c extends Error{constructor(){super(...arguments),this.isExpected=!0}}t.ExpectedError=c;class h extends Error{constructor(e){super(e),this.name="CodeExpectedError"}static fromError(e){if(e instanceof h)return e;const t=new h;return t.message=e.message,t.stack=e.stack,t}static isErrorNoTelemetry(e){return"CodeExpectedError"===e.name}}t.ErrorNoTelemetry=h;class u extends Error{constructor(e){super(e||"An unexpected bug occurred."),Object.setPrototypeOf(this,u.prototype)}}t.BugIndicatingError=u},276:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ValueWithChangeEvent=t.Relay=t.EventBufferer=t.DynamicListEventMultiplexer=t.EventMultiplexer=t.MicrotaskEmitter=t.DebounceEmitter=t.PauseableEmitter=t.AsyncEmitter=t.createEventDeliveryQueue=t.Emitter=t.ListenerRefusalError=t.ListenerLeakError=t.EventProfiling=t.Event=void 0,t.setGlobalLeakWarningThreshold=function(e){const t=h;return h=e,{dispose(){h=t}}};const r=s(577),n=s(355),i=s(540),o=s(711),a=s(79);var l;!function(e){function t(e){return(t,s=null,r)=>{let n,i=!1;return n=e((e=>{if(!i)return n?n.dispose():i=!0,t.call(s,e)}),null,r),i&&n.dispose(),n}}function s(e,t,s){return n(((s,r=null,n)=>e((e=>s.call(r,t(e))),null,n)),s)}function r(e,t,s){return n(((s,r=null,n)=>e((e=>t(e)&&s.call(r,e)),null,n)),s)}function n(e,t){let s;const r=new m({onWillAddFirstListener(){s=e(r.fire,r)},onDidRemoveLastListener(){s?.dispose()}});return t?.add(r),r.event}function o(e,t,s=100,r=!1,n=!1,i,o){let a,l,c,h,u=0;const d=new m({leakWarningThreshold:i,onWillAddFirstListener(){a=e((e=>{u++,l=t(l,e),r&&!c&&(d.fire(l),l=void 0),h=()=>{const e=l;l=void 0,c=void 0,(!r||u>1)&&d.fire(e),u=0},"number"==typeof s?(clearTimeout(c),c=setTimeout(h,s)):void 0===c&&(c=0,queueMicrotask(h))}))},onWillRemoveListener(){n&&u>0&&h?.()},onDidRemoveLastListener(){h=void 0,a.dispose()}});return o?.add(d),d.event}e.None=()=>i.Disposable.None,e.defer=function(e,t){return o(e,(()=>{}),0,void 0,!0,void 0,t)},e.once=t,e.map=s,e.forEach=function(e,t,s){return n(((s,r=null,n)=>e((e=>{t(e),s.call(r,e)}),null,n)),s)},e.filter=r,e.signal=function(e){return e},e.any=function(...e){return(t,s=null,r)=>{return n=(0,i.combinedDisposable)(...e.map((e=>e((e=>t.call(s,e)))))),(o=r)instanceof Array?o.push(n):o&&o.add(n),n;var n,o}},e.reduce=function(e,t,r,n){let i=r;return s(e,(e=>(i=t(i,e),i)),n)},e.debounce=o,e.accumulate=function(t,s=0,r){return e.debounce(t,((e,t)=>e?(e.push(t),e):[t]),s,void 0,!0,void 0,r)},e.latch=function(e,t=(e,t)=>e===t,s){let n,i=!0;return r(e,(e=>{const s=i||!t(e,n);return i=!1,n=e,s}),s)},e.split=function(t,s,r){return[e.filter(t,s,r),e.filter(t,(e=>!s(e)),r)]},e.buffer=function(e,t=!1,s=[],r){let n=s.slice(),i=e((e=>{n?n.push(e):a.fire(e)}));r&&r.add(i);const o=()=>{n?.forEach((e=>a.fire(e))),n=null},a=new m({onWillAddFirstListener(){i||(i=e((e=>a.fire(e))),r&&r.add(i))},onDidAddFirstListener(){n&&(t?setTimeout(o):o())},onDidRemoveLastListener(){i&&i.dispose(),i=null}});return r&&r.add(a),a.event},e.chain=function(e,t){return(s,r,n)=>{const i=t(new l);return e((function(e){const t=i.evaluate(e);t!==a&&s.call(r,t)}),void 0,n)}};const a=Symbol("HaltChainable");class l{constructor(){this.steps=[]}map(e){return this.steps.push(e),this}forEach(e){return this.steps.push((t=>(e(t),t))),this}filter(e){return this.steps.push((t=>e(t)?t:a)),this}reduce(e,t){let s=t;return this.steps.push((t=>(s=e(s,t),s))),this}latch(e=(e,t)=>e===t){let t,s=!0;return this.steps.push((r=>{const n=s||!e(r,t);return s=!1,t=r,n?r:a})),this}evaluate(e){for(const t of this.steps)if((e=t(e))===a)break;return e}}e.fromNodeEventEmitter=function(e,t,s=e=>e){const r=(...e)=>n.fire(s(...e)),n=new m({onWillAddFirstListener:()=>e.on(t,r),onDidRemoveLastListener:()=>e.removeListener(t,r)});return n.event},e.fromDOMEventEmitter=function(e,t,s=e=>e){const r=(...e)=>n.fire(s(...e)),n=new m({onWillAddFirstListener:()=>e.addEventListener(t,r),onDidRemoveLastListener:()=>e.removeEventListener(t,r)});return n.event},e.toPromise=function(e){return new Promise((s=>t(e)(s)))},e.fromPromise=function(e){const t=new m;return e.then((e=>{t.fire(e)}),(()=>{t.fire(void 0)})).finally((()=>{t.dispose()})),t.event},e.forward=function(e,t){return e((e=>t.fire(e)))},e.runAndSubscribe=function(e,t,s){return t(s),e((e=>t(e)))};class c{constructor(e,t){this._observable=e,this._counter=0,this._hasChanged=!1;const s={onWillAddFirstListener:()=>{e.addObserver(this)},onDidRemoveLastListener:()=>{e.removeObserver(this)}};this.emitter=new m(s),t&&t.add(this.emitter)}beginUpdate(e){this._counter++}handlePossibleChange(e){}handleChange(e,t){this._hasChanged=!0}endUpdate(e){this._counter--,0===this._counter&&(this._observable.reportChanges(),this._hasChanged&&(this._hasChanged=!1,this.emitter.fire(this._observable.get())))}}e.fromObservable=function(e,t){return new c(e,t).emitter.event},e.fromObservableLight=function(e){return(t,s,r)=>{let n=0,o=!1;const a={beginUpdate(){n++},endUpdate(){n--,0===n&&(e.reportChanges(),o&&(o=!1,t.call(s)))},handlePossibleChange(){},handleChange(){o=!0}};e.addObserver(a),e.reportChanges();const l={dispose(){e.removeObserver(a)}};return r instanceof i.DisposableStore?r.add(l):Array.isArray(r)&&r.push(l),l}}}(l||(t.Event=l={}));class c{static{this.all=new Set}static{this._idPool=0}constructor(e){this.listenerCount=0,this.invocationCount=0,this.elapsedOverall=0,this.durations=[],this.name=`${e}_${c._idPool++}`,c.all.add(this)}start(e){this._stopWatch=new a.StopWatch,this.listenerCount=e}stop(){if(this._stopWatch){const e=this._stopWatch.elapsed();this.durations.push(e),this.elapsedOverall+=e,this.invocationCount+=1,this._stopWatch=void 0}}}t.EventProfiling=c;let h=-1;class u{static{this._idPool=1}constructor(e,t,s=(u._idPool++).toString(16).padStart(3,"0")){this._errorHandler=e,this.threshold=t,this.name=s,this._warnCountdown=0}dispose(){this._stacks?.clear()}check(e,t){const s=this.threshold;if(s<=0||t{const t=this._stacks.get(e.value)||0;this._stacks.set(e.value,t-1)}}getMostFrequentStack(){if(!this._stacks)return;let e,t=0;for(const[s,r]of this._stacks)(!e||t0||this._options?.leakWarningThreshold?new u(e?.onListenerError??r.onUnexpectedError,this._options?.leakWarningThreshold??h):void 0,this._perfMon=this._options?._profName?new c(this._options._profName):void 0,this._deliveryQueue=this._options?.deliveryQueue}dispose(){this._disposed||(this._disposed=!0,this._deliveryQueue?.current===this&&this._deliveryQueue.reset(),this._listeners&&(this._listeners=void 0,this._size=0),this._options?.onDidRemoveLastListener?.(),this._leakageMon?.dispose())}get event(){return this._event??=(e,t,s)=>{if(this._leakageMon&&this._size>this._leakageMon.threshold**2){const e=`[${this._leakageMon.name}] REFUSES to accept new listeners because it exceeded its threshold by far (${this._size} vs ${this._leakageMon.threshold})`;console.warn(e);const t=this._leakageMon.getMostFrequentStack()??["UNKNOWN stack",-1],s=new p(`${e}. HINT: Stack shows most frequent listener (${t[1]}-times)`,t[0]);return(this._options?.onListenerError||r.onUnexpectedError)(s),i.Disposable.None}if(this._disposed)return i.Disposable.None;t&&(e=e.bind(t));const n=new v(e);let o;this._leakageMon&&this._size>=Math.ceil(.2*this._leakageMon.threshold)&&(n.stack=d.create(),o=this._leakageMon.check(n.stack,this._size+1)),this._listeners?this._listeners instanceof v?(this._deliveryQueue??=new g,this._listeners=[this._listeners,n]):this._listeners.push(n):(this._options?.onWillAddFirstListener?.(this),this._listeners=n,this._options?.onDidAddFirstListener?.(this)),this._size++;const a=(0,i.toDisposable)((()=>{o?.(),this._removeListener(n)}));return s instanceof i.DisposableStore?s.add(a):Array.isArray(s)&&s.push(a),a},this._event}_removeListener(e){if(this._options?.onWillRemoveListener?.(this),!this._listeners)return;if(1===this._size)return this._listeners=void 0,this._options?.onDidRemoveLastListener?.(this),void(this._size=0);const t=this._listeners,s=t.indexOf(e);if(-1===s)throw console.log("disposed?",this._disposed),console.log("size?",this._size),console.log("arr?",JSON.stringify(this._listeners)),new Error("Attempted to dispose unknown listener");this._size--,t[s]=void 0;const r=this._deliveryQueue.current===this;if(2*this._size<=t.length){let e=0;for(let s=0;s0}}t.Emitter=m,t.createEventDeliveryQueue=()=>new g;class g{constructor(){this.i=-1,this.end=0}enqueue(e,t,s){this.i=0,this.end=s,this.current=e,this.value=t}reset(){this.i=this.end,this.current=void 0,this.value=void 0}}t.AsyncEmitter=class extends m{async fireAsync(e,t,s){if(this._listeners)for(this._asyncDeliveryQueue||(this._asyncDeliveryQueue=new o.LinkedList),((e,t)=>{if(e instanceof v)t(e);else for(let s=0;sthis._asyncDeliveryQueue.push([t.value,e])));this._asyncDeliveryQueue.size>0&&!t.isCancellationRequested;){const[e,n]=this._asyncDeliveryQueue.shift(),i=[],o={...n,token:t,waitUntil:t=>{if(Object.isFrozen(i))throw new Error("waitUntil can NOT be called asynchronous");s&&(t=s(t,e)),i.push(t)}};try{e(o)}catch(e){(0,r.onUnexpectedError)(e);continue}Object.freeze(i),await Promise.allSettled(i).then((e=>{for(const t of e)"rejected"===t.status&&(0,r.onUnexpectedError)(t.reason)}))}}};class y extends m{get isPaused(){return 0!==this._isPaused}constructor(e){super(e),this._isPaused=0,this._eventQueue=new o.LinkedList,this._mergeFn=e?.merge}pause(){this._isPaused++}resume(){if(0!==this._isPaused&&0==--this._isPaused)if(this._mergeFn){if(this._eventQueue.size>0){const e=Array.from(this._eventQueue);this._eventQueue.clear(),super.fire(this._mergeFn(e))}}else for(;!this._isPaused&&0!==this._eventQueue.size;)super.fire(this._eventQueue.shift())}fire(e){this._size&&(0!==this._isPaused?this._eventQueue.push(e):super.fire(e))}}t.PauseableEmitter=y,t.DebounceEmitter=class extends y{constructor(e){super(e),this._delay=e.delay??100}fire(e){this._handle||(this.pause(),this._handle=setTimeout((()=>{this._handle=void 0,this.resume()}),this._delay)),super.fire(e)}},t.MicrotaskEmitter=class extends m{constructor(e){super(e),this._queuedEvents=[],this._mergeFn=e?.merge}fire(e){this.hasListeners()&&(this._queuedEvents.push(e),1===this._queuedEvents.length&&queueMicrotask((()=>{this._mergeFn?super.fire(this._mergeFn(this._queuedEvents)):this._queuedEvents.forEach((e=>super.fire(e))),this._queuedEvents=[]})))}};class b{constructor(){this.hasListeners=!1,this.events=[],this.emitter=new m({onWillAddFirstListener:()=>this.onFirstListenerAdd(),onDidRemoveLastListener:()=>this.onLastListenerRemove()})}get event(){return this.emitter.event}add(e){const t={event:e,listener:null};return this.events.push(t),this.hasListeners&&this.hook(t),(0,i.toDisposable)((0,n.createSingleCallFunction)((()=>{this.hasListeners&&this.unhook(t);const e=this.events.indexOf(t);this.events.splice(e,1)})))}onFirstListenerAdd(){this.hasListeners=!0,this.events.forEach((e=>this.hook(e)))}onLastListenerRemove(){this.hasListeners=!1,this.events.forEach((e=>this.unhook(e)))}hook(e){e.listener=e.event((e=>this.emitter.fire(e)))}unhook(e){e.listener?.dispose(),e.listener=null}dispose(){this.emitter.dispose();for(const e of this.events)e.listener?.dispose();this.events=[]}}t.EventMultiplexer=b,t.DynamicListEventMultiplexer=class{constructor(e,t,s,r){this._store=new i.DisposableStore;const n=this._store.add(new b),o=this._store.add(new i.DisposableMap);function a(e){o.set(e,n.add(r(e)))}for(const t of e)a(t);this._store.add(t((e=>{a(e)}))),this._store.add(s((e=>{o.deleteAndDispose(e)}))),this.event=n.event}dispose(){this._store.dispose()}},t.EventBufferer=class{constructor(){this.data=[]}wrapEvent(e,t,s){return(r,n,i)=>e((e=>{const i=this.data[this.data.length-1];if(!t)return void(i?i.buffers.push((()=>r.call(n,e))):r.call(n,e));const o=i;o?(o.items??=[],o.items.push(e),0===o.buffers.length&&i.buffers.push((()=>{o.reducedResult??=s?o.items.reduce(t,s):o.items.reduce(t),r.call(n,o.reducedResult)}))):r.call(n,t(s,e))}),void 0,i)}bufferEvents(e){const t={buffers:new Array};this.data.push(t);const s=e();return this.data.pop(),t.buffers.forEach((e=>e())),s}},t.Relay=class{constructor(){this.listening=!1,this.inputEvent=l.None,this.inputEventListener=i.Disposable.None,this.emitter=new m({onDidAddFirstListener:()=>{this.listening=!0,this.inputEventListener=this.inputEvent(this.emitter.fire,this.emitter)},onDidRemoveLastListener:()=>{this.listening=!1,this.inputEventListener.dispose()}}),this.event=this.emitter.event}set input(e){this.inputEvent=e,this.listening&&(this.inputEventListener.dispose(),this.inputEventListener=e(this.emitter.fire,this.emitter))}dispose(){this.inputEventListener.dispose(),this.emitter.dispose()}},t.ValueWithChangeEvent=class{static const(e){return new E(e)}constructor(e){this._value=e,this._onDidChange=new m,this.onDidChange=this._onDidChange.event}get value(){return this._value}set value(e){e!==this._value&&(this._value=e,this._onDidChange.fire(void 0))}};class E{constructor(e){this.value=e,this.onDidChange=l.None}}},355:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.createSingleCallFunction=function(e,t){const s=this;let r,n=!1;return function(){if(n)return r;if(n=!0,t)try{r=e.apply(s,arguments)}finally{t()}else r=e.apply(s,arguments);return r}}},956:(e,t)=>{var s;Object.defineProperty(t,"__esModule",{value:!0}),t.Iterable=void 0,function(e){function t(e){return e&&"object"==typeof e&&"function"==typeof e[Symbol.iterator]}e.is=t;const s=Object.freeze([]);function*r(e){yield e}e.empty=function(){return s},e.single=r,e.wrap=function(e){return t(e)?e:r(e)},e.from=function(e){return e||s},e.reverse=function*(e){for(let t=e.length-1;t>=0;t--)yield e[t]},e.isEmpty=function(e){return!e||!0===e[Symbol.iterator]().next().done},e.first=function(e){return e[Symbol.iterator]().next().value},e.some=function(e,t){let s=0;for(const r of e)if(t(r,s++))return!0;return!1},e.find=function(e,t){for(const s of e)if(t(s))return s},e.filter=function*(e,t){for(const s of e)t(s)&&(yield s)},e.map=function*(e,t){let s=0;for(const r of e)yield t(r,s++)},e.flatMap=function*(e,t){let s=0;for(const r of e)yield*t(r,s++)},e.concat=function*(...e){for(const t of e)yield*t},e.reduce=function(e,t,s){let r=s;for(const s of e)r=t(r,s);return r},e.slice=function*(e,t,s=e.length){for(t<0&&(t+=e.length),s<0?s+=e.length:s>e.length&&(s=e.length);tn}]},e.asyncToArray=async function(e){const t=[];for await(const s of e)t.push(s);return Promise.resolve(t)}}(s||(t.Iterable=s={}))},540:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.DisposableMap=t.ImmortalReference=t.AsyncReferenceCollection=t.ReferenceCollection=t.SafeDisposable=t.RefCountedDisposable=t.MandatoryMutableDisposable=t.MutableDisposable=t.Disposable=t.DisposableStore=t.DisposableTracker=void 0,t.setDisposableTracker=function(e){l=e},t.trackDisposable=h,t.markAsDisposed=u,t.markAsSingleton=function(e){return l?.markAsSingleton(e),e},t.isDisposable=f,t.dispose=p,t.disposeIfDisposable=function(e){for(const t of e)f(t)&&t.dispose();return[]},t.combinedDisposable=function(...e){const t=_((()=>p(e)));return function(e,t){if(l)for(const s of e)l.setParent(s,t)}(e,t),t},t.toDisposable=_,t.disposeOnReturn=function(e){const t=new v;try{e(t)}finally{t.dispose()}};const r=s(732),n=s(33),i=s(714),o=s(355),a=s(956);let l=null;class c{constructor(){this.livingDisposables=new Map}static{this.idx=0}getDisposableData(e){let t=this.livingDisposables.get(e);return t||(t={parent:null,source:null,isSingleton:!1,value:e,idx:c.idx++},this.livingDisposables.set(e,t)),t}trackDisposable(e){const t=this.getDisposableData(e);t.source||(t.source=(new Error).stack)}setParent(e,t){this.getDisposableData(e).parent=t}markAsDisposed(e){this.livingDisposables.delete(e)}markAsSingleton(e){this.getDisposableData(e).isSingleton=!0}getRootParent(e,t){const s=t.get(e);if(s)return s;const r=e.parent?this.getRootParent(this.getDisposableData(e.parent),t):e;return t.set(e,r),r}getTrackedDisposables(){const e=new Map;return[...this.livingDisposables.entries()].filter((([,t])=>null!==t.source&&!this.getRootParent(t,e).isSingleton)).flatMap((([e])=>e))}computeLeakingDisposables(e=10,t){let s;if(t)s=t;else{const e=new Map,t=[...this.livingDisposables.values()].filter((t=>null!==t.source&&!this.getRootParent(t,e).isSingleton));if(0===t.length)return;const r=new Set(t.map((e=>e.value)));if(s=t.filter((e=>!(e.parent&&r.has(e.parent)))),0===s.length)throw new Error("There are cyclic diposable chains!")}if(!s)return;function o(e){const t=e.source.split("\n").map((e=>e.trim().replace("at ",""))).filter((e=>""!==e));return function(e,t){for(;e.length>0&&t.some((t=>"string"==typeof t?t===e[0]:e[0].match(t)));)e.shift()}(t,["Error",/^trackDisposable \(.*\)$/,/^DisposableTracker.trackDisposable \(.*\)$/]),t.reverse()}const a=new i.SetMap;for(const e of s){const t=o(e);for(let s=0;s<=t.length;s++)a.add(t.slice(0,s).join("\n"),e)}s.sort((0,r.compareBy)((e=>e.idx),r.numberComparator));let l="",c=0;for(const t of s.slice(0,e)){c++;const e=o(t),r=[];for(let t=0;to(e)[t])),(e=>e));delete c[e[t]];for(const[e,t]of Object.entries(c))r.unshift(` - stacktraces of ${t.length} other leaks continue with ${e}`);r.unshift(i)}l+=`\n\n\n==================== Leaking disposable ${c}/${s.length}: ${t.value.constructor.name} ====================\n${r.join("\n")}\n============================================================\n\n`}return s.length>e&&(l+=`\n\n\n... and ${s.length-e} more leaking disposables\n\n`),{leaks:s,details:l}}}function h(e){return l?.trackDisposable(e),e}function u(e){l?.markAsDisposed(e)}function d(e,t){l?.setParent(e,t)}function f(e){return"object"==typeof e&&null!==e&&"function"==typeof e.dispose&&0===e.dispose.length}function p(e){if(a.Iterable.is(e)){const t=[];for(const s of e)if(s)try{s.dispose()}catch(e){t.push(e)}if(1===t.length)throw t[0];if(t.length>1)throw new AggregateError(t,"Encountered errors while disposing of store");return Array.isArray(e)?[]:e}if(e)return e.dispose(),e}function _(e){const t=h({dispose:(0,o.createSingleCallFunction)((()=>{u(t),e()}))});return t}t.DisposableTracker=c;class v{static{this.DISABLE_DISPOSED_WARNING=!1}constructor(){this._toDispose=new Set,this._isDisposed=!1,h(this)}dispose(){this._isDisposed||(u(this),this._isDisposed=!0,this.clear())}get isDisposed(){return this._isDisposed}clear(){if(0!==this._toDispose.size)try{p(this._toDispose)}finally{this._toDispose.clear()}}add(e){if(!e)return e;if(e===this)throw new Error("Cannot register a disposable on itself!");return d(e,this),this._isDisposed?v.DISABLE_DISPOSED_WARNING||console.warn(new Error("Trying to add a disposable to a DisposableStore that has already been disposed of. The added object will be leaked!").stack):this._toDispose.add(e),e}delete(e){if(e){if(e===this)throw new Error("Cannot dispose a disposable on itself!");this._toDispose.delete(e),e.dispose()}}deleteAndLeak(e){e&&this._toDispose.has(e)&&(this._toDispose.delete(e),d(e,null))}}t.DisposableStore=v;class m{static{this.None=Object.freeze({dispose(){}})}constructor(){this._store=new v,h(this),d(this._store,this)}dispose(){u(this),this._store.dispose()}_register(e){if(e===this)throw new Error("Cannot register a disposable on itself!");return this._store.add(e)}}t.Disposable=m;class g{constructor(){this._isDisposed=!1,h(this)}get value(){return this._isDisposed?void 0:this._value}set value(e){this._isDisposed||e===this._value||(this._value?.dispose(),e&&d(e,this),this._value=e)}clear(){this.value=void 0}dispose(){this._isDisposed=!0,u(this),this._value?.dispose(),this._value=void 0}clearAndLeak(){const e=this._value;return this._value=void 0,e&&d(e,null),e}}t.MutableDisposable=g,t.MandatoryMutableDisposable=class{constructor(e){this._disposable=new g,this._isDisposed=!1,this._disposable.value=e}get value(){return this._disposable.value}set value(e){this._isDisposed||e===this._disposable.value||(this._disposable.value=e)}dispose(){this._isDisposed=!0,this._disposable.dispose()}},t.RefCountedDisposable=class{constructor(e){this._disposable=e,this._counter=1}acquire(){return this._counter++,this}release(){return 0==--this._counter&&this._disposable.dispose(),this}},t.SafeDisposable=class{constructor(){this.dispose=()=>{},this.unset=()=>{},this.isset=()=>!1,h(this)}set(e){let t=e;return this.unset=()=>t=void 0,this.isset=()=>void 0!==t,this.dispose=()=>{t&&(t(),t=void 0,u(this))},this}},t.ReferenceCollection=class{constructor(){this.references=new Map}acquire(e,...t){let s=this.references.get(e);s||(s={counter:0,object:this.createReferencedObject(e,...t)},this.references.set(e,s));const{object:r}=s,n=(0,o.createSingleCallFunction)((()=>{0==--s.counter&&(this.destroyReferencedObject(e,s.object),this.references.delete(e))}));return s.counter++,{object:r,dispose:n}}},t.AsyncReferenceCollection=class{constructor(e){this.referenceCollection=e}async acquire(e,...t){const s=this.referenceCollection.acquire(e,...t);try{return{object:await s.object,dispose:()=>s.dispose()}}catch(e){throw s.dispose(),e}}},t.ImmortalReference=class{constructor(e){this.object=e}dispose(){}};class y{constructor(){this._store=new Map,this._isDisposed=!1,h(this)}dispose(){u(this),this._isDisposed=!0,this.clearAndDisposeAll()}clearAndDisposeAll(){if(this._store.size)try{p(this._store.values())}finally{this._store.clear()}}has(e){return this._store.has(e)}get size(){return this._store.size}get(e){return this._store.get(e)}set(e,t,s=!1){this._isDisposed&&console.warn(new Error("Trying to add a disposable to a DisposableMap that has already been disposed of. The added object will be leaked!").stack),s||this._store.get(e)?.dispose(),this._store.set(e,t)}deleteAndDispose(e){this._store.get(e)?.dispose(),this._store.delete(e)}deleteAndLeak(e){const t=this._store.get(e);return this._store.delete(e),t}keys(){return this._store.keys()}values(){return this._store.values()}[Symbol.iterator](){return this._store[Symbol.iterator]()}}t.DisposableMap=y},711:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.LinkedList=void 0;class s{static{this.Undefined=new s(void 0)}constructor(e){this.element=e,this.next=s.Undefined,this.prev=s.Undefined}}class r{constructor(){this._first=s.Undefined,this._last=s.Undefined,this._size=0}get size(){return this._size}isEmpty(){return this._first===s.Undefined}clear(){let e=this._first;for(;e!==s.Undefined;){const t=e.next;e.prev=s.Undefined,e.next=s.Undefined,e=t}this._first=s.Undefined,this._last=s.Undefined,this._size=0}unshift(e){return this._insert(e,!1)}push(e){return this._insert(e,!0)}_insert(e,t){const r=new s(e);if(this._first===s.Undefined)this._first=r,this._last=r;else if(t){const e=this._last;this._last=r,r.prev=e,e.next=r}else{const e=this._first;this._first=r,r.next=e,e.prev=r}this._size+=1;let n=!1;return()=>{n||(n=!0,this._remove(r))}}shift(){if(this._first!==s.Undefined){const e=this._first.element;return this._remove(this._first),e}}pop(){if(this._last!==s.Undefined){const e=this._last.element;return this._remove(this._last),e}}_remove(e){if(e.prev!==s.Undefined&&e.next!==s.Undefined){const t=e.prev;t.next=e.next,e.next.prev=t}else e.prev===s.Undefined&&e.next===s.Undefined?(this._first=s.Undefined,this._last=s.Undefined):e.next===s.Undefined?(this._last=this._last.prev,this._last.next=s.Undefined):e.prev===s.Undefined&&(this._first=this._first.next,this._first.prev=s.Undefined);this._size-=1}*[Symbol.iterator](){let e=this._first;for(;e!==s.Undefined;)yield e.element,e=e.next}}t.LinkedList=r},714:(e,t)=>{var s;Object.defineProperty(t,"__esModule",{value:!0}),t.SetMap=t.BidirectionalMap=t.CounterSet=t.Touch=void 0,t.getOrSet=function(e,t,s){let r=e.get(t);return void 0===r&&(r=s,e.set(t,r)),r},t.mapToString=function(e){const t=[];return e.forEach(((e,s)=>{t.push(`${s} => ${e}`)})),`Map(${e.size}) {${t.join(", ")}}`},t.setToString=function(e){const t=[];return e.forEach((e=>{t.push(e)})),`Set(${e.size}) {${t.join(", ")}}`},t.mapsStrictEqualIgnoreOrder=function(e,t){if(e===t)return!0;if(e.size!==t.size)return!1;for(const[s,r]of e)if(!t.has(s)||t.get(s)!==r)return!1;for(const[s]of t)if(!e.has(s))return!1;return!0},function(e){e[e.None=0]="None",e[e.AsOld=1]="AsOld",e[e.AsNew=2]="AsNew"}(s||(t.Touch=s={})),t.CounterSet=class{constructor(){this.map=new Map}add(e){return this.map.set(e,(this.map.get(e)||0)+1),this}delete(e){let t=this.map.get(e)||0;return 0!==t&&(t--,0===t?this.map.delete(e):this.map.set(e,t),!0)}has(e){return this.map.has(e)}},t.BidirectionalMap=class{constructor(e){if(this._m1=new Map,this._m2=new Map,e)for(const[t,s]of e)this.set(t,s)}clear(){this._m1.clear(),this._m2.clear()}set(e,t){this._m1.set(e,t),this._m2.set(t,e)}get(e){return this._m1.get(e)}getKey(e){return this._m2.get(e)}delete(e){const t=this._m1.get(e);return void 0!==t&&(this._m1.delete(e),this._m2.delete(t),!0)}forEach(e,t){this._m1.forEach(((s,r)=>{e.call(t,s,r,this)}))}keys(){return this._m1.keys()}values(){return this._m1.values()}},t.SetMap=class{constructor(){this.map=new Map}add(e,t){let s=this.map.get(e);s||(s=new Set,this.map.set(e,s)),s.add(t)}delete(e,t){const s=this.map.get(e);s&&(s.delete(t),0===s.size&&this.map.delete(e))}forEach(e,t){const s=this.map.get(e);s&&s.forEach(t)}get(e){return this.map.get(e)||new Set}}},79:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.StopWatch=void 0;const s=globalThis.performance&&"function"==typeof globalThis.performance.now;class r{static create(e){return new r(e)}constructor(e){this._now=s&&!1===e?Date.now:globalThis.performance.now.bind(globalThis.performance),this._startTime=this._now(),this._stopTime=-1}stop(){this._stopTime=this._now()}reset(){this._startTime=this._now(),this._stopTime=-1}elapsed(){return-1!==this._stopTime?this._stopTime-this._startTime:this._now()-this._startTime}}t.StopWatch=r}},t={};function s(r){var n=t[r];if(void 0!==n)return n.exports;var i=t[r]={exports:{}};return e[r](i,i.exports,s),i.exports}var r={};return(()=>{var e=r;Object.defineProperty(e,"__esModule",{value:!0}),e.Unicode11Addon=void 0;const t=s(384);e.Unicode11Addon=class{activate(e){e.unicode.register(new t.UnicodeV11)}dispose(){}}})(),r})())); +//# sourceMappingURL=addon-unicode11.js.map \ No newline at end of file diff --git a/crates/shell-use/assets/xterm/shim.js b/crates/shell-use/assets/xterm/shim.js index bb6d10a..04c50ec 100644 --- a/crates/shell-use/assets/xterm/shim.js +++ b/crates/shell-use/assets/xterm/shim.js @@ -49,6 +49,16 @@ globalThis.__boot = function (cols, rows, scrollback) { allowProposedApi: true, }); + // The headless bundle ships only the Unicode 6 width tables, which call + // every astral emoji one column wide. alacritty measures them as two, so + // without this a line containing an emoji puts every following cell in a + // different column on the two backends, moving what `cells`, the locator, + // and the SVG renderer report. The Unicode 11 provider restores the pair. + if (typeof globalThis.__unicode11 === 'function') { + term.loadAddon(new globalThis.__unicode11()); + term.unicode.activeVersion = '11'; + } + // Replies the terminal wants sent back up the PTY (DA, CPR, and friends). var replies = []; term.onData(function (d) { replies.push(d); }); @@ -103,10 +113,18 @@ globalThis.__boot = function (cols, rows, scrollback) { for (var y = start; y < end; y++) { var line = buf.getLine(y); for (var x = 0; x < cols; x++) { - if (!line) { chars.push(' '); meta.push(1, 0, 0, 0, 0, 0); continue; } + if (!line) { chars.push(' '); meta.push(1, -1, -1, -1, 0, 0); continue; } var c = line.getCell(x, CELL); chars.push(c.getChars()); + // Reading a cell costs a JS call per getter, and a full-scrollback + // dump is hundreds of thousands of cells. Most of them are ordinary + // unstyled text, and for those one call answers all nineteen: -1 is + // the "no color" value every getter returns, and no attribute bit is + // set. Verified to produce byte-identical output to the long form + // across every SGR in the cell vocabulary. + if (c.isAttributeDefault()) { meta.push(c.getWidth(), -1, -1, -1, 0, 0); continue; } + var fg = c.getFgColor(); var fgMode = c.isFgPalette() ? 1 : (c.isFgRGB() ? 2 : 0); var ulColor = c.getUnderlineColor(); @@ -124,6 +142,16 @@ globalThis.__boot = function (cols, rows, scrollback) { // the same either way. if (ulColor === fg && ulMode === fgMode) { ulMode = 0; } + // SGR 59 (reset underline color) does not clear the record: it + // stores a sentinel that reads back through the public getters as + // RGB #ffffff, so an ordinary reset produced a white underline where + // there should be none. The sentinel is indistinguishable from a + // real `58;2;255;255;255` at this layer -- both report RGB with + // value 0xffffff -- so one of the two has to be wrong. Resetting is + // overwhelmingly the more common of the two, and getting it wrong + // paints a color the terminal never asked for, so it wins. + if (ulMode === 2 && ulColor === 0xffffff) { ulMode = 0; } + var flags = (c.isBold() ? 1 : 0) | (c.isDim() ? 2 : 0) | diff --git a/crates/shell-use/src/terminal/alacritty.rs b/crates/shell-use/src/terminal/alacritty.rs index 47c41a6..e71ed92 100644 --- a/crates/shell-use/src/terminal/alacritty.rs +++ b/crates/shell-use/src/terminal/alacritty.rs @@ -183,6 +183,9 @@ impl Emulator for AlacrittyEmu { } fn resize(&mut self, cols: u16, rows: u16) { + // Clamped because alacritty's own grid arithmetic underflows on a + // zero-width resize; see `backend::clamp_size`. + let (cols, rows) = crate::terminal::backend::clamp_size(cols, rows); self.term .resize(TermSize::new(cols as usize, rows as usize)); self.cols = cols; diff --git a/crates/shell-use/src/terminal/backend.rs b/crates/shell-use/src/terminal/backend.rs index 65d0280..1419e1f 100644 --- a/crates/shell-use/src/terminal/backend.rs +++ b/crates/shell-use/src/terminal/backend.rs @@ -9,6 +9,22 @@ use crate::terminal::xtermjs::XtermJsEmu; /// Scrollback retained by every session, in rows. pub const SCROLLBACK: usize = 5_000; +/// The smallest grid any backend is asked for. +/// +/// The two emulators disagree about degenerate sizes: xterm.js silently clamps +/// to two columns by one row, while alacritty panics inside its own grid code +/// on a zero-width resize — which takes the daemon with it, since requests are +/// served on the main thread. Nothing between the wire and here rejects a zero, +/// so `cols`/`rows` are clamped once, at the seam, and both backends then agree +/// on what a session that asked for something impossible actually got. +pub const MIN_COLS: u16 = 2; +pub const MIN_ROWS: u16 = 1; + +/// Clamp a requested grid size to what every backend can represent. +pub fn clamp_size(cols: u16, rows: u16) -> (u16, u16) { + (cols.max(MIN_COLS), rows.max(MIN_ROWS)) +} + /// The emulator a session drives its PTY output through. /// /// Both backends pass the same conformance suite, so this picks which @@ -35,6 +51,7 @@ impl Backend { pub const ALL: [Backend; 2] = [Backend::Alacritty, Backend::XtermJs]; pub fn build(self, cols: u16, rows: u16) -> anyhow::Result> { + let (cols, rows) = clamp_size(cols, rows); Ok(match self { Backend::Alacritty => Box::new(AlacrittyEmu::new(cols, rows, SCROLLBACK)), Backend::XtermJs => Box::new(XtermJsEmu::new(cols, rows, SCROLLBACK)?), diff --git a/crates/shell-use/src/terminal/conformance.rs b/crates/shell-use/src/terminal/conformance.rs index 98c734d..45224b4 100644 --- a/crates/shell-use/src/terminal/conformance.rs +++ b/crates/shell-use/src/terminal/conformance.rs @@ -309,6 +309,159 @@ macro_rules! emulator_conformance_tests { ); } + /// Emoji occupy two columns, like any other wide character. + /// + /// This is not pedantry about Unicode: every consumer addresses cells + /// by column, so a backend that calls an emoji one column wide moves + /// the reported position of everything after it on the line. The + /// headless xterm.js bundle ships only the Unicode 6 tables, which get + /// this wrong, which is why that backend loads a wider provider. + #[test] + fn conformance_emoji_is_two_columns_wide() { + let mut e = conformance_emu(12, 2, 100); + e.process("🙂X".as_bytes()); + let rows = e.viewable_rows(); + assert_eq!(rows[0][0].ch, "🙂"); + assert_eq!( + rows[0][1].ch, + $crate::terminal::cell::CONTINUATION, + "an emoji's second column is a continuation" + ); + assert_eq!(rows[0][2].ch, "X", "the next glyph starts at column 2"); + assert_eq!(e.cursor(), (3, 0)); + } + + /// A zero-width character with no base to attach to still leaves the + /// grid rectangular. + /// + /// Backends disagree about what such a cell holds: alacritty discards + /// the mark, xterm.js gives it a column of its own. Both are defensible + /// for a sequence no terminal defines, so this pins only the invariant + /// every consumer depends on. It is a regression test with teeth: the + /// xterm.js backend used to report this cell as a continuation, which + /// made the row serialize one column short of the grid and shifted + /// every snapshot and screenshot after it. + #[test] + fn conformance_a_baseless_combining_mark_keeps_the_grid_rectangular() { + let mut e = conformance_emu(6, 2, 100); + e.process("\u{064b}hi".as_bytes()); + let rows = e.viewable_rows(); + for row in &rows { + assert_eq!(row.len(), 6, "every row stays full width"); + } + assert_eq!( + $crate::terminal::cell::rows_to_strings(&rows)[0] + .chars() + .count(), + 6, + "the serialized row is as wide as the grid" + ); + assert!( + conformance_text(&rows)[0].contains("hi"), + "the text that followed the mark survives" + ); + } + + /// SGR 59 resets the underline color, leaving the cell with none. + /// + /// xterm.js stores that reset as a sentinel its public getters report + /// as RGB white, so a backend that trusts them paints a white underline + /// the terminal never asked for. + #[test] + fn conformance_sgr_59_clears_the_underline_color() { + let mut e = conformance_emu(8, 1, 100); + e.process(b"\x1b[4;58;5;33mA\x1b[59mB"); + let rows = e.viewable_rows(); + assert_eq!( + rows[0][0].underline_color, + Some($crate::terminal::cell::Color::from_index(33)), + "58 sets the color" + ); + assert_eq!(rows[0][1].underline_color, None, "59 clears it"); + assert_eq!( + rows[0][1].underline, + $crate::terminal::cell::UnderlineStyle::Single, + "59 clears the color without clearing the underline" + ); + } + + /// `size()` reports the grid the emulator actually has. + /// + /// Emulators clamp: xterm.js will not go below two columns. A backend + /// that reports the size it was *asked* for while holding a different + /// one makes every consumer address a coordinate space that does not + /// exist, and made the row decoder mis-chunk the grid into twice as + /// many rows as the terminal has. + #[test] + fn conformance_size_matches_the_grid_that_is_returned() { + for (req_cols, req_rows) in [(1u16, 4u16), (10, 3), (80, 24)] { + let mut e = conformance_emu(req_cols, req_rows, 100); + e.process(b"abcdef"); + let (cols, rows) = e.size(); + let grid = e.viewable_rows(); + assert_eq!( + grid.len(), + rows as usize, + "asked for {req_cols}x{req_rows}: row count must equal the reported height" + ); + for row in &grid { + assert_eq!( + row.len(), + cols as usize, + "asked for {req_cols}x{req_rows}: every row must be the reported width" + ); + } + } + } + + /// Reading the grid never panics on a degenerate size. + /// + /// `resize` takes a `u16` and nothing on the path from the wire to the + /// emulator rejects zero, so this has to be survivable rather than + /// merely unlikely: the daemon serves requests on its main thread, so a + /// panic here takes the session and its child process with it. + #[test] + fn conformance_a_zero_width_grid_does_not_panic() { + let mut e = conformance_emu(10, 3, 100); + e.process(b"hello"); + e.resize(0, 3); + let _ = e.viewable_rows(); + let _ = e.full_rows(); + let _ = e.cursor(); + } + + /// A narrowing resize leaves a well-formed grid at the new size, and + /// keeps the part of each line that still fits. + /// + /// What happens to the part that *doesn't* fit is genuinely divergent, + /// so the test stops there. alacritty reflows, rewrapping the overflow + /// onto following rows; xterm.js truncates each line at the new width + /// and drops it. Narrowing `abcdefghijklmnop` from 10 columns to 6 + /// gives `abcdef/ghijkl/mnop` on one and `abcdef/klmnop` on the other. + /// Pinning either would fail the other backend, but shape corruption + /// here would break every consumer, so that much is pinned. + #[test] + fn conformance_resize_leaves_a_well_formed_grid() { + let mut e = conformance_emu(10, 4, 100); + e.process(b"abcdefghijklmnop"); + e.resize(6, 4); + + assert_eq!(e.size(), (6, 4)); + let rows = e.viewable_rows(); + assert_eq!(rows.len(), 4, "row count follows the new height"); + for row in &rows { + assert_eq!(row.len(), 6, "every row follows the new width"); + } + let (cx, cy) = e.cursor(); + assert!(cx < 6 && cy < 4, "cursor stays inside the new grid"); + assert!( + conformance_text(&e.full_rows()) + .iter() + .any(|r| r.starts_with("abcdef")), + "the part of the first line that still fits survives" + ); + } + /// A wide char that does not fit in the last column wraps whole to the /// next row, and the column it left behind is a blank it still owns. /// Backends mark that filler with a distinct flag from a real diff --git a/crates/shell-use/src/terminal/xtermjs.rs b/crates/shell-use/src/terminal/xtermjs.rs index cfbd860..e220109 100644 --- a/crates/shell-use/src/terminal/xtermjs.rs +++ b/crates/shell-use/src/terminal/xtermjs.rs @@ -28,11 +28,22 @@ use crate::terminal::cell::{Attrs, Color, EmuCell, UnderlineStyle, CONTINUATION} use crate::terminal::emu::Emulator; const XTERM_BUNDLE: &str = include_str!("../../assets/xterm/xterm-headless.js"); +const UNICODE11: &str = include_str!("../../assets/xterm/addon-unicode11.js"); const SHIM: &str = include_str!("../../assets/xterm/shim.js"); +/// The unicode11 addon is UMD and publishes itself by *replacing* +/// `module.exports`, so it is lifted onto a global the shim can find. Reading +/// it back before `__boot` runs also leaves `exports.Terminal`, which the shim +/// set up, untouched. +const UNICODE11_CAPTURE: &str = "globalThis.__unicode11 = module.exports.Unicode11Addon;"; + /// Ints per cell in the packed `meta` array, mirroring `pack()` in the shim. const STRIDE: usize = 6; +/// Rows decoded per `pack` call. Bounds the size of the temporary JS array a +/// full-scrollback read builds; see [`XtermJsEmu::rows_in_range`]. +const PACK_BATCH_ROWS: usize = 256; + /// Color-mode bits, packed alongside the SGR booleans in the `flags` int. const FG_PALETTE: i32 = 256; const FG_RGB: i32 = 512; @@ -93,6 +104,10 @@ pub struct XtermJsEmu { // in it; nothing calls through it directly. _runtime: Runtime, ctx: Context, + /// The size xterm.js actually applied, which is not always the size that + /// was asked for: it clamps to a 2x1 minimum. Caching the *requested* size + /// sheared the grid, because `pack` emits `term.cols` cells per row while + /// the decoder chunks by this value. cols: u16, rows: u16, } @@ -107,18 +122,28 @@ impl XtermJsEmu { // evaluates, not just when the terminal is constructed. ctx.eval::<(), _>(SHIM)?; ctx.eval::<(), _>(XTERM_BUNDLE)?; + ctx.eval::<(), _>(UNICODE11)?; + ctx.eval::<(), _>(UNICODE11_CAPTURE)?; let boot: Function = ctx.globals().get("__boot")?; let emu: Object = boot.call((cols, rows, scrollback as u32))?; ctx.globals().set("__emu", emu)?; Ok(()) })?; - Ok(XtermJsEmu { + let mut emu = XtermJsEmu { _runtime: runtime, ctx, cols, rows, - }) + }; + emu.sync_size(); + Ok(emu) + } + + /// Adopt the size xterm.js settled on. + fn sync_size(&mut self) { + self.cols = self.call::("cols").clamp(0, u16::MAX as i32) as u16; + self.rows = self.call::("rows").clamp(0, u16::MAX as i32) as u16; } /// Call a zero-argument method on the shim's emulator object. @@ -138,58 +163,92 @@ impl XtermJsEmu { .unwrap_or_default() } + /// Decode one packed row span. + /// + /// Rows are read in batches rather than all at once. A full-scrollback + /// grid is 5,000 rows, and packing it in one call builds a JS array of six + /// boxed numbers per cell — 2.4 million of them — which lands above what + /// QuickJS reclaims eagerly and below what makes it collect, so a poll loop + /// calling `full_rows` grew the daemon by tens of megabytes per call. + /// Batching keeps each allocation small enough to be collected between + /// calls. fn rows_in_range(&self, full: bool) -> Vec> { - let cols = self.cols as usize; - let packed = self - .ctx - .with(|ctx| -> rquickjs::Result<(String, Vec)> { - let emu: Object = ctx.globals().get("__emu")?; - let start: i32 = emu.get::<_, Function>("start")?.call((full,))?; - let end: i32 = emu.get::<_, Function>("end")?.call((full,))?; - let packed: rquickjs::Array = emu.get::<_, Function>("pack")?.call((start, end))?; - Ok((packed.get(0)?, packed.get(1)?)) - }); - - let (chars, meta) = match packed { - Ok(p) => p, + let (cols, _) = self.size(); + let cols = cols as usize; + if cols == 0 { + return Vec::new(); + } + + let span = self.ctx.with(|ctx| -> rquickjs::Result<(i32, i32)> { + let emu: Object = ctx.globals().get("__emu")?; + let start: i32 = emu.get::<_, Function>("start")?.call((full,))?; + let end: i32 = emu.get::<_, Function>("end")?.call((full,))?; + Ok((start, end)) + }); + let (start, end) = match span { + Ok(span) => span, Err(_) => return Vec::new(), }; - let mut cells = chars.split('\0'); - let mut out = Vec::with_capacity(meta.len() / STRIDE / cols.max(1)); - let mut row = Vec::with_capacity(cols); - for (i, m) in meta.chunks_exact(STRIDE).enumerate() { - let ch = cells.next().unwrap_or(" "); - let (width, fg, bg, ul_color, ul_style, flags) = (m[0], m[1], m[2], m[3], m[4], m[5]); - - // A zero-width cell is the second column of a double-width - // character. Everything else owns its column, so an empty string - // there is a cell nothing has been printed to and renders blank. - let ch = if width == 0 { - CompactString::const_new(CONTINUATION) - } else if ch.is_empty() { - CompactString::const_new(" ") - } else { - ch.to_compact_string() + let mut out = Vec::with_capacity((end - start).max(0) as usize); + for batch in (start..end).step_by(PACK_BATCH_ROWS) { + let batch_end = (batch + PACK_BATCH_ROWS as i32).min(end); + let packed = self + .ctx + .with(|ctx| -> rquickjs::Result<(String, Vec)> { + let emu: Object = ctx.globals().get("__emu")?; + let packed: rquickjs::Array = + emu.get::<_, Function>("pack")?.call((batch, batch_end))?; + Ok((packed.get(0)?, packed.get(1)?)) + }); + let (chars, meta) = match packed { + Ok(p) => p, + Err(_) => return Vec::new(), }; - - row.push(EmuCell { - ch, - fg: color(fg, flags, FG_PALETTE, FG_RGB), - bg: color(bg, flags, BG_PALETTE, BG_RGB), - underline: underline(ul_style), - underline_color: color(ul_color, flags, UL_PALETTE, UL_RGB), - attrs: attrs(flags), - }); - - if (i + 1) % cols == 0 { - out.push(std::mem::replace(&mut row, Vec::with_capacity(cols))); - } + decode_into(&mut out, &chars, &meta, cols); } out } } +/// Decode a packed batch into whole rows, appending to `out`. +fn decode_into(out: &mut Vec>, chars: &str, meta: &[i32], cols: usize) { + let mut cells = chars.split('\0'); + let mut row = Vec::with_capacity(cols); + for m in meta.chunks_exact(STRIDE) { + let ch = cells.next().unwrap_or(""); + let (width, fg, bg, ul_color, ul_style, flags) = (m[0], m[1], m[2], m[3], m[4], m[5]); + + // Width alone does not identify a continuation. xterm.js also reports + // width 0 for a genuine zero-width grapheme that had no base character + // to combine with (a lone combining mark, ZWSP, ZWJ, or a variation + // selector at the start of a row): that cell owns its column and holds + // real text. Only an *empty* zero-width cell is the second column of a + // double-width character. Reading width alone dropped the grapheme and + // left the row one column short of the grid. + let ch = if !ch.is_empty() { + ch.to_compact_string() + } else if width == 0 { + CompactString::const_new(CONTINUATION) + } else { + CompactString::const_new(" ") + }; + + row.push(EmuCell { + ch, + fg: color(fg, flags, FG_PALETTE, FG_RGB), + bg: color(bg, flags, BG_PALETTE, BG_RGB), + underline: underline(ul_style), + underline_color: color(ul_color, flags, UL_PALETTE, UL_RGB), + attrs: attrs(flags), + }); + + if row.len() == cols { + out.push(std::mem::replace(&mut row, Vec::with_capacity(cols))); + } + } +} + impl Emulator for XtermJsEmu { fn process(&mut self, bytes: &[u8]) { // Fed as bytes rather than as a string on purpose: xterm.js runs its @@ -208,12 +267,15 @@ impl Emulator for XtermJsEmu { } fn resize(&mut self, cols: u16, rows: u16) { + let (cols, rows) = crate::terminal::backend::clamp_size(cols, rows); let _ = self.ctx.with(|ctx| -> rquickjs::Result<()> { let emu: Object = ctx.globals().get("__emu")?; emu.get::<_, Function>("resize")?.call((cols, rows)) }); - self.cols = cols; - self.rows = rows; + // Read the size back rather than trusting the request: xterm.js clamps + // to its 2x1 minimum, and recording a smaller size than the grid it + // actually holds makes every later decode mis-chunk the rows. + self.sync_size(); } fn size(&self) -> (u16, u16) {