@fkn/lib 0.9.41 → 0.9.42

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.
Files changed (76) hide show
  1. package/{account-generation-CSnZiN18.cjs → account-generation-B-6Pn0b5.cjs} +1 -1
  2. package/{account-generation-D7TpIoKt.js → account-generation-XNWOvLea.js} +5 -5
  3. package/account.cjs +1 -1
  4. package/account.js +6 -6
  5. package/api--LOXTOpv.cjs +3 -0
  6. package/{api-Dp-2AT3u.js → api-DIgTslNb.js} +154 -114
  7. package/{api-Cbty0JUM.d.ts → api-SwxtiYVU.d.ts} +24 -2
  8. package/api.cjs +1 -1
  9. package/api.d.ts +3 -3
  10. package/api.js +2 -2
  11. package/attach-policy.cjs +1 -1
  12. package/attach-policy.js +2 -2
  13. package/cloud/dns.d.ts +1 -1
  14. package/cloud/fetch.cjs +1 -1
  15. package/cloud/fetch.d.ts +1 -1
  16. package/cloud/fetch.js +1 -1
  17. package/cloud/fs.cjs +1 -1
  18. package/cloud/fs.js +1 -1
  19. package/cloud/net.d.ts +1 -1
  20. package/cloud-868OlBKn.cjs +1 -0
  21. package/{cloud-4t1WoEZn.d.ts → cloud-DUH-v10C.d.ts} +5 -3
  22. package/cloud-f3j4s8yZ.js +545 -0
  23. package/cloud.cjs +1 -1
  24. package/cloud.d.ts +3 -3
  25. package/cloud.js +2 -2
  26. package/{contract-BRc2ptdC.d.ts → contract-CCxPKIC7.d.ts} +77 -7
  27. package/contract.d.ts +3 -2
  28. package/dgram.cjs +1 -1
  29. package/dgram.d.ts +2 -2
  30. package/dgram.js +1 -1
  31. package/dns.cjs +1 -1
  32. package/dns.d.ts +1 -1
  33. package/dns.js +1 -1
  34. package/extension-BOBuYwZc.js +92 -0
  35. package/extension-hoUs5yJ7.cjs +1 -0
  36. package/{extension-DMU-CwMw.d.ts → extension-yhwDSIiD.d.ts} +22 -3
  37. package/extension.cjs +1 -1
  38. package/extension.d.ts +3 -3
  39. package/extension.js +3 -3
  40. package/fs/promises.cjs +1 -1
  41. package/fs/promises.js +1 -1
  42. package/{fs-q7Kg51hq.js → fs-CVnmXRf7.js} +1 -1
  43. package/{fs-BTyRnUPI.cjs → fs-p0bOOj5n.cjs} +1 -1
  44. package/fs.cjs +1 -1
  45. package/fs.js +2 -2
  46. package/{hosts-9dYv63ud.cjs → hosts-GNBhZO3-.cjs} +1 -1
  47. package/{hosts-BzbzOhG8.js → hosts-t7CKGTRz.js} +4 -1
  48. package/http.d.ts +1 -1
  49. package/{index-D2CA-NX5.d.ts → index-BtFiGoVQ.d.ts} +465 -51
  50. package/index.cjs +1 -1
  51. package/index.d.ts +16 -16
  52. package/index.js +62 -59
  53. package/lib-CfdmsLoI.cjs +53 -0
  54. package/{lib-C4Eeg9eM.js → lib-DppqX10G.js} +470 -302
  55. package/{net-CcEZP6Bb.d.ts → net-DcLF-6E-.d.ts} +2 -2
  56. package/net.cjs +1 -1
  57. package/net.d.ts +1 -1
  58. package/net.js +1 -1
  59. package/package.json +1 -1
  60. package/packages.cjs +1 -1
  61. package/packages.d.ts +1 -1
  62. package/packages.js +14 -14
  63. package/{proxy-D6YtsO1g.d.ts → proxy-CE46SkyA.d.ts} +2 -2
  64. package/{proxy-DjoPtJH9.cjs → proxy-CFK-KiwE.cjs} +1 -1
  65. package/{proxy-DMTdQ4dN.js → proxy-Dixbk1WL.js} +1 -1
  66. package/rooms.cjs +1 -1
  67. package/rooms.d.ts +1 -1
  68. package/rooms.js +11 -11
  69. package/{storage-BS5WMO4f.cjs → storage-D2cUJlVH.cjs} +1 -1
  70. package/{storage-BWmGrO6a.js → storage-Dn1gTLSZ.js} +2 -2
  71. package/api-jOTOA-5n.cjs +0 -3
  72. package/cloud-BLv19j-W.js +0 -480
  73. package/cloud-D7aQY4GH.cjs +0 -1
  74. package/extension-B9v933cT.js +0 -89
  75. package/extension-D2zMdc2f.cjs +0 -1
  76. package/lib-BfAg9mHD.cjs +0 -53
@@ -47,6 +47,20 @@ type OperationModule = {
47
47
  * from `args[1]`, so it declares `options => [undefined, options]`.
48
48
  */
49
49
  ensureArgs?: (options: Record<string, unknown>) => unknown[];
50
+ /**
51
+ * Maps the arguments a caller passes to the ones the wire carries, on the calling side, before the
52
+ * gate and the executor see them, and gives the chain method its parameter types. It lets a public
53
+ * option take a new name while every backend keeps reading the old one, since a backend resolves
54
+ * options by its own copy. Throw to refuse a call before anything is gated or sent. Absent, the
55
+ * arguments travel verbatim.
56
+ */
57
+ send?: (...args: any[]) => unknown[];
58
+ /**
59
+ * `false` leaves the operation off the chain types, so a call every backend refuses on a chain is a
60
+ * compile error. Types only: the chain still carries it and the backend still refuses it by name,
61
+ * for a caller the compiler does not see. A surface that serves it declares it itself.
62
+ */
63
+ typed?: false;
50
64
  };
