@lvce-editor/renderer-process 30.55.2 → 30.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,499 @@
1
+ const omitted = new Set(['SCRIPT', 'STYLE', 'LINK', 'META', 'BASE', 'NOSCRIPT']);
2
+ const unsupported = new Set(['IFRAME', 'WEBVIEW', 'CANVAS', 'OBJECT', 'EMBED', 'VIDEO', 'AUDIO']);
3
+ const attributes$1 = /^(class|style|id|title|role|type|checked|disabled|selected|placeholder|width|height|viewBox|d|fill|stroke|cx|cy|r|x|y|x1|x2|y1|y2|points|transform|xmlns|aria-[\w-]+)$/i;
4
+ const capture = document => {
5
+ const visit = node => {
6
+ if (node.nodeType === 3) return {
7
+ text: node.textContent
8
+ };
9
+ if (node.nodeType !== 1 || omitted.has(node.tagName)) return undefined;
10
+ if (node.hasAttribute('data-session-replay-ignore')) return undefined;
11
+ if (unsupported.has(node.tagName) || node.matches('.Terminal, .TerminalView, .xterm, [data-session-replay-placeholder]')) {
12
+ const {
13
+ width,
14
+ height
15
+ } = node.getBoundingClientRect();
16
+ return {
17
+ tag: 'div',
18
+ attrs: {
19
+ class: 'SessionReplayPlaceholder',
20
+ style: `background:#808080;color:white;width:${width}px;height:${height}px;overflow:hidden`
21
+ },
22
+ children: [{
23
+ text: 'Content unavailable in replay'
24
+ }]
25
+ };
26
+ }
27
+ if (node.matches('[data-session-replay-mask], input[type=password]')) return {
28
+ tag: 'span',
29
+ children: [{
30
+ text: '••••••••'
31
+ }]
32
+ };
33
+ const attrs = Object.fromEntries([...node.attributes].filter(({
34
+ name
35
+ }) => attributes$1.test(name)).map(({
36
+ name,
37
+ value
38
+ }) => [name, value]));
39
+ if (node.tagName === 'IMG' && node.src.startsWith('data:image/')) attrs.src = node.src;
40
+ return {
41
+ tag: node.localName,
42
+ attrs,
43
+ ...(node.namespaceURI === 'http://www.w3.org/2000/svg' ? {
44
+ svg: true
45
+ } : {}),
46
+ ...(typeof node.value === 'string' ? {
47
+ value: node.value
48
+ } : {}),
49
+ ...(typeof node.checked === 'boolean' ? {
50
+ checked: node.checked
51
+ } : {}),
52
+ ...(node.scrollTop || node.scrollLeft ? {
53
+ scroll: [node.scrollLeft, node.scrollTop]
54
+ } : {}),
55
+ children: [...node.childNodes].map(visit).filter(Boolean)
56
+ };
57
+ };
58
+ const styles = [];
59
+ const visitSheet = (sheet, seen = new Set()) => {
60
+ if (!sheet || seen.has(sheet)) return '';
61
+ seen.add(sheet);
62
+ try {
63
+ return [...sheet.cssRules].map(rule => {
64
+ if (rule.type !== 3) return rule.cssText;
65
+ const imported = visitSheet(rule.styleSheet, seen);
66
+ return rule.media.mediaText ? `@media ${rule.media.mediaText} { ${imported} }` : imported;
67
+ }).join('\n');
68
+ } catch {
69
+ return '';
70
+ }
71
+ };
72
+ for (const sheet of [...document.styleSheets, ...document.adoptedStyleSheets]) styles.push(visitSheet(sheet));
73
+ return {
74
+ dom: visit(document.body),
75
+ styles,
76
+ documentElement: {
77
+ className: document.documentElement.className,
78
+ style: document.documentElement.style.cssText
79
+ },
80
+ viewport: [document.defaultView.innerWidth, document.defaultView.innerHeight]
81
+ };
82
+ };
83
+ const observe = (document, record, onError) => {
84
+ let dirty = true;
85
+ let busy = false;
86
+ let stopped = false;
87
+ const mark = () => {
88
+ dirty = true;
89
+ };
90
+ const observer = new MutationObserver(mark);
91
+ observer.observe(document.documentElement, {
92
+ subtree: true,
93
+ childList: true,
94
+ attributes: true,
95
+ characterData: true
96
+ });
97
+ for (const type of ['input', 'change', 'scroll']) document.addEventListener(type, mark, true);
98
+ document.defaultView.addEventListener('resize', mark);
99
+ let lastStyles = '';
100
+ const snapshot = async (force = false) => {
101
+ if (busy || stopped) return;
102
+ busy = true;
103
+ try {
104
+ // CSSStyleSheet.replaceSync/insertRule don't produce DOM mutation records.
105
+ const frame = capture(document);
106
+ const styles = frame.styles.join('\n');
107
+ if (force || dirty || styles !== lastStyles) {
108
+ dirty = false;
109
+ lastStyles = styles;
110
+ await record('frame', frame);
111
+ }
112
+ } catch (error) {
113
+ onError(error);
114
+ } finally {
115
+ busy = false;
116
+ }
117
+ };
118
+ void snapshot(true);
119
+ const timer = setInterval(snapshot, 100);
120
+ return () => {
121
+ stopped = true;
122
+ clearInterval(timer);
123
+ observer.disconnect();
124
+ for (const type of ['input', 'change', 'scroll']) document.removeEventListener(type, mark, true);
125
+ document.defaultView.removeEventListener('resize', mark);
126
+ };
127
+ };
128
+ const serializeMessage = message => {
129
+ const seen = new WeakSet();
130
+ return JSON.parse(JSON.stringify(message, (key, value) => {
131
+ if (/password|token|secret|authorization|cookie/i.test(key)) return '[redacted]';
132
+ if (typeof value === 'bigint') return String(value);
133
+ if (typeof value !== 'object' || value === null) return value;
134
+ if (seen.has(value)) return '[circular]';
135
+ seen.add(value);
136
+ if (value instanceof Error) return {
137
+ name: value.name,
138
+ message: value.message,
139
+ stack: value.stack
140
+ };
141
+ if (value instanceof ArrayBuffer || ArrayBuffer.isView(value)) return {
142
+ type: value.constructor.name,
143
+ byteLength: value.byteLength
144
+ };
145
+ if (value.constructor?.name === 'MessagePort') return {
146
+ type: 'MessagePort'
147
+ };
148
+ return value;
149
+ }));
150
+ };
151
+
152
+ const createClient = url => {
153
+ const worker = new Worker(url, {
154
+ type: 'module',
155
+ name: 'Session Replay Worker'
156
+ });
157
+ const callbacks = new Map();
158
+ let nextId = 0;
159
+ let disposed = false;
160
+ const fail = error => {
161
+ for (const {
162
+ reject
163
+ } of callbacks.values()) reject(error);
164
+ callbacks.clear();
165
+ };
166
+ worker.onmessage = ({
167
+ data
168
+ }) => {
169
+ const callback = callbacks.get(data.id);
170
+ if (!callback) return;
171
+ callbacks.delete(data.id);
172
+ if (data.error) callback.reject(new Error(data.error));else callback.resolve(data.result);
173
+ };
174
+ worker.onerror = () => {
175
+ disposed = true;
176
+ worker.terminate();
177
+ fail(new Error('Session replay worker failed to load'));
178
+ };
179
+ return {
180
+ invoke(method, ...params) {
181
+ if (disposed) return Promise.reject(new Error('Session replay worker is closed'));
182
+ return new Promise((resolve, reject) => {
183
+ const id = nextId++;
184
+ callbacks.set(id, {
185
+ resolve,
186
+ reject
187
+ });
188
+ try {
189
+ worker.postMessage({
190
+ id,
191
+ method,
192
+ params
193
+ });
194
+ } catch (error) {
195
+ callbacks.delete(id);
196
+ reject(error);
197
+ }
198
+ });
199
+ },
200
+ dispose() {
201
+ disposed = true;
202
+ worker.terminate();
203
+ fail(new Error('Session replay worker is closed'));
204
+ }
205
+ };
206
+ };
207
+
208
+ const tags = new Set('body div span p pre code main section article header footer nav aside h1 h2 h3 h4 h5 h6 ul ol li table thead tbody tr td th button input textarea select option label form fieldset legend a img br hr strong em b i u s small details summary svg path rect circle ellipse line polyline polygon g defs clipPath text tspan'.split(' '));
209
+ const attributes = /^(class|style|id|title|role|type|checked|disabled|selected|placeholder|width|height|viewBox|d|fill|stroke|cx|cy|r|x|y|x1|x2|y1|y2|points|transform|xmlns|aria-[\w-]+)$/i;
210
+ const renderFrame = (document, frame) => {
211
+ let count = 0;
212
+ const scrolls = [];
213
+ const visit = (value, depth = 0) => {
214
+ if (++count > 100_000 || depth > 150 || !value || typeof value !== 'object') throw new Error('Invalid replay DOM');
215
+ if (typeof value.text === 'string') return document.createTextNode(value.text);
216
+ const tag = tags.has(value.tag) ? value.tag : 'div';
217
+ const node = value.svg ? document.createElementNS('http://www.w3.org/2000/svg', tag) : document.createElement(tag);
218
+ for (const [key, val] of Object.entries(value.attrs || {})) {
219
+ if (attributes.test(key) && typeof val === 'string') node.setAttribute(key, val);
220
+ if (key === 'src' && tag === 'img' && typeof val === 'string' && /^data:image\/(png|jpeg|gif|webp);base64,/.test(val)) node.setAttribute(key, val);
221
+ }
222
+ if (typeof value.value === 'string' && 'value' in node && node.type !== 'file') node.value = value.value;
223
+ if (typeof value.checked === 'boolean') node.checked = value.checked;
224
+ for (const child of value.children || []) node.append(visit(child, depth + 1));
225
+ if (Array.isArray(value.scroll)) scrolls.push([node, value.scroll]);
226
+ return node;
227
+ };
228
+ const root = visit(frame.dom);
229
+ const style = document.createElement('style');
230
+ style.textContent = (frame.styles || []).filter(value => typeof value === 'string').join('\n');
231
+ document.head.querySelectorAll('style').forEach(node => node.remove());
232
+ document.head.append(style);
233
+ document.documentElement.className = typeof frame.documentElement?.className === 'string' ? frame.documentElement.className : '';
234
+ document.documentElement.style.cssText = typeof frame.documentElement?.style === 'string' ? frame.documentElement.style : '';
235
+ if (root.nodeName === 'BODY') document.body.replaceWith(root);else document.body.replaceChildren(root);
236
+ for (const [node, [x, y]] of scrolls) node.scrollTo(x, y);
237
+ };
238
+ const mountPlayer = async (container, {
239
+ workerUrl,
240
+ source
241
+ }) => {
242
+ const client = createClient(workerUrl);
243
+ container.replaceChildren();
244
+ container.className = 'SessionReplay';
245
+ container.style.cssText = 'position:fixed;inset:0;display:flex;flex-direction:column;background:#202020;color:white;z-index:2147483647';
246
+ const document = container.ownerDocument;
247
+ const viewport = document.createElement('div');
248
+ viewport.style.cssText = 'flex:1;min-height:0;overflow:auto;position:relative';
249
+ const iframe = document.createElement('iframe');
250
+ iframe.title = 'Recorded session';
251
+ iframe.setAttribute('sandbox', 'allow-same-origin');
252
+ iframe.style.cssText = 'border:0;pointer-events:none;display:block';
253
+ const loaded = new Promise(resolve => {
254
+ iframe.onload = resolve;
255
+ });
256
+ // An opaque, inert visual document: recorded markup cannot run scripts, submit forms or fetch URLs.
257
+ iframe.srcdoc = '<!doctype html><html><head><meta http-equiv="Content-Security-Policy" content="default-src &#39;none&#39;; style-src &#39;unsafe-inline&#39;; img-src data:; font-src data:"></head><body></body></html>';
258
+ viewport.append(iframe);
259
+ const controls = document.createElement('div');
260
+ controls.style.cssText = 'display:flex;gap:12px;align-items:center;padding:12px;font:14px sans-serif;background:#202020;color:white';
261
+ const play = document.createElement('button');
262
+ play.textContent = 'Play';
263
+ const slider = document.createElement('input');
264
+ slider.type = 'range';
265
+ slider.min = '0';
266
+ slider.step = '1';
267
+ slider.value = '0';
268
+ slider.setAttribute('aria-label', 'Session replay position');
269
+ slider.style.flex = '1';
270
+ const status = document.createElement('output');
271
+ status.setAttribute('aria-live', 'polite');
272
+ controls.append(play, slider, status);
273
+ container.append(viewport, controls);
274
+ let disposed = false;
275
+ let playing = false;
276
+ let timer;
277
+ let requestId = 0;
278
+ let position = 0;
279
+ let duration = 0;
280
+ const show = result => {
281
+ position = result.position;
282
+ duration = result.duration;
283
+ slider.max = String(Math.ceil(duration));
284
+ slider.value = String(Math.round(position));
285
+ status.textContent = `${(position / 1000).toFixed(1)} / ${(duration / 1000).toFixed(1)} s`;
286
+ const [width, height] = result.frame.viewport || [1280, 720];
287
+ iframe.style.width = `${Math.max(1, Math.min(16384, width))}px`;
288
+ iframe.style.height = `${Math.max(1, Math.min(16384, height))}px`;
289
+ renderFrame(iframe.contentDocument, result.frame);
290
+ };
291
+ const pause = () => {
292
+ playing = false;
293
+ clearTimeout(timer);
294
+ play.textContent = 'Play';
295
+ };
296
+ const seek = async time => {
297
+ const id = ++requestId;
298
+ const result = await client.invoke('seek', time);
299
+ if (!disposed && id === requestId) show(result);
300
+ };
301
+ const report = error => {
302
+ pause();
303
+ status.textContent = error.message;
304
+ };
305
+ slider.oninput = () => {
306
+ pause();
307
+ void seek(Number(slider.value)).catch(report);
308
+ };
309
+ play.onclick = () => {
310
+ if (playing) {
311
+ pause();
312
+ return;
313
+ }
314
+ playing = true;
315
+ play.textContent = 'Pause';
316
+ const origin = performance.now() - (position >= duration ? 0 : position);
317
+ const tick = async () => {
318
+ if (!playing || disposed) return;
319
+ try {
320
+ await seek(performance.now() - origin);
321
+ if (position >= duration) pause();else if (playing) timer = setTimeout(tick, 50);
322
+ } catch (error) {
323
+ report(error);
324
+ }
325
+ };
326
+ void tick();
327
+ };
328
+ try {
329
+ const [initial] = await Promise.all([client.invoke('load', source), loaded]);
330
+ show(initial);
331
+ } catch (error) {
332
+ play.disabled = slider.disabled = true;
333
+ report(error);
334
+ }
335
+ return () => {
336
+ disposed = true;
337
+ pause();
338
+ client.dispose();
339
+ container.replaceChildren();
340
+ };
341
+ };
342
+
343
+ const state$h = {
344
+ client: undefined,
345
+ inFlight: 0,
346
+ lastError: '',
347
+ stopObserving: undefined
348
+ };
349
+ const attached = new WeakSet();
350
+ const workerUrl = new URL('sessionReplayWorkerMain.js', import.meta.url);
351
+ const report = error => {
352
+ state$h.lastError = error.message;
353
+ state$h.stopObserving?.();
354
+ state$h.stopObserving = undefined;
355
+ console.warn(`Session replay: ${error.message}`);
356
+ };
357
+ const record$1 = (direction, message) => {
358
+ if (!state$h.client || state$h.lastError) return;
359
+ if (state$h.inFlight >= 500) {
360
+ report(new Error('Recording cannot keep up with renderer messages'));
361
+ return;
362
+ }
363
+ try {
364
+ const value = serializeMessage({
365
+ direction,
366
+ message
367
+ });
368
+ state$h.inFlight++;
369
+ void state$h.client.invoke('record', 'message', value).catch(report).finally(() => {
370
+ state$h.inFlight--;
371
+ });
372
+ } catch (error) {
373
+ report(error);
374
+ }
375
+ };
376
+
377
+ // Observe the actual transports, including messages on direct view-worker ports.
378
+ // The recording path never changes or delays the original message or transfer list.
379
+ const attach = rpc => {
380
+ const ipc = rpc.ipc;
381
+ if (!ipc || attached.has(ipc)) return;
382
+ attached.add(ipc);
383
+ const ignoredReplies = {
384
+ received: new Set(),
385
+ sent: new Set()
386
+ };
387
+ const trace = (direction, message) => {
388
+ if (message?.method?.startsWith('SessionReplay.')) {
389
+ if (message.id !== undefined) ignoredReplies[direction === 'received' ? 'sent' : 'received'].add(message.id);
390
+ return;
391
+ }
392
+ if (message && ('result' in message || 'error' in message) && ignoredReplies[direction].delete(message.id)) return;
393
+ record$1(direction, message);
394
+ };
395
+ if (typeof ipc.addEventListener === 'function') {
396
+ ipc.addEventListener('message', event => trace('received', ipc.getData ? ipc.getData(event) : event.data));
397
+ }
398
+ for (const name of ['send', 'sendAndTransfer']) {
399
+ if (typeof ipc[name] !== 'function') continue;
400
+ const original = ipc[name].bind(ipc);
401
+ ipc[name] = (...args) => {
402
+ trace('sent', args[0]);
403
+ return original(...args);
404
+ };
405
+ }
406
+ };
407
+ const configure = async options => {
408
+ state$h.stopObserving?.();
409
+ state$h.stopObserving = undefined;
410
+ if (state$h.client) {
411
+ try {
412
+ await state$h.client.invoke('stop');
413
+ } catch {
414
+ /* Preserve already saved local data when an upload is unavailable. */
415
+ }
416
+ state$h.client.dispose();
417
+ state$h.client = undefined;
418
+ }
419
+ state$h.lastError = '';
420
+ if (!options.local && !options.upload) return '';
421
+ const next = createClient(workerUrl);
422
+ try {
423
+ const id = await next.invoke('start', options);
424
+ state$h.client = next;
425
+ state$h.stopObserving = observe(document, (type, data) => next.invoke('record', type, data), report);
426
+ return id;
427
+ } catch (error) {
428
+ next.dispose();
429
+ throw error;
430
+ }
431
+ };
432
+ const getSession = async () => {
433
+ if (!state$h.client) throw new Error('Session replay is disabled in settings');
434
+ return state$h.client.invoke('export');
435
+ };
436
+ const getStatus = async () => {
437
+ if (!state$h.client) return {
438
+ enabled: false,
439
+ error: state$h.lastError
440
+ };
441
+ return {
442
+ enabled: true,
443
+ ...(await state$h.client.invoke('status')),
444
+ captureError: state$h.lastError
445
+ };
446
+ };
447
+ const flush = async () => state$h.client?.invoke('flush');
448
+ const openLocalFile = async () => {
449
+ const input = document.createElement('input');
450
+ input.type = 'file';
451
+ input.accept = '.json,application/json';
452
+ input.onchange = async () => {
453
+ const file = input.files?.[0];
454
+ if (!file) return;
455
+ try {
456
+ if (file.size > 64 * 1024 * 1024) throw new Error('Session replay file is too large');
457
+ const session = JSON.parse(await file.text());
458
+ await configure({
459
+ endpoint: '',
460
+ local: false,
461
+ upload: false
462
+ });
463
+ await mountPlayer(document.body, {
464
+ source: {
465
+ session
466
+ },
467
+ workerUrl
468
+ });
469
+ } catch (error) {
470
+ console.error(error);
471
+ }
472
+ };
473
+ input.click();
474
+ };
475
+
476
+ // Replay gets its own layout before any editor, extension or shared worker starts.
477
+ const initializeLayout = async href => {
478
+ const url = new URL(href);
479
+ const localId = url.searchParams.get('replayId');
480
+ if (!localId && !url.searchParams.has('sessionReplay')) return false;
481
+ if (localId) await mountPlayer(document.body, {
482
+ source: {
483
+ localId
484
+ },
485
+ workerUrl
486
+ });else {
487
+ const button = document.createElement('button');
488
+ button.textContent = 'Open session replay file';
489
+ button.onclick = () => {
490
+ void openLocalFile();
491
+ };
492
+ document.body.replaceChildren(button);
493
+ }
494
+ return true;
495
+ };
496
+
1
497
  const play = async src => {
2
498
  const audio = new Audio(src);
3
499
  await audio.play();
@@ -2094,6 +2590,7 @@ const registerRpc = (rpcId, rpc) => {
2094
2590
  if (previous && previous !== rpc) {
2095
2591
  previous.dispose();
2096
2592
  }
2593
+ attach(rpc);
2097
2594
  rpcs.set(rpcId, rpc);
2098
2595
  };
2099
2596
  const registerView = (uid, rpcId) => {
@@ -2797,6 +3294,9 @@ const restoreExistingError = (error, currentStack) => {
2797
3294
  };
2798
3295
  const restoreMethodNotFoundError = (error, currentStack) => {
2799
3296
  const restoredError = new JsonRpcError(error.message);
3297
+ Object.assign(restoredError, {
3298
+ code: error.code
3299
+ });
2800
3300
  const parentStack = getParentStack(error);
2801
3301
  setStack(restoredError, `${parentStack}${NewLine$1}${currentStack}`);
2802
3302
  return restoredError;
@@ -2816,9 +3316,13 @@ const applyDataProperties = (restoredError, error) => {
2816
3316
  // @ts-ignore
2817
3317
  restoredError.codeFrame = error.data.codeFrame;
2818
3318
  }
2819
- if (error.data.code) {
3319
+ if (typeof error.data.code === 'string' || typeof error.data.code === 'number') {
2820
3320
  // @ts-ignore
2821
- restoredError.code = error.data.code;
3321
+ Object.defineProperty(restoredError, 'code', {
3322
+ configurable: true,
3323
+ value: error.data.code,
3324
+ writable: true
3325
+ });
2822
3326
  }
2823
3327
  if (error.data.type) {
2824
3328
  // @ts-ignore
@@ -2840,6 +3344,13 @@ const applyDirectProperties = (restoredError, error) => {
2840
3344
  };
2841
3345
  const restoreMessageError = (error, _currentStack) => {
2842
3346
  const restoredError = constructError(error.message, error.type, error.name);
3347
+ if (typeof error.code === 'string' || typeof error.code === 'number') {
3348
+ Object.defineProperty(restoredError, 'code', {
3349
+ configurable: true,
3350
+ value: error.code,
3351
+ writable: true
3352
+ });
3353
+ }
2843
3354
  if (error.data) {
2844
3355
  applyDataProperties(restoredError, error);
2845
3356
  } else {
@@ -2918,7 +3429,7 @@ const getErrorProperty = (error, prettyError) => {
2918
3429
  return {
2919
3430
  code: Custom,
2920
3431
  data: {
2921
- code: prettyError.code,
3432
+ code: prettyError.code ?? error?.code,
2922
3433
  codeFrame: prettyError.codeFrame,
2923
3434
  name: prettyError.name,
2924
3435
  stack: getStack(prettyError),
@@ -2955,7 +3466,12 @@ const getErrorResponseSimple = (id, error) => {
2955
3466
  return {
2956
3467
  error: {
2957
3468
  code: Custom,
2958
- data: error,
3469
+ data: error instanceof Error ? {
3470
+ ...error,
3471
+ code: 'code' in error ? error.code : undefined,
3472
+ stack: error.stack,
3473
+ type: error.name
3474
+ } : error,
2959
3475
  // @ts-ignore
2960
3476
  message: error.message
2961
3477
  },
@@ -3343,6 +3859,7 @@ const launchDragAndDropWorker = async () => {
3343
3859
  commandMap: commandMapRef,
3344
3860
  messagePort: port2
3345
3861
  });
3862
+ attach(rpc);
3346
3863
  return success(rpc);
3347
3864
  } catch (error$1) {
3348
3865
  return error(error$1);
@@ -3521,6 +4038,7 @@ const launchWorker = async ({
3521
4038
  name,
3522
4039
  url
3523
4040
  });
4041
+ attach(rpc);
3524
4042
  return success(rpc);
3525
4043
  } catch (error$1) {
3526
4044
  return error(error$1);
@@ -4084,6 +4602,7 @@ const create$v = async ({
4084
4602
  commandMap: {},
4085
4603
  window
4086
4604
  });
4605
+ attach(rpc);
4087
4606
  const webContentsIds = await rpc.invokeAndTransfer('CreateMessagePort.createMessagePort', ipcId, port);
4088
4607
  return webContentsIds;
4089
4608
  };
@@ -4534,7 +5053,6 @@ const setHeight = ($Element, height) => {
4534
5053
 
4535
5054
  const FocusLocationList = 17;
4536
5055
  const FocusMenu = 18;
4537
- const FocusSimpleBrowserInput = 23;
4538
5056
  const FocusOutput = 28;
4539
5057
 
4540
5058
  // TODO when pressing tab -> focus next element in tab order and close menu
@@ -5912,10 +6430,10 @@ const handleMouseDown$3 = event => {
5912
6430
  const index = getNodeIndex($Item);
5913
6431
  return ['handleClickIndex', button, index, clientX, clientY];
5914
6432
  };
5915
- const handleBlur$7 = () => {
6433
+ const handleBlur$6 = () => {
5916
6434
  return ['handleBlur'];
5917
6435
  };
5918
- const handleFocus$9 = () => {
6436
+ const handleFocus$8 = () => {
5919
6437
  return ['handleFocus'];
5920
6438
  };
5921
6439
 
@@ -5934,9 +6452,9 @@ const returnValue$8 = true;
5934
6452
 
5935
6453
  const ViewletActivityBarEvents = {
5936
6454
  __proto__: null,
5937
- handleBlur: handleBlur$7,
6455
+ handleBlur: handleBlur$6,
5938
6456
  handleContextMenu: handleContextMenu$6,
5939
- handleFocus: handleFocus$9,
6457
+ handleFocus: handleFocus$8,
5940
6458
  handleMouseDown: handleMouseDown$3,
5941
6459
  returnValue: returnValue$8
5942
6460
  };
@@ -5999,7 +6517,7 @@ forwardViewletCommand('focusPrevious');
5999
6517
  const handleAudioError$1 = forwardViewletCommand('handleAudioError');
6000
6518
  forwardViewletCommand('handleBeforeInput');
6001
6519
  forwardViewletCommand('handleBeforeInputFromContentEditable');
6002
- const handleBlur$6 = forwardViewletCommand('handleBlur');
6520
+ const handleBlur$5 = forwardViewletCommand('handleBlur');
6003
6521
  const handleButtonClick = forwardViewletCommand('handleButtonClick');
6004
6522
  const handleClick$6 = forwardViewletCommand('handleClick');
6005
6523
  const handleClickAction$2 = forwardViewletCommand('handleClickAction');
@@ -6027,11 +6545,11 @@ forwardViewletCommand('handleClickSize');
6027
6545
  forwardViewletCommand('handleClickDisable');
6028
6546
  forwardViewletCommand('handleClickUninstall');
6029
6547
  forwardViewletCommand('handleFilterInput');
6030
- const handleFocus$8 = forwardViewletCommand('handleFocus');
6548
+ const handleFocus$7 = forwardViewletCommand('handleFocus');
6031
6549
  const handleFocusIn$4 = forwardViewletCommand('handleFocusIn');
6032
6550
  forwardViewletCommand('handleIconError');
6033
6551
  const handleImageError = forwardViewletCommand('handleImageError');
6034
- const handleInput$6 = forwardViewletCommand('handleInput');
6552
+ const handleInput$4 = forwardViewletCommand('handleInput');
6035
6553
  const handleKeyDown$3 = forwardViewletCommand('handleKeyDown');
6036
6554
  const handleLink = forwardViewletCommand('handleLink');
6037
6555
  forwardViewletCommand('handleListBlur');
@@ -6257,7 +6775,7 @@ const ViewletColorPicker = {
6257
6775
  setOffsetX
6258
6776
  };
6259
6777
 
6260
- const handleInput$5 = event => {
6778
+ const handleInput$3 = event => {
6261
6779
  const uid = fromEvent(event);
6262
6780
  const {
6263
6781
  target
@@ -6265,17 +6783,17 @@ const handleInput$5 = event => {
6265
6783
  const {
6266
6784
  value
6267
6785
  } = target;
6268
- handleInput$6(uid, value);
6786
+ handleInput$4(uid, value);
6269
6787
  };
6270
- const handleFocus$7 = event => {
6788
+ const handleFocus$6 = event => {
6271
6789
  const uid = fromEvent(event);
6272
- handleFocus$8(uid);
6790
+ handleFocus$7(uid);
6273
6791
  };
6274
6792
 
6275
6793
  const ViewletDebugConsoleEvents = {
6276
6794
  __proto__: null,
6277
- handleFocus: handleFocus$7,
6278
- handleInput: handleInput$5
6795
+ handleFocus: handleFocus$6,
6796
+ handleInput: handleInput$3
6279
6797
  };
6280
6798
 
6281
6799
  const create$n = () => {
@@ -6311,14 +6829,14 @@ const handleKeyDown$2 = event => {
6311
6829
  } = event;
6312
6830
  handleKeyDown$3(uid, key, altKey, ctrlKey, shiftKey, metaKey);
6313
6831
  };
6314
- const handleBlur$5 = event => {
6832
+ const handleBlur$4 = event => {
6315
6833
  const uid = fromEvent(event);
6316
- handleBlur$6(uid);
6834
+ handleBlur$5(uid);
6317
6835
  };
6318
6836
 
6319
6837
  const ViewletDefineKeyBindingEvents = {
6320
6838
  __proto__: null,
6321
- handleBlur: handleBlur$5,
6839
+ handleBlur: handleBlur$4,
6322
6840
  handleKeyDown: handleKeyDown$2
6323
6841
  };
6324
6842
 
@@ -6676,15 +7194,15 @@ const handleFocusIn$3 = event => {
6676
7194
  const uid = fromEvent(event);
6677
7195
  handleFocusIn$4(uid);
6678
7196
  };
6679
- const handleBlur$4 = event => {
7197
+ const handleBlur$3 = event => {
6680
7198
  preventDefault(event);
6681
7199
  const uid = fromEvent(event);
6682
- handleBlur$6(uid);
7200
+ handleBlur$5(uid);
6683
7201
  };
6684
7202
 
6685
7203
  const ViewletEditorCodeGeneratorEvents = {
6686
7204
  __proto__: null,
6687
- handleBlur: handleBlur$4,
7205
+ handleBlur: handleBlur$3,
6688
7206
  handleFocusIn: handleFocusIn$3
6689
7207
  };
6690
7208
 
@@ -7187,9 +7705,9 @@ const handleError$4 = event => {
7187
7705
  const uid = fromEvent(event);
7188
7706
  handleImageError(uid);
7189
7707
  };
7190
- const handleFocus$6 = event => {
7708
+ const handleFocus$5 = event => {
7191
7709
  const uid = fromEvent(event);
7192
- handleFocus$8(uid);
7710
+ handleFocus$7(uid);
7193
7711
  };
7194
7712
 
7195
7713
  const create$i = () => {
@@ -7205,7 +7723,7 @@ const attachEvents$4 = state => {
7205
7723
  } = state;
7206
7724
  attachEvents$7($Viewlet, {
7207
7725
  [ContextMenu]: handleContextMenu$2,
7208
- [FocusIn]: handleFocus$6,
7726
+ [FocusIn]: handleFocus$5,
7209
7727
  [PointerDown]: handlePointerDown$1,
7210
7728
  [PointerUp]: handlePointerUp
7211
7729
  });
@@ -7464,7 +7982,7 @@ const ViewletExtensionView = {
7464
7982
  setIframe: setIframe$1
7465
7983
  };
7466
7984
 
7467
- const handleInput$4 = event => {
7985
+ const handleInput$2 = event => {
7468
7986
  const {
7469
7987
  target
7470
7988
  } = event;
@@ -7512,7 +8030,7 @@ const handleReplaceInput = event => {
7512
8030
  const handleReplaceFocus = event => {
7513
8031
  return ['FindWidget.handleReplaceFocus'];
7514
8032
  };
7515
- const handleFocus$5 = event => {
8033
+ const handleFocus$4 = event => {
7516
8034
  return ['FindWidget.handleFocus'];
7517
8035
  };
7518
8036
  const handleToggleReplaceFocus = event => {
@@ -7540,12 +8058,12 @@ const ViewletFindWidgetEvents = {
7540
8058
  handleClickReplace,
7541
8059
  handleClickReplaceAll,
7542
8060
  handleClickToggleReplace,
7543
- handleFocus: handleFocus$5,
8061
+ handleFocus: handleFocus$4,
7544
8062
  handleFocusClose,
7545
8063
  handleFocusNext,
7546
8064
  handleFocusPrevious,
7547
8065
  handleFocusReplaceAll,
7548
- handleInput: handleInput$4,
8066
+ handleInput: handleInput$2,
7549
8067
  handleInputBlur,
7550
8068
  handleReplaceFocus,
7551
8069
  handleReplaceInput,
@@ -7885,10 +8403,10 @@ const handleSashDoubleClick$1 = id => {
7885
8403
  const handleResize$1 = (width, height) => {
7886
8404
  send$1('Layout.handleResize', width, height);
7887
8405
  };
7888
- const handleFocus$4 = () => {
8406
+ const handleFocus$3 = () => {
7889
8407
  send$1('Layout.handleFocus');
7890
8408
  };
7891
- const handleBlur$3 = () => {
8409
+ const handleBlur$2 = () => {
7892
8410
  send$1('Layout.handleBlur');
7893
8411
  };
7894
8412
 
@@ -7934,11 +8452,11 @@ const handleResize = () => {
7934
8452
  } = window;
7935
8453
  handleResize$1(innerWidth, innerHeight);
7936
8454
  };
7937
- const handleFocus$3 = () => {
7938
- handleFocus$4();
8455
+ const handleFocus$2 = () => {
8456
+ handleFocus$3();
7939
8457
  };
7940
- const handleBlur$2 = () => {
7941
- handleBlur$3();
8458
+ const handleBlur$1 = () => {
8459
+ handleBlur$2();
7942
8460
  };
7943
8461
  const handleKeyDown = handleKeyDown$1;
7944
8462
  const handleKeyUp = handleKeyUp$1;
@@ -7978,8 +8496,8 @@ const attachEvents$3 = state => {
7978
8496
  [PointerDown]: handleSashPointerDown
7979
8497
  });
7980
8498
  attachEvents$7(window, {
7981
- [Blur]: handleBlur$2,
7982
- [Focus]: handleFocus$3,
8499
+ [Blur]: handleBlur$1,
8500
+ [Focus]: handleFocus$2,
7983
8501
  [KeyDown]: handleKeyDown,
7984
8502
  [KeyUp]: handleKeyUp,
7985
8503
  [Resize]: handleResize
@@ -8420,186 +8938,8 @@ const ViewletSidebar = {
8420
8938
  setTitle
8421
8939
  };
8422
8940
 
8423
- const pendingSelections = new WeakMap();
8424
- const state$2 = {};
8425
- const handleFocus$2 = event => {
8426
- const target = event.target;
8427
- if (target instanceof HTMLElement && !target.closest('.SimpleBrowser') && target.closest('.Main, .Panel, .Editor, .Terminal')) {
8428
- state$2.codingFocus = new WeakRef(target);
8429
- }
8430
- };
8431
- const listen = () => {
8432
- document.addEventListener('focusin', handleFocus$2);
8433
- };
8434
- const restoreCodingFocus$1 = () => {
8435
- const target = state$2.codingFocus?.deref();
8436
- if (!target?.isConnected) {
8437
- return false;
8438
- }
8439
- target.focus({
8440
- preventScroll: true
8441
- });
8442
- return document.activeElement === target;
8443
- };
8444
- const getAddress = uid => {
8445
- return get$a(uid)?.state.$Viewlet.querySelector('[name="simple-browser-address"]');
8446
- };
8447
- const captureBrowserAddress$1 = uid => {
8448
- const address = getAddress(uid);
8449
- return address && document.activeElement === address ? {
8450
- end: address.selectionEnd,
8451
- start: address.selectionStart
8452
- } : undefined;
8453
- };
8454
- const queueBrowserAddressSelection = address => {
8455
- clearTimeout(pendingSelections.get(address));
8456
- const timer = setTimeout(() => {
8457
- pendingSelections.delete(address);
8458
- if (!address.isConnected) return;
8459
- const suggestions = address.closest('.SimpleBrowser')?.querySelector('.SimpleBrowserSuggestions');
8460
- if (suggestions) address.setSelectionRange(address.value.length, address.value.length);else address.select();
8461
- });
8462
- pendingSelections.set(address, timer);
8463
- };
8464
- const focusBrowserAddress$1 = (uid, selection) => {
8465
- const address = getAddress(uid);
8466
- if (!address) return;
8467
- address.focus({
8468
- preventScroll: true
8469
- });
8470
- clearTimeout(pendingSelections.get(address));
8471
- pendingSelections.delete(address);
8472
- if (selection) address.setSelectionRange(selection.start, selection.end);else address.select();
8473
- };
8474
- const revealBrowserTab$1 = uid => {
8475
- const root = get$a(uid)?.state.$Viewlet;
8476
- root?.querySelector('.SimpleBrowserTabSelected')?.scrollIntoView({
8477
- block: 'nearest',
8478
- inline: 'nearest'
8479
- });
8480
- };
8481
- const browserParents = new Map();
8482
- const rememberBrowserParent$1 = uid => {
8483
- if (browserParents.has(uid)) return;
8484
- const browser = get$a(uid)?.state.$Viewlet;
8485
- if (!browser?.parentNode) return;
8486
- const marker = document.createComment('browser workspace position');
8487
- browser.before(marker);
8488
- browserParents.set(uid, marker);
8489
- };
8490
- const restoreBrowserParent$1 = uid => {
8491
- const marker = browserParents.get(uid);
8492
- browserParents.delete(uid);
8493
- if (!marker) return;
8494
- const browser = get$a(uid)?.state.$Viewlet;
8495
- if (browser && marker.isConnected) marker.replaceWith(browser);else marker.remove();
8496
- };
8497
-
8498
- const handleInput$3 = value => {
8499
- send$1('SimpleBrowser.handleInput', value);
8500
- };
8501
- const acceptSuggestion = value => {
8502
- send$1('SimpleBrowser.acceptSuggestion', value);
8503
- };
8504
- const closeSuggestions = () => {
8505
- send$1('SimpleBrowser.closeSuggestions');
8506
- };
8507
- const forward = () => {
8508
- send$1('SimpleBrowser.forward');
8509
- };
8510
- const backward = () => {
8511
- send$1('SimpleBrowser.backward');
8512
- };
8513
- const reload$1 = () => {
8514
- send$1('SimpleBrowser.reload');
8515
- };
8516
- const cancelNavigation = () => {
8517
- send$1('SimpleBrowser.cancelNavigation');
8518
- };
8519
- const openExternal = () => {
8520
- send$1('SimpleBrowser.openExternal');
8521
- };
8522
-
8523
- const simpleBrowserAddressName = 'simple-browser-address';
8524
- const handleInput$2 = event => {
8525
- const {
8526
- target
8527
- } = event;
8528
- const {
8529
- value
8530
- } = target;
8531
- handleInput$3(value);
8532
- };
8533
- const handleClickSuggestion = event => {
8534
- const suggestion = event.target.closest?.('.SimpleBrowserSuggestion');
8535
- const value = suggestion?.dataset.value;
8536
- if (typeof value !== 'string') {
8537
- return;
8538
- }
8539
- acceptSuggestion(value);
8540
- };
8541
- const handleFocus$1 = event => {
8542
- const {
8543
- target
8544
- } = event;
8545
- send$1('Focus.setFocus', FocusSimpleBrowserInput);
8546
- queueBrowserAddressSelection(target);
8547
- };
8548
- const handleBlur$1 = event => {
8549
- const {
8550
- relatedTarget,
8551
- target
8552
- } = event;
8553
- setTimeout(() => {
8554
- if (!target.isConnected) {
8555
- return;
8556
- }
8557
- if (target.ownerDocument.activeElement?.getAttribute('name') === simpleBrowserAddressName) {
8558
- return;
8559
- }
8560
- target.setSelectionRange(0, 0);
8561
- if (!relatedTarget?.closest?.('.SimpleBrowserSuggestions')) {
8562
- closeSuggestions();
8563
- }
8564
- });
8565
- };
8566
- const handleClickForward = () => {
8567
- forward();
8568
- };
8569
- const handleClickBackward = () => {
8570
- backward();
8571
- };
8572
- const handleClickReload = event => {
8573
- const {
8574
- target
8575
- } = event;
8576
- // TODO maybe set data attribute to check if it is a cancel button
8577
- // TODO do checks in renderer worker
8578
- if (target.title === 'Cancel') {
8579
- cancelNavigation();
8580
- } else {
8581
- reload$1();
8582
- }
8583
- };
8584
- const handleClickOpenExternal = () => {
8585
- openExternal();
8586
- };
8587
-
8588
- const ViewletSimpleBrowserEvents = {
8589
- __proto__: null,
8590
- handleBlur: handleBlur$1,
8591
- handleClickBackward,
8592
- handleClickForward,
8593
- handleClickOpenExternal,
8594
- handleClickReload,
8595
- handleClickSuggestion,
8596
- handleFocus: handleFocus$1,
8597
- handleInput: handleInput$2
8598
- };
8599
-
8600
8941
  const ViewletSimpleBrowser = {
8601
- __proto__: null,
8602
- Events: ViewletSimpleBrowserEvents
8942
+ __proto__: null
8603
8943
  };
8604
8944
 
8605
8945
  const ViewletSimpleBrowserHistory = {
@@ -8617,9 +8957,9 @@ const handleContextMenu$1 = event => {
8617
8957
  handleContextMenu$5(uid, button, clientX, clientY);
8618
8958
  };
8619
8959
 
8620
- const handleFocus = event => {
8960
+ const handleFocus$1 = event => {
8621
8961
  const uid = fromEvent(event);
8622
- handleFocus$8(uid);
8962
+ handleFocus$7(uid);
8623
8963
  };
8624
8964
  const getButtonIndex = $Node => {
8625
8965
  let index = -1;
@@ -8687,14 +9027,14 @@ const handleInput$1 = event => {
8687
9027
  value
8688
9028
  } = target;
8689
9029
  const uid = fromEvent(event);
8690
- handleInput$6(uid, value);
9030
+ handleInput$4(uid, value);
8691
9031
  };
8692
9032
 
8693
9033
  const ViewletSourceControlEvents = {
8694
9034
  __proto__: null,
8695
9035
  handleClick: handleClick$3,
8696
9036
  handleContextMenu: handleContextMenu$1,
8697
- handleFocus,
9037
+ handleFocus: handleFocus$1,
8698
9038
  handleInput: handleInput$1,
8699
9039
  handleMouseOut,
8700
9040
  handleMouseOver,
@@ -8937,7 +9277,7 @@ const handleMenuClick = event => {
8937
9277
  };
8938
9278
  const handleFocusIn$1 = event => {
8939
9279
  const uid = fromEvent(event);
8940
- handleFocus$8(uid);
9280
+ handleFocus$7(uid);
8941
9281
  };
8942
9282
 
8943
9283
  const ViewletTitleBarMenuBarEvents = {
@@ -9482,14 +9822,14 @@ const load$1 = moduleId => {
9482
9822
  return loadModule();
9483
9823
  };
9484
9824
 
9485
- const state$1 = {
9825
+ const state$2 = {
9486
9826
  currentPanelView: undefined,
9487
9827
  currentSidebarView: undefined,
9488
9828
  modules: Object.create(null)
9489
9829
  };
9490
9830
 
9491
9831
  const create$2 = (id, uid = id) => {
9492
- const module = state$1.modules[id];
9832
+ const module = state$2.modules[id];
9493
9833
  if (!module) {
9494
9834
  throw new Error(`module not found: ${id}`);
9495
9835
  }
@@ -9508,7 +9848,7 @@ const create$2 = (id, uid = id) => {
9508
9848
  });
9509
9849
  };
9510
9850
  const createFunctionalRoot = (id, uid = id, hasFunctionalEvents, directEventRpcId) => {
9511
- let module = state$1.modules[id];
9851
+ let module = state$2.modules[id];
9512
9852
  if (hasFunctionalEvents) {
9513
9853
  module ||= {};
9514
9854
  }
@@ -9540,7 +9880,7 @@ const removeKeyBindings = id => {
9540
9880
  const loadModule = async id => {
9541
9881
  try {
9542
9882
  const module = await load$1(id);
9543
- state$1.modules[id] = module;
9883
+ state$2.modules[id] = module;
9544
9884
  } catch (error) {
9545
9885
  throw new VError(error, `Failed to load ${id}`);
9546
9886
  }
@@ -9695,7 +10035,7 @@ const refresh = (viewletId, viewletContext) => {
9695
10035
  instance.factory.refresh(instance.state, viewletContext);
9696
10036
  } else {
9697
10037
  // @ts-expect-error
9698
- state$1.refreshContext[viewletId] = viewletContext;
10038
+ state$2.refreshContext[viewletId] = viewletContext;
9699
10039
  }
9700
10040
  };
9701
10041
  const specialIds = new Set(['TitleBar', 'SideBar', 'Main', 'ActivityBar', 'StatusBar', 'Panel']);
@@ -9891,7 +10231,7 @@ const setDom2 = (viewletId, dom) => {
9891
10231
  }
9892
10232
  });
9893
10233
  };
9894
- const setPatches = (uid, patches) => {
10234
+ const setTreePatches = (uid, patches) => {
9895
10235
  if (patches.length === 0) {
9896
10236
  return;
9897
10237
  }
@@ -9906,12 +10246,17 @@ const setPatches = (uid, patches) => {
9906
10246
  if (!$Viewlet) {
9907
10247
  throw new Error('element not found');
9908
10248
  }
10249
+ applyPatch($Viewlet, patches, {}, uid);
10250
+ applyLateFocusMaybe();
10251
+ };
10252
+ const setPatches = (uid, patches) => {
10253
+ // Legacy flat diffs encode a complete initial render as one Add patch.
10254
+ // Tree diffs use Add to append children to an existing root instead.
9909
10255
  if (patches.length === 1 && patches[0].type === 6) {
9910
10256
  setDom2(uid, patches[0].nodes);
9911
10257
  return;
9912
10258
  }
9913
- applyPatch($Viewlet, patches, {}, uid);
9914
- applyLateFocusMaybe();
10259
+ setTreePatches(uid, patches);
9915
10260
  };
9916
10261
  const waitForElement = selector => {
9917
10262
  const element = document.querySelector(selector);
@@ -9946,8 +10291,8 @@ const move = async (uid, selector, target) => {
9946
10291
  };
9947
10292
  const attachWindowEvents = () => {
9948
10293
  attachEvents$7(window, {
9949
- [Blur]: handleBlur$2,
9950
- [Focus]: handleFocus$3,
10294
+ [Blur]: handleBlur$1,
10295
+ [Focus]: handleFocus$2,
9951
10296
  [KeyDown]: handleKeyDown,
9952
10297
  [KeyUp]: handleKeyUp,
9953
10298
  [Resize]: handleResize
@@ -10272,6 +10617,7 @@ const commandHandlers = {
10272
10617
  'Viewlet.setPatches': setPatches,
10273
10618
  'Viewlet.setProperty': setProperty,
10274
10619
  'Viewlet.setSelectionByName': setSelectionByName,
10620
+ 'Viewlet.setTreePatches': setTreePatches,
10275
10621
  'Viewlet.setUid': setUid,
10276
10622
  'Viewlet.setValueByName': setValueByName,
10277
10623
  'Viewlet.show': show
@@ -10318,6 +10664,68 @@ const clear = storageType => {
10318
10664
  storage.clear();
10319
10665
  };
10320
10666
 
10667
+ const state$1 = {};
10668
+ const handleFocus = event => {
10669
+ const target = event.target;
10670
+ if (target instanceof HTMLElement && !target.closest('.SimpleBrowser') && target.closest('.Main, .Panel, .Editor, .Terminal')) {
10671
+ state$1.codingFocus = new WeakRef(target);
10672
+ }
10673
+ };
10674
+ const listen = () => {
10675
+ document.addEventListener('focusin', handleFocus);
10676
+ };
10677
+ const restoreCodingFocus$1 = () => {
10678
+ const target = state$1.codingFocus?.deref();
10679
+ if (!target?.isConnected) {
10680
+ return false;
10681
+ }
10682
+ target.focus({
10683
+ preventScroll: true
10684
+ });
10685
+ return document.activeElement === target;
10686
+ };
10687
+ const getAddress = uid => {
10688
+ return get$a(uid)?.state.$Viewlet.querySelector('[name="simple-browser-address"]');
10689
+ };
10690
+ const captureBrowserAddress$1 = uid => {
10691
+ const address = getAddress(uid);
10692
+ return address && document.activeElement === address ? {
10693
+ end: address.selectionEnd,
10694
+ start: address.selectionStart
10695
+ } : undefined;
10696
+ };
10697
+ const focusBrowserAddress$1 = (uid, selection) => {
10698
+ const address = getAddress(uid);
10699
+ if (!address) return;
10700
+ address.focus({
10701
+ preventScroll: true
10702
+ });
10703
+ if (selection) address.setSelectionRange(selection.start, selection.end);else address.select();
10704
+ };
10705
+ const revealBrowserTab$1 = uid => {
10706
+ const root = get$a(uid)?.state.$Viewlet;
10707
+ root?.querySelector('.SimpleBrowserTabSelected')?.scrollIntoView({
10708
+ block: 'nearest',
10709
+ inline: 'nearest'
10710
+ });
10711
+ };
10712
+ const browserParents = new Map();
10713
+ const rememberBrowserParent$1 = uid => {
10714
+ if (browserParents.has(uid)) return;
10715
+ const browser = get$a(uid)?.state.$Viewlet;
10716
+ if (!browser?.parentNode) return;
10717
+ const marker = document.createComment('browser workspace position');
10718
+ browser.before(marker);
10719
+ browserParents.set(uid, marker);
10720
+ };
10721
+ const restoreBrowserParent$1 = uid => {
10722
+ const marker = browserParents.get(uid);
10723
+ browserParents.delete(uid);
10724
+ if (!marker) return;
10725
+ const browser = get$a(uid)?.state.$Viewlet;
10726
+ if (browser && marker.isConnected) marker.replaceWith(browser);else marker.remove();
10727
+ };
10728
+
10321
10729
  const reload = () => {
10322
10730
  location.reload();
10323
10731
  };
@@ -10404,6 +10812,7 @@ const handleMessagePort = async (port, rpcId) => {
10404
10812
  },
10405
10813
  messagePort: port
10406
10814
  });
10815
+ attach(rpc);
10407
10816
  if (rpcId !== undefined) {
10408
10817
  registerRpc(rpcId, rpc);
10409
10818
  }
@@ -10783,6 +11192,11 @@ const commandMap = {
10783
11192
  'PointerCapture.unmock': unmock,
10784
11193
  'Prompt.prompt': prompt,
10785
11194
  'ScreenCapture.start': start,
11195
+ 'SessionReplay.configure': configure,
11196
+ 'SessionReplay.flush': flush,
11197
+ 'SessionReplay.getSession': getSession,
11198
+ 'SessionReplay.getStatus': getStatus,
11199
+ 'SessionReplay.openLocalFile': openLocalFile,
10786
11200
  'TestFrameWork.checkConditionError': checkConditionError,
10787
11201
  'TestFrameWork.checkMultiElementCondition': checkMultiElementCondition,
10788
11202
  'TestFrameWork.checkSingleElementCondition': checkSingleElementCondition,
@@ -11299,18 +11713,19 @@ const enable = async window => {
11299
11713
  };
11300
11714
 
11301
11715
  const main = async () => {
11716
+ if (await initializeLayout(location.href)) return;
11302
11717
  initialize(location.search);
11303
11718
  Object.assign(commandMapRef, commandMap);
11304
11719
  enable(window);
11305
- state$1.modules[ColorPicker] = ViewletColorPicker;
11306
- state$1.modules[EditorCodeGenerator] = ViewletEditorCodeGenerator;
11307
- state$1.modules[EditorCompletion] = ViewletEditorCompletion;
11308
- state$1.modules[EditorCompletionDetails] = ViewletEditorCompletionDetails;
11309
- state$1.modules[EditorHover] = ViewletEditorHover;
11310
- state$1.modules[EditorRename] = ViewletEditorRename;
11311
- state$1.modules[EditorSourceActions] = ViewletEditorSourceActions;
11312
- state$1.modules[FindWidget] = ViewletFindWidget;
11313
- state$1.modules[TitleBar] = ViewletTitleBar;
11720
+ state$2.modules[ColorPicker] = ViewletColorPicker;
11721
+ state$2.modules[EditorCodeGenerator] = ViewletEditorCodeGenerator;
11722
+ state$2.modules[EditorCompletion] = ViewletEditorCompletion;
11723
+ state$2.modules[EditorCompletionDetails] = ViewletEditorCompletionDetails;
11724
+ state$2.modules[EditorHover] = ViewletEditorHover;
11725
+ state$2.modules[EditorRename] = ViewletEditorRename;
11726
+ state$2.modules[EditorSourceActions] = ViewletEditorSourceActions;
11727
+ state$2.modules[FindWidget] = ViewletFindWidget;
11728
+ state$2.modules[TitleBar] = ViewletTitleBar;
11314
11729
  // TODO this is discovered very late
11315
11730
  const launchWorkersResult = await launchWorkers();
11316
11731
  if (isError(launchWorkersResult)) {
@@ -11385,7 +11800,7 @@ const mountTerminal = async (state, uid) => {
11385
11800
  return;
11386
11801
  }
11387
11802
  const inputDisposable = terminal.onData(data => {
11388
- handleInput$6(uid, data);
11803
+ handleInput$4(uid, data);
11389
11804
  });
11390
11805
  const resizeDisposable = terminal.onResize(({
11391
11806
  cols,