@push.rocks/smartbrowser 4.1.0 → 4.3.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_ts/00_commitinfo_data.js +1 -1
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/classes.livebrowsercanvasrenderer.d.ts +4 -187
- package/dist_ts_web/classes.livebrowsercanvasrenderer.js +5 -1750
- package/dist_ts_web/classes.livebrowserrenderer.d.ts +194 -0
- package/dist_ts_web/classes.livebrowserrenderer.js +1830 -0
- package/dist_ts_web/classes.livebrowservideoreceiver.d.ts +46 -0
- package/dist_ts_web/classes.livebrowservideoreceiver.js +243 -0
- package/dist_ts_web/classes.livebrowservideorenderer.d.ts +6 -0
- package/dist_ts_web/classes.livebrowservideorenderer.js +8 -0
- package/dist_ts_web/index.d.ts +3 -0
- package/dist_ts_web/index.js +2 -1
- package/dist_ts_web/interfaces.livebrowsercanvas.d.ts +8 -2
- package/dist_ts_web/interfaces.livebrowservideo.d.ts +31 -0
- package/dist_ts_web/interfaces.livebrowservideo.js +2 -0
- package/package.json +4 -4
- package/readme.md +25 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/classes.livebrowsercanvasrenderer.ts +5 -2151
- package/ts_web/classes.livebrowserrenderer.ts +2232 -0
- package/ts_web/classes.livebrowservideoreceiver.ts +250 -0
- package/ts_web/classes.livebrowservideorenderer.ts +9 -0
- package/ts_web/index.ts +4 -0
- package/ts_web/interfaces.livebrowsercanvas.ts +11 -1
- package/ts_web/interfaces.livebrowservideo.ts +46 -0
- package/readme.hints.md +0 -34
|
@@ -1,1753 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const maxWheelDelta = 1000000;
|
|
5
|
-
const animationFrameFallbackMs = 16;
|
|
6
|
-
const resizeDebounceMs = 100;
|
|
7
|
-
const maxPendingAcknowledgements = 16;
|
|
8
|
-
const maxInputReleaseAttempts = 2;
|
|
9
|
-
const maxFrameDimension = 12288;
|
|
10
|
-
const maxFramePixelArea = 8294400;
|
|
11
|
-
const maxFrameByteLength = (maxFramePixelArea * 4) + 1048576;
|
|
12
|
-
const maxViewportWidth = 4096;
|
|
13
|
-
const maxViewportHeight = 4096;
|
|
14
|
-
const minDeviceScaleFactor = 0.25;
|
|
15
|
-
const maxDeviceScaleFactor = 3;
|
|
16
|
-
const coordinateEdgeInset = 0.001;
|
|
17
|
-
const defaultOperationTimeoutMs = 10000;
|
|
18
|
-
class LiveBrowserOperationTimeoutError extends Error {
|
|
19
|
-
}
|
|
20
|
-
class LiveBrowserRunAbortedError extends Error {
|
|
21
|
-
}
|
|
22
|
-
class LiveBrowserFrameProtocolError extends Error {
|
|
23
|
-
}
|
|
24
|
-
class LiveBrowserFrameIntegrityError extends Error {
|
|
25
|
-
}
|
|
26
|
-
const isCoalescableInputCommand = (kindArg) => kindArg === 'mouseMove' || kindArg === 'wheel';
|
|
27
|
-
const clampWheelDelta = (valueArg) => (Math.max(-maxWheelDelta, Math.min(maxWheelDelta, valueArg)));
|
|
28
|
-
const mergeWheelInput = (targetArg, sourceArg) => {
|
|
29
|
-
targetArg.x = sourceArg.x;
|
|
30
|
-
targetArg.y = sourceArg.y;
|
|
31
|
-
targetArg.deltaX = clampWheelDelta(targetArg.deltaX + sourceArg.deltaX);
|
|
32
|
-
targetArg.deltaY = clampWheelDelta(targetArg.deltaY + sourceArg.deltaY);
|
|
33
|
-
targetArg.modifiers = sourceArg.modifiers;
|
|
34
|
-
};
|
|
35
|
-
const inputIdentityEquals = (firstArg, secondArg) => (firstArg.tabId === secondArg.tabId
|
|
36
|
-
&& firstArg.generation === secondArg.generation
|
|
37
|
-
&& firstArg.viewportRevision === secondArg.viewportRevision);
|
|
38
|
-
const viewportEquals = (firstArg, secondArg) => (firstArg.width === secondArg.width
|
|
39
|
-
&& firstArg.height === secondArg.height
|
|
40
|
-
&& firstArg.deviceScaleFactor === secondArg.deviceScaleFactor);
|
|
41
|
-
const createModifiers = (eventArg) => ({
|
|
42
|
-
alt: eventArg.altKey,
|
|
43
|
-
control: eventArg.ctrlKey,
|
|
44
|
-
meta: eventArg.metaKey,
|
|
45
|
-
shift: eventArg.shiftKey,
|
|
46
|
-
});
|
|
47
|
-
const createFrameAcknowledgementRequest = (frameArg) => ({
|
|
48
|
-
tabId: frameArg.tabId,
|
|
49
|
-
sequence: frameArg.sequence,
|
|
50
|
-
generation: frameArg.generation,
|
|
51
|
-
viewportRevision: frameArg.viewportRevision,
|
|
52
|
-
});
|
|
53
|
-
const createInputIdentity = (displayedFrameArg) => ({
|
|
54
|
-
tabId: displayedFrameArg.tabId,
|
|
55
|
-
generation: displayedFrameArg.generation,
|
|
56
|
-
viewportRevision: displayedFrameArg.viewportRevision,
|
|
57
|
-
});
|
|
58
|
-
const getErrorMessage = (errorArg) => (errorArg instanceof Error ? errorArg.message : String(errorArg));
|
|
59
|
-
/**
|
|
60
|
-
* Renders transport-neutral live browser frames and maps DOM input back to the
|
|
61
|
-
* currently displayed SmartPuppeteer frame identity.
|
|
62
|
-
*/
|
|
63
|
-
export class LiveBrowserCanvasRenderer {
|
|
1
|
+
import { LiveBrowserRenderer } from './classes.livebrowserrenderer.js';
|
|
2
|
+
/** JPEG/PNG canvas presentation with bounded input and frame delivery. */
|
|
3
|
+
export class LiveBrowserCanvasRenderer extends LiveBrowserRenderer {
|
|
64
4
|
constructor(optionsArg) {
|
|
65
|
-
|
|
66
|
-
this.runEpoch = 0;
|
|
67
|
-
this.running = false;
|
|
68
|
-
this.suspended = false;
|
|
69
|
-
this.stopping = false;
|
|
70
|
-
this.interruptionRequested = false;
|
|
71
|
-
this.operationControllers = new Set();
|
|
72
|
-
this.acceptingFrames = false;
|
|
73
|
-
this.focusWasAdjusted = false;
|
|
74
|
-
this.focusHadTabIndex = false;
|
|
75
|
-
this.focusTabIndexValue = null;
|
|
76
|
-
this.highestFrameSequence = -1;
|
|
77
|
-
this.acknowledgementPromises = new Set();
|
|
78
|
-
this.rawDecodeSettlementPromises = new Set();
|
|
79
|
-
this.inputBlocked = true;
|
|
80
|
-
this.inputCommands = [];
|
|
81
|
-
this.inFlightInputCommands = 0;
|
|
82
|
-
this.inFlightWheelCommands = 0;
|
|
83
|
-
this.inputIdleResolvers = [];
|
|
84
|
-
this.inputResetTail = Promise.resolve();
|
|
85
|
-
this.inputResetCount = 0;
|
|
86
|
-
this.wheelFrameElapsed = true;
|
|
87
|
-
this.pressedKeys = new Map();
|
|
88
|
-
this.pressedMouseButtons = new Map();
|
|
89
|
-
this.capturedPointerIds = new Set();
|
|
90
|
-
this.viewportProcessing = false;
|
|
91
|
-
this.statistics = {
|
|
92
|
-
framesReceived: 0,
|
|
93
|
-
framesDecoded: 0,
|
|
94
|
-
framesSkipped: 0,
|
|
95
|
-
inputCommandsEnqueued: 0,
|
|
96
|
-
inputCommandsCoalesced: 0,
|
|
97
|
-
lastInputRoundTripMs: 0,
|
|
98
|
-
};
|
|
99
|
-
this.canvas = optionsArg.canvas;
|
|
100
|
-
this.client = optionsArg.client;
|
|
101
|
-
this.focusTarget = optionsArg.focusTarget ?? this.canvas;
|
|
102
|
-
this.resizeTarget = optionsArg.resizeTarget;
|
|
103
|
-
this.getDeviceScaleFactor = optionsArg.getDeviceScaleFactor
|
|
104
|
-
?? (() => window.devicePixelRatio || 1);
|
|
105
|
-
this.operationTimeoutMs = this.validateTimeout(optionsArg.operationTimeoutMs ?? defaultOperationTimeoutMs, 'operationTimeoutMs');
|
|
106
|
-
this.frameDecodeTimeoutMs = this.validateTimeout(optionsArg.frameDecodeTimeoutMs ?? this.operationTimeoutMs, 'frameDecodeTimeoutMs');
|
|
107
|
-
this.onError = optionsArg.onError;
|
|
108
|
-
this.onFrameRendered = optionsArg.onFrameRendered;
|
|
109
|
-
this.initialCanvasWidth = this.canvas.width;
|
|
110
|
-
this.initialCanvasHeight = this.canvas.height;
|
|
111
|
-
const bitmapContext = this.canvas.getContext('bitmaprenderer');
|
|
112
|
-
if (bitmapContext) {
|
|
113
|
-
this.bitmapContext = bitmapContext;
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
// A canvas that already owns a 2D context keeps the 2D drawing path.
|
|
117
|
-
const canvasContext = this.canvas.getContext('2d');
|
|
118
|
-
if (!canvasContext) {
|
|
119
|
-
throw new Error('LiveBrowserCanvasRenderer requires a bitmaprenderer or 2D canvas context');
|
|
120
|
-
}
|
|
121
|
-
this.canvasContext = canvasContext;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
get isRunning() {
|
|
125
|
-
return this.running;
|
|
126
|
-
}
|
|
127
|
-
get isSuspended() {
|
|
128
|
-
return this.suspended;
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Cumulative frame and input counters for this renderer instance across runs.
|
|
132
|
-
*/
|
|
133
|
-
getStatistics() {
|
|
134
|
-
return {
|
|
135
|
-
...this.statistics,
|
|
136
|
-
inputCommandsInFlight: this.inFlightInputCommands,
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
start() {
|
|
140
|
-
return this.enqueueLifecycle(async () => {
|
|
141
|
-
if (this.running) {
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
if (this.suspended) {
|
|
145
|
-
throw new Error('Live browser renderer is suspended; call resume() to start a fresh run');
|
|
146
|
-
}
|
|
147
|
-
await this.startRun(false);
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
stop() {
|
|
151
|
-
this.interruptRun(this.runEpoch);
|
|
152
|
-
return this.enqueueLifecycle(async () => {
|
|
153
|
-
const runEpoch = this.runEpoch;
|
|
154
|
-
this.interruptRun(runEpoch);
|
|
155
|
-
if (this.stopping) {
|
|
156
|
-
await this.finishRun(runEpoch, false);
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
if (!this.suspended) {
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
this.suspended = false;
|
|
163
|
-
this.restoreCanvasAndFocus();
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Aborts the current transport generation without replaying input recovery.
|
|
168
|
-
*/
|
|
169
|
-
suspend() {
|
|
170
|
-
this.interruptRun(this.runEpoch);
|
|
171
|
-
return this.enqueueLifecycle(async () => {
|
|
172
|
-
const runEpoch = this.runEpoch;
|
|
173
|
-
this.interruptRun(runEpoch);
|
|
174
|
-
if (!this.stopping) {
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
await this.finishRun(runEpoch, true);
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Starts a new transport generation that requires new state and a new frame.
|
|
182
|
-
*/
|
|
183
|
-
resume() {
|
|
184
|
-
return this.enqueueLifecycle(async () => {
|
|
185
|
-
if (this.running) {
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
if (!this.suspended) {
|
|
189
|
-
throw new Error('Live browser renderer is not suspended');
|
|
190
|
-
}
|
|
191
|
-
await this.startRun(true);
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Sends arbitrary committed text, including text produced by an external IME.
|
|
196
|
-
*/
|
|
197
|
-
async insertText(textArg) {
|
|
198
|
-
const displayedFrame = this.requireInputFrame();
|
|
199
|
-
const inputIdentity = createInputIdentity(displayedFrame);
|
|
200
|
-
await this.enqueueInputCommand({
|
|
201
|
-
kind: 'text',
|
|
202
|
-
runEpoch: this.runEpoch,
|
|
203
|
-
execute: async (optionsArg) => {
|
|
204
|
-
await this.client.insertText({
|
|
205
|
-
...inputIdentity,
|
|
206
|
-
text: textArg,
|
|
207
|
-
}, optionsArg);
|
|
208
|
-
},
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Reads the configured stable resize target and requests the corresponding
|
|
213
|
-
* remote CSS viewport. Intrinsic canvas dimensions are never used here.
|
|
214
|
-
*/
|
|
215
|
-
syncViewport() {
|
|
216
|
-
if (!this.running || this.stopping || this.interruptionRequested || !this.resizeTarget) {
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
this.queueViewport(this.resizeTarget.clientWidth, this.resizeTarget.clientHeight, this.runEpoch);
|
|
220
|
-
}
|
|
221
|
-
enqueueLifecycle(operationArg) {
|
|
222
|
-
const operation = this.lifecycleTail.then(operationArg, operationArg);
|
|
223
|
-
this.lifecycleTail = operation.then(() => undefined, () => undefined);
|
|
224
|
-
return operation;
|
|
225
|
-
}
|
|
226
|
-
async startRun(resumingArg) {
|
|
227
|
-
await Promise.all([...this.rawDecodeSettlementPromises]);
|
|
228
|
-
const runEpoch = ++this.runEpoch;
|
|
229
|
-
this.runController = new AbortController();
|
|
230
|
-
this.running = true;
|
|
231
|
-
this.suspended = false;
|
|
232
|
-
this.stopping = false;
|
|
233
|
-
this.interruptionRequested = false;
|
|
234
|
-
this.acceptingFrames = true;
|
|
235
|
-
this.inputBlocked = true;
|
|
236
|
-
this.wheelFrameElapsed = true;
|
|
237
|
-
this.state = undefined;
|
|
238
|
-
this.displayedFrame = undefined;
|
|
239
|
-
this.highestFrameSequence = -1;
|
|
240
|
-
this.clearCanvas();
|
|
241
|
-
try {
|
|
242
|
-
this.makeFocusTargetFocusable();
|
|
243
|
-
this.installDomListeners(runEpoch);
|
|
244
|
-
this.unsubscribe = this.client.onEvent((eventArg) => {
|
|
245
|
-
this.handleEvent(eventArg, runEpoch);
|
|
246
|
-
});
|
|
247
|
-
this.applyState(this.client.getState(), runEpoch);
|
|
248
|
-
this.installResizeObserver(runEpoch);
|
|
249
|
-
}
|
|
250
|
-
catch (error) {
|
|
251
|
-
this.interruptRun(runEpoch);
|
|
252
|
-
await this.finishRun(runEpoch, resumingArg);
|
|
253
|
-
throw error;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
interruptRun(runEpochArg) {
|
|
257
|
-
if (runEpochArg !== this.runEpoch
|
|
258
|
-
|| (!this.running && !this.stopping)) {
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
this.running = false;
|
|
262
|
-
this.stopping = true;
|
|
263
|
-
this.interruptionRequested = true;
|
|
264
|
-
this.acceptingFrames = false;
|
|
265
|
-
this.inputBlocked = true;
|
|
266
|
-
this.pendingViewport = undefined;
|
|
267
|
-
this.queuedFrame = undefined;
|
|
268
|
-
this.displayedFrame = undefined;
|
|
269
|
-
this.resizeFence = undefined;
|
|
270
|
-
this.discardPendingDraw();
|
|
271
|
-
this.discardPendingWheel();
|
|
272
|
-
this.releasePointerCaptures();
|
|
273
|
-
this.clearCanvas();
|
|
274
|
-
const interruptionError = new LiveBrowserRunAbortedError(`Live browser renderer run ${runEpochArg} was interrupted`);
|
|
275
|
-
this.runController?.abort(interruptionError);
|
|
276
|
-
for (const controller of this.operationControllers) {
|
|
277
|
-
controller.abort(interruptionError);
|
|
278
|
-
}
|
|
279
|
-
const abandonedCommands = this.inputCommands.splice(0);
|
|
280
|
-
for (const command of abandonedCommands) {
|
|
281
|
-
command.reject(interruptionError);
|
|
282
|
-
}
|
|
283
|
-
this.pressedKeys.clear();
|
|
284
|
-
this.pressedMouseButtons.clear();
|
|
285
|
-
}
|
|
286
|
-
async finishRun(runEpochArg, suspendArg) {
|
|
287
|
-
if (runEpochArg !== this.runEpoch) {
|
|
288
|
-
return;
|
|
289
|
-
}
|
|
290
|
-
try {
|
|
291
|
-
this.resizeObserver?.disconnect();
|
|
292
|
-
this.resizeObserver = undefined;
|
|
293
|
-
this.clearResizeDebounce();
|
|
294
|
-
this.listenerController?.abort();
|
|
295
|
-
this.listenerController = undefined;
|
|
296
|
-
const unsubscribe = this.unsubscribe;
|
|
297
|
-
this.unsubscribe = undefined;
|
|
298
|
-
if (unsubscribe) {
|
|
299
|
-
try {
|
|
300
|
-
unsubscribe();
|
|
301
|
-
}
|
|
302
|
-
catch (error) {
|
|
303
|
-
this.reportError({
|
|
304
|
-
code: 'renderer_cleanup_failed',
|
|
305
|
-
message: `Could not unsubscribe the live browser renderer: ${getErrorMessage(error)}`,
|
|
306
|
-
cause: error,
|
|
307
|
-
}, runEpochArg);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
await Promise.allSettled([
|
|
311
|
-
this.viewportProcessingPromise,
|
|
312
|
-
this.inputResetTail,
|
|
313
|
-
this.waitForInputIdle(),
|
|
314
|
-
this.frameProcessingPromise,
|
|
315
|
-
...this.acknowledgementPromises,
|
|
316
|
-
]);
|
|
317
|
-
}
|
|
318
|
-
finally {
|
|
319
|
-
for (const controller of this.operationControllers) {
|
|
320
|
-
controller.abort(new LiveBrowserRunAbortedError(`Live browser renderer run ${runEpochArg} finished`));
|
|
321
|
-
}
|
|
322
|
-
this.operationControllers.clear();
|
|
323
|
-
this.runController = undefined;
|
|
324
|
-
this.running = false;
|
|
325
|
-
this.suspended = suspendArg;
|
|
326
|
-
this.acceptingFrames = false;
|
|
327
|
-
this.state = undefined;
|
|
328
|
-
this.displayedFrame = undefined;
|
|
329
|
-
this.highestFrameSequence = -1;
|
|
330
|
-
this.queuedFrame = undefined;
|
|
331
|
-
this.frameProcessingPromise = undefined;
|
|
332
|
-
this.discardPendingDraw();
|
|
333
|
-
this.discardPendingWheel();
|
|
334
|
-
this.clearResizeDebounce();
|
|
335
|
-
this.acknowledgementPromises.clear();
|
|
336
|
-
this.resizeFence = undefined;
|
|
337
|
-
this.pendingViewport = undefined;
|
|
338
|
-
this.inFlightViewport = undefined;
|
|
339
|
-
this.viewportProcessing = false;
|
|
340
|
-
this.viewportProcessingPromise = undefined;
|
|
341
|
-
this.inputResetPromise = undefined;
|
|
342
|
-
this.inputResetTail = Promise.resolve();
|
|
343
|
-
this.inputResetCount = 0;
|
|
344
|
-
this.inputBlocked = true;
|
|
345
|
-
this.pressedKeys.clear();
|
|
346
|
-
this.pressedMouseButtons.clear();
|
|
347
|
-
this.releasePointerCaptures();
|
|
348
|
-
const abandonedCommands = this.inputCommands.splice(0);
|
|
349
|
-
for (const command of abandonedCommands) {
|
|
350
|
-
command.reject(new Error('Live browser renderer stopped before dispatching input'));
|
|
351
|
-
}
|
|
352
|
-
const inputIdleResolvers = this.inputIdleResolvers;
|
|
353
|
-
this.inputIdleResolvers = [];
|
|
354
|
-
for (const resolver of inputIdleResolvers) {
|
|
355
|
-
resolver();
|
|
356
|
-
}
|
|
357
|
-
this.restoreCanvasAndFocus();
|
|
358
|
-
this.interruptionRequested = false;
|
|
359
|
-
this.stopping = false;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
restoreCanvasAndFocus() {
|
|
363
|
-
this.canvas.width = this.initialCanvasWidth;
|
|
364
|
-
this.canvas.height = this.initialCanvasHeight;
|
|
365
|
-
this.restoreFocusTarget();
|
|
366
|
-
}
|
|
367
|
-
installDomListeners(runEpochArg) {
|
|
368
|
-
const listenerController = new AbortController();
|
|
369
|
-
const signal = listenerController.signal;
|
|
370
|
-
this.listenerController = listenerController;
|
|
371
|
-
this.canvas.addEventListener('pointerdown', (eventArg) => {
|
|
372
|
-
this.handlePointerDown(eventArg, runEpochArg);
|
|
373
|
-
}, { signal });
|
|
374
|
-
this.canvas.addEventListener('pointermove', (eventArg) => {
|
|
375
|
-
this.handlePointerMove(eventArg, runEpochArg);
|
|
376
|
-
}, { signal });
|
|
377
|
-
this.canvas.addEventListener('pointerup', (eventArg) => {
|
|
378
|
-
this.handlePointerUp(eventArg, runEpochArg);
|
|
379
|
-
}, { signal });
|
|
380
|
-
this.canvas.addEventListener('pointercancel', (eventArg) => {
|
|
381
|
-
this.releasePointerCapture(eventArg.pointerId);
|
|
382
|
-
void this.scheduleInputReset(false, runEpochArg);
|
|
383
|
-
}, { signal });
|
|
384
|
-
this.canvas.addEventListener('lostpointercapture', (eventArg) => {
|
|
385
|
-
this.capturedPointerIds.delete(eventArg.pointerId);
|
|
386
|
-
if (this.pressedMouseButtons.size > 0) {
|
|
387
|
-
void this.scheduleInputReset(false, runEpochArg);
|
|
388
|
-
}
|
|
389
|
-
}, { signal });
|
|
390
|
-
this.canvas.addEventListener('contextmenu', (eventArg) => {
|
|
391
|
-
eventArg.preventDefault();
|
|
392
|
-
}, { signal });
|
|
393
|
-
this.canvas.addEventListener('wheel', (eventArg) => {
|
|
394
|
-
this.handleWheel(eventArg, runEpochArg);
|
|
395
|
-
}, { passive: false, signal });
|
|
396
|
-
this.focusTarget.addEventListener('keydown', (eventArg) => {
|
|
397
|
-
this.handleKey(eventArg, 'down', runEpochArg);
|
|
398
|
-
}, { signal });
|
|
399
|
-
this.focusTarget.addEventListener('keyup', (eventArg) => {
|
|
400
|
-
this.handleKey(eventArg, 'up', runEpochArg);
|
|
401
|
-
}, { signal });
|
|
402
|
-
this.focusTarget.addEventListener('compositionend', (eventArg) => {
|
|
403
|
-
if (!this.inputBlocked && eventArg.data) {
|
|
404
|
-
void this.insertText(eventArg.data).catch(() => undefined);
|
|
405
|
-
}
|
|
406
|
-
}, { signal });
|
|
407
|
-
window.addEventListener('blur', () => {
|
|
408
|
-
void this.scheduleInputReset(false, runEpochArg);
|
|
409
|
-
}, { signal });
|
|
410
|
-
window.addEventListener('resize', () => {
|
|
411
|
-
this.syncViewport();
|
|
412
|
-
}, { signal });
|
|
413
|
-
document.addEventListener('visibilitychange', () => {
|
|
414
|
-
if (document.visibilityState === 'hidden') {
|
|
415
|
-
void this.scheduleInputReset(false, runEpochArg);
|
|
416
|
-
}
|
|
417
|
-
}, { signal });
|
|
418
|
-
}
|
|
419
|
-
installResizeObserver(runEpochArg) {
|
|
420
|
-
if (!this.resizeTarget) {
|
|
421
|
-
return;
|
|
422
|
-
}
|
|
423
|
-
this.resizeObserver = new ResizeObserver((entriesArg) => {
|
|
424
|
-
const matchingEntry = entriesArg.find((entryArg) => entryArg.target === this.resizeTarget);
|
|
425
|
-
if (!matchingEntry || runEpochArg !== this.runEpoch) {
|
|
426
|
-
return;
|
|
427
|
-
}
|
|
428
|
-
this.pendingResizeSize = {
|
|
429
|
-
width: matchingEntry.contentRect.width,
|
|
430
|
-
height: matchingEntry.contentRect.height,
|
|
431
|
-
};
|
|
432
|
-
if (this.resizeDebounceTimer !== undefined) {
|
|
433
|
-
globalThis.clearTimeout(this.resizeDebounceTimer);
|
|
434
|
-
}
|
|
435
|
-
this.resizeDebounceTimer = globalThis.setTimeout(() => {
|
|
436
|
-
this.resizeDebounceTimer = undefined;
|
|
437
|
-
const pendingResizeSize = this.pendingResizeSize;
|
|
438
|
-
this.pendingResizeSize = undefined;
|
|
439
|
-
if (pendingResizeSize) {
|
|
440
|
-
this.queueViewport(pendingResizeSize.width, pendingResizeSize.height, runEpochArg);
|
|
441
|
-
}
|
|
442
|
-
}, resizeDebounceMs);
|
|
443
|
-
});
|
|
444
|
-
this.resizeObserver.observe(this.resizeTarget);
|
|
445
|
-
this.syncViewport();
|
|
446
|
-
}
|
|
447
|
-
clearResizeDebounce() {
|
|
448
|
-
if (this.resizeDebounceTimer !== undefined) {
|
|
449
|
-
globalThis.clearTimeout(this.resizeDebounceTimer);
|
|
450
|
-
this.resizeDebounceTimer = undefined;
|
|
451
|
-
}
|
|
452
|
-
this.pendingResizeSize = undefined;
|
|
453
|
-
}
|
|
454
|
-
handleEvent(eventArg, runEpochArg) {
|
|
455
|
-
if (eventArg.type === 'frame') {
|
|
456
|
-
this.queueFrame(eventArg.frame, runEpochArg);
|
|
457
|
-
return;
|
|
458
|
-
}
|
|
459
|
-
if (!this.running || runEpochArg !== this.runEpoch) {
|
|
460
|
-
return;
|
|
461
|
-
}
|
|
462
|
-
if (eventArg.type === 'state') {
|
|
463
|
-
this.applyState(eventArg.state, runEpochArg);
|
|
464
|
-
return;
|
|
465
|
-
}
|
|
466
|
-
this.reportError({
|
|
467
|
-
code: 'remote_browser_error',
|
|
468
|
-
message: `${eventArg.error.code}: ${eventArg.error.message}`,
|
|
469
|
-
cause: eventArg.error,
|
|
470
|
-
}, runEpochArg);
|
|
471
|
-
}
|
|
472
|
-
applyState(stateArg, runEpochArg) {
|
|
473
|
-
if (!this.running || runEpochArg !== this.runEpoch) {
|
|
474
|
-
return;
|
|
475
|
-
}
|
|
476
|
-
this.state = stateArg;
|
|
477
|
-
if (this.displayedFrame && this.isStateAheadOfDisplayedFrame(stateArg, this.displayedFrame)) {
|
|
478
|
-
this.displayedFrame = undefined;
|
|
479
|
-
this.clearCanvas();
|
|
480
|
-
void this.scheduleInputReset(false, runEpochArg);
|
|
481
|
-
return;
|
|
482
|
-
}
|
|
483
|
-
this.updateInputAvailability();
|
|
484
|
-
}
|
|
485
|
-
isStateAheadOfDisplayedFrame(stateArg, displayedFrameArg) {
|
|
486
|
-
if (stateArg.status !== 'running' || stateArg.activeTabId !== displayedFrameArg.tabId) {
|
|
487
|
-
return true;
|
|
488
|
-
}
|
|
489
|
-
const activeTab = stateArg.tabs.find((tabArg) => tabArg.id === displayedFrameArg.tabId);
|
|
490
|
-
if (!activeTab || activeTab.status !== 'open' || !activeTab.streaming) {
|
|
491
|
-
return true;
|
|
492
|
-
}
|
|
493
|
-
return stateArg.viewportRevision > displayedFrameArg.viewportRevision
|
|
494
|
-
|| activeTab.generation > displayedFrameArg.generation;
|
|
495
|
-
}
|
|
496
|
-
queueFrame(frameArg, runEpochArg) {
|
|
497
|
-
if (!this.running || !this.acceptingFrames || runEpochArg !== this.runEpoch) {
|
|
498
|
-
return;
|
|
499
|
-
}
|
|
500
|
-
this.statistics.framesReceived++;
|
|
501
|
-
try {
|
|
502
|
-
this.validateFrame(frameArg);
|
|
503
|
-
if (frameArg.sequence <= this.highestFrameSequence) {
|
|
504
|
-
throw new LiveBrowserFrameProtocolError(`frame.sequence ${frameArg.sequence} must be strictly greater than current run high-water ${this.highestFrameSequence}`);
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
catch (error) {
|
|
508
|
-
this.requestSuspend(runEpochArg);
|
|
509
|
-
this.reportError({
|
|
510
|
-
code: 'frame_render_failed',
|
|
511
|
-
message: `Rejected invalid live browser frame: ${getErrorMessage(error)}`,
|
|
512
|
-
cause: error,
|
|
513
|
-
frame: frameArg,
|
|
514
|
-
}, runEpochArg);
|
|
515
|
-
return;
|
|
516
|
-
}
|
|
517
|
-
this.highestFrameSequence = frameArg.sequence;
|
|
518
|
-
const frameWork = {
|
|
519
|
-
frame: frameArg,
|
|
520
|
-
runEpoch: runEpochArg,
|
|
521
|
-
acknowledgementAttempted: false,
|
|
522
|
-
};
|
|
523
|
-
if (this.queuedFrame) {
|
|
524
|
-
// The superseded frame was already acknowledged at receipt.
|
|
525
|
-
this.queuedFrame = undefined;
|
|
526
|
-
this.statistics.framesSkipped++;
|
|
527
|
-
}
|
|
528
|
-
this.queuedFrame = frameWork;
|
|
529
|
-
void this.acknowledgeFrame(frameWork);
|
|
530
|
-
this.ensureFrameProcessor();
|
|
531
|
-
}
|
|
532
|
-
ensureFrameProcessor() {
|
|
533
|
-
if (this.frameProcessingPromise || !this.queuedFrame) {
|
|
534
|
-
return;
|
|
535
|
-
}
|
|
536
|
-
const processingPromise = this.processFrameQueue().finally(() => {
|
|
537
|
-
if (this.frameProcessingPromise === processingPromise) {
|
|
538
|
-
this.frameProcessingPromise = undefined;
|
|
539
|
-
if (this.queuedFrame) {
|
|
540
|
-
this.ensureFrameProcessor();
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
});
|
|
544
|
-
this.frameProcessingPromise = processingPromise;
|
|
545
|
-
}
|
|
546
|
-
async processFrameQueue() {
|
|
547
|
-
while (this.queuedFrame) {
|
|
548
|
-
const frameWork = this.queuedFrame;
|
|
549
|
-
this.queuedFrame = undefined;
|
|
550
|
-
await this.processFrame(frameWork);
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
async processFrame(frameWorkArg) {
|
|
554
|
-
const { frame, runEpoch } = frameWorkArg;
|
|
555
|
-
let imageBitmap;
|
|
556
|
-
let terminalFailure = false;
|
|
557
|
-
let terminalError;
|
|
558
|
-
try {
|
|
559
|
-
if (!this.canRenderFrame(frame, runEpoch)) {
|
|
560
|
-
return;
|
|
561
|
-
}
|
|
562
|
-
const frameBytes = new Uint8Array(frame.data.byteLength);
|
|
563
|
-
frameBytes.set(frame.data);
|
|
564
|
-
imageBitmap = await this.decodeFrame(new Blob([frameBytes.buffer], {
|
|
565
|
-
type: frame.mimeType,
|
|
566
|
-
}), runEpoch);
|
|
567
|
-
if (imageBitmap.width !== frame.width || imageBitmap.height !== frame.height) {
|
|
568
|
-
throw new LiveBrowserFrameIntegrityError(`decoded frame dimensions ${imageBitmap.width}x${imageBitmap.height} do not match ${frame.width}x${frame.height}`);
|
|
569
|
-
}
|
|
570
|
-
this.statistics.framesDecoded++;
|
|
571
|
-
if (!this.canRenderFrame(frame, runEpoch)) {
|
|
572
|
-
this.statistics.framesSkipped++;
|
|
573
|
-
return;
|
|
574
|
-
}
|
|
575
|
-
this.setPendingDraw({ bitmap: imageBitmap, frame, runEpoch });
|
|
576
|
-
imageBitmap = undefined;
|
|
577
|
-
}
|
|
578
|
-
catch (error) {
|
|
579
|
-
if (error instanceof LiveBrowserRunAbortedError) {
|
|
580
|
-
return;
|
|
581
|
-
}
|
|
582
|
-
terminalFailure = true;
|
|
583
|
-
terminalError = error;
|
|
584
|
-
}
|
|
585
|
-
finally {
|
|
586
|
-
imageBitmap?.close();
|
|
587
|
-
if (terminalFailure) {
|
|
588
|
-
this.requestSuspend(runEpoch);
|
|
589
|
-
this.reportError({
|
|
590
|
-
code: 'frame_render_failed',
|
|
591
|
-
message: `Could not render live browser frame: ${getErrorMessage(terminalError)}`,
|
|
592
|
-
cause: terminalError,
|
|
593
|
-
frame,
|
|
594
|
-
}, runEpoch);
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
/**
|
|
599
|
-
* Keeps only the newest decoded bitmap and presents it on the next animation frame.
|
|
600
|
-
*/
|
|
601
|
-
setPendingDraw(pendingDrawArg) {
|
|
602
|
-
if (this.pendingDraw) {
|
|
603
|
-
this.pendingDraw.bitmap.close();
|
|
604
|
-
this.statistics.framesSkipped++;
|
|
605
|
-
}
|
|
606
|
-
this.pendingDraw = pendingDrawArg;
|
|
607
|
-
if (!this.drawSchedule) {
|
|
608
|
-
this.drawSchedule = this.scheduleAnimationFrame(() => {
|
|
609
|
-
this.drawSchedule = undefined;
|
|
610
|
-
this.drawPendingFrame();
|
|
611
|
-
});
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
discardPendingDraw() {
|
|
615
|
-
if (this.drawSchedule) {
|
|
616
|
-
this.cancelScheduledFrame(this.drawSchedule);
|
|
617
|
-
this.drawSchedule = undefined;
|
|
618
|
-
}
|
|
619
|
-
const pendingDraw = this.pendingDraw;
|
|
620
|
-
this.pendingDraw = undefined;
|
|
621
|
-
if (pendingDraw) {
|
|
622
|
-
pendingDraw.bitmap.close();
|
|
623
|
-
this.statistics.framesSkipped++;
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
drawPendingFrame() {
|
|
627
|
-
const pendingDraw = this.pendingDraw;
|
|
628
|
-
this.pendingDraw = undefined;
|
|
629
|
-
if (!pendingDraw) {
|
|
630
|
-
return;
|
|
631
|
-
}
|
|
632
|
-
const { bitmap, frame, runEpoch } = pendingDraw;
|
|
633
|
-
if (!this.canRenderFrame(frame, runEpoch)) {
|
|
634
|
-
bitmap.close();
|
|
635
|
-
this.statistics.framesSkipped++;
|
|
636
|
-
return;
|
|
637
|
-
}
|
|
638
|
-
try {
|
|
639
|
-
this.paintBitmap(bitmap, frame.width, frame.height);
|
|
640
|
-
}
|
|
641
|
-
catch (error) {
|
|
642
|
-
bitmap.close();
|
|
643
|
-
this.requestSuspend(runEpoch);
|
|
644
|
-
this.reportError({
|
|
645
|
-
code: 'frame_render_failed',
|
|
646
|
-
message: `Could not render live browser frame: ${getErrorMessage(error)}`,
|
|
647
|
-
cause: error,
|
|
648
|
-
frame,
|
|
649
|
-
}, runEpoch);
|
|
650
|
-
return;
|
|
651
|
-
}
|
|
652
|
-
this.displayedFrame = {
|
|
653
|
-
tabId: frame.tabId,
|
|
654
|
-
sequence: frame.sequence,
|
|
655
|
-
generation: frame.generation,
|
|
656
|
-
viewportRevision: frame.viewportRevision,
|
|
657
|
-
viewport: { ...frame.viewport },
|
|
658
|
-
};
|
|
659
|
-
if (this.resizeFence
|
|
660
|
-
&& !this.viewportProcessing
|
|
661
|
-
&& frame.viewportRevision >= this.resizeFence.minimumViewportRevision
|
|
662
|
-
&& viewportEquals(frame.viewport, this.resizeFence.target)) {
|
|
663
|
-
this.resizeFence = undefined;
|
|
664
|
-
}
|
|
665
|
-
this.updateInputAvailability();
|
|
666
|
-
this.callFrameRendered(frame, runEpoch);
|
|
667
|
-
}
|
|
668
|
-
/**
|
|
669
|
-
* Presents one decoded bitmap. The canvas backing store is reallocated only
|
|
670
|
-
* when the frame dimensions differ from the current intrinsic dimensions.
|
|
671
|
-
*/
|
|
672
|
-
paintBitmap(bitmapArg, widthArg, heightArg) {
|
|
673
|
-
if (this.canvas.width !== widthArg) {
|
|
674
|
-
this.canvas.width = widthArg;
|
|
675
|
-
}
|
|
676
|
-
if (this.canvas.height !== heightArg) {
|
|
677
|
-
this.canvas.height = heightArg;
|
|
678
|
-
}
|
|
679
|
-
if (this.bitmapContext) {
|
|
680
|
-
this.bitmapContext.transferFromImageBitmap(bitmapArg);
|
|
681
|
-
return;
|
|
682
|
-
}
|
|
683
|
-
if (!this.canvasContext) {
|
|
684
|
-
throw new Error('LiveBrowserCanvasRenderer has no rendering context');
|
|
685
|
-
}
|
|
686
|
-
this.canvasContext.clearRect(0, 0, widthArg, heightArg);
|
|
687
|
-
this.canvasContext.drawImage(bitmapArg, 0, 0, widthArg, heightArg);
|
|
688
|
-
bitmapArg.close();
|
|
689
|
-
}
|
|
690
|
-
canRenderFrame(frameArg, runEpochArg) {
|
|
691
|
-
if (!this.running
|
|
692
|
-
|| !this.acceptingFrames
|
|
693
|
-
|| runEpochArg !== this.runEpoch
|
|
694
|
-
|| this.viewportProcessing) {
|
|
695
|
-
return false;
|
|
696
|
-
}
|
|
697
|
-
const state = this.state;
|
|
698
|
-
if (!state || state.status !== 'running' || state.activeTabId !== frameArg.tabId) {
|
|
699
|
-
return false;
|
|
700
|
-
}
|
|
701
|
-
const activeTab = state.tabs.find((tabArg) => tabArg.id === frameArg.tabId);
|
|
702
|
-
if (!activeTab || activeTab.status !== 'open' || !activeTab.streaming) {
|
|
703
|
-
return false;
|
|
704
|
-
}
|
|
705
|
-
if (state.viewportRevision > frameArg.viewportRevision
|
|
706
|
-
|| activeTab.generation > frameArg.generation) {
|
|
707
|
-
return false;
|
|
708
|
-
}
|
|
709
|
-
if (this.resizeFence) {
|
|
710
|
-
return frameArg.viewportRevision >= this.resizeFence.minimumViewportRevision
|
|
711
|
-
&& viewportEquals(frameArg.viewport, this.resizeFence.target);
|
|
712
|
-
}
|
|
713
|
-
return true;
|
|
714
|
-
}
|
|
715
|
-
acknowledgeFrame(frameWorkArg) {
|
|
716
|
-
if (frameWorkArg.acknowledgementAttempted) {
|
|
717
|
-
return Promise.resolve();
|
|
718
|
-
}
|
|
719
|
-
frameWorkArg.acknowledgementAttempted = true;
|
|
720
|
-
if (!this.isRunActive(frameWorkArg.runEpoch)) {
|
|
721
|
-
return Promise.resolve();
|
|
722
|
-
}
|
|
723
|
-
if (this.acknowledgementPromises.size >= maxPendingAcknowledgements) {
|
|
724
|
-
this.requestSuspend(frameWorkArg.runEpoch);
|
|
725
|
-
this.reportError({
|
|
726
|
-
code: 'frame_acknowledgement_failed',
|
|
727
|
-
message: `Live browser frame acknowledgement capacity of ${maxPendingAcknowledgements} was reached`,
|
|
728
|
-
}, frameWorkArg.runEpoch);
|
|
729
|
-
return Promise.resolve();
|
|
730
|
-
}
|
|
731
|
-
const acknowledgement = this.runClientOperation((optionsArg) => this.client.acknowledgeFrame(createFrameAcknowledgementRequest(frameWorkArg.frame), optionsArg), 'frame acknowledgement', frameWorkArg.runEpoch)
|
|
732
|
-
.then(() => undefined)
|
|
733
|
-
.catch((error) => {
|
|
734
|
-
if (error instanceof LiveBrowserRunAbortedError) {
|
|
735
|
-
return;
|
|
736
|
-
}
|
|
737
|
-
this.requestSuspend(frameWorkArg.runEpoch);
|
|
738
|
-
this.reportError({
|
|
739
|
-
code: 'frame_acknowledgement_failed',
|
|
740
|
-
message: `Could not acknowledge live browser frame: ${getErrorMessage(error)}`,
|
|
741
|
-
cause: error,
|
|
742
|
-
frame: frameWorkArg.frame,
|
|
743
|
-
}, frameWorkArg.runEpoch);
|
|
744
|
-
});
|
|
745
|
-
let trackedAcknowledgement;
|
|
746
|
-
trackedAcknowledgement = acknowledgement.finally(() => {
|
|
747
|
-
this.acknowledgementPromises.delete(trackedAcknowledgement);
|
|
748
|
-
});
|
|
749
|
-
this.acknowledgementPromises.add(trackedAcknowledgement);
|
|
750
|
-
return trackedAcknowledgement;
|
|
751
|
-
}
|
|
752
|
-
handlePointerDown(eventArg, runEpochArg) {
|
|
753
|
-
if (eventArg.pointerType && eventArg.pointerType !== 'mouse') {
|
|
754
|
-
return;
|
|
755
|
-
}
|
|
756
|
-
const button = this.getMouseButton(eventArg.button);
|
|
757
|
-
if (!button) {
|
|
758
|
-
return;
|
|
759
|
-
}
|
|
760
|
-
const displayedFrame = this.getInputFrame();
|
|
761
|
-
if (!displayedFrame || runEpochArg !== this.runEpoch) {
|
|
762
|
-
return;
|
|
763
|
-
}
|
|
764
|
-
eventArg.preventDefault();
|
|
765
|
-
const coordinates = this.mapCoordinates(eventArg, displayedFrame.viewport);
|
|
766
|
-
if (!coordinates) {
|
|
767
|
-
return;
|
|
768
|
-
}
|
|
769
|
-
this.focusTarget.focus({ preventScroll: true });
|
|
770
|
-
try {
|
|
771
|
-
this.canvas.setPointerCapture(eventArg.pointerId);
|
|
772
|
-
this.capturedPointerIds.add(eventArg.pointerId);
|
|
773
|
-
}
|
|
774
|
-
catch {
|
|
775
|
-
// Pointer capture may already have been released by the browser.
|
|
776
|
-
}
|
|
777
|
-
const input = {
|
|
778
|
-
...createInputIdentity(displayedFrame),
|
|
779
|
-
type: 'down',
|
|
780
|
-
...coordinates,
|
|
781
|
-
button,
|
|
782
|
-
buttons: eventArg.buttons,
|
|
783
|
-
clickCount: Math.min(3, Math.max(1, eventArg.detail || 1)),
|
|
784
|
-
modifiers: createModifiers(eventArg),
|
|
785
|
-
};
|
|
786
|
-
void this.enqueueInputCommand({
|
|
787
|
-
kind: 'mouse',
|
|
788
|
-
runEpoch: runEpochArg,
|
|
789
|
-
execute: async (optionsArg) => this.client.dispatchMouse(input, optionsArg),
|
|
790
|
-
onAttempt: () => this.pressedMouseButtons.set(button, input),
|
|
791
|
-
}).catch(() => undefined);
|
|
792
|
-
}
|
|
793
|
-
handlePointerMove(eventArg, runEpochArg) {
|
|
794
|
-
if (eventArg.pointerType && eventArg.pointerType !== 'mouse') {
|
|
795
|
-
return;
|
|
796
|
-
}
|
|
797
|
-
const displayedFrame = this.getInputFrame();
|
|
798
|
-
if (!displayedFrame || runEpochArg !== this.runEpoch) {
|
|
799
|
-
return;
|
|
800
|
-
}
|
|
801
|
-
eventArg.preventDefault();
|
|
802
|
-
const coordinates = this.mapCoordinates(eventArg, displayedFrame.viewport);
|
|
803
|
-
if (!coordinates) {
|
|
804
|
-
this.releasePointerCapture(eventArg.pointerId);
|
|
805
|
-
void this.scheduleInputReset(false, runEpochArg);
|
|
806
|
-
return;
|
|
807
|
-
}
|
|
808
|
-
const input = {
|
|
809
|
-
...createInputIdentity(displayedFrame),
|
|
810
|
-
type: 'move',
|
|
811
|
-
...coordinates,
|
|
812
|
-
button: 'none',
|
|
813
|
-
buttons: eventArg.buttons,
|
|
814
|
-
modifiers: createModifiers(eventArg),
|
|
815
|
-
};
|
|
816
|
-
void this.enqueueInputCommand({
|
|
817
|
-
kind: 'mouseMove',
|
|
818
|
-
runEpoch: runEpochArg,
|
|
819
|
-
execute: async (optionsArg) => this.client.dispatchMouse(input, optionsArg),
|
|
820
|
-
}).catch(() => undefined);
|
|
821
|
-
}
|
|
822
|
-
handlePointerUp(eventArg, runEpochArg) {
|
|
823
|
-
if (eventArg.pointerType && eventArg.pointerType !== 'mouse') {
|
|
824
|
-
return;
|
|
825
|
-
}
|
|
826
|
-
const button = this.getMouseButton(eventArg.button);
|
|
827
|
-
const displayedFrame = this.getInputFrame();
|
|
828
|
-
if (!button || !displayedFrame || runEpochArg !== this.runEpoch) {
|
|
829
|
-
this.releasePointerCapture(eventArg.pointerId);
|
|
830
|
-
return;
|
|
831
|
-
}
|
|
832
|
-
eventArg.preventDefault();
|
|
833
|
-
const coordinates = this.mapCoordinates(eventArg, displayedFrame.viewport);
|
|
834
|
-
if (!coordinates) {
|
|
835
|
-
this.releasePointerCapture(eventArg.pointerId);
|
|
836
|
-
void this.scheduleInputReset(false, runEpochArg);
|
|
837
|
-
return;
|
|
838
|
-
}
|
|
839
|
-
const input = {
|
|
840
|
-
...createInputIdentity(displayedFrame),
|
|
841
|
-
type: 'up',
|
|
842
|
-
...coordinates,
|
|
843
|
-
button,
|
|
844
|
-
buttons: eventArg.buttons,
|
|
845
|
-
clickCount: Math.min(3, Math.max(1, eventArg.detail || 1)),
|
|
846
|
-
modifiers: createModifiers(eventArg),
|
|
847
|
-
};
|
|
848
|
-
void this.enqueueInputCommand({
|
|
849
|
-
kind: 'mouse',
|
|
850
|
-
runEpoch: runEpochArg,
|
|
851
|
-
execute: async (optionsArg) => this.client.dispatchMouse(input, optionsArg),
|
|
852
|
-
onSuccess: () => this.pressedMouseButtons.delete(button),
|
|
853
|
-
}).catch(() => undefined);
|
|
854
|
-
this.releasePointerCapture(eventArg.pointerId);
|
|
855
|
-
}
|
|
856
|
-
handleWheel(eventArg, runEpochArg) {
|
|
857
|
-
const displayedFrame = this.getInputFrame();
|
|
858
|
-
if (!displayedFrame || runEpochArg !== this.runEpoch) {
|
|
859
|
-
return;
|
|
860
|
-
}
|
|
861
|
-
eventArg.preventDefault();
|
|
862
|
-
const coordinates = this.mapCoordinates(eventArg, displayedFrame.viewport);
|
|
863
|
-
if (!coordinates) {
|
|
864
|
-
return;
|
|
865
|
-
}
|
|
866
|
-
const multiplier = eventArg.deltaMode === WheelEvent.DOM_DELTA_LINE
|
|
867
|
-
? 16
|
|
868
|
-
: eventArg.deltaMode === WheelEvent.DOM_DELTA_PAGE
|
|
869
|
-
? displayedFrame.viewport.height
|
|
870
|
-
: 1;
|
|
871
|
-
const inputIdentity = createInputIdentity(displayedFrame);
|
|
872
|
-
const modifiers = createModifiers(eventArg);
|
|
873
|
-
this.statistics.inputCommandsEnqueued++;
|
|
874
|
-
const pendingWheel = this.pendingWheel;
|
|
875
|
-
if (pendingWheel
|
|
876
|
-
&& pendingWheel.runEpoch === runEpochArg
|
|
877
|
-
&& inputIdentityEquals(pendingWheel, inputIdentity)) {
|
|
878
|
-
mergeWheelInput(pendingWheel, {
|
|
879
|
-
...inputIdentity,
|
|
880
|
-
...coordinates,
|
|
881
|
-
deltaX: eventArg.deltaX * multiplier,
|
|
882
|
-
deltaY: eventArg.deltaY * multiplier,
|
|
883
|
-
modifiers,
|
|
884
|
-
});
|
|
885
|
-
this.statistics.inputCommandsCoalesced++;
|
|
886
|
-
}
|
|
887
|
-
else {
|
|
888
|
-
if (pendingWheel) {
|
|
889
|
-
this.flushPendingWheel();
|
|
890
|
-
}
|
|
891
|
-
this.pendingWheel = {
|
|
892
|
-
...inputIdentity,
|
|
893
|
-
...coordinates,
|
|
894
|
-
deltaX: clampWheelDelta(eventArg.deltaX * multiplier),
|
|
895
|
-
deltaY: clampWheelDelta(eventArg.deltaY * multiplier),
|
|
896
|
-
modifiers,
|
|
897
|
-
runEpoch: runEpochArg,
|
|
898
|
-
};
|
|
899
|
-
}
|
|
900
|
-
this.tryFlushPendingWheel();
|
|
901
|
-
}
|
|
902
|
-
/**
|
|
903
|
-
* Flushes accumulated wheel input at most once per animation frame and only
|
|
904
|
-
* while no wheel dispatch is in flight; the settling dispatch flushes the rest.
|
|
905
|
-
*/
|
|
906
|
-
tryFlushPendingWheel() {
|
|
907
|
-
if (!this.pendingWheel) {
|
|
908
|
-
return;
|
|
909
|
-
}
|
|
910
|
-
if (!this.wheelFrameElapsed) {
|
|
911
|
-
this.scheduleWheelFlush();
|
|
912
|
-
return;
|
|
913
|
-
}
|
|
914
|
-
if (this.inFlightWheelCommands > 0) {
|
|
915
|
-
return;
|
|
916
|
-
}
|
|
917
|
-
this.flushPendingWheel();
|
|
918
|
-
}
|
|
919
|
-
scheduleWheelFlush() {
|
|
920
|
-
if (this.wheelFlushSchedule) {
|
|
921
|
-
return;
|
|
922
|
-
}
|
|
923
|
-
this.wheelFlushSchedule = this.scheduleAnimationFrame(() => {
|
|
924
|
-
this.wheelFlushSchedule = undefined;
|
|
925
|
-
this.wheelFrameElapsed = true;
|
|
926
|
-
this.tryFlushPendingWheel();
|
|
927
|
-
});
|
|
928
|
-
}
|
|
929
|
-
/**
|
|
930
|
-
* Moves the accumulated wheel input into the command queue regardless of the
|
|
931
|
-
* frame gate so that later discrete commands stay behind it.
|
|
932
|
-
*/
|
|
933
|
-
flushPendingWheel() {
|
|
934
|
-
const pendingWheel = this.pendingWheel;
|
|
935
|
-
if (!pendingWheel) {
|
|
936
|
-
return;
|
|
937
|
-
}
|
|
938
|
-
this.pendingWheel = undefined;
|
|
939
|
-
this.wheelFrameElapsed = false;
|
|
940
|
-
this.scheduleWheelFlush();
|
|
941
|
-
const displayedFrame = this.getInputFrame();
|
|
942
|
-
if (!displayedFrame
|
|
943
|
-
|| pendingWheel.runEpoch !== this.runEpoch
|
|
944
|
-
|| !inputIdentityEquals(pendingWheel, createInputIdentity(displayedFrame))) {
|
|
945
|
-
return;
|
|
946
|
-
}
|
|
947
|
-
const { runEpoch, ...wheelInput } = pendingWheel;
|
|
948
|
-
void this.enqueueInputCommand({
|
|
949
|
-
kind: 'wheel',
|
|
950
|
-
runEpoch,
|
|
951
|
-
wheelInput,
|
|
952
|
-
execute: async (optionsArg) => this.client.dispatchWheel({
|
|
953
|
-
...wheelInput,
|
|
954
|
-
deltaX: clampWheelDelta(wheelInput.deltaX),
|
|
955
|
-
deltaY: clampWheelDelta(wheelInput.deltaY),
|
|
956
|
-
}, optionsArg),
|
|
957
|
-
}).catch(() => undefined);
|
|
958
|
-
}
|
|
959
|
-
discardPendingWheel() {
|
|
960
|
-
this.pendingWheel = undefined;
|
|
961
|
-
if (this.wheelFlushSchedule) {
|
|
962
|
-
this.cancelScheduledFrame(this.wheelFlushSchedule);
|
|
963
|
-
this.wheelFlushSchedule = undefined;
|
|
964
|
-
}
|
|
965
|
-
this.wheelFrameElapsed = true;
|
|
966
|
-
}
|
|
967
|
-
handleKey(eventArg, typeArg, runEpochArg) {
|
|
968
|
-
const displayedFrame = this.getInputFrame();
|
|
969
|
-
if (!displayedFrame
|
|
970
|
-
|| runEpochArg !== this.runEpoch
|
|
971
|
-
|| eventArg.isComposing
|
|
972
|
-
|| eventArg.key === 'Process') {
|
|
973
|
-
return;
|
|
974
|
-
}
|
|
975
|
-
eventArg.preventDefault();
|
|
976
|
-
const text = typeArg === 'down'
|
|
977
|
-
&& eventArg.key.length === 1
|
|
978
|
-
&& !eventArg.metaKey
|
|
979
|
-
&& (!eventArg.ctrlKey || eventArg.altKey)
|
|
980
|
-
? eventArg.key
|
|
981
|
-
: undefined;
|
|
982
|
-
const input = {
|
|
983
|
-
...createInputIdentity(displayedFrame),
|
|
984
|
-
type: typeArg,
|
|
985
|
-
key: eventArg.key,
|
|
986
|
-
code: eventArg.code || undefined,
|
|
987
|
-
text,
|
|
988
|
-
windowsVirtualKeyCode: eventArg.keyCode || undefined,
|
|
989
|
-
autoRepeat: eventArg.repeat,
|
|
990
|
-
isKeypad: eventArg.location === KeyboardEvent.DOM_KEY_LOCATION_NUMPAD,
|
|
991
|
-
location: eventArg.location,
|
|
992
|
-
modifiers: createModifiers(eventArg),
|
|
993
|
-
};
|
|
994
|
-
const keyIdentity = eventArg.code || eventArg.key;
|
|
995
|
-
void this.enqueueInputCommand({
|
|
996
|
-
kind: 'key',
|
|
997
|
-
runEpoch: runEpochArg,
|
|
998
|
-
execute: async (optionsArg) => this.client.dispatchKey(input, optionsArg),
|
|
999
|
-
onAttempt: typeArg === 'down'
|
|
1000
|
-
? () => this.pressedKeys.set(keyIdentity, input)
|
|
1001
|
-
: undefined,
|
|
1002
|
-
onSuccess: () => {
|
|
1003
|
-
if (typeArg === 'up') {
|
|
1004
|
-
this.pressedKeys.delete(keyIdentity);
|
|
1005
|
-
}
|
|
1006
|
-
},
|
|
1007
|
-
}).catch(() => undefined);
|
|
1008
|
-
}
|
|
1009
|
-
mapCoordinates(eventArg, viewportArg) {
|
|
1010
|
-
const canvasBounds = this.canvas.getBoundingClientRect();
|
|
1011
|
-
if (canvasBounds.width <= 0 || canvasBounds.height <= 0) {
|
|
1012
|
-
return undefined;
|
|
1013
|
-
}
|
|
1014
|
-
const x = ((eventArg.clientX - canvasBounds.left) / canvasBounds.width) * viewportArg.width;
|
|
1015
|
-
const y = ((eventArg.clientY - canvasBounds.top) / canvasBounds.height) * viewportArg.height;
|
|
1016
|
-
return {
|
|
1017
|
-
x: Math.max(0, Math.min(viewportArg.width - coordinateEdgeInset, x)),
|
|
1018
|
-
y: Math.max(0, Math.min(viewportArg.height - coordinateEdgeInset, y)),
|
|
1019
|
-
};
|
|
1020
|
-
}
|
|
1021
|
-
getMouseButton(buttonArg) {
|
|
1022
|
-
return buttonArg === 0
|
|
1023
|
-
? 'left'
|
|
1024
|
-
: buttonArg === 1
|
|
1025
|
-
? 'middle'
|
|
1026
|
-
: buttonArg === 2
|
|
1027
|
-
? 'right'
|
|
1028
|
-
: buttonArg === 3
|
|
1029
|
-
? 'back'
|
|
1030
|
-
: buttonArg === 4
|
|
1031
|
-
? 'forward'
|
|
1032
|
-
: undefined;
|
|
1033
|
-
}
|
|
1034
|
-
getInputFrame() {
|
|
1035
|
-
return this.inputBlocked || !this.isDisplayedFrameCurrent()
|
|
1036
|
-
? undefined
|
|
1037
|
-
: this.displayedFrame;
|
|
1038
|
-
}
|
|
1039
|
-
requireInputFrame() {
|
|
1040
|
-
const displayedFrame = this.getInputFrame();
|
|
1041
|
-
if (!displayedFrame) {
|
|
1042
|
-
throw new Error('Live browser input is unavailable until a current frame is displayed');
|
|
1043
|
-
}
|
|
1044
|
-
return displayedFrame;
|
|
1045
|
-
}
|
|
1046
|
-
isDisplayedFrameCurrent() {
|
|
1047
|
-
const state = this.state;
|
|
1048
|
-
const displayedFrame = this.displayedFrame;
|
|
1049
|
-
if (!state || !displayedFrame || state.status !== 'running') {
|
|
1050
|
-
return false;
|
|
1051
|
-
}
|
|
1052
|
-
if (state.activeTabId !== displayedFrame.tabId
|
|
1053
|
-
|| state.viewportRevision > displayedFrame.viewportRevision) {
|
|
1054
|
-
return false;
|
|
1055
|
-
}
|
|
1056
|
-
const activeTab = state.tabs.find((tabArg) => tabArg.id === displayedFrame.tabId);
|
|
1057
|
-
return Boolean(activeTab
|
|
1058
|
-
&& activeTab.status === 'open'
|
|
1059
|
-
&& activeTab.streaming
|
|
1060
|
-
&& activeTab.generation <= displayedFrame.generation);
|
|
1061
|
-
}
|
|
1062
|
-
enqueueInputCommand(commandArg) {
|
|
1063
|
-
if (!this.running || this.inputBlocked || commandArg.runEpoch !== this.runEpoch) {
|
|
1064
|
-
return Promise.reject(new Error('Live browser input is currently blocked'));
|
|
1065
|
-
}
|
|
1066
|
-
return new Promise((resolve, reject) => {
|
|
1067
|
-
const command = {
|
|
1068
|
-
...commandArg,
|
|
1069
|
-
resolve,
|
|
1070
|
-
reject,
|
|
1071
|
-
};
|
|
1072
|
-
if (isCoalescableInputCommand(command.kind)) {
|
|
1073
|
-
this.enqueueCoalescableCommand(command);
|
|
1074
|
-
}
|
|
1075
|
-
else {
|
|
1076
|
-
const queuedDiscreteCommands = this.inputCommands.filter((queuedCommand) => (!isCoalescableInputCommand(queuedCommand.kind))).length;
|
|
1077
|
-
if (queuedDiscreteCommands >= maxInputQueueLength) {
|
|
1078
|
-
const error = new Error('Live browser input queue reached its capacity');
|
|
1079
|
-
this.reportError({
|
|
1080
|
-
code: 'input_queue_capacity_exceeded',
|
|
1081
|
-
message: error.message,
|
|
1082
|
-
cause: error,
|
|
1083
|
-
}, command.runEpoch);
|
|
1084
|
-
reject(error);
|
|
1085
|
-
return;
|
|
1086
|
-
}
|
|
1087
|
-
// Accumulated wheel input precedes this command in event order.
|
|
1088
|
-
this.flushPendingWheel();
|
|
1089
|
-
this.statistics.inputCommandsEnqueued++;
|
|
1090
|
-
this.inputCommands.push(command);
|
|
1091
|
-
}
|
|
1092
|
-
this.processInputCommands();
|
|
1093
|
-
});
|
|
1094
|
-
}
|
|
1095
|
-
/**
|
|
1096
|
-
* Coalescable commands never exhaust capacity: they merge into a same-kind
|
|
1097
|
-
* queue tail or evict the oldest queued coalescable command under pressure.
|
|
1098
|
-
*/
|
|
1099
|
-
enqueueCoalescableCommand(commandArg) {
|
|
1100
|
-
// Wheel submissions are counted per DOM event before accumulation.
|
|
1101
|
-
if (commandArg.kind === 'mouseMove') {
|
|
1102
|
-
this.statistics.inputCommandsEnqueued++;
|
|
1103
|
-
}
|
|
1104
|
-
const lastCommand = this.inputCommands.at(-1);
|
|
1105
|
-
if (lastCommand && lastCommand.kind === commandArg.kind) {
|
|
1106
|
-
this.statistics.inputCommandsCoalesced++;
|
|
1107
|
-
if (commandArg.kind === 'wheel' && lastCommand.wheelInput && commandArg.wheelInput) {
|
|
1108
|
-
mergeWheelInput(lastCommand.wheelInput, commandArg.wheelInput);
|
|
1109
|
-
commandArg.resolve();
|
|
1110
|
-
}
|
|
1111
|
-
else {
|
|
1112
|
-
lastCommand.resolve();
|
|
1113
|
-
this.inputCommands[this.inputCommands.length - 1] = commandArg;
|
|
1114
|
-
}
|
|
1115
|
-
return;
|
|
1116
|
-
}
|
|
1117
|
-
const queuedCoalescableCommands = this.inputCommands.filter((queuedCommand) => (isCoalescableInputCommand(queuedCommand.kind)));
|
|
1118
|
-
if (queuedCoalescableCommands.length >= maxQueuedCoalescableCommands) {
|
|
1119
|
-
this.dropOldestCoalescableCommand(queuedCoalescableCommands[0]);
|
|
1120
|
-
}
|
|
1121
|
-
this.inputCommands.push(commandArg);
|
|
1122
|
-
}
|
|
1123
|
-
dropOldestCoalescableCommand(oldestCommandArg) {
|
|
1124
|
-
const index = this.inputCommands.indexOf(oldestCommandArg);
|
|
1125
|
-
if (index < 0) {
|
|
1126
|
-
return;
|
|
1127
|
-
}
|
|
1128
|
-
this.inputCommands.splice(index, 1);
|
|
1129
|
-
this.statistics.inputCommandsCoalesced++;
|
|
1130
|
-
if (oldestCommandArg.kind === 'wheel' && oldestCommandArg.wheelInput) {
|
|
1131
|
-
const nextWheelCommand = this.inputCommands.find((queuedCommand) => (queuedCommand.kind === 'wheel' && queuedCommand.wheelInput));
|
|
1132
|
-
if (nextWheelCommand?.wheelInput) {
|
|
1133
|
-
const nextWheelInput = nextWheelCommand.wheelInput;
|
|
1134
|
-
nextWheelInput.deltaX = clampWheelDelta(nextWheelInput.deltaX + oldestCommandArg.wheelInput.deltaX);
|
|
1135
|
-
nextWheelInput.deltaY = clampWheelDelta(nextWheelInput.deltaY + oldestCommandArg.wheelInput.deltaY);
|
|
1136
|
-
}
|
|
1137
|
-
}
|
|
1138
|
-
oldestCommandArg.resolve();
|
|
1139
|
-
}
|
|
1140
|
-
/**
|
|
1141
|
-
* Dispatches queued commands in order with a bounded number in flight. The
|
|
1142
|
-
* remote session processes operations sequentially, so order is preserved.
|
|
1143
|
-
*/
|
|
1144
|
-
processInputCommands() {
|
|
1145
|
-
while (this.inputCommands.length > 0
|
|
1146
|
-
&& this.inFlightInputCommands < maxInFlightInputCommands) {
|
|
1147
|
-
const command = this.inputCommands.shift();
|
|
1148
|
-
if (!this.isRunActive(command.runEpoch)) {
|
|
1149
|
-
command.reject(new LiveBrowserRunAbortedError(`Live browser input belongs to inactive run ${command.runEpoch}`));
|
|
1150
|
-
continue;
|
|
1151
|
-
}
|
|
1152
|
-
this.dispatchInputCommand(command);
|
|
1153
|
-
}
|
|
1154
|
-
if (this.inputCommands.length === 0 && this.inFlightInputCommands === 0) {
|
|
1155
|
-
const resolvers = this.inputIdleResolvers;
|
|
1156
|
-
this.inputIdleResolvers = [];
|
|
1157
|
-
for (const resolver of resolvers) {
|
|
1158
|
-
resolver();
|
|
1159
|
-
}
|
|
1160
|
-
}
|
|
1161
|
-
}
|
|
1162
|
-
dispatchInputCommand(commandArg) {
|
|
1163
|
-
this.inFlightInputCommands++;
|
|
1164
|
-
if (commandArg.kind === 'wheel') {
|
|
1165
|
-
this.inFlightWheelCommands++;
|
|
1166
|
-
}
|
|
1167
|
-
const startedAt = performance.now();
|
|
1168
|
-
let dispatch;
|
|
1169
|
-
try {
|
|
1170
|
-
commandArg.onAttempt?.();
|
|
1171
|
-
dispatch = this.runClientOperation(commandArg.execute, 'input dispatch', commandArg.runEpoch);
|
|
1172
|
-
}
|
|
1173
|
-
catch (error) {
|
|
1174
|
-
dispatch = Promise.reject(error);
|
|
1175
|
-
}
|
|
1176
|
-
void dispatch.then(() => {
|
|
1177
|
-
if (!this.isRunActive(commandArg.runEpoch)) {
|
|
1178
|
-
throw new LiveBrowserRunAbortedError(`Live browser input belongs to inactive run ${commandArg.runEpoch}`);
|
|
1179
|
-
}
|
|
1180
|
-
this.statistics.lastInputRoundTripMs = performance.now() - startedAt;
|
|
1181
|
-
commandArg.onSuccess?.();
|
|
1182
|
-
commandArg.resolve();
|
|
1183
|
-
}).catch((error) => {
|
|
1184
|
-
commandArg.reject(error);
|
|
1185
|
-
this.handleInputDispatchFailure(error, commandArg.runEpoch);
|
|
1186
|
-
}).finally(() => {
|
|
1187
|
-
this.inFlightInputCommands--;
|
|
1188
|
-
if (commandArg.kind === 'wheel') {
|
|
1189
|
-
this.inFlightWheelCommands--;
|
|
1190
|
-
if (this.inFlightWheelCommands === 0) {
|
|
1191
|
-
this.tryFlushPendingWheel();
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
|
-
this.processInputCommands();
|
|
1195
|
-
});
|
|
1196
|
-
}
|
|
1197
|
-
handleInputDispatchFailure(errorArg, runEpochArg) {
|
|
1198
|
-
if (errorArg instanceof LiveBrowserRunAbortedError) {
|
|
1199
|
-
return;
|
|
1200
|
-
}
|
|
1201
|
-
if (errorArg instanceof LiveBrowserOperationTimeoutError) {
|
|
1202
|
-
this.requestSuspend(runEpochArg);
|
|
1203
|
-
}
|
|
1204
|
-
this.reportError({
|
|
1205
|
-
code: 'input_dispatch_failed',
|
|
1206
|
-
message: `Could not dispatch live browser input: ${getErrorMessage(errorArg)}`,
|
|
1207
|
-
cause: errorArg,
|
|
1208
|
-
}, runEpochArg);
|
|
1209
|
-
this.discardPendingWheel();
|
|
1210
|
-
const abandonedCommands = this.inputCommands.splice(0);
|
|
1211
|
-
for (const abandonedCommand of abandonedCommands) {
|
|
1212
|
-
abandonedCommand.reject(new Error('Live browser input was abandoned after a dispatch failure'));
|
|
1213
|
-
}
|
|
1214
|
-
if (!(errorArg instanceof LiveBrowserOperationTimeoutError) && !this.stopping) {
|
|
1215
|
-
void this.scheduleInputReset(true, runEpochArg);
|
|
1216
|
-
}
|
|
1217
|
-
}
|
|
1218
|
-
waitForInputIdle() {
|
|
1219
|
-
if (this.inFlightInputCommands === 0 && this.inputCommands.length === 0) {
|
|
1220
|
-
return Promise.resolve();
|
|
1221
|
-
}
|
|
1222
|
-
return new Promise((resolve) => {
|
|
1223
|
-
this.inputIdleResolvers.push(resolve);
|
|
1224
|
-
});
|
|
1225
|
-
}
|
|
1226
|
-
scheduleInputReset(clearDisplayArg, runEpochArg) {
|
|
1227
|
-
if (runEpochArg !== this.runEpoch || this.stopping) {
|
|
1228
|
-
return Promise.resolve();
|
|
1229
|
-
}
|
|
1230
|
-
this.inputBlocked = true;
|
|
1231
|
-
this.releasePointerCaptures();
|
|
1232
|
-
if (clearDisplayArg) {
|
|
1233
|
-
this.displayedFrame = undefined;
|
|
1234
|
-
this.clearCanvas();
|
|
1235
|
-
}
|
|
1236
|
-
if (this.inputResetPromise) {
|
|
1237
|
-
return this.inputResetPromise;
|
|
1238
|
-
}
|
|
1239
|
-
this.inputResetCount++;
|
|
1240
|
-
let resetOperation;
|
|
1241
|
-
resetOperation = this.inputResetTail.then(async () => {
|
|
1242
|
-
await this.waitForInputIdle();
|
|
1243
|
-
await this.releasePressedInput(runEpochArg);
|
|
1244
|
-
}).finally(() => {
|
|
1245
|
-
this.inputResetCount--;
|
|
1246
|
-
if (this.inputResetPromise === resetOperation) {
|
|
1247
|
-
this.inputResetPromise = undefined;
|
|
1248
|
-
}
|
|
1249
|
-
this.updateInputAvailability();
|
|
1250
|
-
});
|
|
1251
|
-
this.inputResetPromise = resetOperation;
|
|
1252
|
-
this.inputResetTail = resetOperation.then(() => undefined, () => undefined);
|
|
1253
|
-
return resetOperation;
|
|
1254
|
-
}
|
|
1255
|
-
async releasePressedInput(runEpochArg) {
|
|
1256
|
-
for (const [keyIdentity, pressedKey] of [...this.pressedKeys.entries()]) {
|
|
1257
|
-
const released = await this.tryInputRelease((optionsArg) => this.client.dispatchKey({
|
|
1258
|
-
...pressedKey,
|
|
1259
|
-
type: 'up',
|
|
1260
|
-
text: undefined,
|
|
1261
|
-
autoRepeat: false,
|
|
1262
|
-
modifiers: {},
|
|
1263
|
-
}, optionsArg), runEpochArg);
|
|
1264
|
-
if (released && this.pressedKeys.get(keyIdentity) === pressedKey) {
|
|
1265
|
-
this.pressedKeys.delete(keyIdentity);
|
|
1266
|
-
}
|
|
1267
|
-
}
|
|
1268
|
-
for (const [button, pressedButton] of [...this.pressedMouseButtons.entries()]) {
|
|
1269
|
-
const released = await this.tryInputRelease((optionsArg) => this.client.dispatchMouse({
|
|
1270
|
-
...pressedButton,
|
|
1271
|
-
type: 'up',
|
|
1272
|
-
buttons: 0,
|
|
1273
|
-
clickCount: 1,
|
|
1274
|
-
modifiers: {},
|
|
1275
|
-
}, optionsArg), runEpochArg);
|
|
1276
|
-
if (released && this.pressedMouseButtons.get(button) === pressedButton) {
|
|
1277
|
-
this.pressedMouseButtons.delete(button);
|
|
1278
|
-
}
|
|
1279
|
-
}
|
|
1280
|
-
}
|
|
1281
|
-
async tryInputRelease(operationArg, runEpochArg) {
|
|
1282
|
-
let lastError;
|
|
1283
|
-
for (let attempt = 0; attempt < maxInputReleaseAttempts; attempt++) {
|
|
1284
|
-
try {
|
|
1285
|
-
await this.runClientOperation(operationArg, 'input release', runEpochArg);
|
|
1286
|
-
return true;
|
|
1287
|
-
}
|
|
1288
|
-
catch (error) {
|
|
1289
|
-
if (error instanceof LiveBrowserRunAbortedError) {
|
|
1290
|
-
return false;
|
|
1291
|
-
}
|
|
1292
|
-
lastError = error;
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
this.requestSuspend(runEpochArg);
|
|
1296
|
-
this.reportInputReleaseError(lastError, runEpochArg);
|
|
1297
|
-
return false;
|
|
1298
|
-
}
|
|
1299
|
-
reportInputReleaseError(errorArg, runEpochArg) {
|
|
1300
|
-
this.reportError({
|
|
1301
|
-
code: 'input_dispatch_failed',
|
|
1302
|
-
message: `Could not release live browser input: ${getErrorMessage(errorArg)}`,
|
|
1303
|
-
cause: errorArg,
|
|
1304
|
-
}, runEpochArg);
|
|
1305
|
-
}
|
|
1306
|
-
queueViewport(widthArg, heightArg, runEpochArg) {
|
|
1307
|
-
if (!this.running
|
|
1308
|
-
|| this.stopping
|
|
1309
|
-
|| this.interruptionRequested
|
|
1310
|
-
|| runEpochArg !== this.runEpoch) {
|
|
1311
|
-
return;
|
|
1312
|
-
}
|
|
1313
|
-
const viewport = this.normalizeGeneratedViewport(widthArg, heightArg, runEpochArg);
|
|
1314
|
-
if (!viewport)
|
|
1315
|
-
return;
|
|
1316
|
-
if (this.pendingViewport && viewportEquals(viewport, this.pendingViewport)) {
|
|
1317
|
-
return;
|
|
1318
|
-
}
|
|
1319
|
-
if (this.inFlightViewport && viewportEquals(viewport, this.inFlightViewport)) {
|
|
1320
|
-
this.pendingViewport = undefined;
|
|
1321
|
-
return;
|
|
1322
|
-
}
|
|
1323
|
-
if (!this.inFlightViewport
|
|
1324
|
-
&& this.resizeFence
|
|
1325
|
-
&& viewportEquals(viewport, this.resizeFence.target)) {
|
|
1326
|
-
this.pendingViewport = undefined;
|
|
1327
|
-
return;
|
|
1328
|
-
}
|
|
1329
|
-
if (!this.inFlightViewport
|
|
1330
|
-
&& !this.resizeFence
|
|
1331
|
-
&& this.state
|
|
1332
|
-
&& viewportEquals(viewport, this.state.viewport)) {
|
|
1333
|
-
this.pendingViewport = undefined;
|
|
1334
|
-
this.updateInputAvailability();
|
|
1335
|
-
return;
|
|
1336
|
-
}
|
|
1337
|
-
this.pendingViewport = viewport;
|
|
1338
|
-
this.inputBlocked = true;
|
|
1339
|
-
this.ensureViewportProcessor(runEpochArg);
|
|
1340
|
-
}
|
|
1341
|
-
normalizeGeneratedViewport(widthArg, heightArg, runEpochArg) {
|
|
1342
|
-
if (!Number.isFinite(widthArg)
|
|
1343
|
-
|| !Number.isFinite(heightArg)
|
|
1344
|
-
|| widthArg <= 0
|
|
1345
|
-
|| heightArg <= 0) {
|
|
1346
|
-
this.reportError({
|
|
1347
|
-
code: 'viewport_update_failed',
|
|
1348
|
-
message: 'Live browser viewport dimensions must be positive finite numbers',
|
|
1349
|
-
}, runEpochArg);
|
|
1350
|
-
return undefined;
|
|
1351
|
-
}
|
|
1352
|
-
const measuredWidth = Math.max(1, Math.floor(widthArg));
|
|
1353
|
-
const measuredHeight = Math.max(1, Math.floor(heightArg));
|
|
1354
|
-
const reductionFactor = Math.min(1, maxViewportWidth / measuredWidth, maxViewportHeight / measuredHeight);
|
|
1355
|
-
const width = Math.max(1, Math.floor(measuredWidth * reductionFactor));
|
|
1356
|
-
const height = Math.max(1, Math.floor(measuredHeight * reductionFactor));
|
|
1357
|
-
const providedScale = this.getDeviceScaleFactor();
|
|
1358
|
-
if (!Number.isFinite(providedScale) || providedScale <= 0) {
|
|
1359
|
-
this.reportError({
|
|
1360
|
-
code: 'viewport_update_failed',
|
|
1361
|
-
message: 'Live browser device scale factor must be a positive finite number',
|
|
1362
|
-
}, runEpochArg);
|
|
1363
|
-
return undefined;
|
|
1364
|
-
}
|
|
1365
|
-
const desiredScale = Math.min(maxDeviceScaleFactor, Math.max(minDeviceScaleFactor, providedScale));
|
|
1366
|
-
const physicalAreaIsValid = (scaleArg) => (Math.ceil(width * scaleArg) * Math.ceil(height * scaleArg) <= maxFramePixelArea);
|
|
1367
|
-
let deviceScaleFactor = desiredScale;
|
|
1368
|
-
if (!physicalAreaIsValid(deviceScaleFactor)) {
|
|
1369
|
-
let lower = minDeviceScaleFactor;
|
|
1370
|
-
let upper = desiredScale;
|
|
1371
|
-
for (let iteration = 0; iteration < 40; iteration += 1) {
|
|
1372
|
-
const candidate = (lower + upper) / 2;
|
|
1373
|
-
if (physicalAreaIsValid(candidate))
|
|
1374
|
-
lower = candidate;
|
|
1375
|
-
else
|
|
1376
|
-
upper = candidate;
|
|
1377
|
-
}
|
|
1378
|
-
deviceScaleFactor = lower;
|
|
1379
|
-
}
|
|
1380
|
-
return { width, height, deviceScaleFactor };
|
|
1381
|
-
}
|
|
1382
|
-
ensureViewportProcessor(runEpochArg) {
|
|
1383
|
-
if (this.viewportProcessingPromise || !this.pendingViewport) {
|
|
1384
|
-
return;
|
|
1385
|
-
}
|
|
1386
|
-
const processingPromise = this.processViewportQueue(runEpochArg).finally(() => {
|
|
1387
|
-
if (this.viewportProcessingPromise === processingPromise) {
|
|
1388
|
-
this.viewportProcessingPromise = undefined;
|
|
1389
|
-
if (this.pendingViewport
|
|
1390
|
-
&& this.running
|
|
1391
|
-
&& !this.stopping
|
|
1392
|
-
&& runEpochArg === this.runEpoch) {
|
|
1393
|
-
this.ensureViewportProcessor(runEpochArg);
|
|
1394
|
-
}
|
|
1395
|
-
}
|
|
1396
|
-
});
|
|
1397
|
-
this.viewportProcessingPromise = processingPromise;
|
|
1398
|
-
}
|
|
1399
|
-
async processViewportQueue(runEpochArg) {
|
|
1400
|
-
this.viewportProcessing = true;
|
|
1401
|
-
try {
|
|
1402
|
-
while (this.pendingViewport
|
|
1403
|
-
&& this.running
|
|
1404
|
-
&& !this.stopping
|
|
1405
|
-
&& runEpochArg === this.runEpoch) {
|
|
1406
|
-
const viewport = this.pendingViewport;
|
|
1407
|
-
this.pendingViewport = undefined;
|
|
1408
|
-
this.inFlightViewport = viewport;
|
|
1409
|
-
if (!this.resizeFence && this.state && viewportEquals(viewport, this.state.viewport)) {
|
|
1410
|
-
this.inFlightViewport = undefined;
|
|
1411
|
-
continue;
|
|
1412
|
-
}
|
|
1413
|
-
await this.scheduleInputReset(true, runEpochArg);
|
|
1414
|
-
if (!this.running || this.stopping || runEpochArg !== this.runEpoch) {
|
|
1415
|
-
return;
|
|
1416
|
-
}
|
|
1417
|
-
const currentRevision = this.state?.viewportRevision ?? 0;
|
|
1418
|
-
const previousMinimumRevision = this.resizeFence?.minimumViewportRevision ?? currentRevision;
|
|
1419
|
-
try {
|
|
1420
|
-
await this.runClientOperation((optionsArg) => this.client.setViewport(viewport, optionsArg), 'viewport update', runEpochArg);
|
|
1421
|
-
if (!this.running || this.stopping || runEpochArg !== this.runEpoch) {
|
|
1422
|
-
return;
|
|
1423
|
-
}
|
|
1424
|
-
this.resizeFence = {
|
|
1425
|
-
target: viewport,
|
|
1426
|
-
minimumViewportRevision: Math.max(currentRevision, previousMinimumRevision) + 1,
|
|
1427
|
-
};
|
|
1428
|
-
}
|
|
1429
|
-
catch (error) {
|
|
1430
|
-
if (runEpochArg === this.runEpoch && !(error instanceof LiveBrowserRunAbortedError)) {
|
|
1431
|
-
this.resizeFence = undefined;
|
|
1432
|
-
if (error instanceof LiveBrowserOperationTimeoutError) {
|
|
1433
|
-
this.requestSuspend(runEpochArg);
|
|
1434
|
-
}
|
|
1435
|
-
this.reportError({
|
|
1436
|
-
code: 'viewport_update_failed',
|
|
1437
|
-
message: `Could not update live browser viewport: ${getErrorMessage(error)}`,
|
|
1438
|
-
cause: error,
|
|
1439
|
-
}, runEpochArg);
|
|
1440
|
-
}
|
|
1441
|
-
}
|
|
1442
|
-
finally {
|
|
1443
|
-
if (this.inFlightViewport && viewportEquals(this.inFlightViewport, viewport)) {
|
|
1444
|
-
this.inFlightViewport = undefined;
|
|
1445
|
-
}
|
|
1446
|
-
}
|
|
1447
|
-
}
|
|
1448
|
-
}
|
|
1449
|
-
finally {
|
|
1450
|
-
this.viewportProcessing = false;
|
|
1451
|
-
this.updateInputAvailability();
|
|
1452
|
-
}
|
|
1453
|
-
}
|
|
1454
|
-
updateInputAvailability() {
|
|
1455
|
-
this.inputBlocked = !(this.running
|
|
1456
|
-
&& this.acceptingFrames
|
|
1457
|
-
&& !this.viewportProcessing
|
|
1458
|
-
&& !this.resizeFence
|
|
1459
|
-
&& this.inputResetCount === 0
|
|
1460
|
-
&& this.isDisplayedFrameCurrent());
|
|
1461
|
-
}
|
|
1462
|
-
makeFocusTargetFocusable() {
|
|
1463
|
-
this.focusWasAdjusted = false;
|
|
1464
|
-
if (this.focusTarget.tabIndex >= 0) {
|
|
1465
|
-
return;
|
|
1466
|
-
}
|
|
1467
|
-
this.focusHadTabIndex = this.focusTarget.hasAttribute('tabindex');
|
|
1468
|
-
this.focusTabIndexValue = this.focusTarget.getAttribute('tabindex');
|
|
1469
|
-
this.focusTarget.setAttribute('tabindex', '0');
|
|
1470
|
-
this.focusWasAdjusted = true;
|
|
1471
|
-
}
|
|
1472
|
-
restoreFocusTarget() {
|
|
1473
|
-
if (!this.focusWasAdjusted) {
|
|
1474
|
-
return;
|
|
1475
|
-
}
|
|
1476
|
-
if (this.focusHadTabIndex && this.focusTabIndexValue !== null) {
|
|
1477
|
-
this.focusTarget.setAttribute('tabindex', this.focusTabIndexValue);
|
|
1478
|
-
}
|
|
1479
|
-
else {
|
|
1480
|
-
this.focusTarget.removeAttribute('tabindex');
|
|
1481
|
-
}
|
|
1482
|
-
this.focusWasAdjusted = false;
|
|
1483
|
-
}
|
|
1484
|
-
clearCanvas() {
|
|
1485
|
-
if (this.bitmapContext) {
|
|
1486
|
-
this.bitmapContext.transferFromImageBitmap(null);
|
|
1487
|
-
return;
|
|
1488
|
-
}
|
|
1489
|
-
this.canvasContext?.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
1490
|
-
}
|
|
1491
|
-
/**
|
|
1492
|
-
* Runs work on the next animation frame, or after one nominal frame period
|
|
1493
|
-
* when the document is not visible and animation frames would not fire.
|
|
1494
|
-
*/
|
|
1495
|
-
scheduleAnimationFrame(callbackArg) {
|
|
1496
|
-
const schedule = {};
|
|
1497
|
-
if (typeof document !== 'undefined'
|
|
1498
|
-
&& document.visibilityState === 'visible'
|
|
1499
|
-
&& typeof globalThis.requestAnimationFrame === 'function') {
|
|
1500
|
-
schedule.animationFrameId = globalThis.requestAnimationFrame(() => {
|
|
1501
|
-
schedule.animationFrameId = undefined;
|
|
1502
|
-
callbackArg();
|
|
1503
|
-
});
|
|
1504
|
-
}
|
|
1505
|
-
else {
|
|
1506
|
-
schedule.timeoutId = globalThis.setTimeout(() => {
|
|
1507
|
-
schedule.timeoutId = undefined;
|
|
1508
|
-
callbackArg();
|
|
1509
|
-
}, animationFrameFallbackMs);
|
|
1510
|
-
}
|
|
1511
|
-
return schedule;
|
|
1512
|
-
}
|
|
1513
|
-
cancelScheduledFrame(scheduleArg) {
|
|
1514
|
-
if (scheduleArg.animationFrameId !== undefined) {
|
|
1515
|
-
globalThis.cancelAnimationFrame(scheduleArg.animationFrameId);
|
|
1516
|
-
scheduleArg.animationFrameId = undefined;
|
|
1517
|
-
}
|
|
1518
|
-
if (scheduleArg.timeoutId !== undefined) {
|
|
1519
|
-
globalThis.clearTimeout(scheduleArg.timeoutId);
|
|
1520
|
-
scheduleArg.timeoutId = undefined;
|
|
1521
|
-
}
|
|
1522
|
-
}
|
|
1523
|
-
callFrameRendered(frameArg, runEpochArg) {
|
|
1524
|
-
if (!this.onFrameRendered || runEpochArg !== this.runEpoch || !this.running) {
|
|
1525
|
-
return;
|
|
1526
|
-
}
|
|
1527
|
-
try {
|
|
1528
|
-
this.onFrameRendered(frameArg);
|
|
1529
|
-
}
|
|
1530
|
-
catch (error) {
|
|
1531
|
-
this.reportError({
|
|
1532
|
-
code: 'renderer_callback_failed',
|
|
1533
|
-
message: `Live browser frame callback failed: ${getErrorMessage(error)}`,
|
|
1534
|
-
cause: error,
|
|
1535
|
-
frame: frameArg,
|
|
1536
|
-
}, runEpochArg);
|
|
1537
|
-
}
|
|
1538
|
-
}
|
|
1539
|
-
reportError(errorArg, runEpochArg) {
|
|
1540
|
-
if (!this.onError || runEpochArg !== this.runEpoch) {
|
|
1541
|
-
return;
|
|
1542
|
-
}
|
|
1543
|
-
try {
|
|
1544
|
-
this.onError(errorArg);
|
|
1545
|
-
}
|
|
1546
|
-
catch {
|
|
1547
|
-
// Consumer error reporting must not break renderer cleanup.
|
|
1548
|
-
}
|
|
1549
|
-
}
|
|
1550
|
-
requestSuspend(runEpochArg) {
|
|
1551
|
-
if (!this.isRunActive(runEpochArg) || this.interruptionRequested) {
|
|
1552
|
-
return;
|
|
1553
|
-
}
|
|
1554
|
-
this.interruptRun(runEpochArg);
|
|
1555
|
-
void this.suspend();
|
|
1556
|
-
}
|
|
1557
|
-
validateTimeout(timeoutArg, nameArg) {
|
|
1558
|
-
if (!Number.isFinite(timeoutArg) || timeoutArg <= 0) {
|
|
1559
|
-
throw new Error(`${nameArg} must be a positive finite number`);
|
|
1560
|
-
}
|
|
1561
|
-
return timeoutArg;
|
|
1562
|
-
}
|
|
1563
|
-
runClientOperation(operationArg, operationNameArg, runEpochArg) {
|
|
1564
|
-
return this.runAbortableOperation((signalArg) => operationArg({ signal: signalArg }), this.operationTimeoutMs, operationNameArg, runEpochArg);
|
|
1565
|
-
}
|
|
1566
|
-
runAbortableOperation(operationArg, timeoutMsArg, operationNameArg, runEpochArg) {
|
|
1567
|
-
const runController = this.runController;
|
|
1568
|
-
if (!runController
|
|
1569
|
-
|| !this.isRunActive(runEpochArg)
|
|
1570
|
-
|| runController.signal.aborted) {
|
|
1571
|
-
return Promise.reject(new LiveBrowserRunAbortedError(`Cannot start ${operationNameArg} for inactive run ${runEpochArg}`));
|
|
1572
|
-
}
|
|
1573
|
-
const operationController = new AbortController();
|
|
1574
|
-
this.operationControllers.add(operationController);
|
|
1575
|
-
const abortFromRun = () => {
|
|
1576
|
-
const reason = runController.signal.reason instanceof Error
|
|
1577
|
-
? runController.signal.reason
|
|
1578
|
-
: new LiveBrowserRunAbortedError(`Live browser renderer run ${runEpochArg} was interrupted`);
|
|
1579
|
-
operationController.abort(reason);
|
|
1580
|
-
};
|
|
1581
|
-
runController.signal.addEventListener('abort', abortFromRun, { once: true });
|
|
1582
|
-
const timeout = globalThis.setTimeout(() => {
|
|
1583
|
-
operationController.abort(new LiveBrowserOperationTimeoutError(`${operationNameArg} timed out after ${timeoutMsArg}ms`));
|
|
1584
|
-
}, timeoutMsArg);
|
|
1585
|
-
let abortOperation = () => undefined;
|
|
1586
|
-
const operation = new Promise((resolve, reject) => {
|
|
1587
|
-
let settled = false;
|
|
1588
|
-
const settle = (callbackArg) => {
|
|
1589
|
-
if (!settled) {
|
|
1590
|
-
settled = true;
|
|
1591
|
-
callbackArg();
|
|
1592
|
-
}
|
|
1593
|
-
};
|
|
1594
|
-
abortOperation = () => {
|
|
1595
|
-
const reason = operationController.signal.reason instanceof Error
|
|
1596
|
-
? operationController.signal.reason
|
|
1597
|
-
: new LiveBrowserRunAbortedError(`${operationNameArg} was aborted`);
|
|
1598
|
-
settle(() => reject(reason));
|
|
1599
|
-
};
|
|
1600
|
-
operationController.signal.addEventListener('abort', abortOperation, { once: true });
|
|
1601
|
-
let operationResult;
|
|
1602
|
-
try {
|
|
1603
|
-
operationResult = operationArg(operationController.signal);
|
|
1604
|
-
}
|
|
1605
|
-
catch (error) {
|
|
1606
|
-
settle(() => reject(error));
|
|
1607
|
-
return;
|
|
1608
|
-
}
|
|
1609
|
-
operationResult.then((valueArg) => {
|
|
1610
|
-
settle(() => resolve(valueArg));
|
|
1611
|
-
}, (errorArg) => {
|
|
1612
|
-
settle(() => reject(errorArg));
|
|
1613
|
-
});
|
|
1614
|
-
}).finally(() => {
|
|
1615
|
-
globalThis.clearTimeout(timeout);
|
|
1616
|
-
runController.signal.removeEventListener('abort', abortFromRun);
|
|
1617
|
-
operationController.signal.removeEventListener('abort', abortOperation);
|
|
1618
|
-
this.operationControllers.delete(operationController);
|
|
1619
|
-
});
|
|
1620
|
-
return operation;
|
|
1621
|
-
}
|
|
1622
|
-
async decodeFrame(blobArg, runEpochArg) {
|
|
1623
|
-
let decodeOperation;
|
|
1624
|
-
try {
|
|
1625
|
-
decodeOperation = createImageBitmap(blobArg);
|
|
1626
|
-
}
|
|
1627
|
-
catch (error) {
|
|
1628
|
-
throw error;
|
|
1629
|
-
}
|
|
1630
|
-
let rawDecodeSettlementPromise;
|
|
1631
|
-
rawDecodeSettlementPromise = decodeOperation.then(() => undefined, () => undefined).finally(() => {
|
|
1632
|
-
this.rawDecodeSettlementPromises.delete(rawDecodeSettlementPromise);
|
|
1633
|
-
});
|
|
1634
|
-
this.rawDecodeSettlementPromises.add(rawDecodeSettlementPromise);
|
|
1635
|
-
try {
|
|
1636
|
-
return await this.runAbortableOperation(async () => decodeOperation, this.frameDecodeTimeoutMs, 'frame decode', runEpochArg);
|
|
1637
|
-
}
|
|
1638
|
-
catch (error) {
|
|
1639
|
-
if (error instanceof LiveBrowserOperationTimeoutError
|
|
1640
|
-
|| error instanceof LiveBrowserRunAbortedError) {
|
|
1641
|
-
void decodeOperation.then((lateBitmapArg) => lateBitmapArg.close(), () => undefined);
|
|
1642
|
-
throw error;
|
|
1643
|
-
}
|
|
1644
|
-
throw new LiveBrowserFrameIntegrityError(`frame bytes could not be decoded: ${getErrorMessage(error)}`, { cause: error });
|
|
1645
|
-
}
|
|
1646
|
-
}
|
|
1647
|
-
isRunActive(runEpochArg) {
|
|
1648
|
-
return Boolean(this.running
|
|
1649
|
-
&& !this.stopping
|
|
1650
|
-
&& runEpochArg === this.runEpoch
|
|
1651
|
-
&& this.runController
|
|
1652
|
-
&& !this.runController.signal.aborted);
|
|
1653
|
-
}
|
|
1654
|
-
validateFrame(frameArg) {
|
|
1655
|
-
if (!frameArg || typeof frameArg !== 'object') {
|
|
1656
|
-
throw new LiveBrowserFrameProtocolError('frame must be an object');
|
|
1657
|
-
}
|
|
1658
|
-
if (typeof frameArg.tabId !== 'string'
|
|
1659
|
-
|| frameArg.tabId.length === 0
|
|
1660
|
-
|| frameArg.tabId.length > 4096) {
|
|
1661
|
-
throw new LiveBrowserFrameProtocolError('frame.tabId must be a non-empty bounded string');
|
|
1662
|
-
}
|
|
1663
|
-
this.validateProtocolInteger(frameArg.sequence, 'frame.sequence', 1);
|
|
1664
|
-
this.validateProtocolInteger(frameArg.generation, 'frame.generation', 1);
|
|
1665
|
-
this.validateProtocolInteger(frameArg.viewportRevision, 'frame.viewportRevision', 1);
|
|
1666
|
-
this.validateViewport(frameArg.viewport, 'frame.viewport');
|
|
1667
|
-
if (frameArg.format !== 'jpeg' && frameArg.format !== 'png') {
|
|
1668
|
-
throw new LiveBrowserFrameProtocolError('frame.format must be jpeg or png');
|
|
1669
|
-
}
|
|
1670
|
-
const expectedMimeType = frameArg.format === 'jpeg' ? 'image/jpeg' : 'image/png';
|
|
1671
|
-
if (frameArg.mimeType !== expectedMimeType) {
|
|
1672
|
-
throw new LiveBrowserFrameProtocolError(`frame.mimeType must be ${expectedMimeType} for ${frameArg.format}`);
|
|
1673
|
-
}
|
|
1674
|
-
this.validateProtocolInteger(frameArg.width, 'frame.width', 1, maxFrameDimension);
|
|
1675
|
-
this.validateProtocolInteger(frameArg.height, 'frame.height', 1, maxFrameDimension);
|
|
1676
|
-
if (frameArg.width * frameArg.height > maxFramePixelArea) {
|
|
1677
|
-
throw new LiveBrowserFrameProtocolError(`frame pixel area must not exceed ${maxFramePixelArea}`);
|
|
1678
|
-
}
|
|
1679
|
-
if (!(frameArg.data instanceof Uint8Array)) {
|
|
1680
|
-
throw new LiveBrowserFrameProtocolError('frame.data must be a Uint8Array');
|
|
1681
|
-
}
|
|
1682
|
-
if (frameArg.data.byteLength === 0 || frameArg.data.byteLength > maxFrameByteLength) {
|
|
1683
|
-
throw new LiveBrowserFrameProtocolError(`frame.data byte length must be between 1 and ${maxFrameByteLength}`);
|
|
1684
|
-
}
|
|
1685
|
-
const metadata = frameArg.metadata;
|
|
1686
|
-
if (!metadata || typeof metadata !== 'object') {
|
|
1687
|
-
throw new LiveBrowserFrameProtocolError('frame.metadata must be an object');
|
|
1688
|
-
}
|
|
1689
|
-
this.validateProtocolNumber(metadata.offsetTop, 'frame.metadata.offsetTop');
|
|
1690
|
-
this.validateProtocolNumber(metadata.pageScaleFactor, 'frame.metadata.pageScaleFactor', true);
|
|
1691
|
-
this.validateProtocolNumber(metadata.deviceWidth, 'frame.metadata.deviceWidth', true);
|
|
1692
|
-
this.validateProtocolNumber(metadata.deviceHeight, 'frame.metadata.deviceHeight', true);
|
|
1693
|
-
if (metadata.deviceWidth > maxFrameDimension
|
|
1694
|
-
|| metadata.deviceHeight > maxFrameDimension
|
|
1695
|
-
|| metadata.deviceWidth * metadata.deviceHeight > maxFramePixelArea) {
|
|
1696
|
-
throw new LiveBrowserFrameProtocolError(`frame metadata dimensions must fit within ${maxFramePixelArea} pixels`);
|
|
1697
|
-
}
|
|
1698
|
-
this.validateProtocolNumber(metadata.scrollOffsetX, 'frame.metadata.scrollOffsetX');
|
|
1699
|
-
this.validateProtocolNumber(metadata.scrollOffsetY, 'frame.metadata.scrollOffsetY');
|
|
1700
|
-
if (metadata.timestamp !== undefined) {
|
|
1701
|
-
this.validateProtocolNumber(metadata.timestamp, 'frame.metadata.timestamp');
|
|
1702
|
-
}
|
|
1703
|
-
}
|
|
1704
|
-
validateViewport(viewportArg, nameArg) {
|
|
1705
|
-
if (!viewportArg || typeof viewportArg !== 'object') {
|
|
1706
|
-
throw new LiveBrowserFrameProtocolError(`${nameArg} must be an object`);
|
|
1707
|
-
}
|
|
1708
|
-
this.validateProtocolInteger(viewportArg.width, `${nameArg}.width`, 1, maxViewportWidth);
|
|
1709
|
-
this.validateProtocolInteger(viewportArg.height, `${nameArg}.height`, 1, maxViewportHeight);
|
|
1710
|
-
this.validateProtocolNumber(viewportArg.deviceScaleFactor, `${nameArg}.deviceScaleFactor`, true);
|
|
1711
|
-
if (viewportArg.deviceScaleFactor > maxDeviceScaleFactor) {
|
|
1712
|
-
throw new LiveBrowserFrameProtocolError(`${nameArg}.deviceScaleFactor must not exceed ${maxDeviceScaleFactor}`);
|
|
1713
|
-
}
|
|
1714
|
-
const physicalArea = viewportArg.width
|
|
1715
|
-
* viewportArg.height
|
|
1716
|
-
* viewportArg.deviceScaleFactor
|
|
1717
|
-
* viewportArg.deviceScaleFactor;
|
|
1718
|
-
if (physicalArea > maxFramePixelArea) {
|
|
1719
|
-
throw new LiveBrowserFrameProtocolError(`${nameArg} physical pixel area must not exceed ${maxFramePixelArea}`);
|
|
1720
|
-
}
|
|
1721
|
-
}
|
|
1722
|
-
validateProtocolInteger(valueArg, nameArg, minimumArg, maximumArg = Number.MAX_SAFE_INTEGER) {
|
|
1723
|
-
if (!Number.isSafeInteger(valueArg)
|
|
1724
|
-
|| valueArg < minimumArg
|
|
1725
|
-
|| valueArg > maximumArg) {
|
|
1726
|
-
throw new LiveBrowserFrameProtocolError(`${nameArg} must be an integer between ${minimumArg} and ${maximumArg}`);
|
|
1727
|
-
}
|
|
1728
|
-
}
|
|
1729
|
-
validateProtocolNumber(valueArg, nameArg, positiveArg = false) {
|
|
1730
|
-
if (!Number.isFinite(valueArg) || (positiveArg && valueArg <= 0)) {
|
|
1731
|
-
throw new LiveBrowserFrameProtocolError(`${nameArg} must be a ${positiveArg ? 'positive ' : ''}finite number`);
|
|
1732
|
-
}
|
|
1733
|
-
}
|
|
1734
|
-
releasePointerCapture(pointerIdArg) {
|
|
1735
|
-
this.capturedPointerIds.delete(pointerIdArg);
|
|
1736
|
-
try {
|
|
1737
|
-
if (this.canvas.hasPointerCapture(pointerIdArg)) {
|
|
1738
|
-
this.canvas.releasePointerCapture(pointerIdArg);
|
|
1739
|
-
}
|
|
1740
|
-
}
|
|
1741
|
-
catch {
|
|
1742
|
-
// Pointer capture may already have been released by the browser.
|
|
1743
|
-
}
|
|
1744
|
-
}
|
|
1745
|
-
releasePointerCaptures() {
|
|
1746
|
-
const pointerIds = [...this.capturedPointerIds];
|
|
1747
|
-
this.capturedPointerIds.clear();
|
|
1748
|
-
for (const pointerId of pointerIds) {
|
|
1749
|
-
this.releasePointerCapture(pointerId);
|
|
1750
|
-
}
|
|
5
|
+
super(optionsArg);
|
|
1751
6
|
}
|
|
1752
7
|
}
|
|
1753
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5saXZlYnJvd3NlcmNhbnZhc3JlbmRlcmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHNfd2ViL2NsYXNzZXMubGl2ZWJyb3dzZXJjYW52YXNyZW5kZXJlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFtQkEsTUFBTSxtQkFBbUIsR0FBRyxHQUFHLENBQUM7QUFDaEMsTUFBTSx3QkFBd0IsR0FBRyxDQUFDLENBQUM7QUFDbkMsTUFBTSw0QkFBNEIsR0FBRyxFQUFFLENBQUM7QUFDeEMsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDO0FBQzlCLE1BQU0sd0JBQXdCLEdBQUcsRUFBRSxDQUFDO0FBQ3BDLE1BQU0sZ0JBQWdCLEdBQUcsR0FBRyxDQUFDO0FBQzdCLE1BQU0sMEJBQTBCLEdBQUcsRUFBRSxDQUFDO0FBQ3RDLE1BQU0sdUJBQXVCLEdBQUcsQ0FBQyxDQUFDO0FBQ2xDLE1BQU0saUJBQWlCLEdBQUcsS0FBSyxDQUFDO0FBQ2hDLE1BQU0saUJBQWlCLEdBQUcsT0FBTyxDQUFDO0FBQ2xDLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxpQkFBaUIsR0FBRyxDQUFDLENBQUMsR0FBRyxPQUFPLENBQUM7QUFDN0QsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUM7QUFDOUIsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLENBQUM7QUFDL0IsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLENBQUM7QUFDbEMsTUFBTSxvQkFBb0IsR0FBRyxDQUFDLENBQUM7QUFDL0IsTUFBTSxtQkFBbUIsR0FBRyxLQUFLLENBQUM7QUFDbEMsTUFBTSx5QkFBeUIsR0FBRyxLQUFLLENBQUM7QUFFeEMsTUFBTSxnQ0FBaUMsU0FBUSxLQUFLO0NBQUc7QUFDdkQsTUFBTSwwQkFBMkIsU0FBUSxLQUFLO0NBQUc7QUFDakQsTUFBTSw2QkFBOEIsU0FBUSxLQUFLO0NBQUc7QUFDcEQsTUFBTSw4QkFBK0IsU0FBUSxLQUFLO0NBQUc7QUEyQ3JELE1BQU0seUJBQXlC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
|
|
8
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5saXZlYnJvd3NlcmNhbnZhc3JlbmRlcmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHNfd2ViL2NsYXNzZXMubGl2ZWJyb3dzZXJjYW52YXNyZW5kZXJlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUd2RSwwRUFBMEU7QUFDMUUsTUFBTSxPQUFPLHlCQUEwQixTQUFRLG1CQUFtQjtJQUNoRSxZQUFZLFVBQTZDO1FBQ3ZELEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNwQixDQUFDO0NBQ0YifQ==
|