From 02d884c9b9ee5811e74952e593d19ed1d8fcdb05 Mon Sep 17 00:00:00 2001 From: PJ Date: Mon, 1 Jun 2026 21:01:47 +0530 Subject: [PATCH] refactor(spec): extract samplerRng into shared sampler-rng module --- pkg/spec/src/actions.ts | 17 +++++------------ pkg/spec/src/pick.ts | 2 +- pkg/spec/src/sampler-rng.ts | 17 +++++++++++++++++ 3 files changed, 23 insertions(+), 13 deletions(-) create mode 100644 pkg/spec/src/sampler-rng.ts diff --git a/pkg/spec/src/actions.ts b/pkg/spec/src/actions.ts index 639e420..5e11445 100644 --- a/pkg/spec/src/actions.ts +++ b/pkg/spec/src/actions.ts @@ -4,7 +4,6 @@ // factory forwards to globalThis.__sanderling__ anymore: the same data tree // drives both the goja verifier and the V8 web runtime. -import type { Pcg } from "./pcg.ts"; import type { AccessibilityElement, Action, @@ -23,6 +22,9 @@ import type { WeightedEntry, } from "./types.ts"; import type { ActionDescriptor, BuiltinVerb, GeneratorNode } from "./action-tree.ts"; +import { getSamplerRng } from "./sampler-rng.ts"; + +export { setSamplerRng } from "./sampler-rng.ts"; function builtinNode(verb: BuiltinVerb): GeneratorNode { return { kind: "builtin", verb }; @@ -49,21 +51,12 @@ export function weighted(...entries: WeightedEntry[]): GeneratorNode { return { kind: "weighted", branches: entries }; } -// samplerRng is the picker's Pcg while it evaluates an `actions` node's -// generator (set by pick.ts walkActions). `from(...).generate()` draws from it -// so sampling shares the single deterministic stream. It is null outside a -// walk; eager spec-time generate() calls then fall back to the first item. -let samplerRng: Pcg | null = null; - -export function setSamplerRng(rng: Pcg | null): void { - samplerRng = rng; -} - export function from(items: readonly T[]): Sampler { return { generate(): T { if (items.length <= 1) return items[0] as T; - const index = samplerRng ? samplerRng.intN(items.length) : 0; + const rng = getSamplerRng(); + const index = rng ? rng.intN(items.length) : 0; return items[index] as T; }, }; diff --git a/pkg/spec/src/pick.ts b/pkg/spec/src/pick.ts index c11f1b3..97c7b4f 100644 --- a/pkg/spec/src/pick.ts +++ b/pkg/spec/src/pick.ts @@ -37,7 +37,7 @@ import type { } from "./action-tree.ts"; import type { Direction, Point } from "./types.ts"; import { INPUT_CORPUS, NATIVE_PRESS_KEYS, WEB_PRESS_KEYS } from "./corpus.ts"; -import { setSamplerRng } from "./actions.ts"; +import { setSamplerRng } from "./sampler-rng.ts"; import { supports, warnUnsupportedOnce } from "./verbs.ts"; // SWIPE_MIN_MAGNITUDE / SWIPE_MAGNITUDE_SPAN reproduce worker.go's diff --git a/pkg/spec/src/sampler-rng.ts b/pkg/spec/src/sampler-rng.ts new file mode 100644 index 0000000..0924dbe --- /dev/null +++ b/pkg/spec/src/sampler-rng.ts @@ -0,0 +1,17 @@ +// samplerRng is the picker's Pcg while it evaluates an `actions` node's +// generator (set by pick.ts walkActions). Author sampling, from(...).generate() +// and the values.ts generators, draws from it so every sample shares the single +// deterministic stream. It is null outside a walk; eager spec-time generate() +// calls then fall back to a fixed deterministic default. + +import type { Pcg } from "./pcg.ts"; + +let samplerRng: Pcg | null = null; + +export function setSamplerRng(rng: Pcg | null): void { + samplerRng = rng; +} + +export function getSamplerRng(): Pcg | null { + return samplerRng; +}