51
65
  type KindModules = {
52
66
  selectors: Record<string, SelectorModule>;
@@ -56,6 +70,22 @@ type Modules = {
56
70
  element: KindModules;
57
71
  frame: KindModules;
58
72
  };
73
+ /**
74
+ * A chain method answered on the calling side by rewriting the parts collected so far into parts every
75
+ * executor already resolves, rather than by appending a part of its own name. An executor resolves
76
+ * selector names by its own copy of the registry and refuses one it lacks, so a member added this way
77
+ * reaches an older executor with a meaning it already has. `to` is the kind of chain it returns.
78
+ * Throw to refuse a chain the rewrite cannot express. The executor never sees it.
79
+ */
80
+ type ChainRewrite = {
81
+ to: ChainKind;
82
+ rewrite: (parts: SelectorPart[], ...args: any[]) => SelectorPart[];
83
+ };
84
+ /** Rewrites per kind. One named as a selector of its kind takes that selector's place on the chain. */
85
+ type Rewrites = {
86
+ element?: Record<string, ChainRewrite>;
87
+ frame?: Record<string, ChainRewrite>;
88
+ };
59
89
  type OperationOptions = {
60
90
  timeout?: number;
61
91
  };
@@ -320,24 +350,33 @@ type Extended<B extends Modules, S extends ModulesSpec> = {
320
350
  type ArgsOf<M> = M extends {
321
351
  resolve: (context: never, ...args: infer A) => unknown;
322
352
  } ? A : never;
353
+ type SendArgsOf<M> = M extends {
354
+ send: (...args: infer A) => unknown[];
355
+ } ? A : ArgsOf<M>;
356
+ type RewriteArgsOf<W> = W extends {
357
+ rewrite: (parts: never, ...args: infer A) => unknown;
358
+ } ? A : never;
323
359
  type ResultOf<M> = M extends {
324
360
  resolve: (...args: never[]) => infer R;
325
361
  } ? Awaited<R> : never;
326
362
  type ToOf<M> = M extends {
327
363
  to: infer K extends ChainKind;
328
364
  } ? K : 'element';
329
- type ChainOf<M extends Modules, K extends ChainKind> = K extends 'frame' ? FrameLocator<M> : Locator$1<M>;
365
+ type KindRewrites<R, K extends ChainKind> = K extends keyof R ? (R[K] extends Record<string, ChainRewrite> ? R[K] : {}) : {};
366
+ type ChainOf<M extends Modules, K extends ChainKind, R extends Rewrites> = K extends 'frame' ? FrameLocator$1<M, R> : Locator$1<M, R>;
330
367
  /**
331
368
  * What `ensure` may carry. An option no gate reads is accepted and ignored rather than refused:
332
369
  * `subtree` is the one apps still pass, and the scope it once narrowed is now decided per site by
333
370
  * the gate, so passing it changes nothing.
334
371
  */
335
372
  type EnsureOptions = OperationOptions & Record<string, unknown>;
336
- type Chain<M extends Modules, K extends ChainKind> = { [N in keyof M[K]['selectors']]: (...args: ArgsOf<M[K]['selectors'][N]>) => ChainOf<M, ToOf<M[K]['selectors'][N]>>; } & { [N in keyof M[K]['operations']]: (...args: ArgsOf<M[K]['operations'][N]>) => Promise<ResultOf<M[K]['operations'][N]>>; } & {
373
+ type Chain<M extends Modules, K extends ChainKind, R extends Rewrites = {}> = { [N in Exclude<keyof M[K]['selectors'], keyof KindRewrites<R, K>>]: (...args: ArgsOf<M[K]['selectors'][N]>) => ChainOf<M, ToOf<M[K]['selectors'][N]>, R>; } & { [N in keyof M[K]['operations'] as M[K]['operations'][N] extends {
374
+ typed: false;
375
+ } ? never : N]: (...args: SendArgsOf<M[K]['operations'][N]>) => Promise<ResultOf<M[K]['operations'][N]>>; } & { [N in keyof KindRewrites<R, K>]: (...args: RewriteArgsOf<KindRewrites<R, K>[N]>) => ChainOf<M, ToOf<KindRewrites<R, K>[N]>, R>; } & {
337
376
  ensure: (operation: Extract<keyof M[K]['operations'], string>, options?: EnsureOptions) => Promise<void>;
338
377
  };
339
- type Locator$1<M extends Modules = DefaultModules> = Chain<M, 'element'>;
340
- type FrameLocator<M extends Modules = DefaultModules> = Chain<M, 'frame'>;
378
+ type Locator$1<M extends Modules = DefaultModules, R extends Rewrites = {}> = Chain<M, 'element', R>;
379
+ type FrameLocator$1<M extends Modules = DefaultModules, R extends Rewrites = {}> = Chain<M, 'frame', R>;
341
380
  declare namespace video_d_exports {
342
381
  export { BoxedVideoElement, RemoteVideoElement, VideoElementState, box, createVideoElementHandle, isType, revive, type };
343
382
  }
@@ -446,7 +485,20 @@ declare const handleRevivableModules: (defaults: DefaultRevivableModules) => rea
446
485
  type LocatorOptions = OperationOptions & {
447
486
  reason?: string;
448
487
  };
488
+ /** `click` and `hover`'s options. */
449
489
  type PositionOptions = LocatorOptions & {
490
+ /**
491
+ * Where the pointer lands, as a 0..1 fraction of the element's box from its top-left corner: `x`
492
+ * across, `y` down, each 0.5 when left out, so the centre when absent. FKN's name, since
493
+ * Playwright's `position` is in pixels, which no backend serves yet: passing `position` is a
494
+ * TypeError, before anything is sent.
495
+ */
496
+ relativePosition?: {
497
+ x?: number;
498
+ y?: number;
499
+ };
500
+ };
501
+ type WirePositionOptions = LocatorOptions & {
450
502
  position?: {
451
503
  x?: number;
452
504
  y?: number;
@@ -588,10 +640,12 @@ declare const locatorModules: Extended<{
588
640
  readonly element: {
589
641
  operations: {
590
642
  click: {
591
- resolve: (context: LocatorContext, options?: PositionOptions) => void;
643
+ resolve: (context: LocatorContext, options?: WirePositionOptions) => void;
644
+ send: (options?: PositionOptions) => unknown[];
592
645
  };
593
646
  hover: {
594
- resolve: (context: LocatorContext, options?: PositionOptions) => void;
647
+ resolve: (context: LocatorContext, options?: WirePositionOptions) => void;
648
+ send: (options?: PositionOptions) => unknown[];
595
649
  };
596
650
  fill: {
597
651
  resolve: (context: LocatorContext, value: string, options?: LocatorOptions) => void;
@@ -628,6 +682,7 @@ declare const locatorModules: Extended<{
628
682
  };
629
683
  readonly evaluate: {
630
684
  readonly kind: "frame";
685
+ readonly typed: false;
631
686
  readonly resolve: (_context: LocatorContext, _source: string, _arg?: unknown) => never;
632
687
  };
633
688
  };
@@ -635,6 +690,31 @@ declare const locatorModules: Extended<{
635
690
  }>;
636
691
  type LocatorModules = typeof locatorModules;
637
692
  //#endregion
693
+ //#region ../web-extension/lib/lib/locator-rewrites.d.ts
694
+ declare const locatorRewrites: {
695
+ readonly element: {
696
+ readonly last: {
697
+ readonly to: 'element';
698
+ readonly rewrite: (parts: SelectorPart[]) => SelectorPart[];
699
+ };
700
+ readonly contentFrame: {
701
+ readonly to: 'frame';
702
+ readonly rewrite: (parts: SelectorPart[]) => SelectorPart[];
703
+ };
704
+ };
705
+ readonly frame: {
706
+ readonly owner: {
707
+ readonly to: 'element';
708
+ readonly rewrite: (parts: SelectorPart[]) => SelectorPart[];
709
+ };
710
+ readonly getByTestId: {
711
+ readonly to: 'element';
712
+ readonly rewrite: (parts: SelectorPart[], testId: string) => SelectorPart[];
713
+ };
714
+ };
715
+ };
716
+ type LocatorRewrites = typeof locatorRewrites;
717
+ //#endregion
638
718
  //#region ../web-extension/lib/permission/shared/permission.d.ts
639
719
  /**
640
720
  * The four categories a grant is asked and stored under. Every descriptor names one, so a key
@@ -654,7 +734,7 @@ type CategoryMeta = {
654
734
  heading: string;
655
735
  summary: string;
656
736
  title: (site: string) => string;
657
- /** `signedIn` is false when the frame was attached with `syncCookies: false` */
737
+ /** `signedIn` is false when the attach's wire carried `syncCookies: false`, which only a library that predates `cookies` sends; `cookies: 'native'` sends true */
658
738
  description: (site: string, signedIn: boolean) => string;
659
739
  cloudTitle: (site: string) => string;
660
740
  cloudDescription: (site: string) => string;
@@ -888,7 +968,20 @@ declare const permissions: {
888
968
  };
889
969
  //#endregion
890
970
  //#region ../web-extension/lib/lib/frame-core.d.ts
891
- type Locator = Locator$1<LocatorModules>;
971
+ /**
972
+ * Elements in an attached frame, found again on every call. Playwright's members where FKN has
973
+ * Playwright's meaning, plus `exists`, `videoElement` and the `reason` option. `last()` is the last
974
+ * match; `contentFrame()` enters the iframe a trailing `locator(selector)` matches, as
975
+ * `frameLocator(selector)` would, and is a TypeError on a locator that ends in anything else.
976
+ */
977
+ type Locator = Locator$1<LocatorModules, LocatorRewrites>;
978
+ /**
979
+ * A frame inside an attached frame, entered with `frameLocator(selector)`. Its document is read
980
+ * as the attached frame's is. `owner()` is Playwright's: a `Locator` on the iframe it entered, whose
981
+ * `contentFrame()` comes back here. `getByTestId` searches from its document root. `evaluate` and
982
+ * `addScriptTag` run on the attached frame only, so neither is offered here.
983
+ */
984
+ type FrameLocator = FrameLocator$1<LocatorModules, LocatorRewrites>;
892
985
  declare const attachFramePermission: {
893
986
  readonly scope: 'embed.iframe';
894
987
  readonly category: 'interaction';
@@ -903,28 +996,81 @@ declare const gotoPermission: {
903
996
  readonly title: 'Open a website inside this app';
904
997
  readonly description: 'Lets the app navigate to another site without leaving its window.';
905
998
  };
999
+ /**
1000
+ * `frame.goto`'s options. Refused with a TypeError before anything is sent: a `waitUntil` other than
1001
+ * `'load'` or `'commit'` (Playwright's `'domcontentloaded'` and `'networkidle'` are not served, and
1002
+ * `'documentstart'` is now `'commit'`), a `timeout` of 0 or below or not finite, and `timeoutMs`.
1003
+ */
906
1004
  type GotoOptions = {
907
1005
  /**
908
- * When `goto` resolves: `'load'`, the default, once the document it brings fired load;
909
- * `'documentstart'` once that document has started, possibly before the page's own scripts ran.
910
- * Either way a call made after it runs on the document the goto brought, never on the one it
911
- * replaced. On the cloud backend a `'documentstart'` goto resolves before its document commits: an
912
- * `evaluate` or `postMessage` made after it waits for that document, and a locator call retries
913
- * until it comes, each within its own timeout. If that document has not come by the goto's deadline,
914
- * `evaluate` and `postMessage` reject, and a locator call runs on whatever document the frame holds,
915
- * since the goto itself already resolved; on the extension the goto rejects instead.
1006
+ * When `goto` resolves: `'load'`, the default, once the document it brings fired load; `'commit'`,
1007
+ * Playwright's, once that document holds the frame, possibly before the page's own scripts ran and
1008
+ * whether or not it ever fires load. Either way a call made after it runs on the document the goto
1009
+ * brought, never on the one it replaced, and the goto rejects with `TimeoutError` when that
1010
+ * document has not come by its deadline.
916
1011
  *
917
1012
  * A goto that changes only the fragment of the url the page is at keeps its document. On the cloud
918
- * backend one awaited to `'load'` resolves once the page reports the new fragment, and a call made
919
- * after one awaited to `'documentstart'` waits only until then. Two pages are the exception there,
920
- * where such a goto brings a new document like any other: one reached through a redirect, and one
921
- * that followed a link onto another origin. On the extension (measured on Chromium) one awaited to
922
- * `'load'` resolves, since the frame fires load for it, and one awaited to `'documentstart'` runs
923
- * out at its timeout, since no new document starts.
1013
+ * backend it resolves, either way, once the page reports the new fragment. Two pages are the
1014
+ * exception there, where such a goto brings a new document like any other: one reached through a
1015
+ * redirect, and one that followed a link onto another origin. On the extension (measured on
1016
+ * Chromium) one awaited to `'load'` resolves, since the frame fires load for it, and one awaited to
1017
+ * `'commit'` runs out at its timeout, since no new document starts.
1018
+ */
1019
+ waitUntil?: 'commit' | 'load';
1020
+ /**
1021
+ * How long the goto may take, in milliseconds: 30000 when absent. Past it the goto rejects with
1022
+ * `TimeoutError`. A positive number: 0 is a TypeError, since every call ends by its deadline and
1023
+ * so does not take Playwright's "0 disables the timeout".
924
1024
  */
925
- waitUntil?: 'documentstart' | 'load';
1025
+ timeout?: number;
926
1026
  domains?: string[];
927
1027
  };
1028
+ /** `frame.addScriptTag`'s options, Playwright's `content` and FKN's `sourceUrl`. */
1029
+ type AddScriptTagOptions = {
1030
+ /** The script's source text. */
1031
+ content: string;
1032
+ /** Names the script in stack traces through `//# sourceURL`. Absent, its frames name the document. */
1033
+ sourceUrl?: string;
1034
+ };
1035
+ /**
1036
+ * `frame.clearCookies`' options, Playwright's `browserContext.clearCookies` names with its string
1037
+ * semantics: each matches exactly. A cookie is removed when it matches every option given; an
1038
+ * option left out, or `undefined`, matches every cookie. Playwright also takes a RegExp for each,
1039
+ * which FKN refuses for now (`Frame.clearCookies` says why).
1040
+ */
1041
+ type ClearCookiesOptions = {
1042
+ /** Only cookies with this name. */
1043
+ name?: string;
1044
+ /**
1045
+ * Only cookies with this domain, in the form Playwright reports it: `.youtube.com` for a cookie
1046
+ * its subdomains also receive, `www.youtube.com` for a host-only one, so `'youtube.com'` matches
1047
+ * neither of those. It must be on a site this attachment reaches.
1048
+ */
1049
+ domain?: string;
1050
+ /** Only cookies with this path, exactly as the cookie carries it. */
1051
+ path?: string;
1052
+ };
1053
+ /**
1054
+ * One `clearCookies` option as it crosses a channel, in the shapes Playwright's own wire carries: a
1055
+ * string as `equals`, a RegExp as its source and flags. The library sends `equals` only for now and
1056
+ * the middle page refuses a pattern; the render proxy shell still reads one.
1057
+ */
1058
+ type CookieMatchWire = {
1059
+ equals: string;
1060
+ } | {
1061
+ pattern: string;
1062
+ flags: string;
1063
+ };
1064
+ /**
1065
+ * `frame.clearCookies`' options as `createFrame` hands them to `FrameBackend.clearCookies`, already
1066
+ * checked, and as the cloud's channels carry them. Only the options given are present, so no options
1067
+ * at all are `{}`; an absent one matches every cookie.
1068
+ */
1069
+ type ClearCookiesWire = {
1070
+ name?: CookieMatchWire;
1071
+ domain?: CookieMatchWire;
1072
+ path?: CookieMatchWire;
1073
+ };
928
1074
  /** `frame.postMessage`'s options form, as `Window.postMessage` takes it. */
929
1075
  type FramePostMessageOptions = {
930
1076
  /** The page's origin as the site knows it, or `'*'`, the default. */
@@ -976,16 +1122,30 @@ type FrameEventListener<K extends keyof FrameEventMap> = (event: FrameEventMap[K
976
1122
  * window or a new one, a popup). A document with nothing of the page's own to run it in, such as an
977
1123
  * error page or a file that is not HTML, cannot be read, and a call on it waits to its deadline.
978
1124
  */
979
- type Frame = Omit<FrameLocator<LocatorModules>, 'evaluate'> & {
1125
+ type Frame = Omit<FrameLocator, 'owner'> & {
1126
+ /**
1127
+ * Navigates the frame to `url`, which must pass the rules an iframe src does, and adds its host
1128
+ * to the attachment. Resolves at `options.waitUntil`, and rejects with `TimeoutError` past
1129
+ * `options.timeout` (`GotoOptions`).
1130
+ */
980
1131
  goto(url: string, options?: GotoOptions): Promise<void>;
981
1132
  /** The url last given to `attachFrame` or `goto`, never the frame's live location: a page that moves itself does not change it. */
982
1133
  url(): string;
1134
+ /**
1135
+ * Which backend serves this attachment, fixed for its life. The same call can draw a card on one
1136
+ * backend and not the other, and spends a different identity on each, so an app must be able to
1137
+ * tell. A method, as Playwright's scalar facts are (`frame.url()`, `frame.name()`,
1138
+ * `page.isClosed()`). Undefined only for a Frame an app built itself with `createFrame` from a
1139
+ * backend that names none.
1140
+ */
1141
+ backend(): 'cloud' | 'extension' | undefined;
983
1142
  /**
984
1143
  * Asks for whole categories on this attachment's hosts, before any call. Resolves per request, in
985
1144
  * the order they were asked; a refusal is `allow: false`, never a rejection. An ask naming a
986
1145
  * category or key the registry cannot place on a row is a `TypeError`, thrown before it is sent.
1146
+ * Not Playwright's `page.request`, which is an HTTP client; the app asks here and the user grants.
987
1147
  */
988
- request(requests: CategoryRequest[]): Promise<CategoryGrant[]>;
1148
+ requestPermissions(requests: CategoryRequest[]): Promise<CategoryGrant[]>;
989
1149
  /**
990
1150
  * Runs `pageFunction` inside the attached site's OWN page realm, as a script of that page would:
991
1151
  * it sees the site's `window`, its globals and its DOM. The function is sent as source
@@ -994,21 +1154,26 @@ type Frame = Omit<FrameLocator<LocatorModules>, 'evaluate'> & {
994
1154
  * does, and is not called. A promise, returned by the function or produced by the expression, is
995
1155
  * awaited.
996
1156
  *
997
- * `arg` and the result cross by structured clone, so an `ArrayBuffer` or a typed array of bytes
998
- * survives the round trip. A thrown error or a rejected promise comes back as an `Error` carrying
1157
+ * `arg` is structured-cloned at the call, in the app's realm, on both backends, and the result
1158
+ * comes back by structured clone, so an `ArrayBuffer` or a typed array of bytes survives the round
1159
+ * trip. A value structured clone refuses in `arg` (a function, a DOM node, an untransferred port)
1160
+ * rejects with the platform's `DataCloneError` before anything is sent; a port goes to the page
1161
+ * with `postMessage`. A thrown error or a rejected promise comes back as an `Error` carrying
999
1162
  * the page's own name and message. A result that cannot be cloned (a function, a DOM node) is a
1000
1163
  * `LocatorInvalidError`, never a silent `undefined` and never a live handle into the page.
1001
1164
  *
1002
- * Every limit is a `LocatorInvalidError` that names it, never a call left pending:
1003
- * - time, both backends: the code has 30 seconds to settle, counted after any consent card. Only
1004
- * the wait ends there; code that never settles keeps running in the page.
1005
- * - size, extension only: the source with its `arg`, and the result, each carry at most 32 MiB
1006
- * (binary data by its bytes, text by its UTF-8 size), the most its message relay carries.
1007
- * - `Blob`, extension only: the relay cannot carry one, so pass or return `await blob.arrayBuffer()`.
1008
- * The cloud backend has neither limit, and returns a `Blob` as a `Blob`.
1165
+ * Every limit is refused by name, never a call left pending:
1166
+ * - time, both backends: the code has 30 seconds to settle, counted after any consent card, and
1167
+ * then the call rejects with `TimeoutError`. Only the wait ends there; code that never settles
1168
+ * keeps running in the page.
1169
+ * - size, extension only, a `LocatorInvalidError`: the source with its `arg`, and the result, each
1170
+ * carry at most 32 MiB (binary data by its bytes, text by its UTF-8 size), the most its message
1171
+ * relay carries.
1172
+ * - `Blob`, extension only, a `LocatorInvalidError`: the relay cannot carry one, so pass or return
1173
+ * `await blob.arrayBuffer()`. The cloud backend has neither limit, and returns a `Blob` as a `Blob`.
1009
1174
  *
1010
1175
  * Needs the Evaluation grant on both backends; an app without it is refused by name. It runs on the
1011
- * attached frame only: a chain into a nested frame (`frameLocator(...).evaluate`) is refused.
1176
+ * attached frame only: a nested `FrameLocator` does not offer it, and a call there anyway is refused.
1012
1177
  *
1013
1178
  * Called after `goto` resolved, whichever `waitUntil`, it runs once on the document that goto
1014
1179
  * brought, never on the one it replaced. On the cloud backend the call waits for that document when
@@ -1020,10 +1185,118 @@ type Frame = Omit<FrameLocator<LocatorModules>, 'evaluate'> & {
1020
1185
  * with `ExtensionOperationUnsupportedError`), and it runs where the page's content security policy
1021
1186
  * allows it: a frame whose host the app declared has its CSP replaced, so code runs; an undeclared
1022
1187
  * frame keeps its CSP, and a page that forbids `eval` refuses with a named error. On the cloud
1023
- * backend the code runs in the proxied document's realm, which mirage virtualizes, so there is no
1024
- * such limit.
1188
+ * backend the code runs in the proxied document's realm, which mirage virtualizes: the page's own
1189
+ * eval refusal and Trusted Types requirement do not refuse the source `evaluate` compiles, and every
1190
+ * string that code compiles itself (`eval`, `Function`, a string timer) is held to them, as the
1191
+ * page's own are.
1025
1192
  */
1026
1193
  evaluate<R = unknown, A = undefined>(pageFunction: ((arg: A) => R | Promise<R>) | string, arg?: A): Promise<Awaited<R>>;
1194
+ /**
1195
+ * Runs `content` as a classic inline script of the attached document, as one of that page's own
1196
+ * scripts would run: its top-level declarations stay on the page's global for later scripts and
1197
+ * `evaluate` calls, `document.currentScript` is the script while it runs, and the page's own error
1198
+ * listeners see its top-level error. Mirage rewrites it as it rewrites the page's scripts, and the
1199
+ * page's eval refusal and Trusted Types requirement do not refuse it, as for `evaluate`.
1200
+ * Playwright's name and its `content` option; its `url`, `path` and `type` are not served, and FKN's
1201
+ * `sourceUrl` names the script rather than loading one.
1202
+ *
1203
+ * Resolves `undefined` once the script ran; what it installed lives as long as the document, and the
1204
+ * `document` event says when that is gone. Same grant, limit and timing as `evaluate`: the
1205
+ * Evaluation grant (one card covers both), 30000 ms counted after any consent card, the attached
1206
+ * frame only, and after a `goto` the document that goto brought, waited for as `evaluate` waits. It
1207
+ * runs once: it never rides the locator retry loop, and a call whose document left before it
1208
+ * answered rejects and is not run again. Cloud only for now: the extension refuses it by name.
1209
+ *
1210
+ * Refused:
1211
+ * - TypeError, before anything is sent, in this order: `frame.addScriptTag: options must be an
1212
+ * object { content }`; for Playwright's `url`, `path` and `type`, `frame.addScriptTag: "<key>" is
1213
+ * not served; it runs content as a classic inline script`; `frame.addScriptTag: unknown option
1214
+ * "<key>"`; `frame.addScriptTag: content must be a string`; `frame.addScriptTag: sourceUrl must
1215
+ * be a non-empty string with no line break`.
1216
+ * - an `Error` carrying the page's own name and message: the script's top-level throw, after it ran.
1217
+ * - `LocatorDeniedError`: no Evaluation grant, the frame holds no page, or its document is outside
1218
+ * the attachment. Against an FKN page that predates `addScriptTag` the call arrives with no proof
1219
+ * of a grant and the render proxy refuses it: `frame.addScriptTag: the call arrived without an
1220
+ * Evaluation grant, so it was not run`.
1221
+ * - cloud, `LocatorUnsupportedError` `frame.addScriptTag: this render proxy predates addScriptTag;
1222
+ * reload the app`.
1223
+ * - cloud, `LocatorError`: the document of the goto before it had not come by that goto's deadline,
1224
+ * or the app started another goto first, so the script was not run.
1225
+ * - extension, `ExtensionOperationUnsupportedError` (operation `'addScriptTag'`)
1226
+ * `frame.addScriptTag: an extension frame does not run scripts through mirage yet; attach with
1227
+ * cloud.attachFrame`, before anything is dispatched.
1228
+ * - `TimeoutError` `frame.addScriptTag: no answer within 30000ms; the script may or may not have
1229
+ * run`.
1230
+ * - the terminal detach error once the attachment ended.
1231
+ */
1232
+ addScriptTag(options: AddScriptTagOptions): Promise<void>;
1233
+ /**
1234
+ * Removes cookies from this attachment's cookie jar, as Playwright's
1235
+ * `browserContext.clearCookies` removes them from a context. With no options it removes every
1236
+ * cookie of the sites this attachment reaches; with options, only the ones that match every option
1237
+ * given (`ClearCookiesOptions`). Each option is a string for now: a RegExp is refused.
1238
+ *
1239
+ * For signing out of a site the user signed in to inside an FKN frame: that session lives in FKN's
1240
+ * jar, never in the app, so the app cannot remove it any other way.
1241
+ *
1242
+ * Which jar: with `cookies: 'persistent'`, the default, the cloud jar of the app's top-level site,
1243
+ * which every app of that site shares (every fkn.app app shares one), so a removal there signs
1244
+ * every one of those apps out of that site. With `'ephemeral'` the attachment's own jar.
1245
+ *
1246
+ * Which cookies: only those of a site this attachment reaches, a site being a host's registered
1247
+ * domain under the Public Suffix List, private section included: the attach url's host (the empty
1248
+ * page's, for `blank`), each goto target's host from the goto's send, and `domains`.
1249
+ * `www.youtube.com` reaches every `*.youtube.com` cookie and no `google.com` one, the rule browsers
1250
+ * follow for `Clear-Site-Data: "cookies"`. A host under the same name is still another site when a
1251
+ * suffix lies between: `amazonaws.com` reaches no `mybucket.s3.amazonaws.com` cookie, since
1252
+ * `s3.amazonaws.com` is a suffix. A host that is itself a public suffix (`com`, `co.uk`,
1253
+ * `github.io`) is no site, and reaches only the cookies set for exactly that host. A Partitioned
1254
+ * cookie matches in every partition.
1255
+ *
1256
+ * Once it resolves: no request a document of this attachment starts carries a removed cookie, its
1257
+ * documents' `document.cookie` lists none, and the removal is committed to the jar, so an
1258
+ * attachment created afterwards never sees one. Another live attachment on the same jar (another
1259
+ * tab, another app's frame) drops them when it hears the commit, normally within milliseconds; a
1260
+ * request it started before then may still carry one. A request already in flight keeps what it
1261
+ * was sent with, and a later response may set cookies again, as in any browser.
1262
+ *
1263
+ * It resolves `undefined` and never says what or how much it removed, so it cannot tell an app
1264
+ * whether the user had a session on a site. It takes the same steps and the same store write
1265
+ * whether or not a cookie matched, so neither how long it takes nor which refusal it meets says so
1266
+ * either. That is why a RegExp is refused before anything is sent: it would be tested in the render
1267
+ * proxy against cookies the app cannot read, and a pattern slow on some of them would make the
1268
+ * call's duration, or a `TimeoutError`, say whether the jar holds one. Calling it again is
1269
+ * harmless. It does not tell the site: the session stays valid there until it lapses, and FKN no
1270
+ * longer holds it.
1271
+ *
1272
+ * No consent card on either jar, and a frame holding no page is served. Cloud only. It runs once,
1273
+ * never inside the locator retry loop, and waits at most 30000 ms.
1274
+ *
1275
+ * Refused:
1276
+ * - TypeError, before anything is sent, in this order: `frame.clearCookies: options must be an
1277
+ * object`; `frame.clearCookies: unknown option "<key>"`; `frame.clearCookies: <key> is a RegExp,
1278
+ * and clearCookies takes strings for name, domain and path for now`; `frame.clearCookies: <key>
1279
+ * must be a string`; `frame.clearCookies: <key> must not be empty; leave it out to match every
1280
+ * <key>`.
1281
+ * - `LocatorDeniedError` `frame.clearCookies: this attachment reaches no site yet; attach a url,
1282
+ * goto one, or declare it in domains`.
1283
+ * - `LocatorDeniedError` `frame.clearCookies: <domain> is not on a site this attachment reaches;
1284
+ * goto it or declare it in domains`, for a string `domain`.
1285
+ * - cloud, `LocatorUnsupportedError` `frame.clearCookies: this FKN page predates clearCookies;
1286
+ * reload the app to load the current one`, with nothing sent.
1287
+ * - cloud, `LocatorUnsupportedError` `frame.clearCookies: this render proxy predates clearCookies;
1288
+ * reload the app`.
1289
+ * - cloud, `Error` `frame.clearCookies: the cookies are gone from this attachment, but its jar did
1290
+ * not take the removal, so other attachments may still send them; call it again`.
1291
+ * - cloud, `TimeoutError` `frame.clearCookies: the render proxy did not answer within 30000ms; the
1292
+ * cookies may or may not be gone, and calling it again is safe`.
1293
+ * - extension, `ExtensionOperationUnsupportedError` (operation `'clearCookies'`)
1294
+ * `frame.clearCookies: an extension frame runs on the browser's own cookies (cookies: 'native'),
1295
+ * which FKN does not clear; attach with cookies: 'persistent' to clear the app's jar`, before
1296
+ * anything is dispatched.
1297
+ * - the terminal detach error once the attachment ended.
1298
+ */
1299
+ clearCookies(options?: ClearCookiesOptions): Promise<void>;
1027
1300
  /**
1028
1301
  * Delivers `message` to the page in the frame as a real `message` event, the way
1029
1302
  * `iframe.contentWindow.postMessage` would. The page sees a trusted event: `data` is the message,
@@ -1080,22 +1353,69 @@ type Frame = Omit<FrameLocator<LocatorModules>, 'evaluate'> & {
1080
1353
  * and not for the document the frame already held when the first listener was added. Extension:
1081
1354
  * fires on every load of the frame, with `origin` `''`.
1082
1355
  *
1083
- * Listeners stay on the Frame across navigations and end with the attachment. A listener that throws
1084
- * is reported and does not stop the others. An unknown `type` is a `TypeError`. On the cloud backend,
1085
- * against an FKN page that predates messaging, nothing arrives and the console says so once.
1356
+ * Listeners stay on the Frame across navigations and end with the attachment, or when `signal`
1357
+ * aborts, FKN's addition to Playwright's `on`. A listener added twice is called once, and one whose
1358
+ * signal already aborted is not added. A listener that throws is reported and does not stop the
1359
+ * others. An unknown `type`, or a listener that is not a function, is a `TypeError`. On the cloud
1360
+ * backend, against an FKN page that predates messaging, nothing arrives and the console says so once.
1086
1361
  */
1087
- addEventListener<K extends keyof FrameEventMap>(type: K, listener: FrameEventListener<K>, options?: {
1362
+ on<K extends keyof FrameEventMap>(type: K, listener: FrameEventListener<K>, options?: {
1088
1363
  signal?: AbortSignal;
1089
1364
  }): void;
1090
- removeEventListener<K extends keyof FrameEventMap>(type: K, listener: FrameEventListener<K>): void;
1365
+ /** Removes a listener `on` added; one that is not on the Frame is ignored. An unknown `type` is a `TypeError`. */
1366
+ off<K extends keyof FrameEventMap>(type: K, listener: FrameEventListener<K>): void;
1091
1367
  };
1368
+ /**
1369
+ * Which cookie jar an attachment runs on, and with it which backend serves it. One attachment, one
1370
+ * jar: no value unions two jars, so which cookie a request carries always has one answer. HttpOnly
1371
+ * values never reach app code on any value.
1372
+ *
1373
+ * - `'persistent'`, the default: the cloud render proxy's jar of the app's top-level site
1374
+ * (https://fkn.app for every fkn.app app), which every app of that site shares, the same jar its
1375
+ * inline frames and its windows use, kept across visits. Always the cloud backend, whatever is
1376
+ * installed, so `frame.backend()` answers `'cloud'`. Its requests leave through WebVPN, which
1377
+ * keeps the cookies their answers set.
1378
+ * - `'ephemeral'`: a fresh jar of the attachment's own, with site storage under a namespace of its
1379
+ * own, both gone with it. Always the cloud backend: the browser keeps a partition's cookies after
1380
+ * its frame goes, so no extension jar ends with the attachment. Its requests leave through WebVPN.
1381
+ * - `'native'`: the person's own browser cookies for `domains` and every goto's host, copied into
1382
+ * the browser's partition for the app's top-level site on the attach and on every goto. Extension
1383
+ * backend only, so `frame.backend()` answers `'extension'`. Without the extension the top-level
1384
+ * `attachFrame` shows the install prompt, as every extension-only call does; `cloud.attachFrame`
1385
+ * refuses it.
1386
+ *
1387
+ * Refused by name before anything is attached, opened, waited for or dispatched, in this order:
1388
+ * - any `syncCookies` key, true and false alike: TypeError `attachFrame: syncCookies was replaced
1389
+ * by cookies. true is cookies: 'persistent', or 'native' for the person's own browser cookies on
1390
+ * the extension; false is cookies: 'ephemeral'`
1391
+ * - an unknown value: TypeError `attachFrame: cookies must be 'persistent', 'ephemeral' or
1392
+ * 'native', not "<value>"`
1393
+ * - any `storageState` key: TypeError `attachFrame: storageState is not available yet`
1394
+ * - then the shape of the attachment: `iframe` and `window` at once, and `lockdown` or `blank` with
1395
+ * a window, each a TypeError
1396
+ * - `lockdown` with anything but `'native'`: TypeError `attachFrame: lockdown runs on the
1397
+ * extension, which serves only cookies: 'native'`
1398
+ * - `cloud.attachFrame` with `'native'`: TypeError `cloud.attachFrame: cookies: 'native' needs the
1399
+ * FKN browser extension; the cloud render proxy has no browser cookies`
1400
+ * - `extension.attachFrame` with `'persistent'` or `'ephemeral'`, so also with no `cookies` at all:
1401
+ * `ExtensionOperationUnsupportedError` (operation `'cookies'`) `attachFrame: cookies: '<value>'
1402
+ * runs on the cloud render proxy; call cloud.attachFrame or the top-level attachFrame`
1403
+ * - a window on `'native'`, through the top-level `attachFrame` or `extension.attachFrame`:
1404
+ * `ExtensionOperationUnsupportedError` (operation `'attachWindow'`) `attachFrame: a window on
1405
+ * cookies: 'native' is not served yet; a window runs on the cloud render proxy, which has no
1406
+ * browser cookies`, with no install prompt, so the click's activation is left for the app's
1407
+ * fallback
1408
+ */
1409
+ type AttachCookies = 'persistent' | 'ephemeral' | 'native';
1092
1410
  type AttachFrameOptions = {
1093
1411
  iframe: HTMLIFrameElement;
1094
1412
  domains?: string[];
1095
- syncCookies?: boolean;
1413
+ /** Which jar, and with it which backend: `'persistent'` when absent. See `AttachCookies`. */
1414
+ cookies?: AttachCookies;
1096
1415
  /**
1097
1416
  * Replace the embedded site's CSP with a lockdown policy: the frame cannot fetch, connect, or load
1098
- * any resource. Extension backend only. It needs an extension that announces an ABI: an older one
1417
+ * any resource. Extension backend only, so it takes `cookies: 'native'`; beside any other value it
1418
+ * is a TypeError (see `AttachCookies`). It needs an extension that announces an ABI: an older one
1099
1419
  * may not serve it, so the attach is refused with `ExtensionOperationUnsupportedError` (operation
1100
1420
  * `'lockdown'`) before anything is attached.
1101
1421
  */
@@ -1105,6 +1425,67 @@ type AttachFrameOptions = {
1105
1425
  * refusal does not reject the attach: it surfaces on the first refused operation.
1106
1426
  */
1107
1427
  permissions?: CategoryRequest[];
1428
+ /**
1429
+ * Starts the frame on an empty page presented at `blank.url`, with nothing requested from that
1430
+ * site for it. For running the app's own code (an attestation VM, a session client) in the origin
1431
+ * it needs, without loading or running the site's page.
1432
+ *
1433
+ * The document is exactly
1434
+ * `<!doctype html><html><head><meta charset="utf-8"></head><body></body></html>`, served 200 with
1435
+ * `content-type: text/html; charset=utf-8` and `cache-control: no-store`: no content security
1436
+ * policy, no Set-Cookie. Its `location`, `origin`, `document.URL`, `document.domain` and
1437
+ * `baseURI` read `blank.url`, and `document.referrer` reads `''` on the first load (after a reload
1438
+ * it reads the page's own url, as on any proxied page). `url()` returns it. `evaluate`,
1439
+ * `postMessage` and the `message` and `document` events work as on any page. Requests the page's
1440
+ * code makes later go out as that page's would, through WebVPN, on the attachment's jar: with
1441
+ * `cookies: 'persistent'`, the default, the cloud jar of the app's top-level site, which every app
1442
+ * of that site shares (HttpOnly values are never readable in the page); with `'ephemeral'` a jar
1443
+ * of the attachment's own, and site storage under a namespace of its own, both gone with it.
1444
+ *
1445
+ * With `cookies: 'ephemeral'` nothing of the user's is reachable, so calls the Evaluation grant
1446
+ * covers ask no card while the frame shows the empty page: until the attachment's first `goto`,
1447
+ * or until code in the page moves it to another url, even on the same host, after which they ask
1448
+ * as on any page. With `'persistent'` the Evaluation card names the url's host, as for any page.
1449
+ *
1450
+ * The empty page answers its url until the first `goto`: a reload of the page, or a replacement
1451
+ * of the render proxy's own document, brings it back and fires `document`, so an installer must
1452
+ * be idempotent. After the first `goto` the url loads from the site like any other.
1453
+ *
1454
+ * Always the cloud render proxy, with or without the extension: only it can present an origin
1455
+ * without loading it. `frame.backend()` then answers `'cloud'`, and the jar is the cloud's, never
1456
+ * the browser's.
1457
+ *
1458
+ * Refused, in this order, before anything is attached, and after the refusals of `cookies`
1459
+ * (`AttachCookies`), so through `cloud.attachFrame` lockdown and `'native'` meet those first:
1460
+ * - TypeError `attachFrame: blank must be an object { url }` (null, a string)
1461
+ * - TypeError `attachFrame: blank takes { url }, not "<key>"` (an unknown key)
1462
+ * - TypeError `attachFrame: blank.url must be an absolute http or https url, not "<value>"`
1463
+ * - TypeError `attachFrame: blank needs an iframe with no src; this one has "<src>"`
1464
+ * - TypeError `attachFrame: blank does not combine with lockdown`
1465
+ * - TypeError `attachFrame: blank runs on the cloud render proxy, which has no browser cookies;
1466
+ * pass cookies: 'persistent' or 'ephemeral'` (with `cookies: 'native'`)
1467
+ * - Error `attachFrame: refusing to target the extension's own pages or an FKN platform origin`,
1468
+ * the scope check every attach url meets
1469
+ * - Error `attachFrame: a blank page is served by the cloud render proxy, which this build does
1470
+ * not configure`
1471
+ *
1472
+ * After the handshake, with the iframe put back on about:blank and nothing requested from the
1473
+ * site: the terminal `LocatorUnsupportedError` `cloud.attachFrame: this FKN page predates blank
1474
+ * pages; reload the app to load the current one`. The handshake and ready limits are every cloud
1475
+ * attach's, 20000 ms and 65000 ms.
1476
+ *
1477
+ * Also refused, before anything opens or is dispatched: with `window`, the TypeError
1478
+ * `attachFrame: blank does not apply to a window`, since a window opened with no `url` is already
1479
+ * called blank there; and through `extension.attachFrame` with `cookies: 'native'`,
1480
+ * `ExtensionOperationUnsupportedError` (operation `'blank'`) `attachFrame: a blank page is served
1481
+ * by the cloud render proxy only; call cloud.attachFrame`.
1482
+ */
1483
+ blank?: BlankPage;
1484
+ };
1485
+ /** Where `attachFrame`'s `blank` option presents its empty page. */
1486
+ type BlankPage = {
1487
+ /** Absolute http or https url the empty page is presented at. The fragment is ignored for matching. */
1488
+ url: string;
1108
1489
  };
1109
1490
  /** Where an attachment's window opens and how big it asks to be. */
1110
1491
  type FrameWindowOptions = {
@@ -1130,12 +1511,14 @@ type AttachWindowOptions = {
1130
1511
  window: FrameWindowOptions;
1131
1512
  domains?: string[];
1132
1513
  /**
1133
- * Cloud, true by default: the window uses the cookie jar of the app that opened it, the same jar
1134
- * as that app's inline frames. A window whose app is on another site shares cookies only with
1135
- * those frames; its site storage stays its own. False: a jar of the window's own that ends with
1136
- * it. Extension: false is a TypeError, since the window is the site's own first-party tab.
1514
+ * The window's jar, with an iframe's values (`AttachCookies`). `'persistent'`, the default: the
1515
+ * jar of the app that opened it, the same as that app's inline frames; a window whose app is on
1516
+ * another site shares cookies only with those frames, and its site storage stays its own.
1517
+ * `'ephemeral'`: a jar of the window's own that ends with it. Both run on the cloud backend
1518
+ * whatever is installed. `'native'` is refused by name: a window runs on the cloud render proxy,
1519
+ * and no backend serves a window on the browser's own cookies yet.
1137
1520
  */
1138
- syncCookies?: boolean;
1521
+ cookies?: AttachCookies;
1139
1522
  /** Whole categories asked for once the window has connected, drawn in the window on the cloud backend. */
1140
1523
  permissions?: CategoryRequest[];
1141
1524
  };
@@ -1182,15 +1565,41 @@ declare class FrameWindowRefusedError extends Error {
1182
1565
  type FrameBackend = {
1183
1566
  executor: Executor;
1184
1567
  gate?: Gate;
1568
+ /**
1569
+ * The backend's name, which `Frame.backend()` answers. Optional so a caller of `createFrame` that
1570
+ * builds its own backend keeps compiling; absent, `Frame.backend()` answers `undefined`.
1571
+ */
1572
+ backend?: 'cloud' | 'extension';
1573
+ /**
1574
+ * Navigates, `options` already checked by `Frame.goto`: the backend maps `waitUntil: 'commit'` and
1575
+ * `timeout` to its own wire's names, rejects with `TimeoutError` at the deadline, and is never
1576
+ * handed `'documentstart'`.
1577
+ */
1185
1578
  goto(url: string, options?: GotoOptions): Promise<void>;
1186
1579
  url(): string;
1187
- request?(requests: CategoryRequest[]): Promise<CategoryGrant[]>;
1580
+ requestPermissions?(requests: CategoryRequest[]): Promise<CategoryGrant[]>;
1188
1581
  /**
1189
1582
  * Runs already-stringified source in the attached site's own realm and answers the cloned result.
1190
1583
  * The backend gates it (Evaluation) and runs it where the site's globals live. Optional so a
1191
1584
  * backend that cannot run code refuses `Frame.evaluate` by name rather than answering as if it had.
1192
1585
  */
1193
1586
  evaluate?(source: string, arg: unknown): Promise<unknown>;
1587
+ /**
1588
+ * Runs `content` as a classic inline script of the attached document and resolves once it ran,
1589
+ * `options` already checked by `Frame.addScriptTag`. The backend gates it (Evaluation), runs it once
1590
+ * and never through the locator retry loop. Optional so a backend that cannot run scripts refuses
1591
+ * `Frame.addScriptTag` by name.
1592
+ */
1593
+ addScriptTag?(content: string, options: {
1594
+ sourceUrl?: string;
1595
+ }): Promise<void>;
1596
+ /**
1597
+ * Removes the cookies `filter` matches from the attachment's jar, `filter` already checked and
1598
+ * serialized by `Frame.clearCookies`, and resolves `undefined` whatever was removed. Called once,
1599
+ * never through the locator retry loop and never gated. Optional so a backend with no jar of its
1600
+ * own refuses `Frame.clearCookies` by name.
1601
+ */
1602
+ clearCookies?(filter: ClearCookiesWire): Promise<void>;
1194
1603
  /**
1195
1604
  * Delivers a message to the page, `targetOrigin` already normalized (`'*'` or a serialized origin)
1196
1605
  * and `transfer` an array. Called synchronously by `Frame.postMessage`, so transfers detach at the
@@ -1224,6 +1633,11 @@ type AttachFrameFunction = {
1224
1633
  //#endregion
1225
1634
  //#region ../web-extension/lib/lib/frame.d.ts
1226
1635
  declare const ATTACH_FRAME_EVENT_KEY = "FKN_WEB_EXTENSION_ATTACH_FRAME_EVENT_KEY";
1636
+ /**
1637
+ * Attaches through the extension, on `cookies: 'native'` only: the other values, the default
1638
+ * among them, are the cloud render proxy's, refused here with `ExtensionOperationUnsupportedError`
1639
+ * (operation `'cookies'`) before any exposure wait (`AttachCookies`).
1640
+ */
1227
1641
  declare const attachFrame: AttachFrameFunction;
1228
1642
  //#endregion
1229
- export { CATEGORIES as A, revive as B, gotoPermission as C, PermissionGrant as D, LegacyPermissionRequest as E, RemoteVideoElement as F, OperationRequest as G, Executor as H, VideoElementState as I, SelectorPart as K, box as L, PermissionCategory as M, handleRevivableModules as N, PermissionRequest as O, BoxedVideoElement as P, createVideoElementHandle as R, createFrame as S, CategoryRequest as T, Gate as U, type as V, GateTools as W, FrameWindowRefusedError as _, AttachWindowOptions as a, WindowFrame as b, FrameBackendEvent as c, FrameEventMap as d, FrameMessageEvent as f, FrameWindowRefusal as g, FrameWindowOptions as h, AttachFrameOptions as i, CategoryMeta as j, permissions as k, FrameDocumentEvent as l, FrameWindowBlockedError as m, attachFrame as n, Frame as o, FramePostMessageOptions as p, AttachFrameFunction as r, FrameBackend as s, ATTACH_FRAME_EVENT_KEY as t, FrameEventListener as u, GotoOptions as v, CategoryGrant as w, attachFramePermission as x, Locator as y, isType as z };
1643
+ export { SelectorPart as $, gotoPermission as A, handleRevivableModules as B, FrameWindowRefusal as C, WindowFrame as D, Locator as E, PermissionRequest as F, createVideoElementHandle as G, RemoteVideoElement as H, permissions as I, type as J, isType as K, CATEGORIES as L, CategoryRequest as M, LegacyPermissionRequest as N, attachFramePermission as O, PermissionGrant as P, OperationRequest as Q, CategoryMeta as R, FrameWindowOptions as S, GotoOptions as T, VideoElementState as U, BoxedVideoElement as V, box as W, Gate as X, Executor as Y, GateTools as Z, FrameEventMap as _, AttachCookies as a, FramePostMessageOptions as b, BlankPage as c, CookieMatchWire as d, Frame as f, FrameEventListener as g, FrameDocumentEvent as h, AddScriptTagOptions as i, CategoryGrant as j, createFrame as k, ClearCookiesOptions as l, FrameBackendEvent as m, attachFrame as n, AttachFrameOptions as o, FrameBackend as p, revive as q, AttachFrameFunction as r, AttachWindowOptions as s, ATTACH_FRAME_EVENT_KEY as t, ClearCookiesWire as u, FrameLocator as v, FrameWindowRefusedError as w, FrameWindowBlockedError as x, FrameMessageEvent as y, PermissionCategory as z };