bunite-core 0.17.1 → 0.17.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,23 @@
1
1
  // <bunite-webview> custom element — registered in every appres:// page via preload.
2
2
 
3
- import type { ClientOf } from "../rpc/index";
4
3
  import type {
5
- SurfaceCap, EvaluateResult, SurfaceCapabilities, ScreenshotResult,
6
- SurfaceEvent, ConsoleEntry, WaitResult, NavigationState,
7
- AccessibilitySnapshotResult, BoundingRectResult, ListFramesResult,
8
- DownloadEvent, DownloadPolicy, WaitForDownloadResult,
4
+ AccessibilitySnapshotResult,
5
+ BoundingRectResult,
6
+ ConsoleEntry,
7
+ DownloadEvent,
8
+ DownloadPolicy,
9
+ EvaluateResult,
10
+ ListFramesResult,
11
+ NavigationState,
9
12
  ResolveAndClickResult,
13
+ ScreenshotResult,
14
+ SurfaceCap,
15
+ SurfaceCapabilities,
16
+ SurfaceEvent,
17
+ WaitForDownloadResult,
18
+ WaitResult,
10
19
  } from "../rpc/framework";
20
+ import type { ClientOf } from "../rpc/index";
11
21
 
12
22
  declare const __buniteWebviewId: number;
13
23
 
@@ -25,12 +35,14 @@ function getSurfaceCap(): Promise<SurfaceClient> {
25
35
  }
26
36
 
27
37
  function callSurface<R>(fn: (s: SurfaceClient) => Promise<R> | R): Promise<R | void> {
28
- return getSurfaceCap().then(fn).catch((err) => {
29
- if ((globalThis as { __BUNITE_DEBUG__?: boolean }).__BUNITE_DEBUG__) {
30
- console.warn("[bunite] surface call failed", err);
31
- }
32
- return undefined;
33
- });
38
+ return getSurfaceCap()
39
+ .then(fn)
40
+ .catch((err) => {
41
+ if ((globalThis as { __BUNITE_DEBUG__?: boolean }).__BUNITE_DEBUG__) {
42
+ console.warn("[bunite] surface call failed", err);
43
+ }
44
+ return undefined;
45
+ });
34
46
  }
35
47
 
36
48
  /** Like `callSurface` but never swallows — automation surface API needs to
@@ -92,7 +104,7 @@ class OverlaySyncController {
92
104
  x: Math.round(r.x * dpr),
93
105
  y: Math.round(r.y * dpr),
94
106
  width: Math.round(r.width * dpr),
95
- height: Math.round(r.height * dpr)
107
+ height: Math.round(r.height * dpr),
96
108
  };
97
109
 
98
110
  // Always check for position changes (not caught by ResizeObserver)
@@ -130,11 +142,6 @@ class BuniteWebviewElement extends HTMLElement {
130
142
  private _unsubNavigate: (() => void) | null = null;
131
143
  private _activeStreams: Array<{ cancel?: () => void }> = [];
132
144
 
133
- constructor() {
134
- super();
135
- // NOTE: Custom element spec forbids setting attributes in constructor.
136
- }
137
-
138
145
  connectedCallback() {
139
146
  this._aborted = false;
140
147
  this._syncHidden = false;
@@ -156,9 +163,13 @@ class BuniteWebviewElement extends HTMLElement {
156
163
  try {
157
164
  for await (const event of dlStream) {
158
165
  if (ctrl.signal.aborted) break;
159
- this.dispatchEvent(new CustomEvent<DownloadEvent>("download-event", { detail: event }));
166
+ this.dispatchEvent(
167
+ new CustomEvent<DownloadEvent>("download-event", { detail: event }),
168
+ );
160
169
  }
161
- } catch { /* stream torn down */ }
170
+ } catch {
171
+ /* stream torn down */
172
+ }
162
173
  })();
