effect-browser 0.3.0-beta.15 → 0.3.0-beta.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/dist/{Browser-BBSySyjT.mjs → Browser-DRPthkNO.mjs} +4 -4
- package/dist/Browser-DRPthkNO.mjs.map +1 -0
- package/dist/Browser.d.mts +2 -2
- package/dist/Browser.mjs +1 -1
- package/dist/{BrowserEvent-BRu2juEz.d.mts → BrowserEvent-dq6FRT8w.d.mts} +9 -9
- package/dist/BrowserEvent.d.mts +1 -1
- package/dist/BrowserEvent.mjs +7 -12
- package/dist/BrowserEvent.mjs.map +1 -1
- package/dist/Cdp.mjs +2 -2
- package/dist/{Change-iMlcuzVD.d.mts → Change-DqING3tr.d.mts} +2 -2
- package/dist/Change.d.mts +1 -1
- package/dist/Chromium.mjs +2 -2
- package/dist/Expect.d.mts +1 -1
- package/dist/Expect.mjs +2 -2
- package/dist/Moment.d.mts +1 -1
- package/dist/Moment.mjs +1 -1
- package/dist/Motion-DND6I-64.d.mts +40 -0
- package/dist/Motion.d.mts +2 -40
- package/dist/Motion.mjs +1 -2
- package/dist/Motion.mjs.map +1 -1
- package/dist/{Page-B5cjaUp5.mjs → Page-C_VkBVwI.mjs} +5 -9
- package/dist/Page-C_VkBVwI.mjs.map +1 -0
- package/dist/{Page-DL9eylp3.d.mts → Page-jHmSJeOS.d.mts} +6 -13
- package/dist/Page.d.mts +1 -1
- package/dist/Page.mjs +1 -1
- package/dist/{Plan-6As6vcwT.d.mts → Plan-DLtRksuu.d.mts} +3 -3
- package/dist/{Plan-CXA2BW-G.mjs → Plan-X-JkACAB.mjs} +6 -9
- package/dist/Plan-X-JkACAB.mjs.map +1 -0
- package/dist/Plan.d.mts +1 -1
- package/dist/Plan.mjs +1 -1
- package/dist/Policy.d.mts +1 -1
- package/dist/Policy.mjs +1 -1
- package/dist/Presentation.d.mts +2 -2
- package/dist/Presentation.mjs +3 -2
- package/dist/Presentation.mjs.map +1 -1
- package/dist/Stage.d.mts +1 -1
- package/dist/Stage.mjs +3 -3
- package/dist/Stage.mjs.map +1 -1
- package/dist/{Supervisor-DaGlQVjv.mjs → Supervisor-BgWP8o9t.mjs} +41 -17
- package/dist/Supervisor-BgWP8o9t.mjs.map +1 -0
- package/dist/{Supervisor-5tZ47hR5.d.mts → Supervisor-mVPeEUp8.d.mts} +12 -5
- package/dist/Supervisor.d.mts +1 -1
- package/dist/Supervisor.mjs +1 -1
- package/dist/{context-BAjRj7Xo.mjs → context-rYTk-3Cv.mjs} +68 -3
- package/dist/context-rYTk-3Cv.mjs.map +1 -0
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +4 -4
- package/dist/match.inpage-xOe9LNO0.mjs.map +1 -1
- package/dist/{page-B92QnRfT.mjs → page-ClEMFnBG.mjs} +48 -110
- package/dist/page-ClEMFnBG.mjs.map +1 -0
- package/package.json +1 -1
- package/src/Browser.ts +1 -1
- package/src/BrowserEvent.ts +7 -12
- package/src/Motion.ts +1 -2
- package/src/Page.ts +5 -9
- package/src/Plan.ts +1 -2
- package/src/Presentation.ts +2 -1
- package/src/Stage.ts +2 -1
- package/src/Supervisor.ts +3 -2
- package/src/internal/input/actions.ts +25 -33
- package/src/internal/input/dispatch.ts +3 -4
- package/src/internal/input/edit.inpage.ts +3 -9
- package/src/internal/input/evidence.inpage.ts +2 -20
- package/src/internal/input/guard.inpage.ts +9 -29
- package/src/internal/input/guard.ts +12 -1
- package/src/internal/input/targets.inpage.ts +4 -8
- package/src/internal/input/targets.ts +8 -11
- package/src/internal/page/context.ts +2 -2
- package/src/internal/pictures/capture.ts +4 -4
- package/src/internal/pictures/clock.ts +8 -3
- package/src/internal/pictures/pictures.ts +2 -1
- package/src/internal/reading/controls.inpage.ts +8 -1
- package/src/internal/reading/match.inpage.ts +2 -1
- package/src/internal/reading/outline.inpage.ts +7 -4
- package/src/internal/reading/reading.ts +5 -16
- package/src/internal/supervisor/lifecycle.ts +56 -13
- package/dist/Browser-BBSySyjT.mjs.map +0 -1
- package/dist/Page-B5cjaUp5.mjs.map +0 -1
- package/dist/Plan-CXA2BW-G.mjs.map +0 -1
- package/dist/Supervisor-DaGlQVjv.mjs.map +0 -1
- package/dist/context-BAjRj7Xo.mjs.map +0 -1
- package/dist/page-B92QnRfT.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-rYTk-3Cv.mjs","names":["make","Url.redactWithin","BrowserClock.monotonicMillis","Lane.make"],"sources":["../src/internal/input/replies.ts","../src/internal/pictures/clock.ts","../src/internal/page/context.ts"],"sourcesContent":["/**\n * Bounded input replies owned by the page, including after an action is interrupted.\n * Canceling a caller cannot cancel a protocol command already sent. The next action waits for\n * those replies, while a stopped run releases only held keys or buttons whose release was never submitted.\n */\nimport { Context, Data, Effect } from \"effect\";\n\nimport { maximumSamples } from \"../../Motion.ts\";\n\nexport const capacity = 64;\n\nexport class InputFailure extends Data.TaggedError(\"InputFailure\")<{\n readonly cause: unknown;\n}> {}\n\nexport interface Run {\n /** A native call made by this operation: cancellation cannot cancel its actual reply. */\n readonly track: <A>(reply: Promise<A>) => Promise<A>;\n /** End ownership after the record and all this operation's native replies have settled. */\n readonly afterIdle: (ended: () => void) => void;\n /** Reserve a complete stroke, including its releases, before sending its first event. */\n readonly reserve: (commands: number) => Effect.Effect<void, InputFailure>;\n /** Admit every sample before a motion starts its published clock; ordinary input stays bounded separately. */\n readonly reserveMotion: (commands: number) => Effect.Effect<void, InputFailure>;\n readonly send: (command: () => Promise<unknown>) => Effect.Effect<void, InputFailure>;\n readonly down: (\n key: string,\n press: () => Promise<unknown>,\n release: () => Promise<unknown>,\n ) => Effect.Effect<void, InputFailure>;\n readonly up: (key: string) => Effect.Effect<void, InputFailure>;\n readonly drain: Effect.Effect<void, InputFailure>;\n /** Stop future input and submit missing releases without waiting indefinitely for replies. */\n readonly close: Effect.Effect<void>;\n}\n\n/** Native page calls join their operation's reply ownership, including script mutations. */\nexport const Current = Context.Reference<Run | undefined>(\"effect-browser/internal/input/Current\", {\n defaultValue: () => undefined,\n});\n\nexport const make = () => {\n const outstanding = new Set<Promise<void>>();\n\n // A timed-out action keeps capacity until its real replies arrive. Waiting for them sends\n // nothing, so cancellation here cannot leave a detached continuation that later types.\n const idle = Effect.gen(function* () {\n while (outstanding.size > 0) yield* Effect.promise(() => Promise.all(outstanding));\n });\n\n const begin = Effect.gen(function* () {\n yield* idle;\n const pending = new Set<Promise<void>>();\n const held: Array<{ readonly key: string; readonly release: () => Promise<unknown> }> = [];\n let failure: InputFailure | undefined;\n let reserved = 0;\n let closed = false;\n const observed = new WeakMap<Promise<unknown>, { input: boolean }>();\n const endings = new Set<() => void>();\n\n const track = <A>(response: Promise<A>, input = false): Promise<A> => {\n const existing = observed.get(response);\n\n if (existing !== undefined) {\n existing.input ||= input;\n\n return response;\n }\n const entry = { input };\n\n observed.set(response, entry);\n\n const reply = response\n .then(\n () => undefined,\n (cause: unknown) => {\n if (entry.input) failure ??= new InputFailure({ cause });\n },\n )\n .then(() => {\n pending.delete(reply);\n outstanding.delete(reply);\n if (pending.size === 0) {\n for (const end of endings) end();\n endings.clear();\n }\n });\n\n pending.add(reply);\n outstanding.add(reply);\n\n return response;\n };\n\n const requireOpen = Effect.suspend(() =>\n closed\n ? Effect.fail(new InputFailure({ cause: new Error(\"the input run has stopped\") }))\n : Effect.void,\n );\n\n const requireSuccess = Effect.suspend(() =>\n failure === undefined ? Effect.void : Effect.fail(failure),\n );\n\n const submit = (command: () => Promise<unknown>) => {\n if (reserved < 1) throw new Error(\"input must reserve capacity before dispatch\");\n reserved--;\n let response: Promise<unknown>;\n\n try {\n response = command();\n } catch (cause) {\n failure ??= new InputFailure({ cause });\n\n return;\n }\n\n void track(response, true);\n };\n\n const reserve = (commands: number, maximum: number, limit: number) =>\n Effect.gen(function* () {\n yield* requireOpen;\n yield* requireSuccess;\n if (!Number.isInteger(commands) || commands < 1 || commands > maximum)\n return yield* Effect.die(new Error(\"invalid input reservation\"));\n while (outstanding.size + reserved + commands > limit) {\n yield* Effect.promise(() => Promise.race(outstanding));\n yield* requireOpen;\n yield* requireSuccess;\n }\n reserved += commands;\n });\n\n const run: Run = {\n track,\n afterIdle: (end) => {\n if (pending.size === 0) end();\n else endings.add(end);\n },\n reserve: (commands) => reserve(commands, capacity, capacity),\n // A dense stroke cannot wait for replies midway without changing its published timing.\n // Its finite reservation also leaves room for the ordinary pool's already-owned releases.\n reserveMotion: (commands) => reserve(commands, maximumSamples, capacity + maximumSamples),\n send: (command) =>\n Effect.gen(function* () {\n yield* requireOpen;\n yield* requireSuccess;\n yield* Effect.sync(() => submit(command));\n yield* requireSuccess;\n }),\n down: (key, press, release) =>\n Effect.gen(function* () {\n yield* requireOpen;\n yield* requireSuccess;\n yield* Effect.sync(() => {\n held.push({ key, release });\n submit(press);\n });\n yield* requireSuccess;\n }),\n up: (key) =>\n Effect.gen(function* () {\n yield* requireOpen;\n yield* Effect.sync(() => {\n const index = held.findLastIndex((entry) => entry.key === key);\n const entry = held[index];\n\n if (entry === undefined) return;\n // Submission owns the release, even if its reply fails. Retrying an uncertain\n // release could run page handlers twice, so cleanup never sends it again.\n held.splice(index, 1);\n submit(entry.release);\n });\n yield* requireSuccess;\n }),\n drain: Effect.gen(function* () {\n while (pending.size > 0) yield* Effect.promise(() => Promise.all(pending));\n yield* requireSuccess;\n }),\n close: Effect.sync(() => {\n if (closed) return;\n closed = true;\n for (const entry of held.toReversed()) submit(entry.release);\n held.length = 0;\n reserved = 0;\n }),\n };\n\n return run;\n });\n\n /** `idle` lets an action wait, in its page's turn, for the page's earlier replies. */\n return { idle, begin };\n};\n","/**\n * Host monotonic milliseconds and the browser's clock read on the owner's: estimates of their\n * offset from timed probes, how an estimate ages, and the mapping a browser's pages share.\n * `pictures.ts` takes the probes.\n */\nimport { type Clock, Duration, Effect, Option } from \"effect\";\n\n/** Read the captured owner's clock, including from native callbacks, without changing its origin. */\nexport const monotonicMillis = (clock: Clock.Clock): number =>\n Number(clock.monotonicTimeNanosUnsafe()) / 1e6;\n\nexport interface Probe {\n readonly hostStart: number;\n readonly hostEnd: number;\n readonly browserTime: number;\n}\n\nexport interface Estimate {\n /** Browser epoch milliseconds minus the owner's host monotonic milliseconds. */\n readonly offsetMillis: number;\n /** Either transport direction can own the entire round trip; symmetry is not assumed. */\n readonly uncertaintyMillis: number;\n readonly roundTripMillis: number;\n readonly sampledAt: number;\n}\n\n/** The fastest complete probe limits uncertainty without mistaking transit delay for clock offset. */\nexport const estimate = (probes: ReadonlyArray<Probe>): Option.Option<Estimate> => {\n let best: Estimate | undefined;\n\n for (const probe of probes) {\n const roundTripMillis = probe.hostEnd - probe.hostStart;\n\n if (\n !Number.isFinite(probe.hostStart) ||\n !Number.isFinite(probe.hostEnd) ||\n !Number.isFinite(probe.browserTime) ||\n !Number.isFinite(roundTripMillis) ||\n roundTripMillis < 0\n )\n continue;\n const sampledAt = probe.hostStart + roundTripMillis / 2;\n const offsetMillis = probe.browserTime - sampledAt;\n\n if (\n !Number.isFinite(offsetMillis) ||\n !Number.isFinite(probe.browserTime - probe.hostStart) ||\n !Number.isFinite(probe.browserTime - probe.hostEnd)\n )\n continue;\n if (best === undefined || roundTripMillis < best.roundTripMillis)\n best = {\n offsetMillis,\n uncertaintyMillis: roundTripMillis / 2,\n roundTripMillis,\n sampledAt,\n };\n }\n\n return Option.fromUndefinedOr(best);\n};\n\n// Two machines' clocks drift apart by up to about 100 parts per million, so an estimate says this\n// much less about the offset for each millisecond of its age.\nconst driftPerMillis = 1e-4;\n\n/** An estimate's uncertainty at `hostTime`, wider the further that is from when it was sampled. */\nexport const uncertaintyAt = (estimate: Estimate, hostTime: number): number =>\n estimate.uncertaintyMillis + Math.abs(hostTime - estimate.sampledAt) * driftPerMillis;\n\n// Ten seconds widen an estimate by a millisecond, far less than a remote round trip, so it is\n// measured again no more often than this.\nconst renewAfter = Duration.seconds(10);\n\n/**\n * The browser's one epoch mapping, shared by its pages, input runs and capture generations. It is\n * measured on first need, by the first capture, never ahead of it.\n */\nexport interface Mapping {\n /** The latest estimate, without measuring: input uses it, and never waits for one. */\n readonly latest: () => Estimate | undefined;\n /** The latest estimate, measured through `measure` only while the browser has none. */\n readonly current: <E>(measure: Effect.Effect<Estimate, E>) => Effect.Effect<Estimate, E>;\n /**\n * Measure again once ten seconds have passed since the latest measurement began. A failed\n * measurement keeps the estimate, which keeps widening with its age.\n */\n readonly renew: <E>(measure: Effect.Effect<Estimate, E>) => Effect.Effect<void>;\n}\n\n/**\n * Whether a new measurement should replace the current estimate. Each interval contains the true\n * offset, so overlapping intervals agree and the narrower one is kept, the current one widened by\n * its age: a probe delayed behind a busy page cannot widen every tab's stamps. A disjoint\n * measurement means the clocks moved (a wall clock step, or drift between a remote browser and\n * this host), so the newer evidence wins.\n */\nexport const supersedes = (next: Estimate, current: Estimate): boolean => {\n const aged = uncertaintyAt(current, next.sampledAt);\n\n return (\n next.uncertaintyMillis <= aged ||\n Math.abs(next.offsetMillis - current.offsetMillis) > next.uncertaintyMillis + aged\n );\n};\n\n/**\n * Every renderer of a browser reads the same host wall clock, so the offset belongs to the\n * browser rather than a page. A busy page cannot fail work that an earlier estimate can serve.\n */\nexport const mapping = (now: () => number): Mapping => {\n let latest: Estimate | undefined;\n let measuredAt = Number.NEGATIVE_INFINITY;\n\n // Called where a measurement is decided, so no other can be decided before this one begins.\n const adopt = <E>(measure: Effect.Effect<Estimate, E>) => {\n measuredAt = now();\n\n return measure.pipe(\n Effect.map((estimate) => {\n if (latest === undefined || supersedes(estimate, latest)) latest = estimate;\n\n return latest;\n }),\n );\n };\n\n return {\n latest: () => latest,\n current: (measure) =>\n Effect.suspend(() => (latest === undefined ? adopt(measure) : Effect.succeed(latest))),\n renew: (measure) =>\n Effect.suspend(() =>\n latest === undefined || now() - measuredAt < Duration.toMillis(renewAfter)\n ? Effect.void\n : Effect.ignore(adopt(measure)),\n ),\n };\n};\n\nexport const toHostTime = (calibration: Estimate, browserEpochMillis: number): number =>\n browserEpochMillis - calibration.offsetMillis;\n\n/** CDP input timestamps use seconds, unlike browser frame timestamps and the owner's clock. */\nexport const toBrowserSeconds = (calibration: Estimate, hostMillis: number): number =>\n (hostMillis + calibration.offsetMillis) / 1000;\n","/**\n * What a page's parts share: the browser state they act on, the page's own lane, pointer and\n * clock, and how they call the browser and report its failures. The assembly in `page.ts` builds\n * one context per page.\n */\nimport {\n Clock,\n Context,\n Duration,\n Effect,\n Fiber,\n MutableRef,\n Option,\n Schema,\n type Scope,\n} from \"effect\";\nimport type { CDPSession, Page as PlaywrightPage } from \"playwright-core\";\n\nimport type { CaptureSource } from \"../../Browser.ts\";\nimport { BrowserError, Closed, Failed, type Reason, Timeout } from \"../../BrowserError.ts\";\nimport type { BrowserEvent } from \"../../BrowserEvent.ts\";\nimport type { InputGuard, Point } from \"../../Page.ts\";\nimport type { Gate } from \"../input/gate.ts\";\nimport { Current } from \"../input/replies.ts\";\nimport * as BrowserClock from \"../pictures/clock.ts\";\nimport * as Lane from \"./lane.ts\";\nimport type { Openings } from \"./openings.ts\";\nimport * as Url from \"./url.ts\";\n\n/** Why a page is gone. */\nexport type ClosedCause = Closed[\"cause\"];\n\n/** What every page of a browser shares, from its options. */\nexport interface Settings {\n readonly actionTimeout: Duration.Duration;\n readonly policyTimeout: Duration.Duration;\n readonly navigationTimeout: Duration.Duration;\n /** How long screencast frames stay in `recentFrames`, measured back from the newest. */\n readonly frameHistory: Duration.Duration;\n readonly guard: InputGuard | undefined;\n}\n\nexport interface MakeOptions {\n /** The page's CDP target id, which is also its main frame's id. */\n readonly id: string;\n /** The id of the browser's session, which its frames carry. */\n readonly session: string;\n /** This tracking connection, distinct from the provider session and capture socket. */\n readonly connection: string;\n /** The page's address when the browser began tracking it. */\n readonly url: string;\n readonly playwright: PlaywrightPage;\n readonly cdp: CDPSession;\n /** A call's reply, or a failure as for a closed page once the browser is lost first. */\n readonly untilLost: <A>(reply: Promise<A>) => Promise<A>;\n readonly settings: Settings;\n readonly clock: Clock.Clock;\n /** Browser-wide input authority; direct internal page fixtures need not provide one. */\n readonly inputGate?: Gate | undefined;\n /** The browser's epoch mapping: its first capture measures it, and later ones renew it. */\n readonly mapping: BrowserClock.Mapping;\n readonly publish: (event: BrowserEvent) => number;\n /** This page's retained events, oldest first. */\n readonly recentEvents: Effect.Effect<ReadonlyArray<BrowserEvent>>;\n /** Registration of the actual popups this page's current input opened. */\n readonly openings: Openings;\n /** Succeeds once the page's own session holds focus emulation, which keeps it painting behind. */\n readonly focused: Effect.Effect<void, BrowserError>;\n /** Succeeds once the page's own session has the Page domain on, so it sees every later commit. */\n readonly paging: (operation: string) => Effect.Effect<void, BrowserError>;\n /** Why the page is gone, once it is: its browser's loss, else its own close or crash. */\n readonly closedBy: () => ClosedCause;\n /** Where the page's screencast runs, if not on its own session. */\n readonly capture?: CaptureSource | undefined;\n}\n\nconst messageOf = (cause: unknown): string =>\n cause instanceof Error ? cause.message : typeof cause === \"string\" ? cause : \"unknown error\";\n\nconst closedPattern =\n /has been closed|Target closed|Session closed|browser has disconnected|Target page, context or browser/i;\n\n/**\n * Map a Playwright or protocol failure to a reason, `Closed` with `closed` as its cause for a page\n * or browser that is gone. A call that gives Playwright a timeout passes the same bound, so its\n * `Timeout` reports it; without one, Playwright's own message stays.\n */\nexport const reasonOf = (\n cause: unknown,\n timeoutMillis?: number,\n closed: ClosedCause = \"connection\",\n): Reason => {\n const message = messageOf(cause);\n\n if (closedPattern.test(message)) return new Closed({ cause: closed });\n if (cause instanceof Error && cause.name === \"TimeoutError\" && timeoutMillis !== undefined)\n return new Timeout({ millis: timeoutMillis });\n const line = message.split(\"\\n\")[0] ?? message;\n\n return new Failed({ detail: Url.redactWithin(line.replace(/^[\\w.]+: /, \"\")) });\n};\n\n/**\n * One Playwright or protocol call, failing undispatched. A closed page says why it is gone as the\n * browser knows then: the library's own calls fail with the browser's loss, and Playwright fails\n * its calls on a dropped connection after reporting the context closed.\n */\nexport const call = <A>(\n operation: string,\n run: () => Promise<A>,\n closedBy: () => ClosedCause,\n timeoutMillis?: number,\n) =>\n Effect.tryPromise({\n try: run,\n catch: (cause) => undispatched(operation, reasonOf(cause, timeoutMillis, closedBy())),\n });\n\nexport const contextGone = (error: BrowserError) =>\n error.reason._tag === \"Failed\" &&\n /Cannot find context|Execution context was destroyed|__effectBrowser|Inspected target navigated/i.test(\n error.reason.detail,\n );\n\n/**\n * What a page operation spent on the page's own protocol session: its calls, the bytes of their\n * parameters and results, and how long at least one of them awaited its reply. An operation inside\n * another counts toward both.\n */\ninterface Cost {\n readonly enclosing: Cost | undefined;\n calls: number;\n bytesOut: number;\n bytesIn: number;\n waitedMillis: number;\n awaiting: number;\n awaitingSince: number;\n}\n\n/** The cost of the page operation the current fiber runs, if any. */\nconst CurrentCost = Context.Reference<Cost | undefined>(\n \"effect-browser/internal/page/CurrentCost\",\n {\n defaultValue: () => undefined,\n },\n);\n\n/** Track the promise returned to the action, after tracing wraps it, so input counts once. */\nconst track = <A>(reply: Promise<A>) => Fiber.getCurrent()?.getRef(Current)?.track(reply) ?? reply;\n\n// A message's size on the wire, give or take its envelope.\nconst sizeOf = (value: unknown) =>\n value === undefined ? 0 : Buffer.byteLength(JSON.stringify(value));\n\n/** A failure of `operation` before any of its input reached the browser. */\nexport const undispatched = (operation: string, reason: Reason) =>\n new BrowserError({ operation, reason, dispatched: false });\n\nexport const failWith = (operation: string, reason: Reason) =>\n Effect.fail(undispatched(operation, reason));\n\nexport const decodeWith =\n <A>(operation: string, schema: Schema.Codec<A, unknown>) =>\n (value: unknown) =>\n Schema.decodeUnknownEffect(schema)(value).pipe(\n Effect.mapError((error) => undispatched(operation, new Failed({ detail: error.message }))),\n );\n\nexport const make = (options: MakeOptions, scope: Scope.Scope) => {\n const { id, clock } = options;\n const now = () => BrowserClock.monotonicMillis(clock);\n // Deadlines and pacing guard the page's lane, so page operations run on the owner's clock; a\n // caller's clock, such as a TestClock, cannot stall or stretch them.\n const owned = Effect.provideService(Clock.Clock, clock);\n\n // This page's spans name it and report what the operation cost on the protocol. Fine-grained\n // ones carry a level below the default Info, so an application keeps only the coarse ones by\n // raising `Tracer.MinimumTraceLevel`.\n const span =\n (name: string, attributes: Record<string, unknown> = {}, level?: \"Debug\" | \"Trace\") =>\n <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n Effect.gen(function* () {\n const cost: Cost = {\n enclosing: yield* CurrentCost,\n calls: 0,\n bytesOut: 0,\n bytesIn: 0,\n waitedMillis: 0,\n awaiting: 0,\n awaitingSince: 0,\n };\n\n return yield* effect.pipe(\n Effect.provideService(CurrentCost, cost),\n Effect.ensuring(\n Effect.suspend(() =>\n Effect.annotateCurrentSpan({\n calls: cost.calls,\n bytesOut: cost.bytesOut,\n bytesIn: cost.bytesIn,\n waitedMillis: Math.round(cost.waitedMillis * 10) / 10,\n }),\n ),\n ),\n );\n }).pipe(\n Effect.withSpan(\n name,\n { attributes: { page: id, ...attributes }, ...(level === undefined ? {} : { level }) },\n { captureStackTrace: false },\n ),\n );\n\n // Every call on the page's own protocol session, counted into the operation that sends it and\n // the operations around that one. It is looked up when the call is sent, so input pipelined\n // from inside an operation counts toward it too.\n const send: CDPSession[\"send\"] = (method, params) => {\n const cost = Fiber.getCurrent()?.getRef(CurrentCost);\n const sentAt = now();\n const bytesOut = sizeOf(params);\n\n for (let each = cost; each !== undefined; each = each.enclosing) {\n each.calls++;\n each.bytesOut += bytesOut;\n if (each.awaiting++ === 0) each.awaitingSince = sentAt;\n }\n const reply = options.untilLost(options.cdp.send(method, params));\n\n if (cost === undefined) return track(reply);\n\n const settle = (bytesIn: number) => {\n const at = now();\n\n for (let each: Cost | undefined = cost; each !== undefined; each = each.enclosing) {\n each.bytesIn += bytesIn;\n if (--each.awaiting === 0) each.waitedMillis += at - each.awaitingSince;\n }\n };\n\n return track(\n reply.then(\n (result) => {\n settle(sizeOf(result));\n\n return result;\n },\n (cause: unknown) => {\n settle(0);\n\n return Promise.reject(cause);\n },\n ),\n );\n };\n\n // Every protocol or Playwright call. Errors are undispatched here; `perform` marks them\n // dispatched once input has gone out.\n const native = <A>(operation: string, run: () => Promise<A>, timeoutMillis?: number) =>\n call(operation, () => track(run()), options.closedBy, timeoutMillis);\n\n /** Fail with `Timeout` once `duration` has passed, the action timeout unless another is given. */\n const within =\n (operation: string, duration: Duration.Input = options.settings.actionTimeout) =>\n <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n Effect.timeoutOrElse(effect, {\n duration,\n orElse: () => failWith(operation, new Timeout({ millis: Duration.toMillis(duration) })),\n });\n\n // Stop a navigation whose bounded wait failed. The stop and original mutation keep their\n // actual replies owned; this cleanup does not turn an unanswered acknowledgement into success.\n const stopLoading = native(\"stopLoading\", () => send(\"Page.stopLoading\")).pipe(\n within(\"stopLoading\", options.settings.navigationTimeout),\n Effect.ignore,\n );\n\n // The latest submitted input or page change. A read that must follow it waits for the action in\n // flight, so only paint from after its latest input is current. An action ends after its input\n // was handled, so if that input changed the page, newer paint follows; a lost final paint is\n // bounded by recency instead. Paint from before the current document began, when the page's own\n // session saw the main frame commit it, shows a page the tab has left, so no read reuses it,\n // whatever it asks.\n const activity = { inputAt: 0, documentAt: Number.NEGATIVE_INFINITY };\n\n const noteInput = () => {\n activity.inputAt = Math.max(activity.inputAt, now());\n };\n\n const lane = Lane.make({\n now,\n actionTimeout: options.settings.actionTimeout,\n documentAt: () => activity.documentAt,\n gone: (operation) => undispatched(operation, new Closed({ cause: options.closedBy() })),\n scope,\n inputGate: options.inputGate,\n });\n\n // Where this page's latest move left its pointer, which is where its next plain glide starts and\n // where a held button is released. Its lane orders the page's input, and Chromium keeps a\n // pointer per page too.\n const pointer = MutableRef.make(Option.none<Point>());\n\n // Named, so that the declarations of what holds it need not spell out Playwright's protocol types.\n const protocol: Pick<CDPSession, \"send\"> = { send };\n\n return {\n ...options,\n lane,\n pointer,\n now,\n owned,\n span,\n protocol,\n native,\n within,\n stopLoading,\n activity,\n noteInput,\n };\n};\n\nexport type PageContext = ReturnType<typeof make>;\n"],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { n as BrowserError_d_exports } from "./BrowserError-Coy7EW1N.mjs";
|
|
2
|
-
import { a as BrowserEvent_d_exports } from "./BrowserEvent-
|
|
3
|
-
import { n as Change_d_exports } from "./Change-
|
|
2
|
+
import { a as BrowserEvent_d_exports } from "./BrowserEvent-dq6FRT8w.mjs";
|
|
3
|
+
import { n as Change_d_exports } from "./Change-DqING3tr.mjs";
|
|
4
4
|
import { i as Frame_d_exports } from "./Frame-DkNdjjjr.mjs";
|
|
5
5
|
import { i as Snapshot_d_exports } from "./Snapshot-B34hZ4Jl.mjs";
|
|
6
|
-
import { N as Moment_d_exports, d as Page_d_exports } from "./Page-
|
|
6
|
+
import { N as Moment_d_exports, d as Page_d_exports } from "./Page-jHmSJeOS.mjs";
|
|
7
|
+
import { t as Motion_d_exports } from "./Motion-DND6I-64.mjs";
|
|
7
8
|
import { t as Browser_d_exports } from "./Browser.mjs";
|
|
8
9
|
import { t as Cdp_d_exports } from "./Cdp.mjs";
|
|
9
10
|
import { t as Chromium_d_exports } from "./Chromium.mjs";
|
|
10
11
|
import { t as Expect_d_exports } from "./Expect.mjs";
|
|
11
|
-
import {
|
|
12
|
-
import { r as Plan_d_exports } from "./Plan-6As6vcwT.mjs";
|
|
12
|
+
import { r as Plan_d_exports } from "./Plan-DLtRksuu.mjs";
|
|
13
13
|
import { t as Policy_d_exports } from "./Policy.mjs";
|
|
14
14
|
import { t as Presentation_d_exports } from "./Presentation.mjs";
|
|
15
15
|
import { t as Stage_d_exports } from "./Stage.mjs";
|
|
16
|
-
import { l as Supervisor_d_exports } from "./Supervisor-
|
|
16
|
+
import { l as Supervisor_d_exports } from "./Supervisor-mVPeEUp8.mjs";
|
|
17
17
|
export { Browser_d_exports as Browser, BrowserError_d_exports as BrowserError, BrowserEvent_d_exports as BrowserEvent, Cdp_d_exports as Cdp, Change_d_exports as Change, Chromium_d_exports as Chromium, Expect_d_exports as Expect, Frame_d_exports as Frame, Moment_d_exports as Moment, Motion_d_exports as Motion, Page_d_exports as Page, Plan_d_exports as Plan, Policy_d_exports as Policy, Presentation_d_exports as Presentation, Snapshot_d_exports as Snapshot, Stage_d_exports as Stage, Supervisor_d_exports as Supervisor };
|
package/dist/index.mjs
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { t as Motion_exports } from "./Motion.mjs";
|
|
2
2
|
import { t as BrowserEvent_exports } from "./BrowserEvent.mjs";
|
|
3
3
|
import { t as BrowserError_exports } from "./BrowserError.mjs";
|
|
4
|
-
import { n as Browser_exports } from "./Browser-
|
|
4
|
+
import { n as Browser_exports } from "./Browser-DRPthkNO.mjs";
|
|
5
5
|
import { t as Frame_exports } from "./Frame.mjs";
|
|
6
|
-
import { a as Page_exports } from "./Page-
|
|
6
|
+
import { a as Page_exports } from "./Page-C_VkBVwI.mjs";
|
|
7
7
|
import { t as Snapshot_exports } from "./Snapshot.mjs";
|
|
8
8
|
import { n as Change_exports } from "./Change-DNvztNLu.mjs";
|
|
9
9
|
import { t as Moment_exports } from "./Moment.mjs";
|
|
10
10
|
import { t as Cdp_exports } from "./Cdp.mjs";
|
|
11
11
|
import { t as Chromium_exports } from "./Chromium.mjs";
|
|
12
12
|
import { t as Expect_exports } from "./Expect.mjs";
|
|
13
|
-
import { r as Plan_exports } from "./Plan-
|
|
13
|
+
import { r as Plan_exports } from "./Plan-X-JkACAB.mjs";
|
|
14
14
|
import { t as Policy_exports } from "./Policy.mjs";
|
|
15
15
|
import { t as Presentation_exports } from "./Presentation.mjs";
|
|
16
16
|
import { t as Stage_exports } from "./Stage.mjs";
|
|
17
|
-
import { i as Supervisor_exports } from "./Supervisor-
|
|
17
|
+
import { i as Supervisor_exports } from "./Supervisor-BgWP8o9t.mjs";
|
|
18
18
|
export { Browser_exports as Browser, BrowserError_exports as BrowserError, BrowserEvent_exports as BrowserEvent, Cdp_exports as Cdp, Change_exports as Change, Chromium_exports as Chromium, Expect_exports as Expect, Frame_exports as Frame, Moment_exports as Moment, Motion_exports as Motion, Page_exports as Page, Plan_exports as Plan, Policy_exports as Policy, Presentation_exports as Presentation, Snapshot_exports as Snapshot, Stage_exports as Stage, Supervisor_exports as Supervisor };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"match.inpage-xOe9LNO0.mjs","names":[],"sources":["../src/internal/reading/match.inpage.ts"],"sourcesContent":["/**\n * In the page: the rules `find` matches by. It touches no DOM, so it also runs outside a page.\n *\n * - A role matches when it is the same token, ignoring case and the space around it.\n * - A name given as a string matches when the two read the same once their spaces are collapsed,\n * their case folded and their characters given one Unicode form; a pattern matches when it\n * finds itself in the name.\n * - Text matches when it appears, read the same way, in the element's text.\n * - `near` matches when its words appear, whole and in order, in any of the element's context:\n * its row, column, label or heading. Replay chooses among candidates by the same rule.\n */\nimport type { SubjectContext } from \"../../BrowserEvent.ts\";\n\n/** A string, or a pattern sent to the page as its source and flags. */\nexport type Wanted = string | { readonly source: string; readonly flags: string };\n\nexport interface FindRequest {\n readonly role: string | null;\n readonly name: Wanted | null;\n readonly text: Wanted | null;\n readonly near: string | null;\n readonly at:
|
|
1
|
+
{"version":3,"file":"match.inpage-xOe9LNO0.mjs","names":[],"sources":["../src/internal/reading/match.inpage.ts"],"sourcesContent":["/**\n * In the page: the rules `find` matches by. It touches no DOM, so it also runs outside a page.\n *\n * - A role matches when it is the same token, ignoring case and the space around it.\n * - A name given as a string matches when the two read the same once their spaces are collapsed,\n * their case folded and their characters given one Unicode form; a pattern matches when it\n * finds itself in the name.\n * - Text matches when it appears, read the same way, in the element's text.\n * - `near` matches when its words appear, whole and in order, in any of the element's context:\n * its row, column, label or heading. Replay chooses among candidates by the same rule.\n */\nimport type { SubjectContext } from \"../../BrowserEvent.ts\";\nimport type { Point } from \"../../Motion.ts\";\n\n/** A string, or a pattern sent to the page as its source and flags. */\nexport type Wanted = string | { readonly source: string; readonly flags: string };\n\nexport interface FindRequest {\n readonly role: string | null;\n readonly name: Wanted | null;\n readonly text: Wanted | null;\n readonly near: string | null;\n readonly at: Point | null;\n readonly scope: \"viewport\" | \"document\";\n readonly firstRef: number;\n}\n\n/** What a query is matched against, read only when a rule needs it. */\nexport interface Candidate {\n readonly role: string | null;\n readonly name: () => string;\n readonly text: () => string;\n readonly context: () => SubjectContext;\n}\n\nexport const match = () => {\n /**\n * How names, text and context compare: one Unicode form, without invisible format characters,\n * spaces collapsed, and case folded upper first, so that \"ß\" and \"SS\" read the same.\n */\n const normalize = (value: string): string =>\n value\n .normalize(\"NFKC\")\n .replace(/\\p{Cf}/gu, \"\")\n .replace(/\\s+/g, \" \")\n .trim()\n .toUpperCase()\n .toLowerCase();\n\n /** A string that reads the same, or, unless `whole`, appears within; or a pattern found within. */\n const rule = (wanted: Wanted, whole: boolean) => {\n if (typeof wanted !== \"string\") {\n // `g` and `y` keep a position from one test to the next, so one pattern would answer\n // differently for each element. A pattern is tried on the text as the page shows it.\n const found = new RegExp(wanted.source, wanted.flags.replace(/[gy]/g, \"\"));\n\n return (value: string) => found.test(value.replace(/\\s+/g, \" \").trim());\n }\n const target = normalize(wanted);\n\n return whole\n ? (value: string) => normalize(value) === target\n : (value: string) => normalize(value).includes(target);\n };\n\n /** Whether a value's words appear, whole and in order, among a text's: \"BTC\" not in \"WBTC\". */\n const holds = (text: string, value: string) =>\n ` ${normalize(text)} `.includes(` ${normalize(value)} `);\n\n /** Whether a candidate meets every rule a query gives; a rule left out always holds. */\n const compile = (request: Pick<FindRequest, \"role\" | \"name\" | \"text\" | \"near\">) => {\n const role = request.role === null ? null : normalize(request.role);\n const name = request.name === null ? null : rule(request.name, true);\n const text = request.text === null ? null : rule(request.text, false);\n const { near } = request;\n\n return (candidate: Candidate): boolean => {\n if (role !== null && normalize(candidate.role ?? \"\") !== role) return false;\n if (text !== null && !text(candidate.text())) return false;\n if (name !== null && !name(candidate.name())) return false;\n if (near === null) return true;\n const { row, column, label, heading } = candidate.context();\n\n return [row, column, label, heading].some(\n (value) => value !== undefined && holds(value, near),\n );\n };\n };\n\n return { compile, holds, normalize };\n};\n\nexport type Match = ReturnType<typeof match>;\n"],"mappings":";AAmCA,MAAa,cAAc;;;;;CAKzB,MAAM,aAAa,UACjB,MACG,UAAU,MAAM,CAAC,CACjB,QAAQ,YAAY,EAAE,CAAC,CACvB,QAAQ,QAAQ,GAAG,CAAC,CACpB,KAAK,CAAC,CACN,YAAY,CAAC,CACb,YAAY;;CAGjB,MAAM,QAAQ,QAAgB,UAAmB;EAC/C,IAAI,OAAO,WAAW,UAAU;GAG9B,MAAM,QAAQ,IAAI,OAAO,OAAO,QAAQ,OAAO,MAAM,QAAQ,SAAS,EAAE,CAAC;GAEzE,QAAQ,UAAkB,MAAM,KAAK,MAAM,QAAQ,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC;EACxE;EACA,MAAM,SAAS,UAAU,MAAM;EAE/B,OAAO,SACF,UAAkB,UAAU,KAAK,MAAM,UACvC,UAAkB,UAAU,KAAK,CAAC,CAAC,SAAS,MAAM;CACzD;;CAGA,MAAM,SAAS,MAAc,UAC3B,IAAI,UAAU,IAAI,EAAE,GAAG,SAAS,IAAI,UAAU,KAAK,EAAE,EAAE;;CAGzD,MAAM,WAAW,YAAkE;EACjF,MAAM,OAAO,QAAQ,SAAS,OAAO,OAAO,UAAU,QAAQ,IAAI;EAClE,MAAM,OAAO,QAAQ,SAAS,OAAO,OAAO,KAAK,QAAQ,MAAM,IAAI;EACnE,MAAM,OAAO,QAAQ,SAAS,OAAO,OAAO,KAAK,QAAQ,MAAM,KAAK;EACpE,MAAM,EAAE,SAAS;EAEjB,QAAQ,cAAkC;GACxC,IAAI,SAAS,QAAQ,UAAU,UAAU,QAAQ,EAAE,MAAM,MAAM,OAAO;GACtE,IAAI,SAAS,QAAQ,CAAC,KAAK,UAAU,KAAK,CAAC,GAAG,OAAO;GACrD,IAAI,SAAS,QAAQ,CAAC,KAAK,UAAU,KAAK,CAAC,GAAG,OAAO;GACrD,IAAI,SAAS,MAAM,OAAO;GAC1B,MAAM,EAAE,KAAK,QAAQ,OAAO,YAAY,UAAU,QAAQ;GAE1D,OAAO;IAAC;IAAK;IAAQ;IAAO;GAAO,CAAC,CAAC,MAClC,UAAU,UAAU,KAAA,KAAa,MAAM,OAAO,IAAI,CACrD;EACF;CACF;CAEA,OAAO;EAAE;EAAS;EAAO;CAAU;AACrC"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Plan } from "./Motion.mjs";
|
|
1
|
+
import { Plan, Point } from "./Motion.mjs";
|
|
2
2
|
import { Action, Box, CursorChanged, KeyChanged, Navigated, PageLoaded, PointerPressed, PointerReleased, Subject, SubjectContext, TextInserted, TrackEvent, TrackPerformed, TrackPlanned, WheelScrolled } from "./BrowserEvent.mjs";
|
|
3
3
|
import { BrowserError, Failed, InvalidRequest, NavigationFailed, NotActionable, NotFound, PolicyTimeout, StaleRef, Timeout } from "./BrowserError.mjs";
|
|
4
|
-
import { a as make$20, c as
|
|
4
|
+
import { a as make$20, c as estimate, d as toBrowserSeconds, f as toHostTime, h as make$19, i as failWith, m as Current, n as contextGone, o as reasonOf, p as uncertaintyAt, r as decodeWith, s as undispatched, u as monotonicMillis } from "./context-rYTk-3Cv.mjs";
|
|
5
5
|
import { i as redact, n as parse, s as Correlation, t as addresses } from "./url-Cd04Okid.mjs";
|
|
6
6
|
import { BrowserPaint, CaptureStats, Frame, Image, Screenshot } from "./Frame.mjs";
|
|
7
|
-
import { _ as evidence, c as State, g as guard, h as ValidatedInputResultSchema, i as InputRequest, l as Text, m as PreparedInputResultSchema, o as Region, p as redacted, r as Found, s as ResolvedTarget, u as Zoom } from "./Page-
|
|
7
|
+
import { _ as evidence, c as State, g as guard, h as ValidatedInputResultSchema, i as InputRequest, l as Text, m as PreparedInputResultSchema, o as Region, p as redacted, r as Found, s as ResolvedTarget, u as Zoom } from "./Page-C_VkBVwI.mjs";
|
|
8
8
|
import { Snapshot } from "./Snapshot.mjs";
|
|
9
9
|
import { t as match } from "./match.inpage-xOe9LNO0.mjs";
|
|
10
10
|
import { r as Changes, t as Change } from "./Change-DNvztNLu.mjs";
|
|
@@ -333,8 +333,7 @@ const targets = (names, walked, placing) => {
|
|
|
333
333
|
};
|
|
334
334
|
};
|
|
335
335
|
const ResolvedPointSchema = Schema.Struct({
|
|
336
|
-
|
|
337
|
-
y: Schema.Finite,
|
|
336
|
+
...Point.fields,
|
|
338
337
|
element: Schema.String,
|
|
339
338
|
tag: Schema.String,
|
|
340
339
|
role: Schema.NullOr(Schema.String),
|
|
@@ -356,8 +355,7 @@ const PointResultSchema = Schema.Union([ResolvedPointSchema, Schema.Struct({
|
|
|
356
355
|
detail: Schema.String
|
|
357
356
|
})]);
|
|
358
357
|
const ScrollPlanSchema = Schema.NullOr(Schema.Struct({
|
|
359
|
-
|
|
360
|
-
y: Schema.Finite,
|
|
358
|
+
...Point.fields,
|
|
361
359
|
dx: Schema.Finite,
|
|
362
360
|
dy: Schema.Finite
|
|
363
361
|
}));
|
|
@@ -464,6 +462,11 @@ const context = (names, walked) => {
|
|
|
464
462
|
};
|
|
465
463
|
//#endregion
|
|
466
464
|
//#region src/internal/reading/controls.inpage.ts
|
|
465
|
+
/**
|
|
466
|
+
* In the page: a control's states and value as the outline shows them, and as a value; the elements a CSS selector scopes a
|
|
467
|
+
* read to; and a condition `Page.waitFor` waits for. See `names.inpage.ts` for what a page-side part
|
|
468
|
+
* may use.
|
|
469
|
+
*/
|
|
467
470
|
const controls = (names, walked, subjects, texts) => {
|
|
468
471
|
const { clean, isDisabled, isHtml, isInput, isSelect, isTextArea, refFor, textOf } = names;
|
|
469
472
|
const { visible } = walked;
|
|
@@ -553,6 +556,7 @@ const controls = (names, walked, subjects, texts) => {
|
|
|
553
556
|
waitUntil
|
|
554
557
|
};
|
|
555
558
|
};
|
|
559
|
+
const ConditionResultSchema = Schema.Union([Schema.Struct({ met: Schema.Boolean }), Schema.Struct({ invalid: Schema.String })]);
|
|
556
560
|
//#endregion
|
|
557
561
|
//#region src/internal/reading/expect.inpage.ts
|
|
558
562
|
const expectations = (names, subjected) => {
|
|
@@ -942,6 +946,10 @@ const outline = (names, walked, subjects, texts, controlling, url) => {
|
|
|
942
946
|
viewport
|
|
943
947
|
};
|
|
944
948
|
};
|
|
949
|
+
const SnapshotResultSchema = Schema.Union([Schema.Struct({
|
|
950
|
+
snapshot: Snapshot,
|
|
951
|
+
nextRef: Schema.Finite
|
|
952
|
+
}), Schema.Struct({ invalid: Schema.String })]);
|
|
945
953
|
const ViewportResultSchema = Schema.Struct({
|
|
946
954
|
width: Schema.Finite,
|
|
947
955
|
height: Schema.Finite
|
|
@@ -2284,68 +2292,6 @@ const make$18 = Effect.fnUntraced(function* (page) {
|
|
|
2284
2292
|
};
|
|
2285
2293
|
});
|
|
2286
2294
|
//#endregion
|
|
2287
|
-
//#region src/internal/pictures/clock.ts
|
|
2288
|
-
/**
|
|
2289
|
-
* The browser's clock read on the owner's: estimates of their offset from timed probes, how an
|
|
2290
|
-
* estimate ages, and the one mapping a browser's pages share. `pictures.ts` takes the probes.
|
|
2291
|
-
*/
|
|
2292
|
-
/** The fastest complete probe limits uncertainty without mistaking transit delay for clock offset. */
|
|
2293
|
-
const estimate = (probes) => {
|
|
2294
|
-
let best;
|
|
2295
|
-
for (const probe of probes) {
|
|
2296
|
-
const roundTripMillis = probe.hostEnd - probe.hostStart;
|
|
2297
|
-
if (!Number.isFinite(probe.hostStart) || !Number.isFinite(probe.hostEnd) || !Number.isFinite(probe.browserTime) || !Number.isFinite(roundTripMillis) || roundTripMillis < 0) continue;
|
|
2298
|
-
const sampledAt = probe.hostStart + roundTripMillis / 2;
|
|
2299
|
-
const offsetMillis = probe.browserTime - sampledAt;
|
|
2300
|
-
if (!Number.isFinite(offsetMillis) || !Number.isFinite(probe.browserTime - probe.hostStart) || !Number.isFinite(probe.browserTime - probe.hostEnd)) continue;
|
|
2301
|
-
if (best === void 0 || roundTripMillis < best.roundTripMillis) best = {
|
|
2302
|
-
offsetMillis,
|
|
2303
|
-
uncertaintyMillis: roundTripMillis / 2,
|
|
2304
|
-
roundTripMillis,
|
|
2305
|
-
sampledAt
|
|
2306
|
-
};
|
|
2307
|
-
}
|
|
2308
|
-
return Option.fromUndefinedOr(best);
|
|
2309
|
-
};
|
|
2310
|
-
const driftPerMillis = 1e-4;
|
|
2311
|
-
/** An estimate's uncertainty at `hostTime`, wider the further that is from when it was sampled. */
|
|
2312
|
-
const uncertaintyAt = (estimate, hostTime) => estimate.uncertaintyMillis + Math.abs(hostTime - estimate.sampledAt) * driftPerMillis;
|
|
2313
|
-
const renewAfter = Duration.seconds(10);
|
|
2314
|
-
/**
|
|
2315
|
-
* Whether a new measurement should replace the current estimate. Each interval contains the true
|
|
2316
|
-
* offset, so overlapping intervals agree and the narrower one is kept, the current one widened by
|
|
2317
|
-
* its age: a probe delayed behind a busy page cannot widen every tab's stamps. A disjoint
|
|
2318
|
-
* measurement means the clocks moved (a wall clock step, or drift between a remote browser and
|
|
2319
|
-
* this host), so the newer evidence wins.
|
|
2320
|
-
*/
|
|
2321
|
-
const supersedes = (next, current) => {
|
|
2322
|
-
const aged = uncertaintyAt(current, next.sampledAt);
|
|
2323
|
-
return next.uncertaintyMillis <= aged || Math.abs(next.offsetMillis - current.offsetMillis) > next.uncertaintyMillis + aged;
|
|
2324
|
-
};
|
|
2325
|
-
/**
|
|
2326
|
-
* Every renderer of a browser reads the same host wall clock, so the offset belongs to the
|
|
2327
|
-
* browser rather than a page. A busy page cannot fail work that an earlier estimate can serve.
|
|
2328
|
-
*/
|
|
2329
|
-
const mapping = (now) => {
|
|
2330
|
-
let latest;
|
|
2331
|
-
let measuredAt = Number.NEGATIVE_INFINITY;
|
|
2332
|
-
const adopt = (measure) => {
|
|
2333
|
-
measuredAt = now();
|
|
2334
|
-
return measure.pipe(Effect.map((estimate) => {
|
|
2335
|
-
if (latest === void 0 || supersedes(estimate, latest)) latest = estimate;
|
|
2336
|
-
return latest;
|
|
2337
|
-
}));
|
|
2338
|
-
};
|
|
2339
|
-
return {
|
|
2340
|
-
latest: () => latest,
|
|
2341
|
-
current: (measure) => Effect.suspend(() => latest === void 0 ? adopt(measure) : Effect.succeed(latest)),
|
|
2342
|
-
renew: (measure) => Effect.suspend(() => latest === void 0 || now() - measuredAt < Duration.toMillis(renewAfter) ? Effect.void : Effect.ignore(adopt(measure)))
|
|
2343
|
-
};
|
|
2344
|
-
};
|
|
2345
|
-
const toHostTime = (calibration, browserEpochMillis) => browserEpochMillis - calibration.offsetMillis;
|
|
2346
|
-
/** CDP input timestamps use seconds, unlike browser frame timestamps and the owner's clock. */
|
|
2347
|
-
const toBrowserSeconds = (calibration, hostMillis) => (hostMillis + calibration.offsetMillis) / 1e3;
|
|
2348
|
-
//#endregion
|
|
2349
2295
|
//#region src/internal/input/dispatch.ts
|
|
2350
2296
|
/**
|
|
2351
2297
|
* Sending input to the browser. Each mouse event, key and inserted text goes out on the page's
|
|
@@ -2453,6 +2399,8 @@ const make$17 = (page) => {
|
|
|
2453
2399
|
* policy decides on, binds an approval to the document and targets it saw, and runs the page
|
|
2454
2400
|
* script's changes in the approved document only.
|
|
2455
2401
|
*/
|
|
2402
|
+
/** Recheck an approval, after any pending input it must see; neither runs without a guard. */
|
|
2403
|
+
const check = (approval, options = {}, before = Effect.void) => approval === void 0 ? Effect.void : before.pipe(Effect.andThen(approval.check(options)));
|
|
2456
2404
|
const inputFailure = (operation, targets, failure) => {
|
|
2457
2405
|
const target = failure.index === void 0 ? void 0 : targets[failure.index];
|
|
2458
2406
|
return failWith(operation, failure.error === "outside" ? new InvalidRequest({ detail: failure.detail }) : failure.error === "stale" && typeof target === "string" ? new StaleRef({ ref: target }) : new NotActionable({ detail: failure.detail }));
|
|
@@ -2511,9 +2459,12 @@ const make$16 = (page, bridge) => {
|
|
|
2511
2459
|
};
|
|
2512
2460
|
});
|
|
2513
2461
|
const mutate = (operation, call, approval, mayHaveRun = Effect.void) => (approval === void 0 ? current(operation) : Effect.succeed(approval.contextId)).pipe(Effect.flatMap((contextId) => evaluateIn(operation, call, contextId).pipe(Effect.onInterrupt(() => mayHaveRun), Effect.tapError((error) => error.reason._tag === "Failed" && /Cannot find context|__effectBrowser/i.test(error.reason.detail) ? Effect.void : mayHaveRun))), Effect.catchIf(contextGone, () => failWith(operation, new NotActionable({ detail: "the page changed before the approved input could run" }))));
|
|
2462
|
+
/** A read may follow the current document only when no approval binds it to one. */
|
|
2463
|
+
const evaluate = (operation, call, approval) => approval === void 0 ? bridge.evaluate(operation, call) : mutate(operation, call, approval);
|
|
2514
2464
|
return {
|
|
2515
2465
|
preparePolicy,
|
|
2516
|
-
mutate
|
|
2466
|
+
mutate,
|
|
2467
|
+
evaluate
|
|
2517
2468
|
};
|
|
2518
2469
|
};
|
|
2519
2470
|
//#endregion
|
|
@@ -3196,12 +3147,11 @@ const resolvedTarget = (result) => new ResolvedTarget({
|
|
|
3196
3147
|
cursor: result.cursor,
|
|
3197
3148
|
...result.href === void 0 ? {} : { href: result.href }
|
|
3198
3149
|
});
|
|
3199
|
-
const make$11 = (
|
|
3200
|
-
const { evaluate } =
|
|
3201
|
-
const { mutate } = guard;
|
|
3150
|
+
const make$11 = (viewport, guard, pointer, dispatch, settling) => {
|
|
3151
|
+
const { evaluate, mutate } = guard;
|
|
3202
3152
|
const { moveTo, wheel } = pointer;
|
|
3203
3153
|
const { flush } = dispatch;
|
|
3204
|
-
const readPoint = (operation, target, approval, scroll) =>
|
|
3154
|
+
const readPoint = (operation, target, approval, scroll) => evaluate(operation, scriptCall("point", target, scroll), approval).pipe(Effect.flatMap(decodeWith(operation, PointResultSchema)));
|
|
3205
3155
|
const resolve = (operation, target, approval, scroll = true) => {
|
|
3206
3156
|
if (typeof target === "string" && !/^e\d+$/.test(target)) return failWith(operation, new InvalidRequest({ detail: target + " is not a ref; refs look like e12" }));
|
|
3207
3157
|
if (typeof target !== "string" && (!Number.isFinite(target.x) || !Number.isFinite(target.y))) return failWith(operation, new InvalidRequest({ detail: "point coordinates must be finite" }));
|
|
@@ -3228,13 +3178,13 @@ const make$11 = (bridge, viewport, guard, pointer, dispatch, settling) => {
|
|
|
3228
3178
|
yield* wheel(operation, marks, point, Math.max(-size.width * .9, Math.min(size.width * .9, plan.dx)), Math.max(-size.height * .9, Math.min(size.height * .9, plan.dy)));
|
|
3229
3179
|
yield* flush(operation, marks.input);
|
|
3230
3180
|
yield* settling.settle(operation, before);
|
|
3231
|
-
|
|
3181
|
+
yield* check(approval);
|
|
3232
3182
|
}
|
|
3233
3183
|
yield* marks.touched;
|
|
3234
3184
|
const before = settling.mark();
|
|
3235
3185
|
yield* resolve(operation, target, approval);
|
|
3236
3186
|
yield* settling.settle(operation, before);
|
|
3237
|
-
|
|
3187
|
+
yield* check(approval);
|
|
3238
3188
|
return yield* resolve(operation, target, approval, false);
|
|
3239
3189
|
})
|
|
3240
3190
|
};
|
|
@@ -3260,12 +3210,11 @@ const partsOf = (page, bridge, viewport) => {
|
|
|
3260
3210
|
const settling = make$12(page, bridge);
|
|
3261
3211
|
return {
|
|
3262
3212
|
page,
|
|
3263
|
-
bridge,
|
|
3264
3213
|
...settling,
|
|
3265
3214
|
viewportFor: viewport.viewportFor,
|
|
3266
3215
|
perform: make$14(page, dispatch),
|
|
3267
3216
|
...guard,
|
|
3268
|
-
...make$11(
|
|
3217
|
+
...make$11(viewport, guard, pointer, dispatch, settling),
|
|
3269
3218
|
...pointer,
|
|
3270
3219
|
...make$15(page, bridge, dispatch),
|
|
3271
3220
|
sendMouse: dispatch.sendMouse,
|
|
@@ -3303,20 +3252,17 @@ const click = (input) => {
|
|
|
3303
3252
|
yield* marks.at(point);
|
|
3304
3253
|
yield* marks.on(resolved);
|
|
3305
3254
|
yield* moveTo("click", marks, point, resolved.cursor);
|
|
3306
|
-
|
|
3255
|
+
yield* check(approval, { presses: [{
|
|
3307
3256
|
index: 0,
|
|
3308
3257
|
...point
|
|
3309
3258
|
}] });
|
|
3310
3259
|
const before = mark();
|
|
3311
3260
|
yield* marks.sent;
|
|
3312
3261
|
for (let index = 1; index <= count; index++) {
|
|
3313
|
-
if (
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
...point
|
|
3318
|
-
}] }).pipe(Effect.catchIf((error) => error.reason._tag === "StaleRef", () => failWith("click", new NotActionable({ detail: "an earlier click removed the approved target, so no further press was sent" }))));
|
|
3319
|
-
}
|
|
3262
|
+
if (index > 1) yield* check(approval, { presses: [{
|
|
3263
|
+
index: 0,
|
|
3264
|
+
...point
|
|
3265
|
+
}] }, flush("click", marks.input)).pipe(Effect.catchIf((error) => error.reason._tag === "StaleRef", () => failWith("click", new NotActionable({ detail: "an earlier click removed the approved target, so no further press was sent" }))));
|
|
3320
3266
|
yield* sendMouse("click", marks.input, {
|
|
3321
3267
|
type: "mousePressed",
|
|
3322
3268
|
...point,
|
|
@@ -3375,7 +3321,7 @@ const drag = (input) => {
|
|
|
3375
3321
|
yield* marks.at(end.point);
|
|
3376
3322
|
yield* marks.on(start, end);
|
|
3377
3323
|
yield* moveTo("drag", marks, start.point, start.cursor);
|
|
3378
|
-
|
|
3324
|
+
yield* check(approval, { presses: [{
|
|
3379
3325
|
index: 0,
|
|
3380
3326
|
...start.point
|
|
3381
3327
|
}, {
|
|
@@ -3403,7 +3349,7 @@ const drag = (input) => {
|
|
|
3403
3349
|
};
|
|
3404
3350
|
const typeText = (input) => {
|
|
3405
3351
|
const { settings, now } = input.page;
|
|
3406
|
-
const { perform, preparePolicy, mutate, targetFor, moveTo, sendMouse, flush,
|
|
3352
|
+
const { perform, preparePolicy, mutate, targetFor, moveTo, sendMouse, flush, evaluate } = input;
|
|
3407
3353
|
const { currentDocument, sameDocument, keyStroke, typeEvent, mark, settle } = input;
|
|
3408
3354
|
return (text, typeOptions = {}, style = plain) => perform("type", {
|
|
3409
3355
|
target: typeOptions.into,
|
|
@@ -3421,7 +3367,7 @@ const typeText = (input) => {
|
|
|
3421
3367
|
const into = typeOptions.into;
|
|
3422
3368
|
if (into !== void 0 && !/^e\d+$/.test(into)) return yield* failWith("type", new InvalidRequest({ detail: `"${into}" is not a ref; refs look like e12` }));
|
|
3423
3369
|
const asked = scriptCall("typeable", into ?? null, typeOptions.secret === true);
|
|
3424
|
-
const typeable = yield*
|
|
3370
|
+
const typeable = yield* evaluate("type", asked, approval).pipe(Effect.flatMap(decodeWith("type", TypeableResultSchema)));
|
|
3425
3371
|
if ("error" in typeable) return yield* failWith("type", typeable.error === "stale" && into !== void 0 ? new StaleRef({ ref: into }) : new NotActionable({ detail: typeable.detail }));
|
|
3426
3372
|
if (typeable.subject !== void 0) yield* marks.on(typeable.subject);
|
|
3427
3373
|
const since = yield* currentDocument("type");
|
|
@@ -3432,7 +3378,7 @@ const typeText = (input) => {
|
|
|
3432
3378
|
yield* marks.on(target);
|
|
3433
3379
|
if (marks.style.shown) {
|
|
3434
3380
|
yield* moveTo("type", marks, target.point, target.cursor);
|
|
3435
|
-
|
|
3381
|
+
yield* check(approval, { presses: [{
|
|
3436
3382
|
index: 0,
|
|
3437
3383
|
...target.point
|
|
3438
3384
|
}] });
|
|
@@ -3452,9 +3398,9 @@ const typeText = (input) => {
|
|
|
3452
3398
|
secret ||= focused.secret;
|
|
3453
3399
|
}
|
|
3454
3400
|
if (!secret) yield* marks.reveal;
|
|
3455
|
-
|
|
3401
|
+
yield* check(approval, { focused: true });
|
|
3456
3402
|
yield* marks.sent;
|
|
3457
|
-
const focusHeld = approval
|
|
3403
|
+
const focusHeld = check(approval, { focused: true }, flush("type", marks.input));
|
|
3458
3404
|
if (text === "" && replace && into !== void 0) {
|
|
3459
3405
|
yield* sameDocument("type", since);
|
|
3460
3406
|
yield* keyStroke("type", marks.input, ["Delete"]);
|
|
@@ -3475,7 +3421,7 @@ const typeText = (input) => {
|
|
|
3475
3421
|
}
|
|
3476
3422
|
yield* flush("type", marks.input);
|
|
3477
3423
|
if (typeOptions.submit === true) {
|
|
3478
|
-
|
|
3424
|
+
yield* check(approval, { focused: true });
|
|
3479
3425
|
yield* sameDocument("type", since);
|
|
3480
3426
|
const before = mark();
|
|
3481
3427
|
yield* keyStroke("type", marks.input, ["Enter"]);
|
|
@@ -3508,16 +3454,13 @@ const press = (input) => {
|
|
|
3508
3454
|
yield* marks.on(yield* targetFor("press", on, approval, marks));
|
|
3509
3455
|
const focused = yield* mutate("press", scriptCall("focusOn", on), approval).pipe(Effect.flatMap(decodeWith("press", EditResultSchema)));
|
|
3510
3456
|
if ("error" in focused) return yield* editFailure("press", on, focused);
|
|
3511
|
-
|
|
3457
|
+
yield* check(approval, { focused: true });
|
|
3512
3458
|
}
|
|
3513
3459
|
const before = mark();
|
|
3514
3460
|
let due = now();
|
|
3515
3461
|
yield* marks.sent;
|
|
3516
3462
|
for (let index = 0; index < times; index++) {
|
|
3517
|
-
if (index > 0 && approval
|
|
3518
|
-
yield* flush("press", marks.input);
|
|
3519
|
-
yield* approval.check({ focused: true });
|
|
3520
|
-
}
|
|
3463
|
+
if (index > 0 && activates) yield* check(approval, { focused: true }, flush("press", marks.input));
|
|
3521
3464
|
yield* sameDocument("press", since);
|
|
3522
3465
|
yield* keyStroke("press", marks.input, parts, hold);
|
|
3523
3466
|
if (index + 1 < times) {
|
|
@@ -3765,7 +3708,7 @@ const timed = (options, native, timestamp, generation) => {
|
|
|
3765
3708
|
hostTime,
|
|
3766
3709
|
uncertaintyMillis: uncertaintyAt(estimate, hostTime)
|
|
3767
3710
|
}),
|
|
3768
|
-
receivedAt:
|
|
3711
|
+
receivedAt: monotonicMillis(options.clock),
|
|
3769
3712
|
width: size.width,
|
|
3770
3713
|
height: size.height,
|
|
3771
3714
|
...generation.transport.frameTag()
|
|
@@ -3811,7 +3754,7 @@ const sizeFilter = (options, deliver, drop) => Effect.gen(function* () {
|
|
|
3811
3754
|
run = void 0;
|
|
3812
3755
|
Queue.offerUnsafe(wake, void 0);
|
|
3813
3756
|
};
|
|
3814
|
-
const now = () =>
|
|
3757
|
+
const now = () => monotonicMillis(options.clock);
|
|
3815
3758
|
const adopt = (adopted) => {
|
|
3816
3759
|
run = void 0;
|
|
3817
3760
|
expected = adopted.device;
|
|
@@ -3954,7 +3897,7 @@ const make$8 = (options) => Effect.gen(function* () {
|
|
|
3954
3897
|
let latest = Option.none();
|
|
3955
3898
|
let history = [];
|
|
3956
3899
|
const keepMillis = Duration.toMillis(options.frameHistory);
|
|
3957
|
-
const now = () =>
|
|
3900
|
+
const now = () => monotonicMillis(options.clock);
|
|
3958
3901
|
const counts = tally(now);
|
|
3959
3902
|
let delivered = 0;
|
|
3960
3903
|
const current = (frame) => isCurrent(frame, generation, latest);
|
|
@@ -4578,10 +4521,6 @@ const make$7 = Effect.fnUntraced(function* (page, bridge, viewport) {
|
|
|
4578
4521
|
* read takes its turn on the page and shares its work with identical reads, as `lane.ts`
|
|
4579
4522
|
* describes. The viewport's text as it was last read is kept, for `Page.state`.
|
|
4580
4523
|
*/
|
|
4581
|
-
const SnapshotResult = Schema.Union([Schema.Struct({
|
|
4582
|
-
snapshot: Snapshot,
|
|
4583
|
-
nextRef: Schema.Finite
|
|
4584
|
-
}), Schema.Struct({ invalid: Schema.String })]);
|
|
4585
4524
|
const FindResults = Schema.Struct({
|
|
4586
4525
|
found: Schema.Array(Found),
|
|
4587
4526
|
nextRef: Schema.Finite
|
|
@@ -4590,7 +4529,6 @@ const UntilResult = Schema.Struct({
|
|
|
4590
4529
|
met: Schema.Boolean,
|
|
4591
4530
|
mark: Schema.String
|
|
4592
4531
|
});
|
|
4593
|
-
const ConditionResult = Schema.Union([Schema.Struct({ met: Schema.Boolean }), Schema.Struct({ invalid: Schema.String })]);
|
|
4594
4532
|
const wanted = (value) => value === void 0 ? null : typeof value === "string" ? value : {
|
|
4595
4533
|
source: value.source,
|
|
4596
4534
|
flags: value.flags
|
|
@@ -4625,7 +4563,7 @@ const make$6 = Effect.fnUntraced(function* (page, bridge) {
|
|
|
4625
4563
|
...asked,
|
|
4626
4564
|
firstRef: yield* Ref.get(nextRef)
|
|
4627
4565
|
};
|
|
4628
|
-
const result = yield* evaluate("snapshot", scriptCall("snapshot", request)).pipe(Effect.flatMap(decodeWith("snapshot",
|
|
4566
|
+
const result = yield* evaluate("snapshot", scriptCall("snapshot", request)).pipe(Effect.flatMap(decodeWith("snapshot", SnapshotResultSchema)));
|
|
4629
4567
|
if ("invalid" in result) return yield* failWith("snapshot", new InvalidRequest({ detail: result.invalid }));
|
|
4630
4568
|
const { text, truncated, url } = result.snapshot;
|
|
4631
4569
|
yield* counted(result.nextRef);
|
|
@@ -4686,7 +4624,7 @@ const make$6 = Effect.fnUntraced(function* (page, bridge) {
|
|
|
4686
4624
|
};
|
|
4687
4625
|
const millis = Math.min(Duration.toMillis(timeout), Number.MAX_SAFE_INTEGER);
|
|
4688
4626
|
const unmet = () => failWith("waitFor", new Timeout({ millis }));
|
|
4689
|
-
const look = evaluate("waitFor", scriptCall("waitUntil", request, millis)).pipe(Effect.flatMap(decodeWith("waitFor",
|
|
4627
|
+
const look = evaluate("waitFor", scriptCall("waitUntil", request, millis)).pipe(Effect.flatMap(decodeWith("waitFor", ConditionResultSchema)), Effect.flatMap((result) => "invalid" in result ? failWith("waitFor", new InvalidRequest({ detail: result.invalid })) : result.met ? Effect.void : unmet()));
|
|
4690
4628
|
return lane.read("waitFor")(Effect.void).pipe(Effect.andThen(Effect.retry(look, { while: contextGone })), Effect.timeoutOrElse({
|
|
4691
4629
|
duration: timeout,
|
|
4692
4630
|
orElse: unmet
|
|
@@ -5099,6 +5037,6 @@ const make = Effect.fnUntraced(function* (options) {
|
|
|
5099
5037
|
return Object.assign(new Built(internals), assembled);
|
|
5100
5038
|
});
|
|
5101
5039
|
//#endregion
|
|
5102
|
-
export { performed as a, pause as i, make as n,
|
|
5040
|
+
export { performed as a, pause as i, make as n, viewOf as r, internalsOf as t };
|
|
5103
5041
|
|
|
5104
|
-
//# sourceMappingURL=page-
|
|
5042
|
+
//# sourceMappingURL=page-ClEMFnBG.mjs.map
|