@simten/embed 0.1.6 → 0.1.7

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.
@@ -124,7 +124,7 @@ export function useCircuitSimulator(circuit, options) {
124
124
  const [cycle, setCycle] = useState(0);
125
125
  const [ready, setReady] = useState(false);
126
126
  const [isRunning, setIsRunning] = useState(false);
127
- const [speed, setSpeedState] = useState(5);
127
+ const [speed, setSpeedState] = useState(15);
128
128
  const autoRunRef = useRef(null);
129
129
  const historyRef = useRef([]);
130
130
  const [historyIndex, setHistoryIndex] = useState(-1);
@@ -1 +1 @@
1
- {"version":3,"file":"useCircuitSimulator.js","sourceRoot":"","sources":["../../src/hooks/useCircuitSimulator.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * useCircuitSimulator — the public circuit-simulation hook.\n *\n * Composes the sandbox bridge (`useSandbox` in @simten/ui) with circuit-level\n * concerns: auto-harness, time-travel history, auto-run, snapshot/restore.\n * This is what every embed/blog/editor consumer calls.\n *\n * Runtime topology (browser path):\n * useCircuitSimulator (here)\n * → useSandbox — packages/ui/src/sandbox/useSandbox.ts (postMessage bridge)\n * → apps/sandbox/main.ts — runs inside the cross-origin iframe\n * → core/simulator — pure simulator engine\n *\n * For non-browser callers (vitest, CI), skip this hook entirely and use\n * `@simten/core/sim` directly — no iframe, no React, just the engine.\n *\n * See: apps/web/content/docs/architecture.mdx → \"Runtime topology\".\n */\n\nimport { useState, useEffect, useCallback, useRef, useMemo } from \"react\";\nimport {\n type SimulatorEngine,\n type CircuitLibrary,\n type FlatPortValueMap,\n type FlatSequentialState,\n} from \"@simten/core/simulator\";\nimport type { Circuit, BitValue, BusValue } from \"@simten/core\";\nimport type { BuiltCircuit } from \"@simten/core/circuit\";\nimport { getCircuitEval, autoHarness, isSequentialCircuit } from \"@simten/core/circuit\";\nimport { Switch, Button, Led, Input, Output, HexDisplay } from \"@simten/core/std\";\nimport { useSandboxContext, type EvalSource } from \"@simten/ui/sandbox\";\n\nconst TOP_LEVEL_NODE = \"__top__\";\n\nexport interface SimulatorState {\n outputs: Record<string, boolean | number>;\n inputs: Record<string, boolean | number>;\n cycleCount: number;\n ready: boolean;\n error: string | null;\n isSequential: boolean;\n circuit: Circuit | null;\n portValues: FlatPortValueMap | null;\n sequentialState: FlatSequentialState | null;\n componentLibrary: CircuitLibrary | null;\n history: readonly { engineSnapshot: unknown; metadata?: unknown }[];\n historyIndex: number;\n isViewingPast: boolean;\n isRunning: boolean;\n speed: number;\n}\n\nexport interface SimulatorActions {\n setNode: (name: string, value: boolean | number) => void;\n toggleInput: (name: string) => void;\n toggleNode: (nodeId: string) => void;\n /**\n * Set a node's value. Returns the resulting port-value Map (so scan-style\n * callers can read debug outputs without waiting for a React re-render),\n * or null if the sandbox isn't ready / errored.\n */\n setNodeValue: (nodeId: string, value: number | boolean | Map<number, number>) => Promise<ReadonlyMap<string, boolean | number> | null>;\n tick: () => void;\n /** Advance N ticks in a single sandbox round-trip; one React update. */\n tickN: (n: number) => Promise<void>;\n /**\n * Combinationally scan a debug-address node across 0..count-1, sampling\n * a value port after each setting. Single round-trip; clock not advanced.\n * Returns the `number[]` of length `count`, or null on error.\n */\n scanPort: (addrNodeId: string, valuePortKey: string, count: number) => Promise<number[] | null>;\n reset: () => void;\n stepBack: () => void;\n stepForward: () => void;\n seek: (index: number) => void;\n startAutoRun: (ticksPerSecond: number, options?: { displayRate?: number; onBeforeTick?: () => void }) => void;\n stopAutoRun: () => void;\n setSpeed: (ticksPerSecond: number) => void;\n runCombinational: () => void;\n getSimulator: () => SimulatorEngine | null;\n}\n\nexport interface UseCircuitSimulatorOptions {\n /** Wrap the circuit with auto-generated Switch/Led nodes */\n autoHarness?: boolean;\n /** Initial values for input ports (only used when autoHarness is true) */\n initialInputs?: Record<string, number | boolean>;\n}\n\n/**\n * Extract eval function sources from a BuiltCircuit and its dependencies.\n * These are serialized and sent to the sandbox, which reconstructs them with new Function().\n * Returns empty object if the circuit's evals aren't registered in this frame\n * (e.g. editor case where evals live only in the sandbox from prior compile).\n */\nfunction extractEvalSources(circuit: BuiltCircuit): Record<string, EvalSource> {\n const sources: Record<string, EvalSource> = {};\n const visited = new Set<string>();\n\n function collect(c: BuiltCircuit) {\n const name = c.circuit.name;\n if (visited.has(name)) return;\n visited.add(name);\n\n const entry = getCircuitEval(name);\n if (entry) {\n sources[name] = {\n evalSource: entry.evalFn.toString(),\n onTickSource: entry.onTickFn?.toString(),\n inputNames: entry.inputNames,\n outputNames: entry.outputNames,\n stateKeys: entry.stateKeys,\n };\n }\n for (const [, dep] of c._dependencies) {\n if (dep) collect(dep);\n }\n }\n\n collect(circuit);\n return sources;\n}\n\n/**\n * Build a minimal BuiltCircuit-like object from a Circuit IR and its dependencies.\n * Used by the editor to adapt sandbox compile results into the shape useCircuitSimulator expects.\n * The resulting object has no live eval functions (empty registry lookups) — the sandbox\n * is expected to already have the evals registered from a prior sandbox.compile(source).\n */\nexport function builtFromIR(circuit: Circuit, dependencies: Circuit[]): BuiltCircuit {\n const depMap = new Map<string, BuiltCircuit>();\n for (const dep of dependencies) {\n depMap.set(dep.name, {\n circuit: dep,\n _dependencies: new Map(),\n } as unknown as BuiltCircuit);\n }\n return {\n circuit,\n _dependencies: depMap,\n } as unknown as BuiltCircuit;\n}\n\n/**\n * Circuit simulator hook — runs simulation in the sandbox iframe.\n *\n * Takes a BuiltCircuit and returns reactive simulation state + actions.\n * All simulation happens inside the sandbox for security (CSP-isolated,\n * cross-origin) — no user code runs in the main frame at simulation time.\n */\nexport function useCircuitSimulator(\n circuit: BuiltCircuit | null,\n options?: UseCircuitSimulatorOptions,\n): SimulatorState & SimulatorActions {\n const sandbox = useSandboxContext();\n const slotId = useMemo(() =>\n `embed-${typeof crypto !== 'undefined' && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2)}`,\n [],\n );\n\n // ── Build library + resolve circuit IR ──\n const { rawCircuit, componentLibrary } = useMemo(() => {\n const circuitMap = new Map<string, Circuit>();\n const lib: CircuitLibrary & { addCircuit(c: Circuit): void } = {\n resolveCircuit: (name) => circuitMap.get(name),\n getAllPrimitiveNames: () => [...circuitMap.entries()].filter(([, c]) => c.implementation.kind === 'primitive').map(([n]) => n),\n addCircuit: (c) => { circuitMap.set(c.name, c); },\n };\n for (const c of [Switch(), Button(), Led, Input(), Output, HexDisplay]) {\n lib.addCircuit(c.circuit);\n }\n if (circuit) {\n lib.addCircuit(circuit.circuit);\n if (circuit._dependencies) {\n for (const [, dep] of circuit._dependencies) {\n if (dep?.circuit) lib.addCircuit(dep.circuit);\n }\n }\n }\n return { rawCircuit: circuit?.circuit ?? null, componentLibrary: lib };\n }, [circuit]);\n\n // ── Auto-harness (wrap with Switches/LEDs if enabled) ──\n const harnessedCircuit = useMemo(() => {\n if (!rawCircuit) return null;\n if (!options?.autoHarness) return rawCircuit;\n return autoHarness(rawCircuit, componentLibrary, options.initialInputs);\n }, [rawCircuit, componentLibrary, options?.autoHarness, options?.initialInputs]);\n\n // ── Detect sequential (recursively) using shared core util ──\n const isSequential = useMemo(\n () => isSequentialCircuit(harnessedCircuit, componentLibrary.resolveCircuit),\n [harnessedCircuit, componentLibrary],\n );\n\n // ── Sandbox simulation state ──\n const [portValues, setPortValues] = useState<FlatPortValueMap>(new Map());\n // Peripheral-bus state exposed by the sandbox — only includes nodes on a\n // peripheral's bus (displays, consoles, etc.). Consumers read it through\n // the `sequentialState` shape below so rendering code doesn't need to know\n // it's narrower than a full FlatSequentialState.\n const [peripheralState, setPeripheralState] = useState<Record<string, unknown>>({});\n const [cycle, setCycle] = useState(0);\n const [ready, setReady] = useState(false);\n const [isRunning, setIsRunning] = useState(false);\n const [speed, setSpeedState] = useState(5);\n const autoRunRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n // ── Time-travel history ──\n // Each entry stores:\n // - snapshotId: opaque handle to a simulator snapshot held in the sandbox\n // - cycle: clock cycle at that snapshot (for the UI counter)\n // - inputs: user-visible input values at that moment. The simulator's\n // snapshot only covers *simulation* state (flip-flops, memory). User\n // inputs (switch positions, etc.) are \"environmental state\" that lives\n // in React — see packages/core/src/simulator/environmental-state.ts.\n // On rewind we restore both so the UI is fully consistent with the\n // cycle being viewed (not just the logic outputs).\n //\n // historyIndex points at the snapshot currently reflected in portValues.\n // At the \"head\" (live state) historyIndex === historyRef.current.length - 1.\n // When the user steps back, historyIndex moves left without shrinking history.\n // If they then make a state-mutating action (tick, setNode), we branch:\n // history is truncated at historyIndex + 1, orphaned sandbox snapshots leak\n // (GC'd by slot disposal or the next cap prune — acceptable for demo sizes).\n type HistoryEntry = {\n snapshotId: number;\n cycle: number;\n inputs: Record<string, boolean | number>;\n };\n const historyRef = useRef<HistoryEntry[]>([]);\n const [historyIndex, setHistoryIndex] = useState(-1);\n const [historyLen, setHistoryLen] = useState(0); // duplicate of historyRef.length for re-renders\n const HISTORY_CAP = 200;\n\n // Default inputs from the harnessed circuit's top-level inputs\n const defaultInputs = useMemo(() => {\n const result: Record<string, boolean | number> = {};\n if (!harnessedCircuit) return result;\n for (const input of harnessedCircuit.inputs) {\n result[input.name] = input.portType.kind === 'bit' ? false : 0;\n }\n return result;\n }, [harnessedCircuit]);\n\n const [outputs, setOutputs] = useState<Record<string, boolean | number>>({});\n const [inputs, setInputs] = useState<Record<string, boolean | number>>(defaultInputs);\n // Mirror of inputs in a ref so tick/tickN can snapshot the latest value\n // synchronously without waiting for setState → re-render.\n const inputsRef = useRef(inputs);\n useEffect(() => { inputsRef.current = inputs; }, [inputs]);\n\n // ── Compile to sandbox on mount / circuit change ──\n useEffect(() => {\n if (!circuit || !harnessedCircuit) {\n setReady(false);\n setPortValues(new Map());\n return;\n }\n\n let cancelled = false;\n\n async function initSandbox() {\n if (!circuit || !harnessedCircuit) return;\n // Extract eval sources from the BuiltCircuit and its dependencies\n const evalSources = extractEvalSources(circuit);\n\n // Collect all library circuits (stdlib + user).\n // The harnessed circuit references the raw circuit as \"dut\" by name, so we\n // need to include it + all its dependencies + harness components.\n const libCircuits: Circuit[] = [];\n const seen = new Set<string>();\n const addCircuit = (c: Circuit) => {\n if (seen.has(c.name)) return;\n seen.add(c.name);\n libCircuits.push(c);\n };\n\n // The raw circuit (referenced as \"dut\" by the harness)\n addCircuit(circuit.circuit);\n // Its transitive dependencies\n for (const [, dep] of circuit._dependencies) {\n if (dep?.circuit) addCircuit(dep.circuit);\n }\n // Harness components (Switch, Led, etc.)\n for (const c of [Switch(), Button(), Led, Input(), Output, HexDisplay]) {\n addCircuit(c.circuit);\n }\n // Anything else in the library\n const primNames = componentLibrary.getAllPrimitiveNames();\n for (const name of primNames) {\n const c = componentLibrary.resolveCircuit(name);\n if (c) addCircuit(c);\n }\n\n // Only bother snapshotting if the circuit is sequential — combinational\n // circuits don't have state worth rewinding to.\n const result = await sandbox.compileIR(harnessedCircuit, libCircuits, slotId, {\n evalSources,\n snapshot: isSequential,\n });\n if (cancelled) return;\n\n if ('error' in result) {\n console.error('[useCircuitSimulator] compileIR failed:', result.error);\n setReady(false);\n return;\n }\n\n const pvMap = new Map<string, BitValue | BusValue>();\n for (const [k, v] of Object.entries(result.portValues)) {\n pvMap.set(k, v);\n }\n setPortValues(pvMap);\n if (result.peripheralState) setPeripheralState(result.peripheralState);\n setCycle(0);\n\n // Seed history with the initial snapshot (if any). Fresh compile means\n // the previous history (if any) is invalid anyway — sandbox already\n // cleared its own snapshots on the recompile.\n historyRef.current = result.snapshotId !== undefined\n ? [{ snapshotId: result.snapshotId, cycle: 0, inputs: { ...defaultInputs } }]\n : [];\n setHistoryIndex(result.snapshotId !== undefined ? 0 : -1);\n setHistoryLen(historyRef.current.length);\n\n setReady(true);\n // isSequential is computed synchronously via useMemo above — no need to set async\n }\n\n initSandbox();\n\n return () => {\n cancelled = true;\n sandbox.dispose(slotId).catch(() => {});\n };\n }, [circuit, harnessedCircuit, componentLibrary, sandbox, slotId, isSequential]);\n\n // Sync inputs when underlying circuit changes\n useEffect(() => {\n setInputs(defaultInputs);\n }, [defaultInputs]);\n\n // Extract outputs from portValues\n useEffect(() => {\n if (!ready || portValues.size === 0 || !harnessedCircuit) return;\n const newOutputs: Record<string, boolean | number> = {};\n for (const output of harnessedCircuit.outputs) {\n const key = `${TOP_LEVEL_NODE}.${output.name}`;\n const value = portValues.get(key);\n if (value !== undefined) {\n newOutputs[output.name] = typeof value === 'number' ? value : Boolean(value);\n }\n }\n setOutputs(newOutputs);\n }, [ready, portValues, harnessedCircuit]);\n\n // ── History bookkeeping helper ──\n //\n // Called after any state-mutating sandbox operation that returns a snapshot.\n // Handles branch-on-past-edit (truncates future), enforces the 200-entry cap,\n // and updates React state so the UI re-renders with fresh ◀▶ counts.\n //\n // The `inputsSnapshot` is what the user-visible inputs (switches, buttons,\n // etc.) looked like at this moment — used on rewind so the UI restores not\n // just the simulator state but the user inputs too.\n const recordSnapshot = useCallback((\n snapshotId: number | undefined,\n newCycle: number,\n inputsSnapshot: Record<string, boolean | number>,\n ) => {\n if (snapshotId === undefined) return; // combinational circuit — nothing to record\n\n const hist = historyRef.current;\n const currentIdx = historyIndexRef.current;\n\n // If the user was viewing the past and just made a mutating action,\n // we branch: discard everything after their current position, then\n // append the new snapshot as the new head. The orphaned sandbox\n // snapshots leak until the next cap-prune or slot disposal.\n if (currentIdx >= 0 && currentIdx < hist.length - 1) {\n hist.length = currentIdx + 1;\n }\n\n hist.push({ snapshotId, cycle: newCycle, inputs: { ...inputsSnapshot } });\n\n // Cap at HISTORY_CAP: drop oldest entries and tell the sandbox to\n // free their snapshots. `keepAfterId` is the highest snapshotId we\n // DO NOT want to keep — anything <= that gets freed in the sandbox.\n if (hist.length > HISTORY_CAP) {\n const drop = hist.length - HISTORY_CAP;\n const keepAfterId = hist[drop - 1].snapshotId;\n hist.splice(0, drop);\n sandbox.pruneSnapshots(keepAfterId, slotId).catch(() => {});\n }\n\n historyIndexRef.current = hist.length - 1;\n setHistoryIndex(hist.length - 1);\n setHistoryLen(hist.length);\n }, [sandbox, slotId]);\n\n // Mirror historyIndex in a ref so the helper above can see its live value\n // without recompiling on every change (avoids rebuilding every callback).\n const historyIndexRef = useRef(-1);\n useEffect(() => { historyIndexRef.current = historyIndex; }, [historyIndex]);\n\n // ── Actions ──\n\n const setNode = useCallback(async (name: string, value: boolean | number) => {\n // Input changes (switch toggles, button presses) don't create a new\n // history entry — history tracks CYCLES (post-tick states), not every\n // input edit. The current cycle's \"inputs\" stay live: the next tick\n // will snapshot them as part of its history entry. If the user is\n // viewing the past when they toggle, the next tick branches from there.\n const newInputs = { ...inputsRef.current, [name]: value };\n inputsRef.current = newInputs;\n setInputs(newInputs);\n if (!ready) return;\n const result = await sandbox.setNode(name, value, slotId);\n if ('error' in result) return;\n const pvMap = new Map<string, BitValue | BusValue>();\n for (const [k, v] of Object.entries(result.portValues)) pvMap.set(k, v);\n setPortValues(pvMap);\n if (result.peripheralState) setPeripheralState(result.peripheralState);\n }, [ready, sandbox, slotId]);\n\n const toggleInput = useCallback((name: string) => {\n const current = inputs[name];\n const newValue = typeof current === 'boolean' ? !current : (current === 0 ? 1 : 0);\n setNode(name, newValue);\n }, [inputs, setNode]);\n\n const toggleNode = useCallback(async (nodeId: string) => {\n if (!ready) return;\n const outKey = `${nodeId}.out`;\n const current = portValues.get(outKey);\n const newValue = typeof current === 'boolean' ? !current : (current === 1 ? 0 : 1);\n // Same reasoning as setNode: no new history entry on input edit.\n const result = await sandbox.setNode(nodeId, newValue, slotId);\n if ('error' in result) return;\n const pvMap = new Map<string, BitValue | BusValue>();\n for (const [k, v] of Object.entries(result.portValues)) pvMap.set(k, v);\n setPortValues(pvMap);\n if (result.peripheralState) setPeripheralState(result.peripheralState);\n }, [ready, portValues, sandbox, slotId]);\n\n const setNodeValue = useCallback(async (nodeId: string, value: number | boolean | Map<number, number>) => {\n if (!ready) return null;\n // Map values (for ROM/RAM loading) are supported via structured clone in postMessage.\n // Same reasoning as setNode: no history entry on this path.\n const result = await sandbox.setNode(nodeId, value as any, slotId);\n if ('error' in result) return null;\n const pvMap = new Map<string, BitValue | BusValue>();\n for (const [k, v] of Object.entries(result.portValues)) pvMap.set(k, v);\n setPortValues(pvMap);\n if (result.peripheralState) setPeripheralState(result.peripheralState);\n return pvMap as ReadonlyMap<string, boolean | number>;\n }, [ready, sandbox, slotId]);\n\n const tick = useCallback(async () => {\n if (!ready) return;\n const result = await sandbox.tick(undefined, slotId, { snapshot: isSequential });\n if ('error' in result) return;\n const pvMap = new Map<string, BitValue | BusValue>();\n for (const [k, v] of Object.entries(result.portValues)) pvMap.set(k, v);\n setPortValues(pvMap);\n setCycle(result.cycle);\n if (result.peripheralState) setPeripheralState(result.peripheralState);\n // tick() doesn't modify user inputs — the switch position at tick time\n // is what goes into history.\n recordSnapshot(result.snapshotId, result.cycle, inputsRef.current);\n }, [ready, sandbox, slotId, isSequential, recordSnapshot]);\n\n // Batched tick — advances N cycles in one round-trip; one React update.\n // Only snapshots the final state (not every intermediate cycle) — time-travel\n // through a batched tick jumps straight to pre-batch.\n const tickN = useCallback(async (n: number) => {\n if (!ready || n <= 0) return;\n const result = await sandbox.tickN(n, undefined, slotId, { snapshot: isSequential });\n if ('error' in result) return;\n const pvMap = new Map<string, BitValue | BusValue>();\n for (const [k, v] of Object.entries(result.portValues)) pvMap.set(k, v);\n setPortValues(pvMap);\n setCycle(result.cycle);\n if (result.peripheralState) setPeripheralState(result.peripheralState);\n recordSnapshot(result.snapshotId, result.cycle, inputsRef.current);\n }, [ready, sandbox, slotId, isSequential, recordSnapshot]);\n\n const scanPort = useCallback(async (addrNodeId: string, valuePortKey: string, count: number): Promise<number[] | null> => {\n if (!ready || count <= 0) return null;\n const result = await sandbox.scanPort(addrNodeId, valuePortKey, count, slotId);\n if ('error' in result) return null;\n return result.values;\n }, [ready, sandbox, slotId]);\n\n const reset = useCallback(async () => {\n const result = await sandbox.reset(slotId);\n if ('error' in result) return;\n const pvMap = new Map<string, BitValue | BusValue>();\n for (const [k, v] of Object.entries(result.portValues)) pvMap.set(k, v);\n setPortValues(pvMap);\n setCycle(0);\n setInputs(defaultInputs);\n if (result.peripheralState) setPeripheralState(result.peripheralState);\n else setPeripheralState({});\n\n // Sandbox reset already cleared its own snapshots. Clear ours too,\n // then seed a fresh initial snapshot for the post-reset state so\n // time-travel starts over from here.\n historyRef.current = [];\n if (isSequential) {\n const snap = await sandbox.snapshot(slotId);\n if (!('error' in snap) && snap.snapshotId !== undefined) {\n historyRef.current = [{ snapshotId: snap.snapshotId, cycle: 0, inputs: { ...defaultInputs } }];\n }\n }\n historyIndexRef.current = historyRef.current.length > 0 ? 0 : -1;\n setHistoryIndex(historyRef.current.length > 0 ? 0 : -1);\n setHistoryLen(historyRef.current.length);\n }, [sandbox, slotId, defaultInputs, isSequential]);\n\n // ── Time-travel actions ──\n\n // Shared restore helper — applies a history entry to both the simulator\n // and the host-side input state. We restore inputs because the UI \"rewind\"\n // promise is a full restoration of user-visible state: switch positions,\n // input values, circuit state. Omitting inputs would leave the UI showing\n // a stale switch while the circuit actually runs with the restored value —\n // see environmental-state.ts in packages/core for the same distinction.\n const applyHistoryEntry = useCallback(async (entry: HistoryEntry, targetIndex: number) => {\n const result = await sandbox.restore(entry.snapshotId, slotId);\n if ('error' in result) return;\n const pvMap = new Map<string, BitValue | BusValue>();\n for (const [k, v] of Object.entries(result.portValues)) pvMap.set(k, v);\n setPortValues(pvMap);\n setCycle(result.cycle);\n if (result.peripheralState) setPeripheralState(result.peripheralState);\n else setPeripheralState({});\n // Restore user inputs too. Keep inputsRef in lockstep so that any\n // immediately-following setNode sees the restored values as its base.\n const restoredInputs = { ...entry.inputs };\n inputsRef.current = restoredInputs;\n setInputs(restoredInputs);\n historyIndexRef.current = targetIndex;\n setHistoryIndex(targetIndex);\n }, [sandbox, slotId]);\n\n const stepBack = useCallback(async () => {\n if (!ready) return;\n const hist = historyRef.current;\n const idx = historyIndexRef.current;\n if (idx <= 0) return; // already at or before the start\n await applyHistoryEntry(hist[idx - 1], idx - 1);\n }, [ready, applyHistoryEntry]);\n\n const stepForward = useCallback(async () => {\n if (!ready) return;\n const hist = historyRef.current;\n const idx = historyIndexRef.current;\n // Already at the live head — nothing to step into yet.\n // (Clicking ▶ at the head is a no-op, not a tick. Users run the clock\n // explicitly via Tick/autorun to add new history.)\n if (idx >= hist.length - 1) return;\n await applyHistoryEntry(hist[idx + 1], idx + 1);\n }, [ready, applyHistoryEntry]);\n\n const seek = useCallback(async (index: number) => {\n if (!ready) return;\n const hist = historyRef.current;\n if (index < 0 || index >= hist.length) return;\n await applyHistoryEntry(hist[index], index);\n }, [ready, applyHistoryEntry]);\n\n // Stable indirection so setInterval always calls the latest tick(). Without\n // this, an auto-run started before `ready` flips true would capture the\n // bail-early version of tick and never recover, even after the sandbox\n // becomes ready — the interval would fire forever calling a stale closure.\n const tickRef = useRef(tick);\n useEffect(() => { tickRef.current = tick; }, [tick]);\n\n const startAutoRun = useCallback((ticksPerSecond: number, _opts?: { displayRate?: number; onBeforeTick?: () => void }) => {\n if (autoRunRef.current) clearInterval(autoRunRef.current);\n setSpeedState(ticksPerSecond);\n setIsRunning(true);\n const interval = Math.max(1, Math.floor(1000 / ticksPerSecond));\n autoRunRef.current = setInterval(() => { tickRef.current(); }, interval);\n }, []);\n\n const stopAutoRun = useCallback(() => {\n if (autoRunRef.current) {\n clearInterval(autoRunRef.current);\n autoRunRef.current = null;\n }\n setIsRunning(false);\n }, []);\n\n const setSpeed = useCallback((ticksPerSecond: number) => {\n setSpeedState(ticksPerSecond);\n if (autoRunRef.current) {\n // Restart with new speed\n clearInterval(autoRunRef.current);\n const interval = Math.max(1, Math.floor(1000 / ticksPerSecond));\n autoRunRef.current = setInterval(() => { tickRef.current(); }, interval);\n }\n }, []);\n\n useEffect(() => {\n return () => {\n if (autoRunRef.current) clearInterval(autoRunRef.current);\n };\n }, []);\n\n // Expose peripheral-bus state as a FlatSequentialState-compatible shape so\n // projection code (which was written against in-process simulation) doesn't\n // need to learn about the sandbox boundary. Only nodes on a peripheral's\n // bus appear here — internal logic state stays sandbox-internal.\n const sequentialState = useMemo<FlatSequentialState | null>(() => {\n const entries = Object.entries(peripheralState);\n if (entries.length === 0) return null;\n const currentState = new Map<string, any>();\n for (const [k, v] of entries) currentState.set(k, v);\n return {\n currentState,\n nextState: new Map(),\n clocks: new Map(),\n cycleCount: cycle,\n };\n }, [peripheralState, cycle]);\n\n // Shadow-typed history for the UI: the consumer only needs a length for\n // showing the `N/M` counter and the ◀ ▶ enable logic. historyLen drives\n // re-renders; the array identity is intentionally stable per-slot.\n const historyForUi = useMemo(\n () => historyRef.current.slice(0, historyLen).map(h => ({ engineSnapshot: h.snapshotId, metadata: h.cycle })),\n [historyLen],\n );\n\n return {\n // State\n outputs,\n inputs,\n cycleCount: cycle,\n ready,\n error: null,\n isSequential,\n circuit: harnessedCircuit,\n portValues: portValues.size > 0 ? portValues : null,\n sequentialState,\n componentLibrary,\n history: historyForUi,\n historyIndex,\n isViewingPast: historyIndex >= 0 && historyIndex < historyLen - 1,\n isRunning,\n speed,\n\n // Actions\n setNode,\n toggleInput,\n toggleNode,\n setNodeValue,\n tick,\n tickN,\n scanPort,\n reset,\n stepBack,\n stepForward,\n seek,\n startAutoRun,\n stopAutoRun,\n setSpeed,\n runCombinational: () => {}, // sandbox.setNode already runs combinational\n getSimulator: () => null, // no local engine when running in sandbox\n };\n}\n"]}
1
+ {"version":3,"file":"useCircuitSimulator.js","sourceRoot":"","sources":["../../src/hooks/useCircuitSimulator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAS1E,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACxF,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAClF,OAAO,EAAE,iBAAiB,EAAmB,MAAM,oBAAoB,CAAC;AAExE,MAAM,cAAc,GAAG,SAAS,CAAC;AAyDjC;;;;;GAKG;AACH,SAAS,kBAAkB,CAAC,OAAqB;IAC/C,MAAM,OAAO,GAA+B,EAAE,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAElC,SAAS,OAAO,CAAC,CAAe;QAC9B,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;QAC5B,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO;QAC9B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAElB,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,IAAI,CAAC,GAAG;gBACd,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE;gBACnC,YAAY,EAAE,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE;gBACxC,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,SAAS,EAAE,KAAK,CAAC,SAAS;aAC3B,CAAC;QACJ,CAAC;QACD,KAAK,MAAM,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;YACtC,IAAI,GAAG;gBAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,OAAO,CAAC,OAAO,CAAC,CAAC;IACjB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,OAAgB,EAAE,YAAuB;IACnE,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC/C,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;QAC/B,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE;YACnB,OAAO,EAAE,GAAG;YACZ,aAAa,EAAE,IAAI,GAAG,EAAE;SACE,CAAC,CAAC;IAChC,CAAC;IACD,OAAO;QACL,OAAO;QACP,aAAa,EAAE,MAAM;KACK,CAAC;AAC/B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAA4B,EAC5B,OAAoC;IAEpC,MAAM,OAAO,GAAG,iBAAiB,EAAE,CAAC;IACpC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAC1B,SAAS,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EACzH,EAAE,CACH,CAAC;IAEF,2CAA2C;IAC3C,MAAM,EAAE,UAAU,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE;QACpD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAmB,CAAC;QAC9C,MAAM,GAAG,GAAsD;YAC7D,cAAc,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;YAC9C,oBAAoB,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;YAC9H,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;SAClD,CAAC;QACF,KAAK,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC;YACvE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC5B,CAAC;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAChC,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;gBAC1B,KAAK,MAAM,CAAC,EAAE,GAAG,CAAC,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;oBAC5C,IAAI,GAAG,EAAE,OAAO;wBAAE,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAChD,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC;IACzE,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,0DAA0D;IAC1D,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,EAAE;QACpC,IAAI,CAAC,UAAU;YAAE,OAAO,IAAI,CAAC;QAC7B,IAAI,CAAC,OAAO,EAAE,WAAW;YAAE,OAAO,UAAU,CAAC;QAC7C,OAAO,WAAW,CAAC,UAAU,EAAE,gBAAgB,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IAC1E,CAAC,EAAE,CAAC,UAAU,EAAE,gBAAgB,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC;IAEjF,+DAA+D;IAC/D,MAAM,YAAY,GAAG,OAAO,CAC1B,GAAG,EAAE,CAAC,mBAAmB,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,cAAc,CAAC,EAC5E,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CACrC,CAAC;IAEF,iCAAiC;IACjC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAmB,IAAI,GAAG,EAAE,CAAC,CAAC;IAC1E,yEAAyE;IACzE,yEAAyE;IACzE,2EAA2E;IAC3E,iDAAiD;IACjD,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CAA0B,EAAE,CAAC,CAAC;IACpF,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,CAAC,KAAK,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG,MAAM,CAAwC,IAAI,CAAC,CAAC;IAwBvE,MAAM,UAAU,GAAG,MAAM,CAAiB,EAAE,CAAC,CAAC;IAC9C,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,gDAAgD;IACjG,MAAM,WAAW,GAAG,GAAG,CAAC;IAExB,+DAA+D;IAC/D,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE;QACjC,MAAM,MAAM,GAAqC,EAAE,CAAC;QACpD,IAAI,CAAC,gBAAgB;YAAE,OAAO,MAAM,CAAC;QACrC,KAAK,MAAM,KAAK,IAAI,gBAAgB,CAAC,MAAM,EAAE,CAAC;YAC5C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAEvB,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAmC,EAAE,CAAC,CAAC;IAC7E,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAmC,aAAa,CAAC,CAAC;IACtF,wEAAwE;IACxE,0DAA0D;IAC1D,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAE3D,qDAAqD;IACrD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAClC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAChB,aAAa,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;YACzB,OAAO;QACT,CAAC;QAED,IAAI,SAAS,GAAG,KAAK,CAAC;QAEtB,KAAK,UAAU,WAAW;YACxB,IAAI,CAAC,OAAO,IAAI,CAAC,gBAAgB;gBAAE,OAAO;YAC1C,kEAAkE;YAClE,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;YAEhD,gDAAgD;YAChD,2EAA2E;YAC3E,kEAAkE;YAClE,MAAM,WAAW,GAAc,EAAE,CAAC;YAClC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;YAC/B,MAAM,UAAU,GAAG,CAAC,CAAU,EAAE,EAAE;gBAChC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;oBAAE,OAAO;gBAC7B,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBACjB,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACtB,CAAC,CAAC;YAEF,uDAAuD;YACvD,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC5B,8BAA8B;YAC9B,KAAK,MAAM,CAAC,EAAE,GAAG,CAAC,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;gBAC5C,IAAI,GAAG,EAAE,OAAO;oBAAE,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC5C,CAAC;YACD,yCAAyC;YACzC,KAAK,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC;gBACvE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YACxB,CAAC;YACD,+BAA+B;YAC/B,MAAM,SAAS,GAAG,gBAAgB,CAAC,oBAAoB,EAAE,CAAC;YAC1D,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;gBAC7B,MAAM,CAAC,GAAG,gBAAgB,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;gBAChD,IAAI,CAAC;oBAAE,UAAU,CAAC,CAAC,CAAC,CAAC;YACvB,CAAC;YAED,wEAAwE;YACxE,gDAAgD;YAChD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,gBAAgB,EAAE,WAAW,EAAE,MAAM,EAAE;gBAC5E,WAAW;gBACX,QAAQ,EAAE,YAAY;aACvB,CAAC,CAAC;YACH,IAAI,SAAS;gBAAE,OAAO;YAEtB,IAAI,OAAO,IAAI,MAAM,EAAE,CAAC;gBACtB,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;gBACvE,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAChB,OAAO;YACT,CAAC;YAED,MAAM,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAC;YACrD,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;gBACvD,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,IAAI,MAAM,CAAC,eAAe;gBAAE,kBAAkB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;YACvE,QAAQ,CAAC,CAAC,CAAC,CAAC;YAEZ,uEAAuE;YACvE,oEAAoE;YACpE,8CAA8C;YAC9C,UAAU,CAAC,OAAO,GAAG,MAAM,CAAC,UAAU,KAAK,SAAS;gBAClD,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,aAAa,EAAE,EAAE,CAAC;gBAC7E,CAAC,CAAC,EAAE,CAAC;YACP,eAAe,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1D,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAEzC,QAAQ,CAAC,IAAI,CAAC,CAAC;YACf,kFAAkF;QACpF,CAAC;QAED,WAAW,EAAE,CAAC;QAEd,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAC;YACjB,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC1C,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IAEjF,8CAA8C;IAC9C,SAAS,CAAC,GAAG,EAAE;QACb,SAAS,CAAC,aAAa,CAAC,CAAC;IAC3B,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;IAEpB,kCAAkC;IAClC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,gBAAgB;YAAE,OAAO;QACjE,MAAM,UAAU,GAAqC,EAAE,CAAC;QACxD,KAAK,MAAM,MAAM,IAAI,gBAAgB,CAAC,OAAO,EAAE,CAAC;YAC9C,MAAM,GAAG,GAAG,GAAG,cAAc,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAC/C,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAC/E,CAAC;QACH,CAAC;QACD,UAAU,CAAC,UAAU,CAAC,CAAC;IACzB,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAE1C,mCAAmC;IACnC,EAAE;IACF,6EAA6E;IAC7E,8EAA8E;IAC9E,qEAAqE;IACrE,EAAE;IACF,2EAA2E;IAC3E,2EAA2E;IAC3E,oDAAoD;IACpD,MAAM,cAAc,GAAG,WAAW,CAAC,CACjC,UAA8B,EAC9B,QAAgB,EAChB,cAAgD,EAChD,EAAE;QACF,IAAI,UAAU,KAAK,SAAS;YAAE,OAAO,CAAC,4CAA4C;QAElF,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC;QAChC,MAAM,UAAU,GAAG,eAAe,CAAC,OAAO,CAAC;QAE3C,oEAAoE;QACpE,mEAAmE;QACnE,gEAAgE;QAChE,4DAA4D;QAC5D,IAAI,UAAU,IAAI,CAAC,IAAI,UAAU,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpD,IAAI,CAAC,MAAM,GAAG,UAAU,GAAG,CAAC,CAAC;QAC/B,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,GAAG,cAAc,EAAE,EAAE,CAAC,CAAC;QAE1E,kEAAkE;QAClE,mEAAmE;QACnE,oEAAoE;QACpE,IAAI,IAAI,CAAC,MAAM,GAAG,WAAW,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC;YACvC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC;YAC9C,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;YACrB,OAAO,CAAC,cAAc,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC9D,CAAC;QAED,eAAe,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAC1C,eAAe,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACjC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAEtB,0EAA0E;IAC1E,0EAA0E;IAC1E,MAAM,eAAe,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACnC,SAAS,CAAC,GAAG,EAAE,GAAG,eAAe,CAAC,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;IAE7E,gBAAgB;IAEhB,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,EAAE,IAAY,EAAE,KAAuB,EAAE,EAAE;QAC1E,oEAAoE;QACpE,sEAAsE;QACtE,oEAAoE;QACpE,kEAAkE;QAClE,wEAAwE;QACxE,MAAM,SAAS,GAAG,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC;QAC1D,SAAS,CAAC,OAAO,GAAG,SAAS,CAAC;QAC9B,SAAS,CAAC,SAAS,CAAC,CAAC;QACrB,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAC1D,IAAI,OAAO,IAAI,MAAM;YAAE,OAAO;QAC9B,MAAM,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAC;QACrD,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACxE,aAAa,CAAC,KAAK,CAAC,CAAC;QACrB,IAAI,MAAM,CAAC,eAAe;YAAE,kBAAkB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IACzE,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAE7B,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC,IAAY,EAAE,EAAE;QAC/C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7B,MAAM,QAAQ,GAAG,OAAO,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACnF,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC1B,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAEtB,MAAM,UAAU,GAAG,WAAW,CAAC,KAAK,EAAE,MAAc,EAAE,EAAE;QACtD,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,MAAM,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC;QAC/B,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,QAAQ,GAAG,OAAO,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACnF,iEAAiE;QACjE,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC/D,IAAI,OAAO,IAAI,MAAM;YAAE,OAAO;QAC9B,MAAM,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAC;QACrD,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACxE,aAAa,CAAC,KAAK,CAAC,CAAC;QACrB,IAAI,MAAM,CAAC,eAAe;YAAE,kBAAkB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IACzE,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAEzC,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,EAAE,MAAc,EAAE,KAA6C,EAAE,EAAE;QACvG,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,sFAAsF;QACtF,4DAA4D;QAC5D,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,KAAY,EAAE,MAAM,CAAC,CAAC;QACnE,IAAI,OAAO,IAAI,MAAM;YAAE,OAAO,IAAI,CAAC;QACnC,MAAM,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAC;QACrD,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACxE,aAAa,CAAC,KAAK,CAAC,CAAC;QACrB,IAAI,MAAM,CAAC,eAAe;YAAE,kBAAkB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QACvE,OAAO,KAA8C,CAAC;IACxD,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAE7B,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QAClC,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC;QACjF,IAAI,OAAO,IAAI,MAAM;YAAE,OAAO;QAC9B,MAAM,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAC;QACrD,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACxE,aAAa,CAAC,KAAK,CAAC,CAAC;QACrB,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB,IAAI,MAAM,CAAC,eAAe;YAAE,kBAAkB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QACvE,uEAAuE;QACvE,6BAA6B;QAC7B,cAAc,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IACrE,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,cAAc,CAAC,CAAC,CAAC;IAE3D,wEAAwE;IACxE,8EAA8E;IAC9E,sDAAsD;IACtD,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,CAAS,EAAE,EAAE;QAC5C,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO;QAC7B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC;QACrF,IAAI,OAAO,IAAI,MAAM;YAAE,OAAO;QAC9B,MAAM,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAC;QACrD,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACxE,aAAa,CAAC,KAAK,CAAC,CAAC;QACrB,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB,IAAI,MAAM,CAAC,eAAe;YAAE,kBAAkB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QACvE,cAAc,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IACrE,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,cAAc,CAAC,CAAC,CAAC;IAE3D,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,EAAE,UAAkB,EAAE,YAAoB,EAAE,KAAa,EAA4B,EAAE;QACvH,IAAI,CAAC,KAAK,IAAI,KAAK,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACtC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,UAAU,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAC/E,IAAI,OAAO,IAAI,MAAM;YAAE,OAAO,IAAI,CAAC;QACnC,OAAO,MAAM,CAAC,MAAM,CAAC;IACvB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAE7B,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACnC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC3C,IAAI,OAAO,IAAI,MAAM;YAAE,OAAO;QAC9B,MAAM,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAC;QACrD,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACxE,aAAa,CAAC,KAAK,CAAC,CAAC;QACrB,QAAQ,CAAC,CAAC,CAAC,CAAC;QACZ,SAAS,CAAC,aAAa,CAAC,CAAC;QACzB,IAAI,MAAM,CAAC,eAAe;YAAE,kBAAkB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;;YAClE,kBAAkB,CAAC,EAAE,CAAC,CAAC;QAE5B,mEAAmE;QACnE,iEAAiE;QACjE,qCAAqC;QACrC,UAAU,CAAC,OAAO,GAAG,EAAE,CAAC;QACxB,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC5C,IAAI,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;gBACxD,UAAU,CAAC,OAAO,GAAG,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,aAAa,EAAE,EAAE,CAAC,CAAC;YACjG,CAAC;QACH,CAAC;QACD,eAAe,CAAC,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjE,eAAe,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,CAAC,CAAC,CAAC;IAEnD,4BAA4B;IAE5B,wEAAwE;IACxE,2EAA2E;IAC3E,yEAAyE;IACzE,0EAA0E;IAC1E,2EAA2E;IAC3E,wEAAwE;IACxE,MAAM,iBAAiB,GAAG,WAAW,CAAC,KAAK,EAAE,KAAmB,EAAE,WAAmB,EAAE,EAAE;QACvF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAC/D,IAAI,OAAO,IAAI,MAAM;YAAE,OAAO;QAC9B,MAAM,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAC;QACrD,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACxE,aAAa,CAAC,KAAK,CAAC,CAAC;QACrB,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB,IAAI,MAAM,CAAC,eAAe;YAAE,kBAAkB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;;YAClE,kBAAkB,CAAC,EAAE,CAAC,CAAC;QAC5B,kEAAkE;QAClE,sEAAsE;QACtE,MAAM,cAAc,GAAG,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAC3C,SAAS,CAAC,OAAO,GAAG,cAAc,CAAC;QACnC,SAAS,CAAC,cAAc,CAAC,CAAC;QAC1B,eAAe,CAAC,OAAO,GAAG,WAAW,CAAC;QACtC,eAAe,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAEtB,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACtC,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC;QAChC,MAAM,GAAG,GAAG,eAAe,CAAC,OAAO,CAAC;QACpC,IAAI,GAAG,IAAI,CAAC;YAAE,OAAO,CAAC,iCAAiC;QACvD,MAAM,iBAAiB,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;IAClD,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAE/B,MAAM,WAAW,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACzC,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC;QAChC,MAAM,GAAG,GAAG,eAAe,CAAC,OAAO,CAAC;QACpC,uDAAuD;QACvD,sEAAsE;QACtE,oDAAoD;QACpD,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO;QACnC,MAAM,iBAAiB,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;IAClD,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAE/B,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,KAAa,EAAE,EAAE;QAC/C,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC;QAChC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QAC9C,MAAM,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;IAC9C,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAE/B,4EAA4E;IAC5E,wEAAwE;IACxE,uEAAuE;IACvE,2EAA2E;IAC3E,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7B,SAAS,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAErD,MAAM,YAAY,GAAG,WAAW,CAAC,CAAC,cAAsB,EAAE,KAA2D,EAAE,EAAE;QACvH,IAAI,UAAU,CAAC,OAAO;YAAE,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAC1D,aAAa,CAAC,cAAc,CAAC,CAAC;QAC9B,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,cAAc,CAAC,CAAC,CAAC;QAChE,UAAU,CAAC,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC3E,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,EAAE;QACnC,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YACvB,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YAClC,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC;QAC5B,CAAC;QACD,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,cAAsB,EAAE,EAAE;QACtD,aAAa,CAAC,cAAc,CAAC,CAAC;QAC9B,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YACvB,yBAAyB;YACzB,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,cAAc,CAAC,CAAC,CAAC;YAChE,UAAU,CAAC,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,GAAG,EAAE;YACV,IAAI,UAAU,CAAC,OAAO;gBAAE,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAC5D,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,2EAA2E;IAC3E,4EAA4E;IAC5E,yEAAyE;IACzE,iEAAiE;IACjE,MAAM,eAAe,GAAG,OAAO,CAA6B,GAAG,EAAE;QAC/D,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAChD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACtC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAe,CAAC;QAC5C,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,OAAO;YAAE,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACrD,OAAO;YACL,YAAY;YACZ,SAAS,EAAE,IAAI,GAAG,EAAE;YACpB,MAAM,EAAE,IAAI,GAAG,EAAE;YACjB,UAAU,EAAE,KAAK;SAClB,CAAC;IACJ,CAAC,EAAE,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC,CAAC;IAE7B,wEAAwE;IACxE,wEAAwE;IACxE,mEAAmE;IACnE,MAAM,YAAY,GAAG,OAAO,CAC1B,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,EAC7G,CAAC,UAAU,CAAC,CACb,CAAC;IAEF,OAAO;QACL,QAAQ;QACR,OAAO;QACP,MAAM;QACN,UAAU,EAAE,KAAK;QACjB,KAAK;QACL,KAAK,EAAE,IAAI;QACX,YAAY;QACZ,OAAO,EAAE,gBAAgB;QACzB,UAAU,EAAE,UAAU,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI;QACnD,eAAe;QACf,gBAAgB;QAChB,OAAO,EAAE,YAAY;QACrB,YAAY;QACZ,aAAa,EAAE,YAAY,IAAI,CAAC,IAAI,YAAY,GAAG,UAAU,GAAG,CAAC;QACjE,SAAS;QACT,KAAK;QAEL,UAAU;QACV,OAAO;QACP,WAAW;QACX,UAAU;QACV,YAAY;QACZ,IAAI;QACJ,KAAK;QACL,QAAQ;QACR,KAAK;QACL,QAAQ;QACR,WAAW;QACX,IAAI;QACJ,YAAY;QACZ,WAAW;QACX,QAAQ;QACR,gBAAgB,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,6CAA6C;QACzE,YAAY,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,0CAA0C;KACrE,CAAC;AACJ,CAAC","sourcesContent":["/**\n * useCircuitSimulator — the public circuit-simulation hook.\n *\n * Composes the sandbox bridge (`useSandbox` in @simten/ui) with circuit-level\n * concerns: auto-harness, time-travel history, auto-run, snapshot/restore.\n * This is what every embed/blog/editor consumer calls.\n *\n * Runtime topology (browser path):\n * useCircuitSimulator (here)\n * → useSandbox — packages/ui/src/sandbox/useSandbox.ts (postMessage bridge)\n * → apps/sandbox/main.ts — runs inside the cross-origin iframe\n * → core/simulator — pure simulator engine\n *\n * For non-browser callers (vitest, CI), skip this hook entirely and use\n * `@simten/core/sim` directly — no iframe, no React, just the engine.\n *\n * See: apps/web/content/docs/architecture.mdx → \"Runtime topology\".\n */\n\nimport { useState, useEffect, useCallback, useRef, useMemo } from \"react\";\nimport {\n type SimulatorEngine,\n type CircuitLibrary,\n type FlatPortValueMap,\n type FlatSequentialState,\n} from \"@simten/core/simulator\";\nimport type { Circuit, BitValue, BusValue } from \"@simten/core\";\nimport type { BuiltCircuit } from \"@simten/core/circuit\";\nimport { getCircuitEval, autoHarness, isSequentialCircuit } from \"@simten/core/circuit\";\nimport { Switch, Button, Led, Input, Output, HexDisplay } from \"@simten/core/std\";\nimport { useSandboxContext, type EvalSource } from \"@simten/ui/sandbox\";\n\nconst TOP_LEVEL_NODE = \"__top__\";\n\nexport interface SimulatorState {\n outputs: Record<string, boolean | number>;\n inputs: Record<string, boolean | number>;\n cycleCount: number;\n ready: boolean;\n error: string | null;\n isSequential: boolean;\n circuit: Circuit | null;\n portValues: FlatPortValueMap | null;\n sequentialState: FlatSequentialState | null;\n componentLibrary: CircuitLibrary | null;\n history: readonly { engineSnapshot: unknown; metadata?: unknown }[];\n historyIndex: number;\n isViewingPast: boolean;\n isRunning: boolean;\n speed: number;\n}\n\nexport interface SimulatorActions {\n setNode: (name: string, value: boolean | number) => void;\n toggleInput: (name: string) => void;\n toggleNode: (nodeId: string) => void;\n /**\n * Set a node's value. Returns the resulting port-value Map (so scan-style\n * callers can read debug outputs without waiting for a React re-render),\n * or null if the sandbox isn't ready / errored.\n */\n setNodeValue: (nodeId: string, value: number | boolean | Map<number, number>) => Promise<ReadonlyMap<string, boolean | number> | null>;\n tick: () => void;\n /** Advance N ticks in a single sandbox round-trip; one React update. */\n tickN: (n: number) => Promise<void>;\n /**\n * Combinationally scan a debug-address node across 0..count-1, sampling\n * a value port after each setting. Single round-trip; clock not advanced.\n * Returns the `number[]` of length `count`, or null on error.\n */\n scanPort: (addrNodeId: string, valuePortKey: string, count: number) => Promise<number[] | null>;\n reset: () => void;\n stepBack: () => void;\n stepForward: () => void;\n seek: (index: number) => void;\n startAutoRun: (ticksPerSecond: number, options?: { displayRate?: number; onBeforeTick?: () => void }) => void;\n stopAutoRun: () => void;\n setSpeed: (ticksPerSecond: number) => void;\n runCombinational: () => void;\n getSimulator: () => SimulatorEngine | null;\n}\n\nexport interface UseCircuitSimulatorOptions {\n /** Wrap the circuit with auto-generated Switch/Led nodes */\n autoHarness?: boolean;\n /** Initial values for input ports (only used when autoHarness is true) */\n initialInputs?: Record<string, number | boolean>;\n}\n\n/**\n * Extract eval function sources from a BuiltCircuit and its dependencies.\n * These are serialized and sent to the sandbox, which reconstructs them with new Function().\n * Returns empty object if the circuit's evals aren't registered in this frame\n * (e.g. editor case where evals live only in the sandbox from prior compile).\n */\nfunction extractEvalSources(circuit: BuiltCircuit): Record<string, EvalSource> {\n const sources: Record<string, EvalSource> = {};\n const visited = new Set<string>();\n\n function collect(c: BuiltCircuit) {\n const name = c.circuit.name;\n if (visited.has(name)) return;\n visited.add(name);\n\n const entry = getCircuitEval(name);\n if (entry) {\n sources[name] = {\n evalSource: entry.evalFn.toString(),\n onTickSource: entry.onTickFn?.toString(),\n inputNames: entry.inputNames,\n outputNames: entry.outputNames,\n stateKeys: entry.stateKeys,\n };\n }\n for (const [, dep] of c._dependencies) {\n if (dep) collect(dep);\n }\n }\n\n collect(circuit);\n return sources;\n}\n\n/**\n * Build a minimal BuiltCircuit-like object from a Circuit IR and its dependencies.\n * Used by the editor to adapt sandbox compile results into the shape useCircuitSimulator expects.\n * The resulting object has no live eval functions (empty registry lookups) — the sandbox\n * is expected to already have the evals registered from a prior sandbox.compile(source).\n */\nexport function builtFromIR(circuit: Circuit, dependencies: Circuit[]): BuiltCircuit {\n const depMap = new Map<string, BuiltCircuit>();\n for (const dep of dependencies) {\n depMap.set(dep.name, {\n circuit: dep,\n _dependencies: new Map(),\n } as unknown as BuiltCircuit);\n }\n return {\n circuit,\n _dependencies: depMap,\n } as unknown as BuiltCircuit;\n}\n\n/**\n * Circuit simulator hook — runs simulation in the sandbox iframe.\n *\n * Takes a BuiltCircuit and returns reactive simulation state + actions.\n * All simulation happens inside the sandbox for security (CSP-isolated,\n * cross-origin) — no user code runs in the main frame at simulation time.\n */\nexport function useCircuitSimulator(\n circuit: BuiltCircuit | null,\n options?: UseCircuitSimulatorOptions,\n): SimulatorState & SimulatorActions {\n const sandbox = useSandboxContext();\n const slotId = useMemo(() =>\n `embed-${typeof crypto !== 'undefined' && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2)}`,\n [],\n );\n\n // ── Build library + resolve circuit IR ──\n const { rawCircuit, componentLibrary } = useMemo(() => {\n const circuitMap = new Map<string, Circuit>();\n const lib: CircuitLibrary & { addCircuit(c: Circuit): void } = {\n resolveCircuit: (name) => circuitMap.get(name),\n getAllPrimitiveNames: () => [...circuitMap.entries()].filter(([, c]) => c.implementation.kind === 'primitive').map(([n]) => n),\n addCircuit: (c) => { circuitMap.set(c.name, c); },\n };\n for (const c of [Switch(), Button(), Led, Input(), Output, HexDisplay]) {\n lib.addCircuit(c.circuit);\n }\n if (circuit) {\n lib.addCircuit(circuit.circuit);\n if (circuit._dependencies) {\n for (const [, dep] of circuit._dependencies) {\n if (dep?.circuit) lib.addCircuit(dep.circuit);\n }\n }\n }\n return { rawCircuit: circuit?.circuit ?? null, componentLibrary: lib };\n }, [circuit]);\n\n // ── Auto-harness (wrap with Switches/LEDs if enabled) ──\n const harnessedCircuit = useMemo(() => {\n if (!rawCircuit) return null;\n if (!options?.autoHarness) return rawCircuit;\n return autoHarness(rawCircuit, componentLibrary, options.initialInputs);\n }, [rawCircuit, componentLibrary, options?.autoHarness, options?.initialInputs]);\n\n // ── Detect sequential (recursively) using shared core util ──\n const isSequential = useMemo(\n () => isSequentialCircuit(harnessedCircuit, componentLibrary.resolveCircuit),\n [harnessedCircuit, componentLibrary],\n );\n\n // ── Sandbox simulation state ──\n const [portValues, setPortValues] = useState<FlatPortValueMap>(new Map());\n // Peripheral-bus state exposed by the sandbox — only includes nodes on a\n // peripheral's bus (displays, consoles, etc.). Consumers read it through\n // the `sequentialState` shape below so rendering code doesn't need to know\n // it's narrower than a full FlatSequentialState.\n const [peripheralState, setPeripheralState] = useState<Record<string, unknown>>({});\n const [cycle, setCycle] = useState(0);\n const [ready, setReady] = useState(false);\n const [isRunning, setIsRunning] = useState(false);\n const [speed, setSpeedState] = useState(15);\n const autoRunRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n // ── Time-travel history ──\n // Each entry stores:\n // - snapshotId: opaque handle to a simulator snapshot held in the sandbox\n // - cycle: clock cycle at that snapshot (for the UI counter)\n // - inputs: user-visible input values at that moment. The simulator's\n // snapshot only covers *simulation* state (flip-flops, memory). User\n // inputs (switch positions, etc.) are \"environmental state\" that lives\n // in React — see packages/core/src/simulator/environmental-state.ts.\n // On rewind we restore both so the UI is fully consistent with the\n // cycle being viewed (not just the logic outputs).\n //\n // historyIndex points at the snapshot currently reflected in portValues.\n // At the \"head\" (live state) historyIndex === historyRef.current.length - 1.\n // When the user steps back, historyIndex moves left without shrinking history.\n // If they then make a state-mutating action (tick, setNode), we branch:\n // history is truncated at historyIndex + 1, orphaned sandbox snapshots leak\n // (GC'd by slot disposal or the next cap prune — acceptable for demo sizes).\n type HistoryEntry = {\n snapshotId: number;\n cycle: number;\n inputs: Record<string, boolean | number>;\n };\n const historyRef = useRef<HistoryEntry[]>([]);\n const [historyIndex, setHistoryIndex] = useState(-1);\n const [historyLen, setHistoryLen] = useState(0); // duplicate of historyRef.length for re-renders\n const HISTORY_CAP = 200;\n\n // Default inputs from the harnessed circuit's top-level inputs\n const defaultInputs = useMemo(() => {\n const result: Record<string, boolean | number> = {};\n if (!harnessedCircuit) return result;\n for (const input of harnessedCircuit.inputs) {\n result[input.name] = input.portType.kind === 'bit' ? false : 0;\n }\n return result;\n }, [harnessedCircuit]);\n\n const [outputs, setOutputs] = useState<Record<string, boolean | number>>({});\n const [inputs, setInputs] = useState<Record<string, boolean | number>>(defaultInputs);\n // Mirror of inputs in a ref so tick/tickN can snapshot the latest value\n // synchronously without waiting for setState → re-render.\n const inputsRef = useRef(inputs);\n useEffect(() => { inputsRef.current = inputs; }, [inputs]);\n\n // ── Compile to sandbox on mount / circuit change ──\n useEffect(() => {\n if (!circuit || !harnessedCircuit) {\n setReady(false);\n setPortValues(new Map());\n return;\n }\n\n let cancelled = false;\n\n async function initSandbox() {\n if (!circuit || !harnessedCircuit) return;\n // Extract eval sources from the BuiltCircuit and its dependencies\n const evalSources = extractEvalSources(circuit);\n\n // Collect all library circuits (stdlib + user).\n // The harnessed circuit references the raw circuit as \"dut\" by name, so we\n // need to include it + all its dependencies + harness components.\n const libCircuits: Circuit[] = [];\n const seen = new Set<string>();\n const addCircuit = (c: Circuit) => {\n if (seen.has(c.name)) return;\n seen.add(c.name);\n libCircuits.push(c);\n };\n\n // The raw circuit (referenced as \"dut\" by the harness)\n addCircuit(circuit.circuit);\n // Its transitive dependencies\n for (const [, dep] of circuit._dependencies) {\n if (dep?.circuit) addCircuit(dep.circuit);\n }\n // Harness components (Switch, Led, etc.)\n for (const c of [Switch(), Button(), Led, Input(), Output, HexDisplay]) {\n addCircuit(c.circuit);\n }\n // Anything else in the library\n const primNames = componentLibrary.getAllPrimitiveNames();\n for (const name of primNames) {\n const c = componentLibrary.resolveCircuit(name);\n if (c) addCircuit(c);\n }\n\n // Only bother snapshotting if the circuit is sequential — combinational\n // circuits don't have state worth rewinding to.\n const result = await sandbox.compileIR(harnessedCircuit, libCircuits, slotId, {\n evalSources,\n snapshot: isSequential,\n });\n if (cancelled) return;\n\n if ('error' in result) {\n console.error('[useCircuitSimulator] compileIR failed:', result.error);\n setReady(false);\n return;\n }\n\n const pvMap = new Map<string, BitValue | BusValue>();\n for (const [k, v] of Object.entries(result.portValues)) {\n pvMap.set(k, v);\n }\n setPortValues(pvMap);\n if (result.peripheralState) setPeripheralState(result.peripheralState);\n setCycle(0);\n\n // Seed history with the initial snapshot (if any). Fresh compile means\n // the previous history (if any) is invalid anyway — sandbox already\n // cleared its own snapshots on the recompile.\n historyRef.current = result.snapshotId !== undefined\n ? [{ snapshotId: result.snapshotId, cycle: 0, inputs: { ...defaultInputs } }]\n : [];\n setHistoryIndex(result.snapshotId !== undefined ? 0 : -1);\n setHistoryLen(historyRef.current.length);\n\n setReady(true);\n // isSequential is computed synchronously via useMemo above — no need to set async\n }\n\n initSandbox();\n\n return () => {\n cancelled = true;\n sandbox.dispose(slotId).catch(() => {});\n };\n }, [circuit, harnessedCircuit, componentLibrary, sandbox, slotId, isSequential]);\n\n // Sync inputs when underlying circuit changes\n useEffect(() => {\n setInputs(defaultInputs);\n }, [defaultInputs]);\n\n // Extract outputs from portValues\n useEffect(() => {\n if (!ready || portValues.size === 0 || !harnessedCircuit) return;\n const newOutputs: Record<string, boolean | number> = {};\n for (const output of harnessedCircuit.outputs) {\n const key = `${TOP_LEVEL_NODE}.${output.name}`;\n const value = portValues.get(key);\n if (value !== undefined) {\n newOutputs[output.name] = typeof value === 'number' ? value : Boolean(value);\n }\n }\n setOutputs(newOutputs);\n }, [ready, portValues, harnessedCircuit]);\n\n // ── History bookkeeping helper ──\n //\n // Called after any state-mutating sandbox operation that returns a snapshot.\n // Handles branch-on-past-edit (truncates future), enforces the 200-entry cap,\n // and updates React state so the UI re-renders with fresh ◀▶ counts.\n //\n // The `inputsSnapshot` is what the user-visible inputs (switches, buttons,\n // etc.) looked like at this moment — used on rewind so the UI restores not\n // just the simulator state but the user inputs too.\n const recordSnapshot = useCallback((\n snapshotId: number | undefined,\n newCycle: number,\n inputsSnapshot: Record<string, boolean | number>,\n ) => {\n if (snapshotId === undefined) return; // combinational circuit — nothing to record\n\n const hist = historyRef.current;\n const currentIdx = historyIndexRef.current;\n\n // If the user was viewing the past and just made a mutating action,\n // we branch: discard everything after their current position, then\n // append the new snapshot as the new head. The orphaned sandbox\n // snapshots leak until the next cap-prune or slot disposal.\n if (currentIdx >= 0 && currentIdx < hist.length - 1) {\n hist.length = currentIdx + 1;\n }\n\n hist.push({ snapshotId, cycle: newCycle, inputs: { ...inputsSnapshot } });\n\n // Cap at HISTORY_CAP: drop oldest entries and tell the sandbox to\n // free their snapshots. `keepAfterId` is the highest snapshotId we\n // DO NOT want to keep — anything <= that gets freed in the sandbox.\n if (hist.length > HISTORY_CAP) {\n const drop = hist.length - HISTORY_CAP;\n const keepAfterId = hist[drop - 1].snapshotId;\n hist.splice(0, drop);\n sandbox.pruneSnapshots(keepAfterId, slotId).catch(() => {});\n }\n\n historyIndexRef.current = hist.length - 1;\n setHistoryIndex(hist.length - 1);\n setHistoryLen(hist.length);\n }, [sandbox, slotId]);\n\n // Mirror historyIndex in a ref so the helper above can see its live value\n // without recompiling on every change (avoids rebuilding every callback).\n const historyIndexRef = useRef(-1);\n useEffect(() => { historyIndexRef.current = historyIndex; }, [historyIndex]);\n\n // ── Actions ──\n\n const setNode = useCallback(async (name: string, value: boolean | number) => {\n // Input changes (switch toggles, button presses) don't create a new\n // history entry — history tracks CYCLES (post-tick states), not every\n // input edit. The current cycle's \"inputs\" stay live: the next tick\n // will snapshot them as part of its history entry. If the user is\n // viewing the past when they toggle, the next tick branches from there.\n const newInputs = { ...inputsRef.current, [name]: value };\n inputsRef.current = newInputs;\n setInputs(newInputs);\n if (!ready) return;\n const result = await sandbox.setNode(name, value, slotId);\n if ('error' in result) return;\n const pvMap = new Map<string, BitValue | BusValue>();\n for (const [k, v] of Object.entries(result.portValues)) pvMap.set(k, v);\n setPortValues(pvMap);\n if (result.peripheralState) setPeripheralState(result.peripheralState);\n }, [ready, sandbox, slotId]);\n\n const toggleInput = useCallback((name: string) => {\n const current = inputs[name];\n const newValue = typeof current === 'boolean' ? !current : (current === 0 ? 1 : 0);\n setNode(name, newValue);\n }, [inputs, setNode]);\n\n const toggleNode = useCallback(async (nodeId: string) => {\n if (!ready) return;\n const outKey = `${nodeId}.out`;\n const current = portValues.get(outKey);\n const newValue = typeof current === 'boolean' ? !current : (current === 1 ? 0 : 1);\n // Same reasoning as setNode: no new history entry on input edit.\n const result = await sandbox.setNode(nodeId, newValue, slotId);\n if ('error' in result) return;\n const pvMap = new Map<string, BitValue | BusValue>();\n for (const [k, v] of Object.entries(result.portValues)) pvMap.set(k, v);\n setPortValues(pvMap);\n if (result.peripheralState) setPeripheralState(result.peripheralState);\n }, [ready, portValues, sandbox, slotId]);\n\n const setNodeValue = useCallback(async (nodeId: string, value: number | boolean | Map<number, number>) => {\n if (!ready) return null;\n // Map values (for ROM/RAM loading) are supported via structured clone in postMessage.\n // Same reasoning as setNode: no history entry on this path.\n const result = await sandbox.setNode(nodeId, value as any, slotId);\n if ('error' in result) return null;\n const pvMap = new Map<string, BitValue | BusValue>();\n for (const [k, v] of Object.entries(result.portValues)) pvMap.set(k, v);\n setPortValues(pvMap);\n if (result.peripheralState) setPeripheralState(result.peripheralState);\n return pvMap as ReadonlyMap<string, boolean | number>;\n }, [ready, sandbox, slotId]);\n\n const tick = useCallback(async () => {\n if (!ready) return;\n const result = await sandbox.tick(undefined, slotId, { snapshot: isSequential });\n if ('error' in result) return;\n const pvMap = new Map<string, BitValue | BusValue>();\n for (const [k, v] of Object.entries(result.portValues)) pvMap.set(k, v);\n setPortValues(pvMap);\n setCycle(result.cycle);\n if (result.peripheralState) setPeripheralState(result.peripheralState);\n // tick() doesn't modify user inputs — the switch position at tick time\n // is what goes into history.\n recordSnapshot(result.snapshotId, result.cycle, inputsRef.current);\n }, [ready, sandbox, slotId, isSequential, recordSnapshot]);\n\n // Batched tick — advances N cycles in one round-trip; one React update.\n // Only snapshots the final state (not every intermediate cycle) — time-travel\n // through a batched tick jumps straight to pre-batch.\n const tickN = useCallback(async (n: number) => {\n if (!ready || n <= 0) return;\n const result = await sandbox.tickN(n, undefined, slotId, { snapshot: isSequential });\n if ('error' in result) return;\n const pvMap = new Map<string, BitValue | BusValue>();\n for (const [k, v] of Object.entries(result.portValues)) pvMap.set(k, v);\n setPortValues(pvMap);\n setCycle(result.cycle);\n if (result.peripheralState) setPeripheralState(result.peripheralState);\n recordSnapshot(result.snapshotId, result.cycle, inputsRef.current);\n }, [ready, sandbox, slotId, isSequential, recordSnapshot]);\n\n const scanPort = useCallback(async (addrNodeId: string, valuePortKey: string, count: number): Promise<number[] | null> => {\n if (!ready || count <= 0) return null;\n const result = await sandbox.scanPort(addrNodeId, valuePortKey, count, slotId);\n if ('error' in result) return null;\n return result.values;\n }, [ready, sandbox, slotId]);\n\n const reset = useCallback(async () => {\n const result = await sandbox.reset(slotId);\n if ('error' in result) return;\n const pvMap = new Map<string, BitValue | BusValue>();\n for (const [k, v] of Object.entries(result.portValues)) pvMap.set(k, v);\n setPortValues(pvMap);\n setCycle(0);\n setInputs(defaultInputs);\n if (result.peripheralState) setPeripheralState(result.peripheralState);\n else setPeripheralState({});\n\n // Sandbox reset already cleared its own snapshots. Clear ours too,\n // then seed a fresh initial snapshot for the post-reset state so\n // time-travel starts over from here.\n historyRef.current = [];\n if (isSequential) {\n const snap = await sandbox.snapshot(slotId);\n if (!('error' in snap) && snap.snapshotId !== undefined) {\n historyRef.current = [{ snapshotId: snap.snapshotId, cycle: 0, inputs: { ...defaultInputs } }];\n }\n }\n historyIndexRef.current = historyRef.current.length > 0 ? 0 : -1;\n setHistoryIndex(historyRef.current.length > 0 ? 0 : -1);\n setHistoryLen(historyRef.current.length);\n }, [sandbox, slotId, defaultInputs, isSequential]);\n\n // ── Time-travel actions ──\n\n // Shared restore helper — applies a history entry to both the simulator\n // and the host-side input state. We restore inputs because the UI \"rewind\"\n // promise is a full restoration of user-visible state: switch positions,\n // input values, circuit state. Omitting inputs would leave the UI showing\n // a stale switch while the circuit actually runs with the restored value —\n // see environmental-state.ts in packages/core for the same distinction.\n const applyHistoryEntry = useCallback(async (entry: HistoryEntry, targetIndex: number) => {\n const result = await sandbox.restore(entry.snapshotId, slotId);\n if ('error' in result) return;\n const pvMap = new Map<string, BitValue | BusValue>();\n for (const [k, v] of Object.entries(result.portValues)) pvMap.set(k, v);\n setPortValues(pvMap);\n setCycle(result.cycle);\n if (result.peripheralState) setPeripheralState(result.peripheralState);\n else setPeripheralState({});\n // Restore user inputs too. Keep inputsRef in lockstep so that any\n // immediately-following setNode sees the restored values as its base.\n const restoredInputs = { ...entry.inputs };\n inputsRef.current = restoredInputs;\n setInputs(restoredInputs);\n historyIndexRef.current = targetIndex;\n setHistoryIndex(targetIndex);\n }, [sandbox, slotId]);\n\n const stepBack = useCallback(async () => {\n if (!ready) return;\n const hist = historyRef.current;\n const idx = historyIndexRef.current;\n if (idx <= 0) return; // already at or before the start\n await applyHistoryEntry(hist[idx - 1], idx - 1);\n }, [ready, applyHistoryEntry]);\n\n const stepForward = useCallback(async () => {\n if (!ready) return;\n const hist = historyRef.current;\n const idx = historyIndexRef.current;\n // Already at the live head — nothing to step into yet.\n // (Clicking ▶ at the head is a no-op, not a tick. Users run the clock\n // explicitly via Tick/autorun to add new history.)\n if (idx >= hist.length - 1) return;\n await applyHistoryEntry(hist[idx + 1], idx + 1);\n }, [ready, applyHistoryEntry]);\n\n const seek = useCallback(async (index: number) => {\n if (!ready) return;\n const hist = historyRef.current;\n if (index < 0 || index >= hist.length) return;\n await applyHistoryEntry(hist[index], index);\n }, [ready, applyHistoryEntry]);\n\n // Stable indirection so setInterval always calls the latest tick(). Without\n // this, an auto-run started before `ready` flips true would capture the\n // bail-early version of tick and never recover, even after the sandbox\n // becomes ready — the interval would fire forever calling a stale closure.\n const tickRef = useRef(tick);\n useEffect(() => { tickRef.current = tick; }, [tick]);\n\n const startAutoRun = useCallback((ticksPerSecond: number, _opts?: { displayRate?: number; onBeforeTick?: () => void }) => {\n if (autoRunRef.current) clearInterval(autoRunRef.current);\n setSpeedState(ticksPerSecond);\n setIsRunning(true);\n const interval = Math.max(1, Math.floor(1000 / ticksPerSecond));\n autoRunRef.current = setInterval(() => { tickRef.current(); }, interval);\n }, []);\n\n const stopAutoRun = useCallback(() => {\n if (autoRunRef.current) {\n clearInterval(autoRunRef.current);\n autoRunRef.current = null;\n }\n setIsRunning(false);\n }, []);\n\n const setSpeed = useCallback((ticksPerSecond: number) => {\n setSpeedState(ticksPerSecond);\n if (autoRunRef.current) {\n // Restart with new speed\n clearInterval(autoRunRef.current);\n const interval = Math.max(1, Math.floor(1000 / ticksPerSecond));\n autoRunRef.current = setInterval(() => { tickRef.current(); }, interval);\n }\n }, []);\n\n useEffect(() => {\n return () => {\n if (autoRunRef.current) clearInterval(autoRunRef.current);\n };\n }, []);\n\n // Expose peripheral-bus state as a FlatSequentialState-compatible shape so\n // projection code (which was written against in-process simulation) doesn't\n // need to learn about the sandbox boundary. Only nodes on a peripheral's\n // bus appear here — internal logic state stays sandbox-internal.\n const sequentialState = useMemo<FlatSequentialState | null>(() => {\n const entries = Object.entries(peripheralState);\n if (entries.length === 0) return null;\n const currentState = new Map<string, any>();\n for (const [k, v] of entries) currentState.set(k, v);\n return {\n currentState,\n nextState: new Map(),\n clocks: new Map(),\n cycleCount: cycle,\n };\n }, [peripheralState, cycle]);\n\n // Shadow-typed history for the UI: the consumer only needs a length for\n // showing the `N/M` counter and the ◀ ▶ enable logic. historyLen drives\n // re-renders; the array identity is intentionally stable per-slot.\n const historyForUi = useMemo(\n () => historyRef.current.slice(0, historyLen).map(h => ({ engineSnapshot: h.snapshotId, metadata: h.cycle })),\n [historyLen],\n );\n\n return {\n // State\n outputs,\n inputs,\n cycleCount: cycle,\n ready,\n error: null,\n isSequential,\n circuit: harnessedCircuit,\n portValues: portValues.size > 0 ? portValues : null,\n sequentialState,\n componentLibrary,\n history: historyForUi,\n historyIndex,\n isViewingPast: historyIndex >= 0 && historyIndex < historyLen - 1,\n isRunning,\n speed,\n\n // Actions\n setNode,\n toggleInput,\n toggleNode,\n setNodeValue,\n tick,\n tickN,\n scanPort,\n reset,\n stepBack,\n stepForward,\n seek,\n startAutoRun,\n stopAutoRun,\n setSpeed,\n runCombinational: () => {}, // sandbox.setNode already runs combinational\n getSimulator: () => null, // no local engine when running in sandbox\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simten/embed",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Embeddable interactive hardware circuits. Drop live, cycle-accurate simulations into any React app or HTML page.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Charles Harris",
@@ -54,8 +54,8 @@
54
54
  "clsx": "^2.1.1",
55
55
  "elkjs": "^0.9.3",
56
56
  "tailwind-merge": "^3.0.0",
57
- "@simten/ui": "0.1.6",
58
- "@simten/core": "0.3.0"
57
+ "@simten/core": "0.4.0",
58
+ "@simten/ui": "0.1.7"
59
59
  },
60
60
  "peerDependencies": {
61
61
  "react": "^18 || ^19",