163
174
  for await (const event of surfStream) {
164
175
  if (ctrl.signal.aborted) break;
@@ -179,7 +190,11 @@ class BuniteWebviewElement extends HTMLElement {
179
190
  if (pending) {
180
191
  // Await this exact init attempt; if it rejects, bail (init failed —
181
192
  // we'd otherwise spin forever waiting for a surfaceId that never lands).
182
- try { await pending; } catch { return; }
193
+ try {
194
+ await pending;
195
+ } catch {
196
+ return;
197
+ }
183
198
  // After resolve, _surfaceId may still be null if disconnect raced —
184
199
  // the next loop iteration checks signal.aborted to exit cleanly.
185
200
  } else {
@@ -223,7 +238,9 @@ class BuniteWebviewElement extends HTMLElement {
223
238
  // Cancel pending stream iterators so the `for await` actually unblocks —
224
239
  // AbortController alone only takes effect at the next received chunk.
225
240
  for (const stream of this._activeStreams) {
226
- try { stream.cancel?.(); } catch {}
241
+ try {
242
+ stream.cancel?.();
243
+ } catch {}
227
244
  }
228
245
  this._activeStreams = [];
229
246
  this._layoutObserver?.disconnect();
@@ -237,7 +254,9 @@ class BuniteWebviewElement extends HTMLElement {
237
254
  void callSurface((s) => s.remove({ surfaceId: id }));
238
255
  } else if (this._initPromise) {
239
256
  this._initPromise
240
- .then((r) => { void callSurface((s) => s.remove({ surfaceId: r.surfaceId })); })
257
+ .then((r) => {
258
+ void callSurface((s) => s.remove({ surfaceId: r.surfaceId }));
259
+ })
241
260
  .catch(() => {});
242
261
  }
243
262
  this._initPromise = null;
@@ -286,11 +305,24 @@ class BuniteWebviewElement extends HTMLElement {
286
305
  const sid = this._surfaceId;
287
306
  if (sid == null) {
288
307
  return {
289
- evaluate: false, crossOriginEval: false, surfaceEvents: false,
290
- nativeInputTrusted: false, click: false, type: false, press: false,
291
- scroll: false, mouse: false, dialogs: false, console: false,
292
- screenshot: false, accessibilitySnapshot: false, getBoundingRect: false,
293
- frames: false, downloads: false, popups: false, resolveAndClick: false,
308
+ evaluate: false,
309
+ crossOriginEval: false,
310
+ surfaceEvents: false,
311
+ nativeInputTrusted: false,
312
+ click: false,
313
+ type: false,
314
+ press: false,
315
+ scroll: false,
316
+ mouse: false,
317
+ dialogs: false,
318
+ console: false,
319
+ screenshot: false,
320
+ accessibilitySnapshot: false,
321
+ getBoundingRect: false,
322
+ frames: false,
323
+ downloads: false,
324
+ popups: false,
325
+ resolveAndClick: false,
294
326
  };
295
327
  }
296
328
  return callSurfaceTyped((s) => s.capabilities({ surfaceId: sid }));
@@ -298,7 +330,8 @@ class BuniteWebviewElement extends HTMLElement {
298
330
 
299
331
  // Automation input — `send*` prefix avoids clashing with HTMLElement.click() / .scroll().
300
332
  async sendClick(args: {
301
- x: number; y: number;
333
+ x: number;
334
+ y: number;
302
335
  button?: "left" | "middle" | "right";
303
336
  clickCount?: number;
304
337
  modifiers?: Array<"alt" | "ctrl" | "meta" | "shift">;
@@ -317,7 +350,7 @@ class BuniteWebviewElement extends HTMLElement {
317
350
  async sendPress(
318
351
  key: string,
319
352
  modifiers?: Array<"alt" | "ctrl" | "meta" | "shift">,
320
- action?: "down" | "up" | "both"
353
+ action?: "down" | "up" | "both",
321
354
  ): Promise<void> {
322
355
  const sid = this._surfaceId;
323
356
  if (sid == null) return;
@@ -325,7 +358,10 @@ class BuniteWebviewElement extends HTMLElement {
325
358
  }
326
359
 
327
360
  async sendScroll(args: {
328
- dx: number; dy: number; x?: number; y?: number;
361
+ dx: number;
362
+ dy: number;
363
+ x?: number;
364
+ y?: number;
329
365
  modifiers?: Array<"alt" | "ctrl" | "meta" | "shift">;
330
366
  }): Promise<void> {
331
367
  const sid = this._surfaceId;
@@ -335,7 +371,8 @@ class BuniteWebviewElement extends HTMLElement {
335
371
 
336
372
  async sendMouse(args: {
337
373
  action: "move" | "down" | "up";
338
- x: number; y: number;
374
+ x: number;
375
+ y: number;
339
376
  button?: "left" | "middle" | "right";
340
377
  modifiers?: Array<"alt" | "ctrl" | "meta" | "shift">;
341
378
  }): Promise<void> {
@@ -362,7 +399,10 @@ class BuniteWebviewElement extends HTMLElement {
362
399
  return callSurfaceTyped((s) => s.waitForSelector({ surfaceId: sid, selector, timeoutMs }));
363
400
  }
364
401
 
365
- async waitForFunction(expression: string, opts?: { timeoutMs?: number; pollIntervalMs?: number }): Promise<WaitResult> {
402
+ async waitForFunction(
403
+ expression: string,
404
+ opts?: { timeoutMs?: number; pollIntervalMs?: number },
405
+ ): Promise<WaitResult> {
366
406
  const sid = this._surfaceId;
367
407
  if (sid == null) return { ok: false, code: "runtime_error", message: "surface not ready" };
368
408
  return callSurfaceTyped((s) => s.waitForFunction({ surfaceId: sid, expression, ...opts }));
@@ -371,7 +411,10 @@ class BuniteWebviewElement extends HTMLElement {
371
411
  async getConsoleBuffer(opts?: { clear?: boolean }): Promise<ConsoleEntry[]> {
372
412
  const sid = this._surfaceId;
373
413
  if (sid == null) return [];
374
- return (await callSurfaceTyped((s) => s.getConsoleBuffer({ surfaceId: sid, clear: opts?.clear }))) ?? [];
414
+ return (
415
+ (await callSurfaceTyped((s) => s.getConsoleBuffer({ surfaceId: sid, clear: opts?.clear }))) ??
416
+ []
417
+ );
375
418
  }
376
419
 
377
420
  async getNavigationState(): Promise<NavigationState> {
@@ -380,16 +423,25 @@ class BuniteWebviewElement extends HTMLElement {
380
423
  return callSurfaceTyped((s) => s.getNavigationState({ surfaceId: sid }));
381
424
  }
382
425
 
383
- async accessibilitySnapshot(opts?: { interestingOnly?: boolean }): Promise<AccessibilitySnapshotResult> {
426
+ async accessibilitySnapshot(opts?: {
427
+ interestingOnly?: boolean;
428
+ }): Promise<AccessibilitySnapshotResult> {
384
429
  const sid = this._surfaceId;
385
430
  if (sid == null) return { ok: false, code: "not_supported", message: "surface not ready" };
386
- return callSurfaceTyped((s) => s.accessibilitySnapshot({ surfaceId: sid, interestingOnly: opts?.interestingOnly }));
431
+ return callSurfaceTyped((s) =>
432
+ s.accessibilitySnapshot({ surfaceId: sid, interestingOnly: opts?.interestingOnly }),
433
+ );
387
434
  }
388
435
 
389
- async getBoundingRect(selector: string, opts?: { frameId?: string }): Promise<BoundingRectResult> {
436
+ async getBoundingRect(
437
+ selector: string,
438
+ opts?: { frameId?: string },
439
+ ): Promise<BoundingRectResult> {
390
440
  const sid = this._surfaceId;
391
441
  if (sid == null) return { ok: false, code: "runtime_error", message: "surface not ready" };
392
- return callSurfaceTyped((s) => s.getBoundingRect({ surfaceId: sid, selector, frameId: opts?.frameId }));
442
+ return callSurfaceTyped((s) =>
443
+ s.getBoundingRect({ surfaceId: sid, selector, frameId: opts?.frameId }),
444
+ );
393
445
  }
394
446
 
395
447
  async listFrames(): Promise<ListFramesResult> {
@@ -405,7 +457,7 @@ class BuniteWebviewElement extends HTMLElement {
405
457
  button?: "left" | "middle" | "right";
406
458
  clickCount?: number;
407
459
  modifiers?: Array<"alt" | "ctrl" | "meta" | "shift">;
408
- }
460
+ },
409
461
  ): Promise<ResolveAndClickResult> {
410
462
  const sid = this._surfaceId;
411
463
  if (sid == null) return { ok: false, code: "runtime_error", message: "surface not ready" };
@@ -421,7 +473,9 @@ class BuniteWebviewElement extends HTMLElement {
421
473
  async waitForDownload(opts?: { timeoutMs?: number }): Promise<WaitForDownloadResult> {
422
474
  const sid = this._surfaceId;
423
475
  if (sid == null) return { ok: false, code: "not_supported", message: "surface not ready" };
424
- return callSurfaceTyped((s) => s.waitForDownload({ surfaceId: sid, timeoutMs: opts?.timeoutMs }));
476
+ return callSurfaceTyped((s) =>
477
+ s.waitForDownload({ surfaceId: sid, timeoutMs: opts?.timeoutMs }),
478
+ );
425
479
  }
426
480
 
427
481
  async dismissPopup(newSurfaceId: number): Promise<void> {
@@ -432,7 +486,10 @@ class BuniteWebviewElement extends HTMLElement {
432
486
  return callSurfaceTyped((s) => s.extendPopupTimeout({ newSurfaceId, gracePeriodMs }));
433
487
  }
434
488
 
435
- async screenshot(args?: { format?: "png" | "jpeg"; quality?: number }): Promise<ScreenshotResult> {
489
+ async screenshot(args?: {
490
+ format?: "png" | "jpeg";
491
+ quality?: number;
492
+ }): Promise<ScreenshotResult> {
436
493
  const sid = this._surfaceId;
437
494
  if (sid == null) return { ok: false, code: "not_supported", message: "surface not ready" };
438
495
  return callSurfaceTyped((s) => s.screenshot({ surfaceId: sid, ...args }));
@@ -461,9 +518,15 @@ class BuniteWebviewElement extends HTMLElement {
461
518
  this._syncHidden = false;
462
519
  this._applySurfaceHidden();
463
520
  }
464
- void callSurface((s) => s.resize({
465
- surfaceId: sid, x: rect.x, y: rect.y, w: rect.width, h: rect.height,
466
- }));
521
+ void callSurface((s) =>
522
+ s.resize({
523
+ surfaceId: sid,
524
+ x: rect.x,
525
+ y: rect.y,
526
+ w: rect.width,
527
+ h: rect.height,
528
+ }),
529
+ );
467
530
  });
468
531
  this._syncCtrl.start();
469
532
  }
@@ -493,34 +556,38 @@ class BuniteWebviewElement extends HTMLElement {
493
556
  return { surfaceId: adoptId };
494
557
  }) as Promise<SurfaceInitResponse>;
495
558
  this._initPromise = initPromise;
496
- initPromise.then((response) => {
497
- if (this._initPromise !== initPromise) return;
498
- if (this._aborted) {
499
- void callSurface((s) => s.remove({ surfaceId: response.surfaceId }));
500
- return;
501
- }
502
- this._surfaceId = response.surfaceId;
503
- this._setupSyncCtrl();
504
- }).catch((err) => {
505
- if ((globalThis as { __BUNITE_DEBUG__?: boolean }).__BUNITE_DEBUG__) {
506
- console.warn("[bunite] adopt-popup-id init failed", err);
507
- }
508
- this._initPromise = null;
509
- });
559
+ initPromise
560
+ .then((response) => {
561
+ if (this._initPromise !== initPromise) return;
562
+ if (this._aborted) {
563
+ void callSurface((s) => s.remove({ surfaceId: response.surfaceId }));
564
+ return;
565
+ }
566
+ this._surfaceId = response.surfaceId;
567
+ this._setupSyncCtrl();
568
+ })
569
+ .catch((err) => {
570
+ if ((globalThis as { __BUNITE_DEBUG__?: boolean }).__BUNITE_DEBUG__) {
571
+ console.warn("[bunite] adopt-popup-id init failed", err);
572
+ }
573
+ this._initPromise = null;
574
+ });
510
575
  return;
511
576
  }
512
577
 
513
578
  const src = this._pendingSrc || this.getAttribute("src") || "";
514
579
  this._pendingSrc = null;
515
580
 
516
- const initPromise = getSurfaceCap().then((s) => s.init({
517
- src,
518
- x: Math.round(r.x * dpr),
519
- y: Math.round(r.y * dpr),
520
- width: Math.round(r.width * dpr),
521
- height: Math.round(r.height * dpr),
522
- hidden: this._userHidden,
523
- })) as Promise<SurfaceInitResponse>;
581
+ const initPromise = getSurfaceCap().then((s) =>
582
+ s.init({
583
+ src,
584
+ x: Math.round(r.x * dpr),
585
+ y: Math.round(r.y * dpr),
586
+ width: Math.round(r.width * dpr),
587
+ height: Math.round(r.height * dpr),
588
+ hidden: this._userHidden,
589
+ }),
590
+ ) as Promise<SurfaceInitResponse>;
524
591
  this._initPromise = initPromise;
525
592
 
526
593
  initPromise
@@ -560,14 +627,24 @@ class BuniteWebviewElement extends HTMLElement {
560
627
  if (typeof customElements !== "undefined") {
561
628
  customElements.define("bunite-webview", BuniteWebviewElement);
562
629
 
563
- const raiseAll = () => { void callSurface((s) => s.bringAllVisiblesToFront()); };
630
+ const raiseAll = () => {
631
+ void callSurface((s) => s.bringAllVisiblesToFront());
632
+ };
564
633
  document.addEventListener("pointerdown", raiseAll, true);
565
634
 
566
- document.addEventListener("dragstart", () => {
567
- void callSurface((s) => s.setAllPassthrough({ passthrough: true }));
568
- }, true);
569
- document.addEventListener("dragend", () => {
570
- void callSurface((s) => s.setAllPassthrough({ passthrough: false }));
571
- raiseAll();
572
- }, true);
635
+ document.addEventListener(
636
+ "dragstart",
637
+ () => {
638
+ void callSurface((s) => s.setAllPassthrough({ passthrough: true }));
639
+ },
640
+ true,
641
+ );
642
+ document.addEventListener(
643
+ "dragend",
644
+ () => {
645
+ void callSurface((s) => s.setAllPassthrough({ passthrough: false }));
646
+ raiseAll();
647
+ },
648
+ true,
649
+ );
573
650
  }