@fkn/lib/extension
Classes
Section titled “Classes”ExtensionOperationUnsupportedError
Section titled “ExtensionOperationUnsupportedError”Thrown when the extension is current but does not serve the operation being asked for. message
replaces the default advice where updating the extension cannot help.
Extends
Section titled “Extends”Error
Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new ExtensionOperationUnsupportedError( operation, abi, message?): ExtensionOperationUnsupportedError;Parameters
Section titled “Parameters”operation
Section titled “operation”string
number
message?
Section titled “message?”string
Returns
Section titled “Returns”ExtensionOperationUnsupportedError
Overrides
Section titled “Overrides”Error.constructorProperties
Section titled “Properties”readonly abi: number;readonly name: "ExtensionOperationUnsupportedError" = "ExtensionOperationUnsupportedError";Overrides
Section titled “Overrides”Error.nameoperation
Section titled “operation”readonly operation: string;ExtensionOutdatedError
Section titled “ExtensionOutdatedError”Thrown instead of the generic “not installed” message when the extension is installed but too old.
Carries both numbers so an app can say which and link its listing. Match it by name, which
survives a structured-clone hop.
Extends
Section titled “Extends”Error
Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new ExtensionOutdatedError(abi, required): ExtensionOutdatedError;Parameters
Section titled “Parameters”number
required
Section titled “required”number
Returns
Section titled “Returns”Overrides
Section titled “Overrides”Error.constructorProperties
Section titled “Properties”readonly abi: number;readonly name: "ExtensionOutdatedError" = "ExtensionOutdatedError";Overrides
Section titled “Overrides”Error.namerequired
Section titled “required”readonly required: number;FrameWindowBlockedError
Section titled “FrameWindowBlockedError”window.open returned null, so nothing was opened: the call ran without user activation, the
popup blocker refused it, or the calling frame is sandboxed without allow-popups.
Extends
Section titled “Extends”Error
Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new FrameWindowBlockedError(): FrameWindowBlockedError;Returns
Section titled “Returns”Overrides
Section titled “Overrides”Error.constructorProperties
Section titled “Properties”readonly name: "FrameWindowBlockedError" = "FrameWindowBlockedError";Overrides
Section titled “Overrides”Error.nameFrameWindowRefusedError
Section titled “FrameWindowRefusedError”The window refused to attach, by reason, after loading nothing.
Extends
Section titled “Extends”Error
Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new FrameWindowRefusedError(reason): FrameWindowRefusedError;reason is what the window said; anything this library does not know becomes 'unknown'.
Parameters
Section titled “Parameters”reason
Section titled “reason”unknown
Returns
Section titled “Returns”Overrides
Section titled “Overrides”Error.constructorProperties
Section titled “Properties”readonly name: "FrameWindowRefusedError" = "FrameWindowRefusedError";Overrides
Section titled “Overrides”Error.namereason
Section titled “reason”readonly reason: FrameWindowRefusal;TimeoutError
Section titled “TimeoutError”A call that ran out of time: its deadline passed before it settled. One class for every call that
has a deadline, as Playwright’s TimeoutError, named 'TimeoutError' so a check by name works as
well as instanceof. It is minted where the call was made, never in the realm that ran it, so it
is an instance of this class in the caller’s realm.
message is what the call reported at its deadline, unchanged from the error it replaces. cause
is the last retryable error an attempt met before the deadline, so a locator call that never found
its element says why; it is absent when no attempt failed (one never settled, or the call is not
retried). Not terminal: nothing retries a call past its own deadline.
Extends
Section titled “Extends”Error
Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new TimeoutError(message, options?): TimeoutError;Parameters
Section titled “Parameters”message
Section titled “message”string
options?
Section titled “options?”cause?
Section titled “cause?”unknown
Returns
Section titled “Returns”Overrides
Section titled “Overrides”Error.constructorProperties
Section titled “Properties”readonly name: "TimeoutError" = "TimeoutError";Overrides
Section titled “Overrides”Error.nameType Aliases
Section titled “Type Aliases”AddScriptTagOptions
Section titled “AddScriptTagOptions”type AddScriptTagOptions = object;frame.addScriptTag’s options, Playwright’s content and FKN’s sourceUrl.
Properties
Section titled “Properties”content
Section titled “content”content: string;The script’s source text.
sourceUrl?
Section titled “sourceUrl?”optional sourceUrl?: string;Names the script in stack traces through //# sourceURL. Absent, its frames name the document.
AttachCookies
Section titled “AttachCookies”type AttachCookies = "persistent" | "ephemeral" | "native";Which cookie jar an attachment runs on, and with it which backend serves it. One attachment, one jar: no value unions two jars, so which cookie a request carries always has one answer. HttpOnly values never reach app code on any value.
'persistent', the default: the cloud render proxy’s jar of the app’s top-level site (https://fkn.app for every fkn.app app), which every app of that site shares, the same jar its inline frames and its windows use, kept across visits on this device, signed in to FKN or not. It is written sealed under a key the render proxy generates for that site’s jar and keeps beside it on the device, so no cookie of it is on disk in the clear, while a copy of the device’s files holds what opens it. Where an earlier build kept that jar in the clear, Chrome can keep the old text in its files for a time after the seal. Always the cloud backend, whatever is installed, soframe.backend()answers'cloud'. Its requests leave through WebVPN, which keeps the cookies their answers set.'ephemeral': a fresh jar of the attachment’s own, with site storage under a namespace of its own, both gone with it, seeded fromstorageStatewhen one is given. Always the cloud backend: the browser keeps a partition’s cookies after its frame goes, so no extension jar ends with the attachment. Its requests leave through WebVPN.'native': the person’s own browser cookies fordomainsand every goto’s host, copied into the browser’s partition for the app’s top-level site on the attach and on every goto. Extension backend only, soframe.backend()answers'extension'. Without the extension the top-levelattachFrameshows the install prompt, as every extension-only call does;cloud.attachFramerefuses it.
Refused by name before anything is attached, opened, waited for or dispatched, in this order:
- any
syncCookieskey, true and false alike: TypeErrorattachFrame: syncCookies was replaced by cookies. true is cookies: 'persistent', or 'native' for the person's own browser cookies on the extension; false is cookies: 'ephemeral' - an unknown value: TypeError
attachFrame: cookies must be 'persistent', 'ephemeral' or 'native', not "<value>" - a
storageStatebeside anything but'ephemeral', the default included: TypeErrorattachFrame: storageState seeds a fresh jar, so it needs cookies: 'ephemeral' - a malformed
storageState: TypeErrorattachFrame: storageState.<path> <what is wrong>, for the first field of another shape in the order the state lists them (StorageState) - a cookie whose
expiresis above 0 and below 100000000000: TypeErrorattachFrame: storageState.cookies[<i>].expires is milliseconds since the epoch, and <value> reads as a date before 1974; a Playwright storageState gives seconds, so multiply it by 1000 - then the shape of the attachment:
iframeandwindowat once, andlockdownorblankwith a window, each a TypeError lockdownwith anything but'native': TypeErrorattachFrame: lockdown runs on the extension, which serves only cookies: 'native'cloud.attachFramewith'native': TypeErrorcloud.attachFrame: cookies: 'native' needs the FKN browser extension; the cloud render proxy has no browser cookiesextension.attachFramewith'persistent'or'ephemeral', so also with nocookiesat all:ExtensionOperationUnsupportedError(operation'cookies')attachFrame: cookies: '<value>' runs on the cloud render proxy; call cloud.attachFrame or the top-level attachFrame- a window on
'native', through the top-levelattachFrameorextension.attachFrame, when the extension does not announceattachWindow(one before ABI 5):ExtensionOperationUnsupportedError(operation'attachWindow') with the advice to update it, and with no extension on the page at allattachFrame: a window on cookies: 'native' needs the FKN WebExtension, which is not on this page. Neither waits or shows the install prompt, so the click’s activation is left for the app’s fallback.
AttachFrameOptions
Section titled “AttachFrameOptions”type AttachFrameOptions = object;Properties
Section titled “Properties”blank?
Section titled “blank?”optional blank?: BlankPage;Starts the frame on an empty page presented at blank.url, with nothing requested from that
site for it. For running the app’s own code (an attestation VM, a session client) in the origin
it needs, without loading or running the site’s page.
The document is exactly
<!doctype html><html><head><meta charset="utf-8"></head><body></body></html>, served 200 with
content-type: text/html; charset=utf-8 and cache-control: no-store: no content security
policy, no Set-Cookie. Its location, origin, document.URL, document.domain and
baseURI read blank.url, and document.referrer reads '' on the first load (after a reload
it reads the page’s own url, as on any proxied page). url() returns it. evaluate,
postMessage and the message and document events work as on any page. Requests the page’s
code makes later go out as that page’s would, through WebVPN, on the attachment’s jar: with
cookies: 'persistent', the default, the cloud jar of the app’s top-level site, which every app
of that site shares (HttpOnly values are never readable in the page); with 'ephemeral' a jar
of the attachment’s own, and site storage under a namespace of its own, both gone with it.
With cookies: 'ephemeral' nothing of the user’s is reachable, so calls the Evaluation grant
covers ask no card while the frame shows the empty page: until the attachment’s first goto,
or until code in the page moves it to another url, even on the same host, after which they ask
as on any page. With 'persistent' the Evaluation card names the url’s host, as for any page.
The empty page answers its url until the first goto: a reload of the page, or a replacement
of the render proxy’s own document, brings it back and fires document, so an installer must
be idempotent. After the first goto the url loads from the site like any other.
Always the cloud render proxy, with or without the extension: only it can present an origin
without loading it. frame.backend() then answers 'cloud', and the jar is the cloud’s, never
the browser’s.
Refused, in this order, before anything is attached, and after the refusals of cookies
(AttachCookies), so through cloud.attachFrame lockdown and 'native' meet those first:
- TypeError
attachFrame: blank must be an object { url }(null, a string) - TypeError
attachFrame: blank takes { url }, not "<key>"(an unknown key) - TypeError
attachFrame: blank.url must be an absolute http or https url, not "<value>" - TypeError
attachFrame: blank needs an iframe with no src; this one has "<src>" - TypeError
attachFrame: blank does not combine with lockdown - TypeError
attachFrame: blank runs on the cloud render proxy, which has no browser cookies; pass cookies: 'persistent' or 'ephemeral'(withcookies: 'native') - Error
attachFrame: refusing to target the extension's own pages or an FKN platform origin, the scope check every attach url meets - Error
attachFrame: a blank page is served by the cloud render proxy, which this build does not configure
After the handshake, with the iframe put back on about:blank and nothing requested from the
site: the terminal LocatorUnsupportedError cloud.attachFrame: this FKN page predates blank pages; reload the app to load the current one. The handshake and ready limits are every cloud
attach’s, 20000 ms and 65000 ms.
Also refused, before anything opens or is dispatched: with window, the TypeError
attachFrame: blank does not apply to a window, since a window opened with no url is already
called blank there; and through extension.attachFrame with cookies: 'native',
ExtensionOperationUnsupportedError (operation 'blank') attachFrame: a blank page is served by the cloud render proxy only; call cloud.attachFrame.
cookies?
Section titled “cookies?”optional cookies?: AttachCookies;Which jar, and with it which backend: 'persistent' when absent. See AttachCookies.
domains?
Section titled “domains?”optional domains?: string[];iframe
Section titled “iframe”iframe: HTMLIFrameElement;lockdown?
Section titled “lockdown?”optional lockdown?: boolean;Replace the embedded site’s CSP with a lockdown policy: the frame cannot fetch, connect, or load
any resource. Extension backend only, so it takes cookies: 'native'; beside any other value it
is a TypeError (see AttachCookies). It needs an extension that announces an ABI: an older one
may not serve it, so the attach is refused with ExtensionOperationUnsupportedError (operation
'lockdown') before anything is attached.
permissions?
Section titled “permissions?”optional permissions?: CategoryRequest[];Whole categories to ask for on one sheet or card right after the attach, before it resolves. A refusal does not reject the attach: it surfaces on the first refused operation.
storageState?
Section titled “storageState?”optional storageState?: StorageState;Seeds an 'ephemeral' jar before the attachment’s first document; with any other value a TypeError. See StorageState.
AttachWindowOptions
Section titled “AttachWindowOptions”type AttachWindowOptions = object;attachFrame’s options when the attachment is a new window rather than an iframe.
Call attachFrame directly in the click or key handler: the window opens before the first await,
with the activation of that event, and the browser’s popup rules apply to it as to any page’s own
window.open. iframe and lockdown do not apply to a window, and passing either is a TypeError.
Properties
Section titled “Properties”cookies?
Section titled “cookies?”optional cookies?: AttachCookies;The window’s jar, with an iframe’s values (AttachCookies). 'persistent', the default: the
jar of the app that opened it, the same as that app’s inline frames; a window whose app is on
another site shares cookies only with those frames, and its site storage stays its own.
'ephemeral': a jar of the window’s own that ends with it, seeded from storageState. Both
run on the cloud backend whatever is installed. 'native': a real browser window on the
extension, on the person’s own browser session for every site it shows, as a window they opened
themselves would be (WindowFrame says what differs there).
domains?
Section titled “domains?”optional domains?: string[];permissions?
Section titled “permissions?”optional permissions?: CategoryRequest[];Whole categories asked for once the window has connected: the card is drawn in the window on the cloud backend, and the sheet on the app’s page on the extension, as every extension sheet is.
storageState?
Section titled “storageState?”optional storageState?: StorageState;As for an iframe: only with 'ephemeral'. The window opens at once, with the click’s
activation, and goes to window.url once the seed is in place.
window
Section titled “window”window: FrameWindowOptions;BackgroundStoppedError
Section titled “BackgroundStoppedError”type BackgroundStoppedError = Error & object;What a call into the extension rejects with when Chrome stopped the extension’s worker before it finished
answering: before the call resolved, or, for a fetch, while its response body was still arriving.
The call may or may not have run, so it is never resent; a retry by the app reaches the restarted worker.
Type Declaration
Section titled “Type Declaration”name: typeof BACKGROUND_STOPPED;BlankPage
Section titled “BlankPage”type BlankPage = object;Where attachFrame’s blank option presents its empty page.
Properties
Section titled “Properties”url: string;Absolute http or https url the empty page is presented at. The fragment is ignored for matching.
ClearCookiesOptions
Section titled “ClearCookiesOptions”type ClearCookiesOptions = object;frame.clearCookies’ options, Playwright’s browserContext.clearCookies names with its string
semantics: each matches exactly. A cookie is removed when it matches every option given; an
option left out, or undefined, matches every cookie. Playwright also takes a RegExp for each,
which FKN refuses for now (Frame.clearCookies says why).
Properties
Section titled “Properties”domain?
Section titled “domain?”optional domain?: string;Only cookies with this domain, in the form Playwright reports it: .youtube.com for a cookie
its subdomains also receive, www.youtube.com for a host-only one, so 'youtube.com' matches
neither of those. It must be on a site this attachment reaches.
optional name?: string;Only cookies with this name.
optional path?: string;Only cookies with this path, exactly as the cookie carries it.
CookieDetails
Section titled “CookieDetails”type CookieDetails = object;Properties
Section titled “Properties”name: string;url: string;Executor
Section titled “Executor”type Executor = object;Properties
Section titled “Properties”execute
Section titled “execute”execute: (parts, operation, args, context?) => Promise<unknown>;Runs operation on what parts resolve to, in whichever realm the chain lands in.
context is an opaque per-call value for the host: frame-locator never reads it, and carries it
unchanged through every pivot and across the window bridge, so each executor the call passes
through hands it to its own assertRealm (see ExecutorOptions). It crosses a window by structured
clone, so it must be cloneable. A chain built with createFrameLocator never sends one; only a
caller holding the executor itself can.
Parameters
Section titled “Parameters”operation
Section titled “operation”string
unknown[]
context?
Section titled “context?”unknown
Returns
Section titled “Returns”Promise<unknown>
highlight
Section titled “highlight”highlight: (parts, on) => Promise<void>;Parameters
Section titled “Parameters”boolean
Returns
Section titled “Returns”Promise<void>
stale?
Section titled “stale?”optional stale?: Promise<void>;ExtensionHandshake
Section titled “ExtensionHandshake”type ExtensionHandshake = | { status: "absent";} | { abi: number; operations: readonly string[] | null; status: "ok";} | { abi: number; operations: readonly string[] | null; required: number; status: "outdated";};operations is null when the extension announced no list, which is not the same as an empty one:
a pre-versioning extension supports the whole original surface and cannot say so, so null reads
as “assume the original set”, never “supports nothing”.
FetchInit
Section titled “FetchInit”type FetchInit = RequestInit & object;Type Declaration
Section titled “Type Declaration”reason?
Section titled “reason?”optional reason?: string;type Frame = Omit<FrameLocator, "owner"> & object;An attached frame. What it promises across navigations is the same on both backends.
A Frame follows its FRAME, not a document. The page in it may move itself (a link, a form, a redirect, a script), and every call runs against the document the frame holds when the call arrives. A call made while the next document commits waits for it, within the call’s own timeout.
It reads a document only while that document’s host is inside the attachment: the attach url’s
host, each goto target’s host, and domains, each matched exactly. A document on any other host
is refused with a LocatorDeniedError (“frame: this frame no longer holds the document the app
attached it to”), which names nothing about where the frame went. The Frame stays attached, and
answers again once the frame is back inside, by the page’s own move or by a goto.
What belongs to a document ends with it. A style addStyleTag added is gone after a navigation. A
videoElement handle from a document that left rejects every call that answers (play, the
picture-in-picture calls), and its fire-and-forget ones (pause, load, the setters) do nothing.
On the cloud backend an evaluate whose document leaves before it settles rejects, and is not run
again.
Not followed: a navigation the page aims out of its frame (a link or a form targeting the top window or a new one, a popup). A document with nothing of the page’s own to run it in, such as an error page or a file that is not HTML, cannot be read, and a call on it waits to its deadline.
Type Declaration
Section titled “Type Declaration”addScriptTag()
Section titled “addScriptTag()”addScriptTag(options): Promise<void>;Runs content as a classic inline script of the attached document, as one of that page’s own
scripts would run: its top-level declarations stay on the page’s global for later scripts and
evaluate calls, document.currentScript is the script while it runs, and the page’s own error
listeners see its top-level error. Mirage rewrites it as it rewrites the page’s scripts, and the
page’s eval refusal and Trusted Types requirement do not refuse it, as for evaluate.
Playwright’s name and its content option; its url, path and type are not served, and FKN’s
sourceUrl names the script rather than loading one.
Resolves undefined once the script ran; what it installed lives as long as the document, and the
document event says when that is gone. Same grant, limit and timing as evaluate: the
Evaluation grant (one card covers both), 30000 ms counted after any consent card, the attached
frame only, and after a goto the document that goto brought, waited for as evaluate waits. It
runs once: it never rides the locator retry loop, and a call whose document left before it
answered rejects and is not run again. Cloud only for now: the extension refuses it by name.
Refused:
- TypeError, before anything is sent, in this order:
frame.addScriptTag: options must be an object { content }; for Playwright’surl,pathandtype,frame.addScriptTag: "<key>" is not served; it runs content as a classic inline script;frame.addScriptTag: unknown option "<key>";frame.addScriptTag: content must be a string;frame.addScriptTag: sourceUrl must be a non-empty string with no line break. - an
Errorcarrying the page’s own name and message: the script’s top-level throw, after it ran. LocatorDeniedError: no Evaluation grant, the frame holds no page, or its document is outside the attachment. Against an FKN page that predatesaddScriptTagthe call arrives with no proof of a grant and the render proxy refuses it:frame.addScriptTag: the call arrived without an Evaluation grant, so it was not run.- cloud,
LocatorUnsupportedErrorframe.addScriptTag: this render proxy predates addScriptTag; reload the app. - cloud,
LocatorError: the document of the goto before it had not come by that goto’s deadline, or the app started another goto first, so the script was not run. - extension,
ExtensionOperationUnsupportedError(operation'addScriptTag')frame.addScriptTag: an extension frame does not run scripts through mirage yet; attach with cloud.attachFrame, before anything is dispatched. TimeoutErrorframe.addScriptTag: no answer within 30000ms; the script may or may not have run.- the terminal detach error once the attachment ended.
Parameters
Section titled “Parameters”options
Section titled “options”Returns
Section titled “Returns”Promise<void>
backend()
Section titled “backend()”backend(): "cloud" | "extension" | undefined;Which backend serves this attachment, fixed for its life. The same call can draw a card on one
backend and not the other, and spends a different identity on each, so an app must be able to
tell. Undefined only for a Frame an app built itself with createFrame from a backend that
names none.
Returns
Section titled “Returns”"cloud" | "extension" | undefined
clearCookies()
Section titled “clearCookies()”clearCookies(options?): Promise<void>;Removes cookies from this attachment’s cookie jar, as Playwright’s
browserContext.clearCookies removes them from a context. With no options it removes every
cookie of the sites this attachment reaches; with options, only the ones that match every option
given (ClearCookiesOptions). Each option is a string for now: a RegExp is refused.
For signing out of a site the user signed in to inside an FKN frame: that session lives in FKN’s jar, never in the app, so the app cannot remove it any other way.
Which jar: with cookies: 'persistent', the default, the cloud jar of the app’s top-level site,
which every app of that site shares (every fkn.app app shares one), so a removal there signs
every one of those apps out of that site. With 'ephemeral' the attachment’s own jar.
Which cookies: only those of a site this attachment reaches, a site being a host’s registered
domain under the Public Suffix List, private section included: the attach url’s host (the empty
page’s, for blank), each goto target’s host from the goto’s send, and domains.
www.youtube.com reaches every *.youtube.com cookie and no google.com one, the rule browsers
follow for Clear-Site-Data: "cookies". A host under the same name is still another site when a
suffix lies between: amazonaws.com reaches no mybucket.s3.amazonaws.com cookie, since
s3.amazonaws.com is a suffix. A host that is itself a public suffix (com, co.uk,
github.io) is no site, and reaches only the cookies set for exactly that host. A Partitioned
cookie matches in every partition.
Once it resolves: no request a document of this attachment starts carries a removed cookie, its
documents’ document.cookie lists none, and the removal is committed to the jar, so an
attachment created afterwards never sees one. Another live attachment on the same jar (another
tab, another app’s frame) drops them when it hears the commit, normally within milliseconds; a
request it started before then may still carry one. A request already in flight keeps what it
was sent with, and a later response may set cookies again, as in any browser.
It resolves undefined and never says what or how much it removed, so it cannot tell an app
whether the user had a session on a site. It takes the same steps and the same store write
whether or not a cookie matched, so neither how long it takes nor which refusal it meets says so
either. That is why a RegExp is refused before anything is sent: it would be tested in the render
proxy against cookies the app cannot read, and a pattern slow on some of them would make the
call’s duration, or a TimeoutError, say whether the jar holds one. Calling it again is
harmless. It does not tell the site: the session stays valid there until it lapses, and FKN no
longer holds it.
No consent card on either jar, and a frame holding no page is served. Cloud only. It runs once, never inside the locator retry loop, and waits at most 30000 ms.
Refused:
- TypeError, before anything is sent, in this order:
frame.clearCookies: options must be an object;frame.clearCookies: unknown option "<key>";frame.clearCookies: <key> is a RegExp, and clearCookies takes strings for name, domain and path for now;frame.clearCookies: <key> must be a string;frame.clearCookies: <key> must not be empty; leave it out to match every <key>. LocatorDeniedErrorframe.clearCookies: this attachment reaches no site yet; attach a url, goto one, or declare it in domains.LocatorDeniedErrorframe.clearCookies: <domain> is not on a site this attachment reaches; goto it or declare it in domains, for a stringdomain.- cloud,
LocatorUnsupportedErrorframe.clearCookies: this FKN page predates clearCookies; reload the app to load the current one, with nothing sent. - cloud,
LocatorUnsupportedErrorframe.clearCookies: this render proxy predates clearCookies; reload the app. - cloud,
Errorframe.clearCookies: the cookies are gone from this attachment, but its jar did not take the removal, so other attachments may still send them; call it again. - cloud,
TimeoutErrorframe.clearCookies: the render proxy did not answer within 30000ms; the cookies may or may not be gone, and calling it again is safe. - extension,
ExtensionOperationUnsupportedError(operation'clearCookies')frame.clearCookies: an extension frame runs on the browser's own cookies (cookies: 'native'), which FKN does not clear; attach with cookies: 'persistent' to clear the app's jar, before anything is dispatched. - the terminal detach error once the attachment ended.
Parameters
Section titled “Parameters”options?
Section titled “options?”Returns
Section titled “Returns”Promise<void>
evaluate()
Section titled “evaluate()”evaluate<R, A>(pageFunction, arg?): Promise<Awaited<R>>;Runs pageFunction inside the attached site’s OWN page realm, as a script of that page would:
it sees the site’s window, its globals and its DOM. The function is sent as source
(Function.prototype.toString), so it captures NOTHING from the caller’s scope; everything it
needs must come through arg. A plain source string is run as an expression, the way Playwright
does, and is not called. A promise, returned by the function or produced by the expression, is
awaited.
arg is structured-cloned at the call, in the app’s realm, on both backends, and the result
comes back by structured clone, so an ArrayBuffer or a typed array of bytes survives the round
trip. A value structured clone refuses in arg (a function, a DOM node, an untransferred port)
rejects with the platform’s DataCloneError before anything is sent; a port goes to the page
with postMessage. A thrown error or a rejected promise comes back as an Error carrying
the page’s own name and message. A result that cannot be cloned (a function, a DOM node) is a
LocatorInvalidError, never a silent undefined and never a live handle into the page.
Every limit is refused by name, never a call left pending:
- time, both backends: the code has 30 seconds to settle, counted after any consent card, and
then the call rejects with
TimeoutError. Only the wait ends there; code that never settles keeps running in the page. - size, extension only, a
LocatorInvalidError: the source with itsarg, and the result, each carry at most 32 MiB (binary data by its bytes, text by its UTF-8 size), the most its message relay carries. Blob, extension only, aLocatorInvalidError: the relay cannot carry one, so pass or returnawait blob.arrayBuffer(). The cloud backend has neither limit, and returns aBlobas aBlob.
Needs the Evaluation grant on both backends; an app without it is refused by name. It runs on the
attached frame only: a nested FrameLocator does not offer it, and a call there anyway is refused.
Called after goto resolved, whichever waitUntil, it runs once on the document that goto
brought, never on the one it replaced. On the cloud backend the call waits for that document when
it has not committed yet, and the wait counts toward the 30 seconds; if it has not come by the
goto’s own deadline (the goto failed, or loaded something that is not a page), or the app started
another goto first, the call rejects with a LocatorError saying the code was not run.
On the extension it also needs an extension new enough to run code (ABI 3, older ones are refused
with ExtensionOperationUnsupportedError), and it runs where the page’s content security policy
allows it: a frame whose host the app declared has its CSP replaced, so code runs; an undeclared
frame, and every attached window, keeps its CSP, and a page that forbids eval refuses with a
named error. On the cloud
backend the code runs in the proxied document’s realm, which mirage virtualizes: the page’s own
eval refusal and Trusted Types requirement do not refuse the source evaluate compiles, and every
string that code compiles itself (eval, Function, a string timer) is held to them, as the
page’s own are.
Type Parameters
Section titled “Type Parameters”R = unknown
A = undefined
Parameters
Section titled “Parameters”pageFunction
Section titled “pageFunction”string | ((arg) => R | Promise<R>)
A
Returns
Section titled “Returns”Promise<Awaited<R>>
goto()
Section titled “goto()”goto(url, options?): Promise<void>;Navigates the frame to url, which must pass the rules an iframe src does, and adds its host
to the attachment. Resolves at options.waitUntil, and rejects with TimeoutError past
options.timeout (GotoOptions).
Parameters
Section titled “Parameters”string
options?
Section titled “options?”Returns
Section titled “Returns”Promise<void>
off<K>(type, listener): void;Removes a listener on added; one that is not on the Frame is ignored. An unknown type is a TypeError.
Type Parameters
Section titled “Type Parameters”K extends keyof FrameEventMap
Parameters
Section titled “Parameters”K
listener
Section titled “listener”FrameEventListener<K>
Returns
Section titled “Returns”void
on<K>( type, listener, options?): void;message: what the page posted to the app, with its origin and ports, and this Frame as
source. The page reaches the app with parent.postMessage(x, appOrigin),
top.postMessage(x, appOrigin), or event.source.postMessage(x, event.origin) on a message the
app sent it; in an extension window, with opener.postMessage(x, appOrigin). A document outside
the attachment is dropped, never masked. On the cloud backend a post to '*' does not reach the
app: there the page is its own parent, so it cannot be told apart from the page messaging itself,
and it stays with the page. The extension delivers it, as a real parent would receive it.
document: a new document arrived in the frame. What evaluate installed in the one before is
gone, with every port it held, and nothing is reinstalled for the app: this is the signal to
install again. It can fire twice for one document (a return from the back/forward cache), so an
install should be idempotent. Cloud: fires for a document inside the attachment, with its origin,
and not for the document the frame already held when the first listener was added. Extension:
fires on every load of an iframe and every new document of a window, with origin ''.
Listeners stay on the Frame across navigations and end with the attachment, or when signal
aborts, FKN’s addition to Playwright’s on. A listener added twice is called once, and one whose
signal already aborted is not added. A listener that throws is reported and does not stop the
others. An unknown type, or a listener that is not a function, is a TypeError. On the cloud
backend, against an FKN page that predates messaging, nothing arrives and the console says so once.
Type Parameters
Section titled “Type Parameters”K extends keyof FrameEventMap
Parameters
Section titled “Parameters”K
listener
Section titled “listener”FrameEventListener<K>
options?
Section titled “options?”signal?
Section titled “signal?”AbortSignal
Returns
Section titled “Returns”void
postMessage()
Section titled “postMessage()”Call Signature
Section titled “Call Signature”postMessage( message, targetOrigin,transfer?): Promise<void>;Delivers message to the page in the frame as a real message event, the way
iframe.contentWindow.postMessage would. The page sees a trusted event: data is the message,
ports are the MessagePorts transfer moved, source is the page’s own parent, and origin
is this app’s origin. So a page script that evaluate installed can take event.ports[0] and run
any port protocol (osra included) over it, and no FKN code sits on that port afterwards.
targetOrigin is the page’s origin as the site knows it (https://anilist.co), parsed as the
platform parses it, so a trailing slash or a path is fine. The message is delivered only if the
frame’s document is on that origin, and otherwise dropped silently, as Window.postMessage does.
'*', the default, means whatever document the frame holds; the extension refuses it for now.
It resolves once the message was handed to the browser for the document the frame holds, in the
order the calls were made. That says nothing about whether the page listened, and a message
dropped for its origin resolves the same way. Sent after goto resolved, it goes to the document
that goto brought, as evaluate runs there.
Refused, and never sent again. On the cloud backend a refusal that depends on the grant or on the
frame’s document comes after transfer was detached, and loses what it moved with the message;
every other refusal comes before anything is detached.
TypeError, before anything is sent or detached: atargetOriginthat is not'*'or an origin ('/'included), or atransferthat is not an array. A message that cannot be cloned is the platform’s ownDataCloneError.LocatorDeniedErrornaming nothing:targetOriginnames a host outside the attachment, or the frame’s document is outside it.LocatorDeniedError“frame: navigate the frame before postMessage”: the frame holds no page.- cloud,
LocatorDeniedError: the app has no Evaluation grant, which is asked for on first use asevaluateasks. Messaging sits under Evaluation because the message arrives as the page’s own traffic and a port handed over is a live channel into the page. - cloud,
LocatorUnsupportedError: an FKN page or render proxy that predates messaging. - cloud,
LocatorError: the document changed during the call, so the message may or may not have reached it and is not sent to the next one; or the document of the goto before it had not come by that goto’s deadline (the goto failed, or loaded something that is not a page) or before the app started another goto, so nothing was sent. - extension,
LocatorUnsupportedError:'*', which needs an extension release that reports the frame’s origin. Pass the origin. - extension,
LocatorDeniedError: a window whose page cut its link to the app’s page (WindowFrame). - the terminal detach error once the attachment ended.
Parameters
Section titled “Parameters”message
Section titled “message”unknown
targetOrigin
Section titled “targetOrigin”string
transfer?
Section titled “transfer?”Transferable[]
Returns
Section titled “Returns”Promise<void>
Call Signature
Section titled “Call Signature”postMessage(message, options?): Promise<void>;Parameters
Section titled “Parameters”message
Section titled “message”unknown
options?
Section titled “options?”FramePostMessageOptions
Returns
Section titled “Returns”Promise<void>
requestPermissions()
Section titled “requestPermissions()”requestPermissions(requests): Promise<CategoryAnswer[]>;Asks for whole categories on this attachment’s hosts, before any call. Resolves per request, in
the order they were asked; a refusal is allow: false, never a rejection. An ask naming a
category or key the registry cannot place on a row is a TypeError, thrown before it is sent.
Not Playwright’s page.request, which is an HTTP client; the app asks here and the user grants.
Parameters
Section titled “Parameters”requests
Section titled “requests”CategoryRequest[]
Returns
Section titled “Returns”Promise<CategoryAnswer[]>
url(): string;The url last given to attachFrame or goto, never the frame’s live location: a page that moves itself does not change it.
Returns
Section titled “Returns”string
FrameLocator
Section titled “FrameLocator”type FrameLocator = FrameLocatorChain<LocatorModules, LocatorRewrites>;A frame inside an attached frame, entered with frameLocator(selector). Its document is read
as the attached frame’s is. owner() is Playwright’s: a Locator on the iframe it entered, whose
contentFrame() comes back here. getByTestId searches from its document root. evaluate and
addScriptTag run on the attached frame only, so neither is offered here.
FrameWindowOptions
Section titled “FrameWindowOptions”type FrameWindowOptions = object;Where an attachment’s window opens and how big it asks to be.
Properties
Section titled “Properties”height?
Section titled “height?”optional height?: number;Inner height in CSS pixels, 700 by default. The browser may clamp it.
optional url?: string;Where the window opens: an http or https address, which must also pass the rules an iframe src
does. Omitted, the window opens blank and the app navigates it with goto, which is how an app
keeps the click’s activation when the url needs an await first.
width?
Section titled “width?”optional width?: number;Inner width in CSS pixels, 500 by default. The browser may clamp it.
FrameWindowRefusal
Section titled “FrameWindowRefusal”type FrameWindowRefusal = "jar-unreachable" | "bad-url" | "opaque-opener" | "unknown";Why a window refused to attach.
'jar-unreachable': the cookie jar of the app that opened it could not be reached.
'bad-url': the window would not open that address.
'opaque-opener': this page’s origin is opaque (a sandboxed frame without allow-same-origin,
or a file: page). A window can never address such a page, so none is opened.
'unknown': a reason this library does not know, sent by a newer window.
type Gate = (request, tools) => void | Promise<void>;Parameters
Section titled “Parameters”request
Section titled “request”Returns
Section titled “Returns”void | Promise<void>
GateTools
Section titled “GateTools”type GateTools = object;Properties
Section titled “Properties”highlight
Section titled “highlight”highlight: (on) => Promise<void>;Parameters
Section titled “Parameters”boolean
Returns
Section titled “Returns”Promise<void>
GotoOptions
Section titled “GotoOptions”type GotoOptions = object;frame.goto’s options. Refused with a TypeError before anything is sent: a waitUntil other than
'load' or 'commit' (Playwright’s 'domcontentloaded' and 'networkidle' are not served, and
'documentstart' is now 'commit'), a timeout of 0 or below or not finite, and timeoutMs.
Properties
Section titled “Properties”domains?
Section titled “domains?”optional domains?: string[];timeout?
Section titled “timeout?”optional timeout?: number;How long the goto may take, in milliseconds: 30000 when absent. Past it the goto rejects with
TimeoutError. A positive number: 0 is a TypeError, since every call ends by its deadline and
so does not take Playwright’s “0 disables the timeout”.
waitUntil?
Section titled “waitUntil?”optional waitUntil?: "commit" | "load";When goto resolves: 'load', the default, once the document it brings fired load; 'commit',
Playwright’s, once that document holds the frame, possibly before the page’s own scripts ran and
whether or not it ever fires load. Either way a call made after it runs on the document the goto
brought, never on the one it replaced, and the goto rejects with TimeoutError when that
document has not come by its deadline.
A goto that changes only the fragment of the url the page is at keeps its document. On the cloud
backend it resolves, either way, once the page reports the new fragment. Two pages are the
exception there, where such a goto brings a new document like any other: one reached through a
redirect, and one that followed a link onto another origin. On the extension (measured on
Chromium) one awaited to 'load' resolves, since the frame fires load for it, and one awaited to
'commit' runs out at its timeout, since no new document starts.
HeaderOperation
Section titled “HeaderOperation”type HeaderOperation = object;Properties
Section titled “Properties”header
Section titled “header”header: string;operation
Section titled “operation”operation: "set" | "remove";value?
Section titled “value?”optional value?: string;OperationRequest
Section titled “OperationRequest”type OperationRequest = object;Properties
Section titled “Properties”args: unknown[];operation
Section titled “operation”operation: string;parts: SelectorPart[];phase: "execute" | "ensure";PermissionGrant
Section titled “PermissionGrant”type PermissionGrant = | CategoryGrant | { allow: boolean; key: PermissionScope; scope: string; site: string;};key and scope are set only for a legacy answer, category and hosts only for a category one.
A legacy answer also carries site, the host its scope named, empty where the scope names none
(a locator selector), which is the case that is always refused.
PermissionRequest
Section titled “PermissionRequest”type PermissionRequest = CategoryRequest & object | LegacyPermissionRequest;hosts is what makes an item a category ask; without it the item is the legacy per-key one.
RemoteVideoElement
Section titled “RemoteVideoElement”type RemoteVideoElement = EventTarget & object;Type Declaration
Section titled “Type Declaration”autoplay
Section titled “autoplay”autoplay: boolean;buffered
Section titled “buffered”readonly buffered: TimeRanges;currentSrc
Section titled “currentSrc”readonly currentSrc: string;currentTime
Section titled “currentTime”currentTime: number;disableRemotePlayback
Section titled “disableRemotePlayback”disableRemotePlayback: boolean;duration
Section titled “duration”readonly duration: number;readonly ended: boolean;readonly error: MediaError | null;HAVE_ENOUGH_DATA
Section titled “HAVE_ENOUGH_DATA”readonly HAVE_ENOUGH_DATA: 4;HAVE_FUTURE_DATA
Section titled “HAVE_FUTURE_DATA”readonly HAVE_FUTURE_DATA: 3;loop: boolean;muted: boolean;paused
Section titled “paused”readonly paused: boolean;playbackRate
Section titled “playbackRate”playbackRate: number;poster
Section titled “poster”poster: string;preload
Section titled “preload”preload: string;readyState
Section titled “readyState”readonly readyState: number;seekable
Section titled “seekable”readonly seekable: TimeRanges;seeking
Section titled “seeking”readonly seeking: boolean;src: string;volume
Section titled “volume”volume: number;exitPictureInPicture()
Section titled “exitPictureInPicture()”exitPictureInPicture(): Promise<void>;Returns
Section titled “Returns”Promise<void>
load()
Section titled “load()”load(): void;Returns
Section titled “Returns”void
pause()
Section titled “pause()”pause(): void;Returns
Section titled “Returns”void
play()
Section titled “play()”play(): Promise<void>;Returns
Section titled “Returns”Promise<void>
requestPictureInPicture()
Section titled “requestPictureInPicture()”requestPictureInPicture(): Promise<void>;Returns
Section titled “Returns”Promise<void>
RequestHeaderRule
Section titled “RequestHeaderRule”type RequestHeaderRule = object;Properties
Section titled “Properties”domains
Section titled “domains”domains: string[];reason?
Section titled “reason?”optional reason?: string;requestHeaders
Section titled “requestHeaders”requestHeaders: HeaderOperation[];SelectorPart
Section titled “SelectorPart”type SelectorPart = object;Properties
Section titled “Properties”args: unknown[];kind: ChainKind;name: string;SiteCookie
Section titled “SiteCookie”type SiteCookie = object;Properties
Section titled “Properties”name: string;value: string;StorageState
Section titled “StorageState”type StorageState = object;A jar’s starting state, in the shape Playwright’s browser.newContext({ storageState }) takes,
except that a cookie’s expires is milliseconds here where Playwright’s is seconds. Seeded into
an 'ephemeral' attachment’s fresh jar and its storage namespace before the attachment’s first
document is requested, so that request already carries its cookies and the page’s first script
already reads its localStorage. With blank, whose empty page requests nothing and runs no code,
it is seeded right after that page is in place, before the attach resolves.
Accepted only with cookies: 'ephemeral': with 'persistent' an app-written cookie would land
in the jar every app of the top-level site shares, and with 'native' in the person’s own
session. The seed travels on FKN’s own channels, never in a url the app page could read. A
seeded HttpOnly cookie is sent to its site and never readable in the page, as any HttpOnly cookie,
and it never comes back to app code.
Refused by name, before anything is attached (AttachCookies has the order): a field of another
shape; a name or value with ; or a control character, or a name with =; a cookie a browser
does not store (SameSite=None or __Secure- without secure, __Host- without secure, a
host-only domain and path ’/’); an origin that is not an absolute http or https origin; and an
expires that reads as seconds. Against an FKN page or render proxy that predates it, after the
iframe is put back on about:blank (or the window closed) and before anything is requested from
the site: the terminal LocatorUnsupportedError attachFrame: this FKN page predates storageState; reload the app to load the current one.
Properties
Section titled “Properties”cookies?
Section titled “cookies?”optional cookies?: StorageStateCookie[];origins?
Section titled “origins?”optional origins?: object[];Each origin’s localStorage items, read by every page of that origin in the attachment.
localStorage
Section titled “localStorage”localStorage: object[];origin
Section titled “origin”origin: string;StorageStateCookie
Section titled “StorageStateCookie”type StorageStateCookie = object;One cookie of a StorageState.
Properties
Section titled “Properties”domain
Section titled “domain”domain: string;.youtube.com for a cookie its subdomains also receive, www.youtube.com for a host-only one, as Playwright writes it.
expires?
Section titled “expires?”optional expires?: number;Milliseconds since the epoch, where Playwright’s is seconds; -1 or absent for a session cookie.
httpOnly?
Section titled “httpOnly?”optional httpOnly?: boolean;name: string;Non-empty, with no =, ; or control character.
optional path?: string;/ when absent.
sameSite?
Section titled “sameSite?”optional sameSite?: "Strict" | "Lax" | "None";'Lax' when absent, as a browser defaults it.
secure?
Section titled “secure?”optional secure?: boolean;value: string;With no ; or control character.
WindowFrame
Section titled “WindowFrame”type WindowFrame = Frame & object;The Frame of an attachment that lives in its own window.
On the extension (cookies: 'native') the window is a real browser popup the app’s page opens with
window.open, whose page is the site itself: there is no FKN page in it. Where that differs:
- The Frame follows the window’s page wherever it goes, as it follows an iframe’s, and its reads
answer only inside the attachment. A page that goes to an FKN host ends the attachment (
closed). postMessageand themessageevent need the window to keep its link to the app’s page. A page served with Cross-Origin-Opener-Policy (same-origin,same-origin-allow-popups) cuts it as it loads, andpostMessageis then theLocatorDeniedErrorframe.postMessage: this window's page no longer keeps a link to the app's page, so a message cannot reach it. Everything else still answers: the extension knows the window by its tab, never by that link. The page reaches the app withopener.postMessage(x, appOrigin)while the link holds.- Its consent sheets are drawn on the app’s page, not in the window.
evaluatekeeps the window page’s content security policy (an attached iframe on a declared host has it replaced), so a page that forbidsevalrefuses with a named error.- Calls after
closedreject with the terminalLocatorUnsupportedErrorextension.attachFrame: the attached window closed; attach a fresh window. - The extension never throws
FrameWindowRefusedError, which is the cloud’s.
Type Declaration
Section titled “Type Declaration”closed
Section titled “closed”closed: Promise<void>;Resolves once the attachment has ended, and never rejects. Calls made after it resolved reject
with the terminal detach error. On the cloud backend: the window was closed by anyone, reloaded,
or left the page FKN attached; it stopped answering (a crash, a frozen page); it lost the app’s
cookie jar mid-session; or the app page went away. On the extension: the window was closed by
anyone, close() ran, its page went to an FKN host (a goto redirected there rejects with the
detach error), or the app page went away; the last two leave the window open for the person. Any
other reload or navigation in the window does not end it, since the Frame follows the window’s page.
close()
Section titled “close()”close(): Promise<void>;Ends the attachment and closes the window. On the cloud backend it first waits, at most 2
seconds, for the window’s cookie changes to be committed to its jar, so a goto on the app’s
inline frame right after sees the session. On the extension the window ran on the person’s own
browser cookies, which are already written, so an inline 'native' frame sees a sign-in on its
next goto. Idempotent, and never rejects.
Returns
Section titled “Returns”Promise<void>
Variables
Section titled “Variables”assertAttachableFrameUrl
Section titled “assertAttachableFrameUrl”const assertAttachableFrameUrl: (raw) => void;Parameters
Section titled “Parameters”string
Returns
Section titled “Returns”void
assertFetchableUrl
Section titled “assertFetchableUrl”const assertFetchableUrl: (raw) => void;Parameters
Section titled “Parameters”string
Returns
Section titled “Returns”void
attachFrame
Section titled “attachFrame”const attachFrame: AttachFrameFunction;Attaches through the extension, on cookies: 'native' only: the other values, the default
among them, are the cloud render proxy’s, refused here with ExtensionOperationUnsupportedError
(operation 'cookies') before any exposure wait (AttachCookies). A domains entry, of the
attach or of a goto, or a goto target’s host, that the frame’s header rule would carry onto an
FKN platform host (one of them, one under one, or a parent such as app) is refused with an Error
before anything is armed.
BACKGROUND_STOPPED
Section titled “BACKGROUND_STOPPED”const BACKGROUND_STOPPED: "BackgroundStoppedError" = "BackgroundStoppedError";cookies
Section titled “cookies”const cookies: object;Type Declaration
Section titled “Type Declaration”get: (details) => Promise<SiteCookie | null>;Reads one named cookie of another site behind a Network ask on its host, null when there is
none. A url on an FKN platform host (fkn.app, fkn.dev, sdbx.app and their subdomains) is
refused with an Error before anything is asked, and again by the extension.
Parameters
Section titled “Parameters”details
Section titled “details”Returns
Section titled “Returns”Promise<SiteCookie | null>
events
Section titled “events”const events: TypedEventTarget;EXTENSION_ABI
Section titled “EXTENSION_ABI”const EXTENSION_ABI: 5 = 5;What the extension half announces about itself. Increment when the callable surface changes in a way a page could notice: an operation added, removed, renamed, or given different semantics. Not the package or manifest version, which move for reasons unrelated to the protocol.
const fetch: (input, init?) => Promise<Response>;Fetches through the extension. A credentialed fetch (credentials: 'include') and one to the local
network are asked for on the target’s host first. A url on the extension’s own pages or an FKN
platform host is refused with an Error before anything is asked. A redirect onto an FKN platform
host is not followed: the hop is blocked before it is sent, on both engines and in every spelling,
and should one ever slip the block the final answer is still withheld with an Error. A fetch that
follows redirects is refused before it is sent when the extension could not set the block up.
Parameters
Section titled “Parameters”RequestInfo | URL
Returns
Section titled “Returns”Promise<Response>
FORGEABLE_HEADERS
Section titled “FORGEABLE_HEADERS”const FORGEABLE_HEADERS: string[];isBackgroundStopped
Section titled “isBackgroundStopped”const isBackgroundStopped: (error) => boolean;Whether error is a BackgroundStoppedError, matched on name since it may arrive as a revived Error or a plain record.
Parameters
Section titled “Parameters”unknown
Returns
Section titled “Returns”boolean
isExtensionExposed
Section titled “isExtensionExposed”const isExtensionExposed: () => boolean;Unchanged on purpose: a page half built before versioning calls exactly this, so an extension that announces an ABI keeps answering it the same way. An outdated extension also answers true.
Returns
Section titled “Returns”boolean
isLocalNetworkUrl
Section titled “isLocalNetworkUrl”const isLocalNetworkUrl: (raw) => boolean;Parameters
Section titled “Parameters”string
Returns
Section titled “Returns”boolean
isLocatorDenied
Section titled “isLocatorDenied”const isLocatorDenied: (error) => boolean;Parameters
Section titled “Parameters”unknown
Returns
Section titled “Returns”boolean
isLocatorInvalid
Section titled “isLocatorInvalid”const isLocatorInvalid: (error) => boolean;Parameters
Section titled “Parameters”unknown
Returns
Section titled “Returns”boolean
isLocatorUnsupported
Section titled “isLocatorUnsupported”const isLocatorUnsupported: (error) => boolean;Parameters
Section titled “Parameters”unknown
Returns
Section titled “Returns”boolean
isTerminalError
Section titled “isTerminalError”const isTerminalError: (error) => boolean;Parameters
Section titled “Parameters”unknown
Returns
Section titled “Returns”boolean
LOCATOR_DENIED
Section titled “LOCATOR_DENIED”const LOCATOR_DENIED: "LocatorDeniedError" = "LocatorDeniedError";LOCATOR_ERROR
Section titled “LOCATOR_ERROR”const LOCATOR_ERROR: "LocatorError" = "LocatorError";LOCATOR_INVALID
Section titled “LOCATOR_INVALID”const LOCATOR_INVALID: "LocatorInvalidError" = "LocatorInvalidError";LOCATOR_UNSUPPORTED
Section titled “LOCATOR_UNSUPPORTED”const LOCATOR_UNSUPPORTED: "LocatorUnsupportedError" = "LocatorUnsupportedError";permissions
Section titled “permissions”const permissions: object;Type Declaration
Section titled “Type Declaration”request
Section titled “request”request: (requests) => Promise<PermissionGrant[]>;Asks for permissions on one sheet (extension) or card (cloud), in the order given, and answers one grant per request.
A category ask needs hosts, the sites the grant applies to, and is answered allow: true only
where every one of them was granted. It needs an extension that serves categories and throws
ExtensionOutdatedError below that; a legacy { key, scope } item is forwarded to any version.
An ask naming a category or key the registry cannot place on a row is a TypeError, thrown
before anything is sent: its answer would have to name a category the caller never asked for.
A category ask naming an FKN platform host is an Error, also before anything is sent; the
extension answers allow: false for any item, legacy ones included, that names one.
Parameters
Section titled “Parameters”requests
Section titled “requests”Returns
Section titled “Returns”readExtensionHandshake
Section titled “readExtensionHandshake”const readExtensionHandshake: () => ExtensionHandshake;The three-way answer: absent, present but too old, or usable.
Returns
Section titled “Returns”removeRequestHeaderRule
Section titled “removeRequestHeaderRule”const removeRequestHeaderRule: (ruleId) => Promise<void>;Parameters
Section titled “Parameters”ruleId
Section titled “ruleId”number
Returns
Section titled “Returns”Promise<void>
REQUIRED_EXTENSION_ABI
Section titled “REQUIRED_EXTENSION_ABI”const REQUIRED_EXTENSION_ABI: 0 = 0;The oldest extension the page half will talk to. Raise it only when the page half starts depending
on something older extensions cannot do, never merely because EXTENSION_ABI moved. Deliberately 0:
extensions that predate versioning announce no ABI, and a floor of 1 would refuse all of them.
setMissingExtensionHandler
Section titled “setMissingExtensionHandler”const setMissingExtensionHandler: (handler) => void;Parameters
Section titled “Parameters”handler
Section titled “handler”MissingExtensionHandler | null
Returns
Section titled “Returns”void
setRequestHeaderRule
Section titled “setRequestHeaderRule”const setRequestHeaderRule: (rule) => Promise<{ ruleId: number;}>;Tab-scoped: the rule is dropped when the tab goes away. A domain the rule would carry onto an FKN
platform host (one of them, one under one, or a parent such as app, since a rule also matches every
host under each domain) is refused with an Error before anything is asked, and again by the extension.
So is a header other than Origin, Referer and Cookie (FORGEABLE_HEADERS).
Parameters
Section titled “Parameters”Returns
Section titled “Returns”Promise<{
ruleId: number;
}>
supportsOperation
Section titled “supportsOperation”const supportsOperation: (handshake, operation) => boolean;Whether a named operation is callable. A null list answers true (the extension predates the list
and supports the original surface); refusing a too-old extension is the ABI floor’s job.
Parameters
Section titled “Parameters”handshake
Section titled “handshake”operation
Section titled “operation”string
Returns
Section titled “Returns”boolean
waitForExtensionExposure
Section titled “waitForExtensionExposure”const waitForExtensionExposure: (timeout?) => Promise<void>;Parameters
Section titled “Parameters”timeout?
Section titled “timeout?”number
Returns
Section titled “Returns”Promise<void>
Functions
Section titled “Functions”available()
Section titled “available()”function available(): boolean;Returns
Section titled “Returns”boolean
promptInstall()
Section titled “promptInstall()”function promptInstall(reason?): Promise<boolean>;Parameters
Section titled “Parameters”reason?
Section titled “reason?”string
Returns
Section titled “Returns”Promise<boolean>
References
Section titled “References”extension
Section titled “extension”Renames and re-exports events