@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.
- package/dist/rendererProcessMain.js +658 -243
- package/dist/sessionReplayWorkerMain.js +219 -0
- package/package.json +1 -1
|
@@ -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 'none'; style-src 'unsafe-inline'; 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
|
|
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$
|
|
6433
|
+
const handleBlur$6 = () => {
|
|
5916
6434
|
return ['handleBlur'];
|
|
5917
6435
|
};
|
|
5918
|
-
const handleFocus$
|
|
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$
|
|
6455
|
+
handleBlur: handleBlur$6,
|
|
5938
6456
|
handleContextMenu: handleContextMenu$6,
|
|
5939
|
-
handleFocus: handleFocus$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
6786
|
+
handleInput$4(uid, value);
|
|
6269
6787
|
};
|
|
6270
|
-
const handleFocus$
|
|
6788
|
+
const handleFocus$6 = event => {
|
|
6271
6789
|
const uid = fromEvent(event);
|
|
6272
|
-
handleFocus$
|
|
6790
|
+
handleFocus$7(uid);
|
|
6273
6791
|
};
|
|
6274
6792
|
|
|
6275
6793
|
const ViewletDebugConsoleEvents = {
|
|
6276
6794
|
__proto__: null,
|
|
6277
|
-
handleFocus: handleFocus$
|
|
6278
|
-
handleInput: handleInput$
|
|
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$
|
|
6832
|
+
const handleBlur$4 = event => {
|
|
6315
6833
|
const uid = fromEvent(event);
|
|
6316
|
-
handleBlur$
|
|
6834
|
+
handleBlur$5(uid);
|
|
6317
6835
|
};
|
|
6318
6836
|
|
|
6319
6837
|
const ViewletDefineKeyBindingEvents = {
|
|
6320
6838
|
__proto__: null,
|
|
6321
|
-
handleBlur: handleBlur$
|
|
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$
|
|
7197
|
+
const handleBlur$3 = event => {
|
|
6680
7198
|
preventDefault(event);
|
|
6681
7199
|
const uid = fromEvent(event);
|
|
6682
|
-
handleBlur$
|
|
7200
|
+
handleBlur$5(uid);
|
|
6683
7201
|
};
|
|
6684
7202
|
|
|
6685
7203
|
const ViewletEditorCodeGeneratorEvents = {
|
|
6686
7204
|
__proto__: null,
|
|
6687
|
-
handleBlur: handleBlur$
|
|
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$
|
|
7708
|
+
const handleFocus$5 = event => {
|
|
7191
7709
|
const uid = fromEvent(event);
|
|
7192
|
-
handleFocus$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
8061
|
+
handleFocus: handleFocus$4,
|
|
7544
8062
|
handleFocusClose,
|
|
7545
8063
|
handleFocusNext,
|
|
7546
8064
|
handleFocusPrevious,
|
|
7547
8065
|
handleFocusReplaceAll,
|
|
7548
|
-
handleInput: handleInput$
|
|
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$
|
|
8406
|
+
const handleFocus$3 = () => {
|
|
7889
8407
|
send$1('Layout.handleFocus');
|
|
7890
8408
|
};
|
|
7891
|
-
const handleBlur$
|
|
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$
|
|
7938
|
-
handleFocus$
|
|
8455
|
+
const handleFocus$2 = () => {
|
|
8456
|
+
handleFocus$3();
|
|
7939
8457
|
};
|
|
7940
|
-
const handleBlur$
|
|
7941
|
-
handleBlur$
|
|
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$
|
|
7982
|
-
[Focus]: handleFocus$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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
|
|
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
|
-
|
|
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$
|
|
9950
|
-
[Focus]: handleFocus$
|
|
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$
|
|
11306
|
-
state$
|
|
11307
|
-
state$
|
|
11308
|
-
state$
|
|
11309
|
-
state$
|
|
11310
|
-
state$
|
|
11311
|
-
state$
|
|
11312
|
-
state$
|
|
11313
|
-
state$
|
|
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$
|
|
11803
|
+
handleInput$4(uid, data);
|
|
11389
11804
|
});
|
|
11390
11805
|
const resizeDisposable = terminal.onResize(({
|
|
11391
11806
|
cols,
|