@orkestrel/browser 0.0.24 → 0.0.25

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.
@@ -107,7 +107,7 @@ export declare const BROWSER_FRAME_WORLD_NAME = "__orkestrelBrowserFrame";
107
107
  */
108
108
  export declare const BROWSER_HAR_CREATOR: Readonly<{
109
109
  name: "@orkestrel/browser";
110
- version: "0.0.24";
110
+ version: "0.0.25";
111
111
  }>;
112
112
 
113
113
  /** Names accessibility roles that receive actionable outline references. */
@@ -711,6 +711,7 @@ export declare class BrowserContext implements BrowserContextInterface {
711
711
  constructor(client: CDPClientInterface, id?: string, viewport?: BrowserViewport, writer?: BrowserWriterInterface, emulation?: BrowserEmulationOptions, downloads?: BrowserDownloadOptions, options?: BrowserContextOptions);
712
712
  get emitter(): EmitterInterface<BrowserContextEventMap>;
713
713
  get id(): string | undefined;
714
+ get disposal(): BrowserContextDisposal | undefined;
714
715
  get cookies(): BrowserCookieManagerInterface;
715
716
  get permissions(): BrowserPermissionManagerInterface;
716
717
  get storage(): BrowserStorageManagerInterface;
@@ -723,6 +724,14 @@ export declare class BrowserContext implements BrowserContextInterface {
723
724
  close(): Promise<void>;
724
725
  }
725
726
 
727
+ /** Records Chromium's disposal acknowledgement or the failure that left disposal unconfirmed. */
728
+ export declare type BrowserContextDisposal = {
729
+ readonly confirmed: true;
730
+ } | {
731
+ readonly confirmed: false;
732
+ readonly error: unknown;
733
+ };
734
+
726
735
  /** Maps the browser-context lifecycle events. */
727
736
  export declare type BrowserContextEventMap = {
728
737
  readonly page: readonly [page: BrowserPageInterface];
@@ -746,6 +755,8 @@ export declare type BrowserContextEventMap = {
746
755
  export declare interface BrowserContextInterface {
747
756
  readonly emitter: EmitterInterface<BrowserContextEventMap>;
748
757
  readonly id: string | undefined;
758
+ /** Holds the remote disposal receipt after `close()` attempts disposal; wrapper destruction has none. */
759
+ readonly disposal: BrowserContextDisposal | undefined;
749
760
  readonly cookies: BrowserCookieManagerInterface;
750
761
  readonly permissions: BrowserPermissionManagerInterface;
751
762
  readonly storage: BrowserStorageManagerInterface;
@@ -4761,9 +4772,7 @@ export declare interface BrowserRunStoreInterface {
4761
4772
  }
4762
4773
 
4763
4774
  /**
4764
- * Reports that a CDP request could not be sent or completed because the client was not in a
4765
- * connectable state — not connected, closed while connecting, or the connection dropped
4766
- * mid-request — under the code `BROWSER_CDP_CONNECTION_ERROR`.
4775
+ * Reports that a CDP request could not be sent or completed because the client was not connected, closed while connecting, lost its connection, or lost the request's target session, under the code `BROWSER_CDP_CONNECTION_ERROR`.
4767
4776
  */
4768
4777
  export declare class CDPConnectionError extends BrowserError {
4769
4778
  constructor(message: string, context?: Readonly<Record<string, unknown>>);
@@ -107,7 +107,7 @@ export declare const BROWSER_FRAME_WORLD_NAME = "__orkestrelBrowserFrame";
107
107
  */
108
108
  export declare const BROWSER_HAR_CREATOR: Readonly<{
109
109
  name: "@orkestrel/browser";
110
- version: "0.0.24";
110
+ version: "0.0.25";
111
111
  }>;
112
112
 
113
113
  /** Names accessibility roles that receive actionable outline references. */
@@ -711,6 +711,7 @@ export declare class BrowserContext implements BrowserContextInterface {
711
711
  constructor(client: CDPClientInterface, id?: string, viewport?: BrowserViewport, writer?: BrowserWriterInterface, emulation?: BrowserEmulationOptions, downloads?: BrowserDownloadOptions, options?: BrowserContextOptions);
712
712
  get emitter(): EmitterInterface<BrowserContextEventMap>;
713
713
  get id(): string | undefined;
714
+ get disposal(): BrowserContextDisposal | undefined;
714
715
  get cookies(): BrowserCookieManagerInterface;
715
716
  get permissions(): BrowserPermissionManagerInterface;
716
717
  get storage(): BrowserStorageManagerInterface;
@@ -723,6 +724,14 @@ export declare class BrowserContext implements BrowserContextInterface {
723
724
  close(): Promise<void>;
724
725
  }
725
726
 
727
+ /** Records Chromium's disposal acknowledgement or the failure that left disposal unconfirmed. */
728
+ export declare type BrowserContextDisposal = {
729
+ readonly confirmed: true;
730
+ } | {
731
+ readonly confirmed: false;
732
+ readonly error: unknown;
733
+ };
734
+
726
735
  /** Maps the browser-context lifecycle events. */
727
736
  export declare type BrowserContextEventMap = {
728
737
  readonly page: readonly [page: BrowserPageInterface];
@@ -746,6 +755,8 @@ export declare type BrowserContextEventMap = {
746
755
  export declare interface BrowserContextInterface {
747
756
  readonly emitter: EmitterInterface<BrowserContextEventMap>;
748
757
  readonly id: string | undefined;
758
+ /** Holds the remote disposal receipt after `close()` attempts disposal; wrapper destruction has none. */
759
+ readonly disposal: BrowserContextDisposal | undefined;
749
760
  readonly cookies: BrowserCookieManagerInterface;
750
761
  readonly permissions: BrowserPermissionManagerInterface;
751
762
  readonly storage: BrowserStorageManagerInterface;
@@ -4761,9 +4772,7 @@ export declare interface BrowserRunStoreInterface {
4761
4772
  }
4762
4773
 
4763
4774
  /**
4764
- * Reports that a CDP request could not be sent or completed because the client was not in a
4765
- * connectable state — not connected, closed while connecting, or the connection dropped
4766
- * mid-request — under the code `BROWSER_CDP_CONNECTION_ERROR`.
4775
+ * Reports that a CDP request could not be sent or completed because the client was not connected, closed while connecting, lost its connection, or lost the request's target session, under the code `BROWSER_CDP_CONNECTION_ERROR`.
4767
4776
  */
4768
4777
  export declare class CDPConnectionError extends BrowserError {
4769
4778
  constructor(message: string, context?: Readonly<Record<string, unknown>>);
@@ -162,7 +162,7 @@ var BROWSER_MOUSE_BUTTON_MASKS = Object.freeze({
162
162
  */
163
163
  var BROWSER_HAR_CREATOR = Object.freeze({
164
164
  name: "@orkestrel/browser",
165
- version: "0.0.24"
165
+ version: "0.0.25"
166
166
  });
167
167
  /** Names the attribute that tags temporary screenshot styles and masks. */
168
168
  var BROWSER_SCREENSHOT_ATTRIBUTE = "data-orkestrel-screenshot";
@@ -1012,9 +1012,7 @@ var CDPError = class extends BrowserError {
1012
1012
  }
1013
1013
  };
1014
1014
  /**
1015
- * Reports that a CDP request could not be sent or completed because the client was not in a
1016
- * connectable state — not connected, closed while connecting, or the connection dropped
1017
- * mid-request — under the code `BROWSER_CDP_CONNECTION_ERROR`.
1015
+ * Reports that a CDP request could not be sent or completed because the client was not connected, closed while connecting, lost its connection, or lost the request's target session, under the code `BROWSER_CDP_CONNECTION_ERROR`.
1018
1016
  */
1019
1017
  var CDPConnectionError = class extends BrowserError {
1020
1018
  constructor(message, context) {
@@ -5224,6 +5222,7 @@ var CDPClient = class {
5224
5222
  const listener = signal === void 0 ? void 0 : this.#abort(id, signal);
5225
5223
  this.#pending.set(id, {
5226
5224
  method,
5225
+ session: options?.session,
5227
5226
  resolve,
5228
5227
  reject,
5229
5228
  timer,
@@ -5368,6 +5367,16 @@ var CDPClient = class {
5368
5367
  const method = parsed["method"];
5369
5368
  const rawParams = parsed["params"];
5370
5369
  const params = isRecord(rawParams) ? rawParams : Object.freeze({});
5370
+ if (method === "Target.detachedFromTarget" && isString(params["sessionId"])) {
5371
+ const detached = params["sessionId"];
5372
+ for (const [id, entry] of this.#pending) {
5373
+ if (entry.session !== detached) continue;
5374
+ this.#settle(id)?.reject(new CDPConnectionError("CDP session detached", {
5375
+ method: entry.method,
5376
+ session: detached
5377
+ }));
5378
+ }
5379
+ }
5371
5380
  const global = this.#subscriptions.get(void 0)?.get(method);
5372
5381
  if (global !== void 0) this.#dispatch(global, method, params);
5373
5382
  const session = parsed["sessionId"];
@@ -7207,10 +7216,12 @@ var BrowserRegistry = class {
7207
7216
  for (const frame of new Set([...this.tools(), ...this.#pending].map((entry) => entry.frame))) this.#invalidate(frame);
7208
7217
  }
7209
7218
  #navigated(params) {
7219
+ if (this.#page.closed || this.#destroying !== void 0) return;
7210
7220
  const frame = params["frame"];
7211
7221
  if (isRecord(frame) && isString(frame["id"])) this.#invalidate(frame["id"]);
7212
7222
  }
7213
7223
  #detached(params) {
7224
+ if (this.#page.closed || this.#destroying !== void 0) return;
7214
7225
  if (isString(params["frameId"])) this.#invalidate(params["frameId"]);
7215
7226
  }
7216
7227
  #invalidate(frame) {
@@ -7224,6 +7235,7 @@ var BrowserRegistry = class {
7224
7235
  if (removed) this.#emitter.emit("change");
7225
7236
  }
7226
7237
  #add(session, params) {
7238
+ if (this.#page.closed || this.#destroying !== void 0) return;
7227
7239
  if (!isArray(params["tools"])) return;
7228
7240
  for (const value of params["tools"]) {
7229
7241
  const tool = parseBrowserTool(value);
@@ -7234,6 +7246,7 @@ var BrowserRegistry = class {
7234
7246
  this.#emitter.emit("change");
7235
7247
  }
7236
7248
  #remove(params) {
7249
+ if (this.#page.closed || this.#destroying !== void 0) return;
7237
7250
  if (!isArray(params["tools"])) return;
7238
7251
  for (const value of params["tools"]) {
7239
7252
  const key = parseBrowserRemoval(value);
@@ -10169,10 +10182,10 @@ var BrowserPage = class BrowserPage extends BrowserFrame {
10169
10182
  } catch {}
10170
10183
  }
10171
10184
  async #close() {
10172
- await this.#release();
10173
10185
  try {
10174
10186
  await this.#client.send("Target.closeTarget", { targetId: this.#targetId });
10175
10187
  } catch {}
10188
+ await this.#release();
10176
10189
  }
10177
10190
  #release() {
10178
10191
  const active = this.#releasing;
@@ -10473,12 +10486,14 @@ var BrowserPage = class BrowserPage extends BrowserFrame {
10473
10486
  }
10474
10487
  async #attachWorker(session, id, url, category) {
10475
10488
  try {
10476
- await this.#client.send("Runtime.enable", void 0, { session });
10489
+ const enabling = this.#client.send("Runtime.enable", void 0, { session });
10490
+ if (category === "service_worker") this.#resumeTarget(session);
10491
+ await enabling;
10477
10492
  if (this.#closed) {
10478
10493
  await this.#detachChild(session, this.#sessionId);
10479
10494
  return;
10480
10495
  }
10481
- this.#resumeTarget(session);
10496
+ if (category !== "service_worker") this.#resumeTarget(session);
10482
10497
  const worker = new BrowserWorker(this.#client, session, id, url, category);
10483
10498
  this.#workers.set(id, worker);
10484
10499
  this.#emitter.emit("worker", worker);
@@ -10815,6 +10830,7 @@ var BrowserPage = class BrowserPage extends BrowserFrame {
10815
10830
  this.#emitter.emit("navigate", params["url"], true);
10816
10831
  }
10817
10832
  #handleFrameDetached(session, params) {
10833
+ if (this.#closed) return;
10818
10834
  const frame = params["frameId"];
10819
10835
  if (!isString(frame) || !this.#accepts(session, frame)) return;
10820
10836
  const swapped = params["reason"] === "swap";
@@ -10915,7 +10931,10 @@ var BrowserPage = class BrowserPage extends BrowserFrame {
10915
10931
  const session = params["sessionId"];
10916
10932
  if (!isRecord(target) || !isString(target["targetId"]) || !isString(session)) return;
10917
10933
  const category = target["type"];
10918
- if (owner !== this.#sessionId && category !== "iframe") return;
10934
+ if (owner !== this.#sessionId && category !== "iframe") {
10935
+ this.#detachChild(session, owner);
10936
+ return;
10937
+ }
10919
10938
  if (category === "worker" || category === "service_worker" || category === "shared_worker") {
10920
10939
  this.#attachWorker(session, target["targetId"], isString(target["url"]) ? target["url"] : "", category);
10921
10940
  return;
@@ -11223,6 +11242,7 @@ var BrowserContext = class {
11223
11242
  #publishing = /* @__PURE__ */ new Map();
11224
11243
  #observed = /* @__PURE__ */ new WeakSet();
11225
11244
  #shutdown;
11245
+ #disposal;
11226
11246
  #reference = 0;
11227
11247
  constructor(client, id, viewport, writer, emulation, downloads, options) {
11228
11248
  this.#client = client;
@@ -11247,6 +11267,9 @@ var BrowserContext = class {
11247
11267
  get id() {
11248
11268
  return this.#id;
11249
11269
  }
11270
+ get disposal() {
11271
+ return this.#disposal;
11272
+ }
11250
11273
  get cookies() {
11251
11274
  return this.#cookies;
11252
11275
  }
@@ -11289,14 +11312,14 @@ var BrowserContext = class {
11289
11312
  destroy() {
11290
11313
  const active = this.#shutdown;
11291
11314
  if (active !== void 0) return active;
11292
- const shutdown = this.#destroyResources();
11315
+ const shutdown = Promise.resolve().then(() => this.#destroyResources());
11293
11316
  this.#shutdown = shutdown;
11294
11317
  return shutdown;
11295
11318
  }
11296
11319
  close() {
11297
11320
  const active = this.#shutdown;
11298
11321
  if (active !== void 0) return active;
11299
- const shutdown = this.#closeResources();
11322
+ const shutdown = Promise.resolve().then(() => this.#closeResources());
11300
11323
  this.#shutdown = shutdown;
11301
11324
  return shutdown;
11302
11325
  }
@@ -11418,9 +11441,15 @@ var BrowserContext = class {
11418
11441
  let failure = await settleBrowserTeardown(...[...this.#pages.values()].map((page) => () => page.close()));
11419
11442
  this.#pages.clear();
11420
11443
  const id = this.#id;
11421
- if (id !== void 0) {
11422
- const settled = await settleBrowserTeardown(() => this.#client.send("Target.disposeBrowserContext", { browserContextId: id }));
11423
- failure ??= settled;
11444
+ if (id !== void 0) try {
11445
+ await this.#client.send("Target.disposeBrowserContext", { browserContextId: id });
11446
+ this.#disposal = { confirmed: true };
11447
+ } catch (error) {
11448
+ this.#disposal = {
11449
+ confirmed: false,
11450
+ error
11451
+ };
11452
+ failure ??= error;
11424
11453
  }
11425
11454
  if (failure !== void 0) throw failure;
11426
11455
  } finally {