benchforge 0.1.0
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 +432 -0
- package/bin/benchforge +3 -0
- package/dist/bin/benchforge.mjs +9 -0
- package/dist/bin/benchforge.mjs.map +1 -0
- package/dist/browser/index.js +914 -0
- package/dist/index.mjs +3 -0
- package/dist/src-CGuaC3Wo.mjs +3676 -0
- package/dist/src-CGuaC3Wo.mjs.map +1 -0
- package/package.json +49 -0
- package/src/BenchMatrix.ts +380 -0
- package/src/Benchmark.ts +33 -0
- package/src/BenchmarkReport.ts +156 -0
- package/src/GitUtils.ts +79 -0
- package/src/HtmlDataPrep.ts +148 -0
- package/src/MeasuredResults.ts +127 -0
- package/src/NodeGC.ts +48 -0
- package/src/PermutationTest.ts +115 -0
- package/src/StandardSections.ts +268 -0
- package/src/StatisticalUtils.ts +176 -0
- package/src/TypeUtil.ts +8 -0
- package/src/bin/benchforge.ts +4 -0
- package/src/browser/BrowserGcStats.ts +44 -0
- package/src/browser/BrowserHeapSampler.ts +248 -0
- package/src/cli/CliArgs.ts +64 -0
- package/src/cli/FilterBenchmarks.ts +68 -0
- package/src/cli/RunBenchCLI.ts +856 -0
- package/src/export/JsonExport.ts +103 -0
- package/src/export/JsonFormat.ts +91 -0
- package/src/export/PerfettoExport.ts +203 -0
- package/src/heap-sample/HeapSampleReport.ts +196 -0
- package/src/heap-sample/HeapSampler.ts +78 -0
- package/src/html/HtmlReport.ts +131 -0
- package/src/html/HtmlTemplate.ts +284 -0
- package/src/html/Types.ts +88 -0
- package/src/html/browser/CIPlot.ts +287 -0
- package/src/html/browser/HistogramKde.ts +118 -0
- package/src/html/browser/LegendUtils.ts +163 -0
- package/src/html/browser/RenderPlots.ts +263 -0
- package/src/html/browser/SampleTimeSeries.ts +389 -0
- package/src/html/browser/Types.ts +96 -0
- package/src/html/browser/index.ts +1 -0
- package/src/html/index.ts +17 -0
- package/src/index.ts +92 -0
- package/src/matrix/CaseLoader.ts +36 -0
- package/src/matrix/MatrixFilter.ts +103 -0
- package/src/matrix/MatrixReport.ts +290 -0
- package/src/matrix/VariantLoader.ts +46 -0
- package/src/runners/AdaptiveWrapper.ts +391 -0
- package/src/runners/BasicRunner.ts +368 -0
- package/src/runners/BenchRunner.ts +60 -0
- package/src/runners/CreateRunner.ts +11 -0
- package/src/runners/GcStats.ts +107 -0
- package/src/runners/RunnerOrchestrator.ts +374 -0
- package/src/runners/RunnerUtils.ts +2 -0
- package/src/runners/TimingUtils.ts +13 -0
- package/src/runners/WorkerScript.ts +256 -0
- package/src/table-util/ConvergenceFormatters.ts +19 -0
- package/src/table-util/Formatters.ts +152 -0
- package/src/table-util/README.md +70 -0
- package/src/table-util/TableReport.ts +293 -0
- package/src/table-util/test/TableReport.test.ts +105 -0
- package/src/table-util/test/TableValueExtractor.test.ts +41 -0
- package/src/table-util/test/TableValueExtractor.ts +100 -0
- package/src/test/AdaptiveRunner.test.ts +185 -0
- package/src/test/AdaptiveStatistics.integration.ts +119 -0
- package/src/test/BenchmarkReport.test.ts +82 -0
- package/src/test/BrowserBench.e2e.test.ts +44 -0
- package/src/test/BrowserBench.test.ts +79 -0
- package/src/test/GcStats.test.ts +94 -0
- package/src/test/PermutationTest.test.ts +121 -0
- package/src/test/RunBenchCLI.test.ts +166 -0
- package/src/test/RunnerOrchestrator.test.ts +102 -0
- package/src/test/StatisticalUtils.test.ts +112 -0
- package/src/test/TestUtils.ts +93 -0
- package/src/test/fixtures/test-bench-script.ts +30 -0
- package/src/tests/AdaptiveConvergence.test.ts +177 -0
- package/src/tests/AdaptiveSampling.test.ts +240 -0
- package/src/tests/BenchMatrix.test.ts +366 -0
- package/src/tests/MatrixFilter.test.ts +117 -0
- package/src/tests/MatrixReport.test.ts +139 -0
- package/src/tests/RealDataValidation.test.ts +177 -0
- package/src/tests/fixtures/baseline/impl.ts +4 -0
- package/src/tests/fixtures/bevy30-samples.ts +158 -0
- package/src/tests/fixtures/cases/asyncCases.ts +7 -0
- package/src/tests/fixtures/cases/cases.ts +8 -0
- package/src/tests/fixtures/cases/variants/product.ts +2 -0
- package/src/tests/fixtures/cases/variants/sum.ts +2 -0
- package/src/tests/fixtures/discover/fast.ts +1 -0
- package/src/tests/fixtures/discover/slow.ts +4 -0
- package/src/tests/fixtures/invalid/bad.ts +1 -0
- package/src/tests/fixtures/loader/fast.ts +1 -0
- package/src/tests/fixtures/loader/slow.ts +4 -0
- package/src/tests/fixtures/loader/stateful.ts +2 -0
- package/src/tests/fixtures/stateful/stateful.ts +2 -0
- package/src/tests/fixtures/variants/extra.ts +1 -0
- package/src/tests/fixtures/variants/impl.ts +1 -0
- package/src/tests/fixtures/worker/fast.ts +1 -0
- package/src/tests/fixtures/worker/slow.ts +4 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"src-CGuaC3Wo.mjs","names":["percentile","percentile","red","pc"],"sources":["../src/matrix/CaseLoader.ts","../src/matrix/VariantLoader.ts","../src/StatisticalUtils.ts","../src/runners/RunnerUtils.ts","../src/runners/AdaptiveWrapper.ts","../src/runners/BenchRunner.ts","../src/runners/BasicRunner.ts","../src/runners/CreateRunner.ts","../src/runners/GcStats.ts","../src/runners/TimingUtils.ts","../src/runners/RunnerOrchestrator.ts","../src/BenchMatrix.ts","../src/table-util/Formatters.ts","../src/table-util/TableReport.ts","../src/BenchmarkReport.ts","../src/cli/CliArgs.ts","../src/browser/BrowserGcStats.ts","../src/browser/BrowserHeapSampler.ts","../src/export/JsonExport.ts","../src/export/PerfettoExport.ts","../src/HtmlDataPrep.ts","../src/heap-sample/HeapSampleReport.ts","../src/html/HtmlTemplate.ts","../src/html/HtmlReport.ts","../src/matrix/MatrixFilter.ts","../src/table-util/ConvergenceFormatters.ts","../src/StandardSections.ts","../src/matrix/MatrixReport.ts","../src/cli/FilterBenchmarks.ts","../src/cli/RunBenchCLI.ts","../src/GitUtils.ts"],"sourcesContent":["import type { LoadedCase } from \"../BenchMatrix.ts\";\n\n/** Module that exports case definitions */\nexport interface CasesModule<T = unknown> {\n cases: string[];\n defaultCases?: string[]; // subset for quick runs\n defaultVariants?: string[]; // subset for quick runs\n loadCase?: (id: string) => LoadedCase<T> | Promise<LoadedCase<T>>;\n}\n\n/** Load a cases module by URL */\nexport async function loadCasesModule<T = unknown>(\n moduleUrl: string,\n): Promise<CasesModule<T>> {\n const module = await import(moduleUrl);\n if (!Array.isArray(module.cases)) {\n throw new Error(`Cases module at ${moduleUrl} must export 'cases' array`);\n }\n return {\n cases: module.cases,\n defaultCases: module.defaultCases,\n defaultVariants: module.defaultVariants,\n loadCase: module.loadCase,\n };\n}\n\n/** Load case data from a CasesModule or pass through the caseId */\nexport async function loadCaseData<T>(\n casesModule: CasesModule<T> | undefined,\n caseId: string,\n): Promise<LoadedCase<T>> {\n if (casesModule?.loadCase) {\n return casesModule.loadCase(caseId);\n }\n return { data: caseId as T };\n}\n","import fs from \"node:fs/promises\";\nimport { fileURLToPath } from \"node:url\";\nimport type { Variant } from \"../BenchMatrix.ts\";\n\n/** Discover variant ids from a directory of .ts files */\nexport async function discoverVariants(dirUrl: string): Promise<string[]> {\n const dirPath = fileURLToPath(dirUrl);\n const entries = await fs.readdir(dirPath, { withFileTypes: true });\n return entries\n .filter(e => e.isFile() && e.name.endsWith(\".ts\"))\n .map(e => e.name.slice(0, -3))\n .sort();\n}\n\n/** Load a variant module and extract run/setup exports */\nexport async function loadVariant<T = unknown>(\n dirUrl: string,\n variantId: string,\n): Promise<Variant<T>> {\n const moduleUrl = variantModuleUrl(dirUrl, variantId);\n const module = await import(moduleUrl);\n return extractVariant(module, variantId, moduleUrl);\n}\n\n/** Extract variant from module exports */\nfunction extractVariant<T>(\n module: Record<string, unknown>,\n variantId: string,\n moduleUrl: string,\n): Variant<T> {\n const { setup, run } = module;\n const loc = `Variant '${variantId}' at ${moduleUrl}`;\n if (typeof run !== \"function\") {\n throw new Error(`${loc} must export 'run'`);\n }\n if (setup === undefined) return run as (data: T) => void;\n if (typeof setup !== \"function\") {\n throw new Error(`${loc}: 'setup' must be a function`);\n }\n return { setup: setup as (data: T) => unknown, run: run as () => void };\n}\n\n/** Get module URL for a variant in a directory */\nexport function variantModuleUrl(dirUrl: string, variantId: string): string {\n return new URL(`${variantId}.ts`, dirUrl).href;\n}\n","const outlierMultiplier = 1.5; // Tukey's fence multiplier\nconst bootstrapSamples = 10000;\nconst confidence = 0.95;\n\n/** Options for bootstrap resampling methods */\ntype BootstrapOptions = {\n resamples?: number;\n confidence?: number;\n};\n\n/** Bootstrap estimate with confidence interval and raw resample data */\nexport interface BootstrapResult {\n estimate: number;\n ci: [number, number];\n samples: number[];\n}\n\n/** @return relative standard deviation (coefficient of variation) */\nexport function coefficientOfVariation(samples: number[]): number {\n const mean = average(samples);\n if (mean === 0) return 0;\n const stdDev = standardDeviation(samples);\n return stdDev / mean;\n}\n\n/** @return median absolute deviation for robust variability measure */\nexport function medianAbsoluteDeviation(samples: number[]): number {\n const median = percentile(samples, 0.5);\n const deviations = samples.map(x => Math.abs(x - median));\n return percentile(deviations, 0.5);\n}\n\n/** @return outliers detected via Tukey's interquartile range method */\nexport function findOutliers(samples: number[]): {\n rate: number;\n indices: number[];\n} {\n const q1 = percentile(samples, 0.25);\n const q3 = percentile(samples, 0.75);\n const iqr = q3 - q1;\n const lowerBound = q1 - outlierMultiplier * iqr;\n const upperBound = q3 + outlierMultiplier * iqr;\n\n const indices = samples\n .map((v, i) => (v < lowerBound || v > upperBound ? i : -1))\n .filter(i => i >= 0);\n return { rate: indices.length / samples.length, indices };\n}\n\n/** @return bootstrap confidence interval for median */\nexport function bootstrapMedian(\n samples: number[],\n options: BootstrapOptions = {},\n): BootstrapResult {\n const { resamples = bootstrapSamples, confidence: conf = confidence } =\n options;\n const medians = generateMedians(samples, resamples);\n const ci = computeInterval(medians, conf);\n\n return {\n estimate: percentile(samples, 0.5),\n ci,\n samples: medians,\n };\n}\n\n/** @return mean of values */\nexport function average(values: number[]): number {\n const sum = values.reduce((a, b) => a + b, 0);\n return sum / values.length;\n}\n\n/** @return standard deviation with Bessel's correction */\nexport function standardDeviation(samples: number[]): number {\n if (samples.length <= 1) return 0;\n const mean = average(samples);\n const variance =\n samples.reduce((sum, x) => sum + (x - mean) ** 2, 0) / (samples.length - 1);\n return Math.sqrt(variance);\n}\n\n/** @return value at percentile p (0-1) */\nexport function percentile(values: number[], p: number): number {\n const sorted = [...values].sort((a, b) => a - b);\n const index = Math.ceil(sorted.length * p) - 1;\n return sorted[Math.max(0, index)];\n}\n\n/** @return medians from bootstrap resamples */\nfunction generateMedians(samples: number[], resamples: number): number[] {\n return Array.from({ length: resamples }, () =>\n percentile(createResample(samples), 0.5),\n );\n}\n\n/** @return bootstrap resample with replacement */\nexport function createResample(samples: number[]): number[] {\n const n = samples.length;\n const rand = () => samples[Math.floor(Math.random() * n)];\n return Array.from({ length: n }, rand);\n}\n\n/** @return confidence interval [lower, upper] */\nfunction computeInterval(\n medians: number[],\n confidence: number,\n): [number, number] {\n const alpha = (1 - confidence) / 2;\n const lower = percentile(medians, alpha);\n const upper = percentile(medians, 1 - alpha);\n return [lower, upper];\n}\n\nexport type CIDirection = \"faster\" | \"slower\" | \"uncertain\";\n\n/** Binned histogram for efficient transfer to browser */\nexport interface HistogramBin {\n x: number; // bin center\n count: number;\n}\n\n/** Bootstrap confidence interval for percentage difference between two samples */\nexport interface DifferenceCI {\n percent: number;\n ci: [number, number];\n direction: CIDirection;\n /** Histogram of bootstrap distribution for visualization */\n histogram?: HistogramBin[];\n}\n\n/** Bin values into histogram for compact visualization */\nfunction binValues(values: number[], binCount = 30): HistogramBin[] {\n const sorted = [...values].sort((a, b) => a - b);\n const min = sorted[0];\n const max = sorted[sorted.length - 1];\n if (min === max) return [{ x: min, count: values.length }];\n\n const step = (max - min) / binCount;\n const counts = new Array(binCount).fill(0);\n for (const v of values) {\n const bin = Math.min(Math.floor((v - min) / step), binCount - 1);\n counts[bin]++;\n }\n return counts.map((count, i) => ({ x: min + (i + 0.5) * step, count }));\n}\n\n/** @return bootstrap CI for percentage difference between baseline and current medians */\nexport function bootstrapDifferenceCI(\n baseline: number[],\n current: number[],\n options: BootstrapOptions = {},\n): DifferenceCI {\n const { resamples = bootstrapSamples, confidence: conf = confidence } =\n options;\n\n const baselineMedian = percentile(baseline, 0.5);\n const currentMedian = percentile(current, 0.5);\n const observedPercent =\n ((currentMedian - baselineMedian) / baselineMedian) * 100;\n\n const diffs: number[] = [];\n for (let i = 0; i < resamples; i++) {\n const resB = createResample(baseline);\n const resC = createResample(current);\n const medB = percentile(resB, 0.5);\n const medC = percentile(resC, 0.5);\n diffs.push(((medC - medB) / medB) * 100);\n }\n\n const ci = computeInterval(diffs, conf);\n const excludesZero = ci[0] > 0 || ci[1] < 0;\n let direction: CIDirection = \"uncertain\";\n if (excludesZero) direction = observedPercent < 0 ? \"faster\" : \"slower\";\n const histogram = binValues(diffs);\n return { percent: observedPercent, ci, direction, histogram };\n}\n","export const msToNs = 1e6;\nexport const nsToMs = 1e-6;\n","import type { BenchmarkSpec } from \"../Benchmark.ts\";\nimport type { MeasuredResults } from \"../MeasuredResults.ts\";\nimport {\n coefficientOfVariation,\n medianAbsoluteDeviation,\n percentile,\n} from \"../StatisticalUtils.ts\";\nimport type { BenchRunner, RunnerOptions } from \"./BenchRunner.ts\";\nimport { msToNs } from \"./RunnerUtils.ts\";\n\nconst minTime = 1000;\nconst maxTime = 10000;\nconst targetConfidence = 95;\nconst fallbackThreshold = 80;\nconst windowSize = 50;\nconst stability = 0.05; // 5% drift threshold (was 2%, too strict for real benchmarks)\nconst initialBatch = 100;\nconst continueBatch = 100;\nconst continueIterations = 10;\n\ntype Metrics = {\n medianDrift: number;\n impactDrift: number;\n medianStable: boolean;\n impactStable: boolean;\n};\n\ninterface ConvergenceResult {\n converged: boolean;\n confidence: number;\n reason: string;\n}\n\nexport interface AdaptiveOptions extends RunnerOptions {\n adaptive?: boolean;\n minTime?: number;\n maxTime?: number;\n targetConfidence?: number;\n convergence?: number; // Confidence threshold (0-100)\n}\n\n/** @return adaptive sampling runner wrapper */\nexport function createAdaptiveWrapper(\n baseRunner: BenchRunner,\n options: AdaptiveOptions,\n): BenchRunner {\n return {\n async runBench<T = unknown>(\n benchmark: BenchmarkSpec<T>,\n runnerOptions: RunnerOptions,\n params?: T,\n ): Promise<MeasuredResults[]> {\n return runAdaptiveBench(\n baseRunner,\n benchmark,\n runnerOptions,\n options,\n params,\n );\n },\n };\n}\n\n/** @return results using adaptive sampling strategy */\nasync function runAdaptiveBench<T>(\n baseRunner: BenchRunner,\n benchmark: BenchmarkSpec<T>,\n runnerOptions: RunnerOptions,\n options: AdaptiveOptions,\n params?: T,\n): Promise<MeasuredResults[]> {\n const {\n minTime: min = options.minTime ?? minTime,\n maxTime: max = options.maxTime ?? maxTime,\n targetConfidence: target = options.convergence ?? targetConfidence,\n } = runnerOptions as AdaptiveOptions;\n const allSamples: number[] = [];\n\n // Collect initial batch (includes warmup + settle)\n const warmup = await collectInitial(\n baseRunner,\n benchmark,\n runnerOptions,\n params,\n allSamples,\n );\n\n // Start timing AFTER warmup - warmup time doesn't count against maxTime\n const startTime = performance.now();\n\n const limits = {\n minTime: min,\n maxTime: max,\n targetConfidence: target,\n startTime,\n };\n await collectAdaptive(\n baseRunner,\n benchmark,\n runnerOptions,\n params,\n allSamples,\n limits,\n );\n\n const convergence = checkConvergence(allSamples.map(s => s * msToNs));\n return buildResults(\n allSamples,\n startTime,\n convergence,\n benchmark.name,\n warmup,\n );\n}\n\n/** @return warmupSamples from initial batch */\nasync function collectInitial<T>(\n baseRunner: BenchRunner,\n benchmark: BenchmarkSpec<T>,\n runnerOptions: RunnerOptions,\n params: T | undefined,\n allSamples: number[],\n): Promise<number[] | undefined> {\n // Don't pass adaptive flag to base runner to avoid double wrapping\n const opts = {\n ...(runnerOptions as any),\n maxTime: initialBatch,\n maxIterations: undefined,\n };\n const results = await baseRunner.runBench(benchmark, opts, params);\n appendSamples(results[0], allSamples);\n return results[0].warmupSamples;\n}\n\n/** @return samples until convergence or timeout */\nasync function collectAdaptive<T>(\n baseRunner: BenchRunner,\n benchmark: BenchmarkSpec<T>,\n runnerOptions: RunnerOptions,\n params: T | undefined,\n allSamples: number[],\n limits: {\n minTime: number;\n maxTime: number;\n targetConfidence: number;\n startTime: number;\n },\n): Promise<void> {\n const { minTime, maxTime, targetConfidence, startTime } = limits;\n let lastLog = 0;\n while (performance.now() - startTime < maxTime) {\n const samplesNs = allSamples.map(s => s * msToNs);\n const convergence = checkConvergence(samplesNs);\n const elapsed = performance.now() - startTime;\n\n if (elapsed - lastLog > 1000) {\n const elapsedSec = (elapsed / 1000).toFixed(1);\n const conf = convergence.confidence.toFixed(0);\n process.stderr.write(\n `\\r◊ ${benchmark.name}: ${conf}% confident (${elapsedSec}s) `,\n );\n lastLog = elapsed;\n }\n\n if (shouldStop(convergence, targetConfidence, elapsed, minTime)) {\n break;\n }\n\n // Skip warmup for continuation batches (warmup done in initial batch)\n const opts = {\n ...(runnerOptions as any),\n maxTime: continueBatch,\n maxIterations: continueIterations,\n skipWarmup: true,\n };\n const batchResults = await baseRunner.runBench(benchmark, opts, params);\n appendSamples(batchResults[0], allSamples);\n }\n process.stderr.write(\"\\r\" + \" \".repeat(60) + \"\\r\");\n}\n\n/** Append samples one-by-one to avoid stack overflow from spread on large arrays */\nfunction appendSamples(result: MeasuredResults, samples: number[]): void {\n if (!result.samples?.length) return;\n for (const sample of result.samples) samples.push(sample);\n}\n\n/** @return true if convergence reached or timeout */\nfunction shouldStop(\n convergence: ConvergenceResult,\n targetConfidence: number,\n elapsedTime: number,\n minTime: number,\n): boolean {\n if (convergence.converged && convergence.confidence >= targetConfidence) {\n return true;\n }\n // After minTime, accept whichever is higher: targetConfidence or fallbackThreshold\n const threshold = Math.max(targetConfidence, fallbackThreshold);\n return elapsedTime >= minTime && convergence.confidence >= threshold;\n}\n\n/** @return measured results with convergence metrics */\nfunction buildResults(\n samplesMs: number[],\n startTime: number,\n convergence: ConvergenceResult,\n name: string,\n warmupSamples?: number[],\n): MeasuredResults[] {\n const totalTime = (performance.now() - startTime) / 1000;\n const samplesNs = samplesMs.map(s => s * msToNs);\n const timeStats = computeTimeStats(samplesNs);\n\n return [\n {\n name,\n samples: samplesMs,\n warmupSamples,\n time: timeStats,\n totalTime,\n convergence,\n },\n ];\n}\n\n/** @return time percentiles and statistics in ms */\nfunction computeTimeStats(samplesNs: number[]) {\n const samplesMs = samplesNs.map(s => s / msToNs);\n const { min, max, sum } = getMinMaxSum(samplesNs);\n const percentiles = getPercentiles(samplesNs);\n const robust = getRobustMetrics(samplesMs);\n\n return {\n min: min / msToNs,\n max: max / msToNs,\n avg: sum / samplesNs.length / msToNs,\n ...percentiles,\n ...robust,\n };\n}\n\n/** @return min, max, sum of samples */\nfunction getMinMaxSum(samples: number[]) {\n const min = samples.reduce(\n (a, b) => Math.min(a, b),\n Number.POSITIVE_INFINITY,\n );\n const max = samples.reduce(\n (a, b) => Math.max(a, b),\n Number.NEGATIVE_INFINITY,\n );\n const sum = samples.reduce((a, b) => a + b, 0);\n return { min, max, sum };\n}\n\n/** @return percentiles in ms */\nfunction getPercentiles(samples: number[]) {\n return {\n p25: percentile(samples, 0.25) / msToNs,\n p50: percentile(samples, 0.5) / msToNs,\n p75: percentile(samples, 0.75) / msToNs,\n p95: percentile(samples, 0.95) / msToNs,\n p99: percentile(samples, 0.99) / msToNs,\n p999: percentile(samples, 0.999) / msToNs,\n };\n}\n\n/** @return robust variability metrics */\nfunction getRobustMetrics(samplesMs: number[]) {\n const impact = getOutlierImpact(samplesMs);\n return {\n cv: coefficientOfVariation(samplesMs),\n mad: medianAbsoluteDeviation(samplesMs),\n outlierRate: impact.ratio,\n };\n}\n\n/** @return outlier impact as proportion of total time */\nfunction getOutlierImpact(samples: number[]): { ratio: number; count: number } {\n if (samples.length === 0) return { ratio: 0, count: 0 };\n\n const median = percentile(samples, 0.5);\n const q75 = percentile(samples, 0.75);\n const threshold = median + 1.5 * (q75 - median);\n\n let excessTime = 0;\n let count = 0;\n\n for (const sample of samples) {\n if (sample > threshold) {\n excessTime += sample - median;\n count++;\n }\n }\n\n const totalTime = samples.reduce((a, b) => a + b, 0);\n return {\n ratio: totalTime > 0 ? excessTime / totalTime : 0,\n count,\n };\n}\n\n/** @return convergence based on window stability */\nexport function checkConvergence(samples: number[]): ConvergenceResult {\n const windowSize = getWindowSize(samples);\n const minSamples = windowSize * 2;\n\n if (samples.length < minSamples) {\n return buildProgressResult(samples.length, minSamples);\n }\n\n const metrics = getStability(samples, windowSize);\n return buildConvergence(metrics);\n}\n\n/** @return progress when samples insufficient */\nfunction buildProgressResult(\n currentSamples: number,\n minSamples: number,\n): ConvergenceResult {\n return {\n converged: false,\n confidence: (currentSamples / minSamples) * 100,\n reason: `Collecting samples: ${currentSamples}/${minSamples}`,\n };\n}\n\n/** @return stability metrics between windows */\nfunction getStability(samples: number[], windowSize: number): Metrics {\n const recent = samples.slice(-windowSize);\n const previous = samples.slice(-windowSize * 2, -windowSize);\n\n const recentMs = recent.map(s => s / msToNs);\n const previousMs = previous.map(s => s / msToNs);\n\n const medianRecent = percentile(recentMs, 0.5);\n const medianPrevious = percentile(previousMs, 0.5);\n const medianDrift = Math.abs(medianRecent - medianPrevious) / medianPrevious;\n\n const impactRecent = getOutlierImpact(recentMs);\n const impactPrevious = getOutlierImpact(previousMs);\n const impactDrift = Math.abs(impactRecent.ratio - impactPrevious.ratio);\n\n return {\n medianDrift,\n impactDrift,\n medianStable: medianDrift < stability,\n impactStable: impactDrift < stability,\n };\n}\n\n/** @return convergence from stability metrics */\nfunction buildConvergence(metrics: Metrics): ConvergenceResult {\n const { medianDrift, impactDrift, medianStable, impactStable } = metrics;\n\n if (medianStable && impactStable) {\n return {\n converged: true,\n confidence: 100,\n reason: \"Stable performance pattern\",\n };\n }\n\n const confidence = Math.min(\n 100,\n (1 - medianDrift / stability) * 50 + (1 - impactDrift / stability) * 50,\n );\n\n const reason =\n medianDrift > impactDrift\n ? `Median drifting: ${(medianDrift * 100).toFixed(1)}%`\n : `Outlier impact changing: ${(impactDrift * 100).toFixed(1)}%`;\n\n return { converged: false, confidence: Math.max(0, confidence), reason };\n}\n\n/** @return window size scaled to execution time */\nfunction getWindowSize(samples: number[]): number {\n if (samples.length < 20) return windowSize; // Default for initial samples\n\n const recentMs = samples.slice(-20).map(s => s / msToNs);\n const recentMedian = percentile(recentMs, 0.5);\n\n // Inverse scaling with execution time\n if (recentMedian < 0.01) return 200; // <10μs\n if (recentMedian < 0.1) return 100; // <100μs\n if (recentMedian < 1) return 50; // <1ms\n if (recentMedian < 10) return 30; // <10ms\n return 20; // >10ms\n}\n","import type { BenchmarkSpec } from \"../Benchmark.ts\";\nimport type { MeasuredResults } from \"../MeasuredResults.ts\";\n\n/** Execute benchmark with optional parameters */\nexport function executeBenchmark<T>(\n benchmark: BenchmarkSpec<T>,\n params?: T,\n): void {\n (benchmark.fn as (params?: T) => void)(params);\n}\n\n/** Interface for benchmark execution libraries */\nexport interface BenchRunner {\n runBench<T = unknown>(\n benchmark: BenchmarkSpec<T>,\n options: RunnerOptions,\n params?: T,\n ): Promise<MeasuredResults[]>;\n}\n\nexport interface RunnerOptions {\n /** Minimum time to run each benchmark (milliseconds) */\n minTime?: number;\n /** Maximum time to run each benchmark - ignored by mitata (milliseconds) */\n maxTime?: number;\n /** Maximum iterations per benchmark - ignored by TinyBench */\n maxIterations?: number;\n /** Warmup iterations before measurement (default: 0) */\n warmup?: number;\n /** Warmup time before measurement (milliseconds) */\n warmupTime?: number;\n /** Warmup samples - mitata only, for reducing test time */\n warmupSamples?: number;\n /** Warmup threshold - mitata only (nanoseconds) */\n warmupThreshold?: number;\n /** Minimum samples required - mitata only */\n minSamples?: number;\n /** Force GC after each iteration (requires --expose-gc) */\n collect?: boolean;\n /** Enable CPU performance counters (requires root access) */\n cpuCounters?: boolean;\n /** Trace V8 optimization tiers (requires --allow-natives-syntax) */\n traceOpt?: boolean;\n /** Skip post-warmup settle time (default: false) */\n noSettle?: boolean;\n /** Iterations before first pause (then pauseInterval applies) */\n pauseFirst?: number;\n /** Iterations between pauses for V8 optimization (0 to disable) */\n pauseInterval?: number;\n /** Pause duration in ms for V8 optimization */\n pauseDuration?: number;\n /** Collect GC stats via --trace-gc-nvp (requires worker mode) */\n gcStats?: boolean;\n /** Heap sampling allocation attribution */\n heapSample?: boolean;\n /** Heap sampling interval in bytes */\n heapInterval?: number;\n /** Heap sampling stack depth */\n heapDepth?: number;\n}\n","import { getHeapStatistics } from \"node:v8\";\nimport type { BenchmarkSpec } from \"../Benchmark.ts\";\nimport type {\n MeasuredResults,\n OptStatusInfo,\n PausePoint,\n} from \"../MeasuredResults.ts\";\nimport { checkConvergence } from \"./AdaptiveWrapper.ts\";\nimport type { BenchRunner, RunnerOptions } from \"./BenchRunner.ts\";\nimport { executeBenchmark } from \"./BenchRunner.ts\";\nimport { msToNs } from \"./RunnerUtils.ts\";\n\n/**\n * Wait time after gc() for V8 to stabilize (ms).\n *\n * V8 has 4 compilation tiers: Ignition (interpreter) -> Sparkplug (baseline) ->\n * Maglev (mid-tier optimizer) -> TurboFan (full optimizer). Tiering thresholds:\n * - Ignition -> Sparkplug: 8 invocations\n * - Sparkplug -> Maglev: 500 invocations\n * - Maglev -> TurboFan: 6000 invocations\n *\n * Optimization compilation happens on background threads and requires idle time\n * on the main thread to complete. Without sufficient warmup + settle time,\n * benchmarks exhibit bimodal timing: slow Sparkplug samples (~30% slower) mixed\n * with fast optimized samples.\n *\n * The warmup iterations trigger the optimization decision, then gcSettleTime\n * provides idle time for background compilation to finish before measurement.\n *\n * @see https://v8.dev/blog/sparkplug\n * @see https://v8.dev/blog/maglev\n * @see https://v8.dev/blog/background-compilation\n */\nconst gcSettleTime = 1000;\n\ntype CollectParams<T = unknown> = {\n benchmark: BenchmarkSpec<T>;\n maxTime: number;\n maxIterations: number;\n warmup: number;\n params?: T;\n skipWarmup?: boolean;\n traceOpt?: boolean;\n noSettle?: boolean;\n pauseFirst?: number;\n pauseInterval?: number;\n pauseDuration?: number;\n};\n\ntype CollectResult = {\n samples: number[];\n warmupSamples: number[]; // timing of warmup iterations\n heapGrowth: number; // amortized KB per sample\n heapSamples?: number[]; // heap size per sample (bytes)\n timestamps?: number[]; // wall-clock μs per sample for Perfetto\n optStatus?: OptStatusInfo;\n optSamples?: number[]; // per-sample V8 opt status codes\n pausePoints: PausePoint[]; // where pauses occurred\n};\n\nexport type SampleTimeStats = {\n min: number;\n max: number;\n avg: number;\n p50: number;\n p75: number;\n p99: number;\n p999: number;\n};\n\n/** @return runner with time and iteration limits */\nexport class BasicRunner implements BenchRunner {\n async runBench<T = unknown>(\n benchmark: BenchmarkSpec<T>,\n options: RunnerOptions,\n params?: T,\n ): Promise<MeasuredResults[]> {\n const opts = { ...defaultCollectOptions, ...(options as any) };\n const collected = await collectSamples({ benchmark, params, ...opts });\n return [buildMeasuredResults(benchmark.name, collected)];\n }\n}\n\nconst defaultCollectOptions = {\n maxTime: 5000,\n maxIterations: 1000000,\n warmup: 0,\n traceOpt: false,\n noSettle: false,\n};\n\nfunction buildMeasuredResults(name: string, c: CollectResult): MeasuredResults {\n const time = computeStats(c.samples);\n const convergence = checkConvergence(c.samples.map(s => s * msToNs));\n return {\n name,\n samples: c.samples,\n warmupSamples: c.warmupSamples,\n heapSamples: c.heapSamples,\n timestamps: c.timestamps,\n time,\n heapSize: { avg: c.heapGrowth, min: c.heapGrowth, max: c.heapGrowth },\n convergence,\n optStatus: c.optStatus,\n optSamples: c.optSamples,\n pausePoints: c.pausePoints,\n };\n}\n\n/** @return timing samples and amortized allocation from benchmark execution */\nasync function collectSamples<T>(p: CollectParams<T>): Promise<CollectResult> {\n if (!p.maxIterations && !p.maxTime) {\n throw new Error(`At least one of maxIterations or maxTime must be set`);\n }\n const warmupSamples = p.skipWarmup ? [] : await runWarmup(p);\n const heapBefore = process.memoryUsage().heapUsed;\n const { samples, heapSamples, timestamps, optStatuses, pausePoints } =\n await runSampleLoop(p);\n const heapGrowth =\n Math.max(0, process.memoryUsage().heapUsed - heapBefore) /\n 1024 /\n samples.length;\n if (samples.length === 0) {\n throw new Error(`No samples collected for benchmark: ${p.benchmark.name}`);\n }\n const optStatus = p.traceOpt\n ? analyzeOptStatus(samples, optStatuses)\n : undefined;\n const optSamples =\n p.traceOpt && optStatuses.length > 0 ? optStatuses : undefined;\n return {\n samples,\n warmupSamples,\n heapGrowth,\n heapSamples,\n timestamps,\n optStatus,\n optSamples,\n pausePoints,\n };\n}\n\n/** Run warmup iterations with gc + settle time for V8 optimization */\nasync function runWarmup<T>(p: CollectParams<T>): Promise<number[]> {\n const gc = gcFunction();\n const samples = new Array<number>(p.warmup);\n for (let i = 0; i < p.warmup; i++) {\n const start = performance.now();\n executeBenchmark(p.benchmark, p.params);\n samples[i] = performance.now() - start;\n }\n gc();\n if (!p.noSettle) {\n await new Promise(r => setTimeout(r, gcSettleTime));\n gc();\n }\n return samples;\n}\n\ntype SampleLoopResult = {\n samples: number[];\n heapSamples?: number[];\n timestamps?: number[];\n optStatuses: number[];\n pausePoints: PausePoint[];\n};\n\n/** Estimate sample count for pre-allocation */\nfunction estimateSampleCount(maxTime: number, maxIterations: number): number {\n return maxIterations || Math.ceil(maxTime / 0.1); // assume 0.1ms per iteration minimum\n}\n\ntype SampleArrays = {\n samples: number[];\n timestamps: number[];\n heapSamples: number[];\n optStatuses: number[];\n pausePoints: PausePoint[];\n};\n\n/** Pre-allocate arrays to reduce GC pressure during measurement */\nfunction createSampleArrays(\n n: number,\n trackHeap: boolean,\n trackOpt: boolean,\n): SampleArrays {\n const arr = (track: boolean) => (track ? new Array<number>(n) : []);\n return {\n samples: new Array<number>(n),\n timestamps: new Array<number>(n),\n heapSamples: arr(trackHeap),\n optStatuses: arr(trackOpt),\n pausePoints: [],\n };\n}\n\n/** Trim arrays to actual sample count */\nfunction trimArrays(\n a: SampleArrays,\n count: number,\n trackHeap: boolean,\n trackOpt: boolean,\n): void {\n a.samples.length = a.timestamps.length = count;\n if (trackHeap) a.heapSamples.length = count;\n if (trackOpt) a.optStatuses.length = count;\n}\n\n/** Collect timing samples with periodic pauses for V8 optimization */\nasync function runSampleLoop<T>(\n p: CollectParams<T>,\n): Promise<SampleLoopResult> {\n const {\n maxTime,\n maxIterations,\n pauseFirst,\n pauseInterval = 0,\n pauseDuration = 100,\n } = p;\n const trackHeap = true; // Always track heap for charts\n const getOptStatus = p.traceOpt ? createOptStatusGetter() : undefined;\n const estimated = estimateSampleCount(maxTime, maxIterations);\n const a = createSampleArrays(estimated, trackHeap, !!getOptStatus);\n\n let count = 0;\n let elapsed = 0;\n let totalPauseTime = 0;\n const loopStart = performance.now();\n\n while (\n (!maxIterations || count < maxIterations) &&\n (!maxTime || elapsed < maxTime)\n ) {\n const start = performance.now();\n executeBenchmark(p.benchmark, p.params);\n const end = performance.now();\n a.samples[count] = end - start;\n a.timestamps[count] = Number(process.hrtime.bigint() / 1000n);\n if (trackHeap) a.heapSamples[count] = getHeapStatistics().used_heap_size;\n if (getOptStatus) a.optStatuses[count] = getOptStatus(p.benchmark.fn);\n count++;\n\n if (shouldPause(count, pauseFirst, pauseInterval)) {\n a.pausePoints.push({ sampleIndex: count - 1, durationMs: pauseDuration });\n const pauseStart = performance.now();\n await new Promise(r => setTimeout(r, pauseDuration));\n totalPauseTime += performance.now() - pauseStart;\n }\n elapsed = performance.now() - loopStart - totalPauseTime;\n }\n\n trimArrays(a, count, trackHeap, !!getOptStatus);\n return {\n samples: a.samples,\n heapSamples: trackHeap ? a.heapSamples : undefined,\n timestamps: a.timestamps,\n optStatuses: a.optStatuses,\n pausePoints: a.pausePoints,\n };\n}\n\n/** Check if we should pause at this iteration for V8 optimization */\nfunction shouldPause(\n iter: number,\n first: number | undefined,\n interval: number,\n): boolean {\n if (first !== undefined && iter === first) return true;\n if (interval <= 0) return false;\n if (first === undefined) return iter % interval === 0;\n return (iter - first) % interval === 0;\n}\n\n/** @return percentiles and basic statistics */\nexport function computeStats(samples: number[]): SampleTimeStats {\n const sorted = [...samples].sort((a, b) => a - b);\n const avg = samples.reduce((sum, s) => sum + s, 0) / samples.length;\n return {\n min: sorted[0],\n max: sorted[sorted.length - 1],\n avg,\n p50: percentile(sorted, 0.5),\n p75: percentile(sorted, 0.75),\n p99: percentile(sorted, 0.99),\n p999: percentile(sorted, 0.999),\n };\n}\n\n/** @return percentile value with linear interpolation */\nfunction percentile(sortedArray: number[], p: number): number {\n const index = (sortedArray.length - 1) * p;\n const lower = Math.floor(index);\n const upper = Math.ceil(index);\n const weight = index % 1;\n\n if (upper >= sortedArray.length) return sortedArray[sortedArray.length - 1];\n\n return sortedArray[lower] * (1 - weight) + sortedArray[upper] * weight;\n}\n\n/** @return runtime gc() function, or no-op if unavailable */\nfunction gcFunction(): () => void {\n const gc = globalThis.gc || (globalThis as any).__gc;\n if (gc) return gc;\n console.warn(\"gc() not available, run node/bun with --expose-gc\");\n return () => {};\n}\n\n/** @return function to get V8 optimization status (requires --allow-natives-syntax) */\nfunction createOptStatusGetter(): ((fn: unknown) => number) | undefined {\n try {\n // %GetOptimizationStatus returns a bitmask\n const getter = new Function(\"f\", \"return %GetOptimizationStatus(f)\");\n getter(() => {});\n return getter as (fn: unknown) => number;\n } catch {\n return undefined;\n }\n}\n\n/**\n * V8 optimization status bit meanings:\n * Bit 0 (1): is_function\n * Bit 4 (16): is_optimized (TurboFan)\n * Bit 5 (32): is_optimized (Maglev)\n * Bit 7 (128): is_baseline (Sparkplug)\n * Bit 3 (8): maybe_deoptimized\n */\nconst statusNames: Record<number, string> = {\n 1: \"interpreted\",\n 129: \"sparkplug\", // 1 + 128\n 17: \"turbofan\", // 1 + 16\n 33: \"maglev\", // 1 + 32\n 49: \"turbofan+maglev\", // 1 + 16 + 32\n 32769: \"optimized\", // common optimized status\n};\n\n/** @return analysis of V8 optimization status per sample */\nfunction analyzeOptStatus(\n samples: number[],\n statuses: number[],\n): OptStatusInfo | undefined {\n if (statuses.length === 0 || statuses[0] === undefined) return undefined;\n\n const byStatusCode = new Map<number, number[]>();\n let deoptCount = 0;\n\n for (let i = 0; i < samples.length; i++) {\n const status = statuses[i];\n if (status === undefined) continue;\n\n // Check deopt flag (bit 3)\n if (status & 8) deoptCount++;\n\n if (!byStatusCode.has(status)) byStatusCode.set(status, []);\n byStatusCode.get(status)!.push(samples[i]);\n }\n\n const byTier: Record<string, { count: number; medianMs: number }> = {};\n for (const [status, times] of byStatusCode) {\n const name = statusNames[status] || `status=${status}`;\n const sorted = [...times].sort((a, b) => a - b);\n const median = sorted[Math.floor(sorted.length / 2)];\n byTier[name] = { count: times.length, medianMs: median };\n }\n\n return { byTier, deoptCount };\n}\n","import { BasicRunner } from \"./BasicRunner.ts\";\nimport type { BenchRunner } from \"./BenchRunner.ts\";\n\nexport type KnownRunner = \"basic\";\n\n/** @return benchmark runner */\nexport async function createRunner(\n _runnerName: KnownRunner,\n): Promise<BenchRunner> {\n return new BasicRunner();\n}\n","/** GC statistics aggregated from V8 trace events.\n * Node (--trace-gc-nvp) provides all fields.\n * Browser (CDP Tracing) provides counts, collected, and pause only. */\nexport interface GcStats {\n scavenges: number;\n markCompacts: number;\n totalCollected: number; // bytes freed\n gcPauseTime: number; // total pause time (ms)\n totalAllocated?: number; // bytes allocated (Node only)\n totalPromoted?: number; // bytes promoted to old gen (Node only)\n totalSurvived?: number; // bytes survived in young gen (Node only)\n}\n\n/** Single GC event. Node provides all fields; browser provides type, pauseMs, collected. */\nexport interface GcEvent {\n type: \"scavenge\" | \"mark-compact\" | \"minor-ms\" | \"unknown\";\n pauseMs: number;\n collected: number;\n allocated?: number; // Node only\n promoted?: number; // Node only\n survived?: number; // Node only\n}\n\n/** Parse a single --trace-gc-nvp stderr line */\nexport function parseGcLine(line: string): GcEvent | undefined {\n // V8 format: [pid:addr:gen] N ms: pause=X gc=s ... allocated=N promoted=N ...\n if (!line.includes(\"pause=\")) return undefined;\n\n const fields = parseNvpFields(line);\n if (!fields.gc) return undefined;\n\n const int = (k: string) => Number.parseInt(fields[k] || \"0\", 10);\n const type = parseGcType(fields.gc);\n const pauseMs = Number.parseFloat(fields.pause || \"0\");\n const allocated = int(\"allocated\");\n const promoted = int(\"promoted\");\n // V8 uses \"new_space_survived\" not \"survived\"\n const survived = int(\"new_space_survived\") || int(\"survived\");\n // Calculate collected from start/end object size if available\n const startSize = int(\"start_object_size\");\n const endSize = int(\"end_object_size\");\n const collected = startSize > endSize ? startSize - endSize : 0;\n\n if (Number.isNaN(pauseMs)) return undefined;\n\n return { type, pauseMs, allocated, collected, promoted, survived };\n}\n\n/** Parse name=value pairs from trace-gc-nvp line */\nfunction parseNvpFields(line: string): Record<string, string> {\n const fields: Record<string, string> = {};\n // Format: \"key=value, key=value, ...\" or \"key=value key=value\"\n const matches = line.matchAll(/(\\w+)=([^\\s,]+)/g);\n for (const [, key, value] of matches) {\n fields[key] = value;\n }\n return fields;\n}\n\n/** Map V8 gc type codes to our types */\nfunction parseGcType(gcField: string): GcEvent[\"type\"] {\n // V8 uses: s=scavenge, mc=mark-compact, mmc=minor-mc (young gen mark-compact)\n if (gcField === \"s\" || gcField === \"scavenge\") return \"scavenge\";\n if (gcField === \"mc\" || gcField === \"ms\" || gcField === \"mark-compact\")\n return \"mark-compact\";\n if (gcField === \"mmc\" || gcField === \"minor-mc\" || gcField === \"minor-ms\")\n return \"minor-ms\";\n return \"unknown\";\n}\n\n/** Aggregate GC events into summary stats */\nexport function aggregateGcStats(events: GcEvent[]): GcStats {\n let scavenges = 0;\n let markCompacts = 0;\n let gcPauseTime = 0;\n let totalCollected = 0;\n let hasNodeFields = false;\n let totalAllocated = 0;\n let totalPromoted = 0;\n let totalSurvived = 0;\n\n for (const e of events) {\n if (e.type === \"scavenge\" || e.type === \"minor-ms\") scavenges++;\n else if (e.type === \"mark-compact\") markCompacts++;\n gcPauseTime += e.pauseMs;\n totalCollected += e.collected;\n if (e.allocated != null) {\n hasNodeFields = true;\n totalAllocated += e.allocated;\n totalPromoted += e.promoted ?? 0;\n totalSurvived += e.survived ?? 0;\n }\n }\n\n return {\n scavenges,\n markCompacts,\n totalCollected,\n gcPauseTime,\n ...(hasNodeFields && { totalAllocated, totalPromoted, totalSurvived }),\n };\n}\n\n/** @return GcStats with all counters zeroed */\nexport function emptyGcStats(): GcStats {\n return { scavenges: 0, markCompacts: 0, totalCollected: 0, gcPauseTime: 0 };\n}\n","export const debugWorkerTiming = false;\n\n/** Get current time or 0 if debugging disabled */\nexport function getPerfNow(): number {\n return debugWorkerTiming ? performance.now() : 0;\n}\n\n/** Calculate elapsed milliseconds between marks */\nexport function getElapsed(startMark: number, endMark?: number): number {\n if (!debugWorkerTiming) return 0;\n const end = endMark ?? performance.now();\n return end - startMark;\n}\n","import { type ChildProcess, fork } from \"node:child_process\";\nimport path from \"node:path\";\nimport type { BenchmarkSpec } from \"../Benchmark.ts\";\nimport type { HeapProfile } from \"../heap-sample/HeapSampler.ts\";\nimport type { MeasuredResults } from \"../MeasuredResults.ts\";\nimport {\n type AdaptiveOptions,\n createAdaptiveWrapper,\n} from \"./AdaptiveWrapper.ts\";\nimport type { RunnerOptions } from \"./BenchRunner.ts\";\nimport { createRunner, type KnownRunner } from \"./CreateRunner.ts\";\nimport { aggregateGcStats, type GcEvent, parseGcLine } from \"./GcStats.ts\";\nimport { debugWorkerTiming, getElapsed, getPerfNow } from \"./TimingUtils.ts\";\nimport type {\n ErrorMessage,\n ResultMessage,\n RunMessage,\n} from \"./WorkerScript.ts\";\n\nconst logTiming = debugWorkerTiming\n ? (message: string) => console.log(`[RunnerOrchestrator] ${message}`)\n : () => {};\n\ntype WorkerParams<T = unknown> = {\n spec: BenchmarkSpec<T>;\n runner: KnownRunner;\n options: RunnerOptions;\n params?: T;\n};\n\ntype WorkerHandlers = {\n resolve: (results: MeasuredResults[], heapProfile?: HeapProfile) => void;\n reject: (error: Error) => void;\n};\n\ninterface RunBenchmarkParams<T = unknown> {\n spec: BenchmarkSpec<T>;\n runner: KnownRunner;\n options: RunnerOptions;\n useWorker?: boolean;\n params?: T;\n}\n\n/** Execute benchmarks directly or in worker process */\nexport async function runBenchmark<T = unknown>({\n spec,\n runner,\n options,\n useWorker = false,\n params,\n}: RunBenchmarkParams<T>): Promise<MeasuredResults[]> {\n if (!useWorker) {\n const resolvedSpec = spec.modulePath\n ? await resolveModuleSpec(spec, params)\n : { spec, params };\n\n const base = await createRunner(runner);\n const benchRunner = (options as any).adaptive\n ? createAdaptiveWrapper(base, options as AdaptiveOptions)\n : base;\n return benchRunner.runBench(\n resolvedSpec.spec,\n options,\n resolvedSpec.params,\n );\n }\n\n return runInWorker({ spec, runner, options, params });\n}\n\n/** Resolve modulePath/exportName to a real function for non-worker mode */\nasync function resolveModuleSpec<T>(\n spec: BenchmarkSpec<T>,\n params: T | undefined,\n): Promise<{ spec: BenchmarkSpec<T>; params: T | undefined }> {\n const module = await import(spec.modulePath!);\n\n const fn = spec.exportName\n ? module[spec.exportName]\n : module.default || module;\n\n if (typeof fn !== \"function\") {\n const name = spec.exportName || \"default\";\n throw new Error(\n `Export '${name}' from ${spec.modulePath} is not a function`,\n );\n }\n\n let resolvedParams = params;\n if (spec.setupExportName) {\n const setupFn = module[spec.setupExportName];\n if (typeof setupFn !== \"function\") {\n const msg = `Setup export '${spec.setupExportName}' from ${spec.modulePath} is not a function`;\n throw new Error(msg);\n }\n resolvedParams = await setupFn(params);\n }\n\n return { spec: { ...spec, fn }, params: resolvedParams };\n}\n\n/** Run benchmark in isolated worker process */\nasync function runInWorker<T>(\n workerParams: WorkerParams<T>,\n): Promise<MeasuredResults[]> {\n const { spec, runner, options, params } = workerParams;\n const msg = createRunMessage(spec, runner, options, params);\n return runWorkerWithMessage(spec.name, options, msg);\n}\n\n/** Create worker process with timing logs */\nfunction createWorkerWithTiming(gcStats: boolean) {\n const workerStart = getPerfNow();\n const gcEvents: GcEvent[] = [];\n const worker = createWorkerProcess(gcStats);\n const createTime = getPerfNow();\n if (gcStats && worker.stdout) setupGcCapture(worker, gcEvents);\n logTiming(\n `Worker process created in ${getElapsed(workerStart, createTime).toFixed(1)}ms`,\n );\n return { worker, createTime, gcEvents };\n}\n\n/** Capture and parse GC lines from stdout (V8's --trace-gc-nvp outputs to stdout) */\nfunction setupGcCapture(worker: ChildProcess, gcEvents: GcEvent[]): void {\n let buffer = \"\";\n worker.stdout!.on(\"data\", (data: Buffer) => {\n buffer += data.toString();\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\"; // Keep incomplete line in buffer\n for (const line of lines) {\n const event = parseGcLine(line);\n if (event) {\n gcEvents.push(event);\n } else if (line.trim()) {\n // Forward non-GC stdout to console (worker status messages)\n process.stdout.write(line + \"\\n\");\n }\n }\n });\n}\n\n/** Spawn worker, wire handlers, send message, return results */\nfunction runWorkerWithMessage(\n name: string,\n options: RunnerOptions,\n message: RunMessage,\n): Promise<MeasuredResults[]> {\n const startTime = getPerfNow();\n const collectGcStats = options.gcStats ?? false;\n logTiming(`Starting worker for ${name}`);\n\n return new Promise((resolve, reject) => {\n const { worker, createTime, gcEvents } =\n createWorkerWithTiming(collectGcStats);\n const handlers = createWorkerHandlers(\n name,\n startTime,\n gcEvents,\n resolve,\n reject,\n );\n setupWorkerHandlers(worker, name, handlers);\n sendWorkerMessage(worker, message, createTime);\n });\n}\n\n/** Send message to worker with timing log */\nfunction sendWorkerMessage(\n worker: ReturnType<typeof createWorkerProcess>,\n message: RunMessage,\n createTime: number,\n): void {\n const messageTime = getPerfNow();\n worker.send(message);\n logTiming(\n `Message sent to worker in ${getElapsed(createTime, messageTime).toFixed(1)}ms`,\n );\n}\n\n/** Setup worker event handlers with cleanup */\nfunction setupWorkerHandlers(\n worker: ReturnType<typeof createWorkerProcess>,\n specName: string,\n handlers: WorkerHandlers,\n) {\n const { resolve, reject } = handlers;\n const cleanup = createCleanup(worker, specName, reject);\n worker.on(\n \"message\",\n createMessageHandler(specName, cleanup, resolve, reject),\n );\n worker.on(\"error\", createErrorHandler(specName, cleanup, reject));\n worker.on(\"exit\", createExitHandler(specName, cleanup, reject));\n}\n\n/** Handle worker messages (results or errors) */\nfunction createMessageHandler(\n specName: string,\n cleanup: () => void,\n resolve: (results: MeasuredResults[], heapProfile?: HeapProfile) => void,\n reject: (error: Error) => void,\n) {\n return (msg: ResultMessage | ErrorMessage) => {\n cleanup();\n if (msg.type === \"result\") {\n resolve(msg.results, msg.heapProfile);\n } else if (msg.type === \"error\") {\n const error = new Error(`Benchmark \"${specName}\" failed: ${msg.error}`);\n if (msg.stack) error.stack = msg.stack;\n reject(error);\n }\n };\n}\n\n/** Handle worker process errors */\nfunction createErrorHandler(\n specName: string,\n cleanup: () => void,\n reject: (error: Error) => void,\n) {\n return (error: Error) => {\n cleanup();\n reject(\n new Error(\n `Worker process failed for benchmark \"${specName}\": ${error.message}`,\n ),\n );\n };\n}\n\n/** Handle worker process exit */\nfunction createExitHandler(\n specName: string,\n cleanup: () => void,\n reject: (error: Error) => void,\n) {\n return (code: number | null, _signal: NodeJS.Signals | null) => {\n if (code !== 0 && code !== null) {\n cleanup();\n const msg = `Worker exited with code ${code} for benchmark \"${specName}\"`;\n reject(new Error(msg));\n }\n };\n}\n\n/** Create cleanup for timeout and termination */\nfunction createCleanup(\n worker: ReturnType<typeof createWorkerProcess>,\n specName: string,\n reject: (error: Error) => void,\n) {\n const timeoutId = setTimeout(() => {\n cleanup();\n reject(new Error(`Benchmark \"${specName}\" timed out after 60 seconds`));\n }, 60000);\n const cleanup = () => {\n clearTimeout(timeoutId);\n if (!worker.killed) worker.kill(\"SIGTERM\");\n };\n return cleanup;\n}\n\n/** Create worker process with configuration */\nfunction createWorkerProcess(gcStats: boolean) {\n const workerPath = path.join(import.meta.dirname!, \"WorkerScript.ts\");\n const execArgv = [\n \"--expose-gc\",\n \"--allow-natives-syntax\",\n \"--experimental-strip-types\",\n \"--no-warnings=ExperimentalWarning\",\n ];\n if (gcStats) execArgv.push(\"--trace-gc-nvp\");\n\n return fork(workerPath, [], {\n execArgv,\n silent: gcStats, // Capture stdout/stderr when collecting GC stats\n env: {\n ...process.env,\n NODE_OPTIONS: \"\",\n },\n });\n}\n\n// Consider: --no-compilation-cache, --max-old-space-size=512, --no-lazy\n// for consistency (less realistic)\n\n/** @return handlers that attach GC stats and heap profile to results */\nfunction createWorkerHandlers(\n specName: string,\n startTime: number,\n gcEvents: GcEvent[] | undefined,\n resolve: (results: MeasuredResults[]) => void,\n reject: (error: Error) => void,\n): WorkerHandlers {\n return {\n resolve: (results: MeasuredResults[], heapProfile?: HeapProfile) => {\n logTiming(\n `Total worker time for ${specName}: ${getElapsed(startTime).toFixed(1)}ms`,\n );\n if (gcEvents?.length) {\n const gcStats = aggregateGcStats(gcEvents);\n for (const r of results) r.gcStats = gcStats;\n }\n if (heapProfile) for (const r of results) r.heapProfile = heapProfile;\n resolve(results);\n },\n reject,\n };\n}\n\n/** Create message for worker execution */\nfunction createRunMessage<T>(\n spec: BenchmarkSpec<T>,\n runnerName: KnownRunner,\n options: RunnerOptions,\n params?: T,\n): RunMessage {\n const { fn, ...rest } = spec;\n const message: RunMessage = {\n type: \"run\",\n spec: rest as BenchmarkSpec,\n runnerName,\n options,\n params,\n };\n if (spec.modulePath) {\n message.modulePath = spec.modulePath;\n message.exportName = spec.exportName;\n if (spec.setupExportName) message.setupExportName = spec.setupExportName;\n } else {\n message.fnCode = fn.toString();\n }\n return message;\n}\n\n/** Parameters for running a matrix variant in worker */\nexport interface RunMatrixVariantParams {\n variantDir: string;\n variantId: string;\n caseId: string;\n caseData?: unknown;\n casesModule?: string;\n runner: KnownRunner;\n options: RunnerOptions;\n}\n\n/** Run a matrix variant benchmark in isolated worker process */\nexport async function runMatrixVariant(\n params: RunMatrixVariantParams,\n): Promise<MeasuredResults[]> {\n const {\n variantDir,\n variantId,\n caseId,\n caseData,\n casesModule,\n runner,\n options,\n } = params;\n const name = `${variantId}/${caseId}`;\n const message: RunMessage = {\n type: \"run\",\n spec: { name, fn: () => {} },\n runnerName: runner,\n options,\n variantDir,\n variantId,\n caseId,\n caseData,\n casesModule,\n };\n return runWorkerWithMessage(name, options, message);\n}\n","import type { MeasuredResults } from \"./MeasuredResults.ts\";\nimport { loadCaseData, loadCasesModule } from \"./matrix/CaseLoader.ts\";\nimport { discoverVariants } from \"./matrix/VariantLoader.ts\";\nimport { BasicRunner } from \"./runners/BasicRunner.ts\";\nimport type { RunnerOptions } from \"./runners/BenchRunner.ts\";\nimport { runMatrixVariant } from \"./runners/RunnerOrchestrator.ts\";\nimport { average } from \"./StatisticalUtils.ts\";\n\n/** Stateless variant - called each iteration with case data */\nexport type VariantFn<T = unknown> = (caseData: T) => void;\n\n/** Stateful variant - setup once, run many */\nexport interface StatefulVariant<T = unknown, S = unknown> {\n setup: (caseData: T) => S | Promise<S>;\n run: (state: S) => void;\n}\n\n/** A variant is either a plain function or a stateful setup+run pair */\nexport type Variant<T = unknown, S = unknown> =\n | VariantFn<T>\n | StatefulVariant<T, S>;\n\n/** Variant with any state type - used in BenchMatrix to allow mixed variants */\nexport type AnyVariant<T = unknown> = VariantFn<T> | StatefulVariant<T, any>;\n\n/** Result from casesModule.loadCase() */\nexport interface LoadedCase<T = unknown> {\n data: T;\n metadata?: Record<string, unknown>;\n}\n\nexport interface MatrixDefaults {\n warmup?: number;\n maxTime?: number;\n iterations?: number;\n}\n\n/** Bench matrix configuration */\nexport interface BenchMatrix<T = unknown> {\n name: string;\n variantDir?: string;\n variants?: Record<string, AnyVariant<T>>;\n cases?: string[];\n casesModule?: string;\n baselineDir?: string;\n baselineVariant?: string;\n defaults?: MatrixDefaults;\n}\n\n/** Collection of matrices */\nexport interface MatrixSuite {\n name: string;\n matrices: BenchMatrix<any>[];\n}\n\n/** Results for a single variant across all cases */\nexport interface VariantResult {\n id: string;\n cases: CaseResult[];\n}\n\n/** Results for a single (variant, case) pair */\nexport interface CaseResult {\n caseId: string;\n measured: MeasuredResults;\n metadata?: Record<string, unknown>;\n baseline?: MeasuredResults;\n deltaPercent?: number;\n}\n\n/** Results from running a matrix */\nexport interface MatrixResults {\n name: string;\n variants: VariantResult[];\n}\n\n/** @return true if variant is a StatefulVariant (has setup + run) */\nexport function isStatefulVariant<T, S>(\n v: Variant<T, S>,\n): v is StatefulVariant<T, S> {\n return typeof v === \"object\" && \"setup\" in v && \"run\" in v;\n}\n\n/** Options for runMatrix */\nexport interface RunMatrixOptions {\n iterations?: number;\n maxTime?: number;\n warmup?: number;\n useWorker?: boolean; // use worker process isolation (default: true for variantDir)\n filteredCases?: string[]; // run only these cases (from filter)\n filteredVariants?: string[]; // run only these variants (from filter)\n // Runner options passthrough\n collect?: boolean;\n cpuCounters?: boolean;\n traceOpt?: boolean;\n noSettle?: boolean;\n pauseFirst?: number;\n pauseInterval?: number;\n pauseDuration?: number;\n gcStats?: boolean;\n heapSample?: boolean;\n heapInterval?: number;\n heapDepth?: number;\n}\n\n/** Run a BenchMatrix with inline variants or variantDir */\nexport async function runMatrix<T>(\n matrix: BenchMatrix<T>,\n options: RunMatrixOptions = {},\n): Promise<MatrixResults> {\n validateBaseline(matrix);\n const effectiveOptions = { ...matrix.defaults, ...options };\n\n if (matrix.variantDir) {\n return runMatrixWithDir(matrix, effectiveOptions);\n }\n if (matrix.variants) {\n return runMatrixInline(matrix, effectiveOptions);\n }\n throw new Error(\"BenchMatrix requires either 'variants' or 'variantDir'\");\n}\n\n/** @throws if both baselineDir and baselineVariant are set */\nfunction validateBaseline<T>(matrix: BenchMatrix<T>): void {\n const msg =\n \"BenchMatrix cannot have both 'baselineDir' and 'baselineVariant'\";\n if (matrix.baselineDir && matrix.baselineVariant) throw new Error(msg);\n}\n\nfunction buildRunnerOptions(options: RunMatrixOptions): RunnerOptions {\n return {\n maxIterations: options.iterations,\n maxTime: options.maxTime ?? 1000,\n warmup: options.warmup ?? 0,\n collect: options.collect,\n cpuCounters: options.cpuCounters,\n traceOpt: options.traceOpt,\n noSettle: options.noSettle,\n pauseFirst: options.pauseFirst,\n pauseInterval: options.pauseInterval,\n pauseDuration: options.pauseDuration,\n gcStats: options.gcStats,\n heapSample: options.heapSample,\n heapInterval: options.heapInterval,\n heapDepth: options.heapDepth,\n };\n}\n\n/** Load cases module and resolve filtered case IDs */\nasync function resolveCases<T>(\n matrix: BenchMatrix<T>,\n options: RunMatrixOptions,\n) {\n const casesModule = matrix.casesModule\n ? await loadCasesModule<T>(matrix.casesModule)\n : undefined;\n const allCaseIds = casesModule?.cases ?? matrix.cases ?? [\"default\"];\n const caseIds = options.filteredCases ?? allCaseIds;\n return { casesModule, caseIds };\n}\n\n/** Run matrix with inline variants (non-worker mode) */\nasync function runMatrixInline<T>(\n matrix: BenchMatrix<T>,\n options: RunMatrixOptions,\n): Promise<MatrixResults> {\n // baselineDir is only valid with variantDir\n const msg =\n \"BenchMatrix with inline 'variants' cannot use 'baselineDir'. Use 'variantDir' instead.\";\n if (matrix.baselineDir) throw new Error(msg);\n\n const { casesModule, caseIds } = await resolveCases(matrix, options);\n const runner = new BasicRunner();\n const runnerOpts = buildRunnerOptions(options);\n\n const variantEntries = options.filteredVariants\n ? Object.entries(matrix.variants!).filter(([id]) =>\n options.filteredVariants!.includes(id),\n )\n : Object.entries(matrix.variants!);\n\n const variants: VariantResult[] = [];\n for (const [variantId, variant] of variantEntries) {\n const cases: CaseResult[] = [];\n for (const caseId of caseIds) {\n const loaded = await loadCaseData(casesModule, caseId);\n const caseData =\n casesModule || matrix.cases ? loaded.data : (undefined as T);\n const measured = await runVariant(\n variant,\n caseData,\n variantId,\n runner,\n runnerOpts,\n );\n cases.push({ caseId, measured, metadata: loaded.metadata });\n }\n variants.push({ id: variantId, cases });\n }\n\n if (matrix.baselineVariant) {\n applyBaselineVariant(variants, matrix.baselineVariant);\n }\n\n return { name: matrix.name, variants };\n}\n\n/** Context for running matrix benchmarks in worker mode */\ninterface DirMatrixContext<T> {\n matrix: BenchMatrix<T>;\n casesModule?: import(\"./matrix/CaseLoader.ts\").CasesModule<T>;\n baselineIds: string[];\n caseIds: string[];\n runnerOpts: RunnerOptions;\n}\n\n/** Run matrix with variantDir (worker mode for memory isolation) */\nasync function runMatrixWithDir<T>(\n matrix: BenchMatrix<T>,\n options: RunMatrixOptions,\n): Promise<MatrixResults> {\n const allVariantIds = await discoverVariants(matrix.variantDir!);\n if (allVariantIds.length === 0) {\n throw new Error(`No variants found in ${matrix.variantDir}`);\n }\n const variantIds = options.filteredVariants ?? allVariantIds;\n\n const ctx = await createDirContext(matrix, options);\n const variants = await runDirVariants(variantIds, ctx);\n\n if (matrix.baselineVariant) {\n applyBaselineVariant(variants, matrix.baselineVariant);\n }\n return { name: matrix.name, variants };\n}\n\n/** Create context for directory-based matrix execution */\nasync function createDirContext<T>(\n matrix: BenchMatrix<T>,\n options: RunMatrixOptions,\n): Promise<DirMatrixContext<T>> {\n const baselineIds = matrix.baselineDir\n ? await discoverVariants(matrix.baselineDir)\n : [];\n const { casesModule, caseIds } = await resolveCases(matrix, options);\n const runnerOpts = buildRunnerOptions(options);\n return { matrix, casesModule, baselineIds, caseIds, runnerOpts };\n}\n\n/** Run all variants using worker processes */\nasync function runDirVariants<T>(\n variantIds: string[],\n ctx: DirMatrixContext<T>,\n): Promise<VariantResult[]> {\n const variants: VariantResult[] = [];\n for (const variantId of variantIds) {\n const cases = await runDirVariantCases(variantId, ctx);\n variants.push({ id: variantId, cases });\n }\n return variants;\n}\n\n/** Run all cases for a single variant */\nasync function runDirVariantCases<T>(\n variantId: string,\n ctx: DirMatrixContext<T>,\n): Promise<CaseResult[]> {\n const { matrix, casesModule, caseIds, runnerOpts } = ctx;\n const cases: CaseResult[] = [];\n\n for (const caseId of caseIds) {\n const caseData = !matrix.casesModule && matrix.cases ? caseId : undefined;\n const [measured] = await runMatrixVariant({\n variantDir: matrix.variantDir!,\n variantId,\n caseId,\n caseData,\n casesModule: matrix.casesModule,\n runner: \"basic\",\n options: runnerOpts,\n });\n\n const loaded = await loadCaseData(casesModule, caseId);\n const baseline = await runBaselineIfExists(\n variantId,\n caseId,\n caseData,\n ctx,\n );\n const deltaPercent = baseline\n ? computeDeltaPercent(baseline, measured)\n : undefined;\n const metadata = loaded.metadata;\n cases.push({ caseId, measured, metadata, baseline, deltaPercent });\n }\n return cases;\n}\n\n/** Run baseline variant if it exists in baselineDir */\nasync function runBaselineIfExists<T>(\n variantId: string,\n caseId: string,\n caseData: unknown,\n ctx: DirMatrixContext<T>,\n): Promise<MeasuredResults | undefined> {\n const { matrix, baselineIds, runnerOpts } = ctx;\n if (!matrix.baselineDir || !baselineIds.includes(variantId)) return undefined;\n\n const [measured] = await runMatrixVariant({\n variantDir: matrix.baselineDir,\n variantId,\n caseId,\n caseData,\n casesModule: matrix.casesModule,\n runner: \"basic\",\n options: runnerOpts,\n });\n return measured;\n}\n\n/** Compute delta percentage: (current - baseline) / baseline * 100 */\nfunction computeDeltaPercent(\n baseline: MeasuredResults,\n current: MeasuredResults,\n): number {\n const baseAvg = average(baseline.samples);\n if (baseAvg === 0) return 0;\n return ((average(current.samples) - baseAvg) / baseAvg) * 100;\n}\n\n/** Apply baselineVariant comparison - one variant is the reference for all others */\nfunction applyBaselineVariant(\n variants: VariantResult[],\n baselineVariantId: string,\n): void {\n const baselineVariant = variants.find(v => v.id === baselineVariantId);\n if (!baselineVariant) return;\n\n const baselineByCase = new Map<string, MeasuredResults>();\n for (const c of baselineVariant.cases) {\n baselineByCase.set(c.caseId, c.measured);\n }\n\n for (const variant of variants) {\n if (variant.id === baselineVariantId) continue;\n for (const caseResult of variant.cases) {\n const baseline = baselineByCase.get(caseResult.caseId);\n if (baseline) {\n caseResult.baseline = baseline;\n caseResult.deltaPercent = computeDeltaPercent(\n baseline,\n caseResult.measured,\n );\n }\n }\n }\n}\n\n/** Run a single variant with case data */\nasync function runVariant<T>(\n variant: AnyVariant<T>,\n caseData: T,\n name: string,\n runner: BasicRunner,\n options: RunnerOptions,\n): Promise<MeasuredResults> {\n if (isStatefulVariant(variant)) {\n const state = await variant.setup(caseData);\n const [result] = await runner.runBench(\n { name, fn: () => variant.run(state) },\n options,\n );\n return result;\n }\n const [result] = await runner.runBench(\n { name, fn: () => variant(caseData) },\n options,\n );\n return result;\n}\n","import pico from \"picocolors\";\nimport type { CIDirection, DifferenceCI } from \"../StatisticalUtils.ts\";\n\nconst isTest = process.env.NODE_ENV === \"test\" || process.env.VITEST === \"true\";\nconst { red, green } = isTest\n ? { red: (str: string) => str, green: (str: string) => str }\n : pico;\n\n/** Format floats with custom precision */\nexport function floatPrecision(precision: number) {\n return (x: unknown): string | null => {\n if (typeof x !== \"number\") return null;\n return x.toFixed(precision).replace(/\\.?0+$/, \"\");\n };\n}\n\n/** Format percentages with custom precision */\nexport function percentPrecision(precision: number) {\n return (x: unknown): string | null => {\n if (typeof x !== \"number\") return null;\n return percent(x, precision);\n };\n}\n\n/** Format duration in milliseconds with appropriate units */\nexport function duration(ms: unknown): string | null {\n if (typeof ms !== \"number\") return null;\n if (ms < 0.001) return `${(ms * 1000000).toFixed(0)}ns`;\n if (ms < 1) return `${(ms * 1000).toFixed(1)}μs`;\n if (ms < 1000) return `${ms.toFixed(2)}ms`;\n return `${(ms / 1000).toFixed(2)}s`;\n}\n\n/** Format time in milliseconds, showing very small values with units */\nexport function timeMs(ms: unknown): string | null {\n if (typeof ms !== \"number\") return null;\n if (ms < 0.001) return `${(ms * 1000000).toFixed(0)}ns`;\n if (ms < 0.01) return `${(ms * 1000).toFixed(1)}μs`;\n if (ms >= 10) return ms.toFixed(0);\n return ms.toFixed(2);\n}\n\n/** Format as rate (value per unit) */\nexport function rate(unit: string) {\n return (value: unknown) => {\n if (typeof value !== \"number\") return null;\n return `${integer(value)}/${unit}`;\n };\n}\n\n/** Format integer with thousand separators */\nexport function integer(x: unknown): string | null {\n if (typeof x !== \"number\") return null;\n return new Intl.NumberFormat(\"en-US\").format(Math.round(x));\n}\n\n/** Format fraction as percentage (0.473 → 47.3%) */\nexport function percent(fraction: unknown, precision = 1): string | null {\n if (typeof fraction !== \"number\") return null;\n return `${Math.abs(fraction * 100).toFixed(precision)}%`;\n}\n\n/** Format percentage difference between two values */\nexport function diffPercent(main: unknown, base: unknown): string {\n if (typeof main !== \"number\" || typeof base !== \"number\") return \" \";\n const diff = main - base;\n return coloredPercent(diff, base);\n}\n\n/** Format percentage difference for benchmarks (lower is better) */\nexport function diffPercentBenchmark(main: unknown, base: unknown): string {\n if (typeof main !== \"number\" || typeof base !== \"number\") return \" \";\n const diff = main - base;\n return coloredPercent(diff, base, false); // negative is good for benchmarks\n}\n\n/** Format fraction as colored +/- percentage */\nfunction coloredPercent(\n numerator: number,\n denominator: number,\n positiveIsGreen = true,\n): string {\n const fraction = numerator / denominator;\n if (Number.isNaN(fraction) || !Number.isFinite(fraction)) {\n return \" \";\n }\n const positive = fraction >= 0;\n const sign = positive ? \"+\" : \"-\";\n const percentStr = `${sign}${percent(fraction)}`;\n const isGood = positive === positiveIsGreen;\n return isGood ? green(percentStr) : red(percentStr);\n}\n\n/** Format memory size in KB with appropriate units */\nexport function memoryKB(kb: unknown): string | null {\n if (typeof kb !== \"number\") return null;\n if (kb < 1024) return `${kb.toFixed(0)}KB`;\n return `${(kb / 1024).toFixed(1)}MB`;\n}\n\n/** Format bytes with appropriate units (B, KB, MB, GB) */\nexport function formatBytes(bytes: unknown): string | null {\n if (typeof bytes !== \"number\") return null;\n if (bytes < 1024) return `${bytes.toFixed(0)}B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;\n if (bytes < 1024 * 1024 * 1024)\n return `${(bytes / 1024 / 1024).toFixed(1)}MB`;\n return `${(bytes / 1024 / 1024 / 1024).toFixed(1)}GB`;\n}\n\n/** Format percentage difference with confidence interval */\nexport function formatDiffWithCI(value: unknown): string | null {\n if (!isDifferenceCI(value)) return null;\n const { percent, ci, direction } = value;\n return colorByDirection(diffCIText(percent, ci), direction);\n}\n\n/** Format percentage difference with CI for throughput metrics (higher is better) */\nexport function formatDiffWithCIHigherIsBetter(value: unknown): string | null {\n if (!isDifferenceCI(value)) return null;\n const { percent, ci, direction } = value;\n // Flip percent sign for \"higher is better\" metrics (direction stays same)\n return colorByDirection(diffCIText(-percent, [-ci[1], -ci[0]]), direction);\n}\n\n/** @return formatted \"pct [lo, hi]\" text for a diff with CI */\nfunction diffCIText(pct: number, ci: [number, number]): string {\n return `${formatBound(pct)} [${formatBound(ci[0])}, ${formatBound(ci[1])}]`;\n}\n\n/** @return text colored green for faster, red for slower */\nfunction colorByDirection(text: string, direction: CIDirection): string {\n if (direction === \"faster\") return green(text);\n if (direction === \"slower\") return red(text);\n return text;\n}\n\n/** @return signed percentage string (e.g. \"+1.2%\", \"-3.4%\") */\nfunction formatBound(v: number): string {\n const sign = v >= 0 ? \"+\" : \"\";\n return `${sign}${v.toFixed(1)}%`;\n}\n\n/** @return true if value is a DifferenceCI object */\nfunction isDifferenceCI(x: unknown): x is DifferenceCI {\n return typeof x === \"object\" && x !== null && \"ci\" in x && \"direction\" in x;\n}\n\n/** @return truncated string with ellipsis if over maxLen */\nexport function truncate(str: string, maxLen = 30): string {\n return str.length > maxLen ? str.slice(0, maxLen - 3) + \"...\" : str;\n}\n","import pico from \"picocolors\";\nimport type { Alignment, SpanningCellConfig, TableUserConfig } from \"table\";\nimport { table } from \"table\";\nimport { diffPercent } from \"./Formatters.ts\";\n\nconst isTest = process.env.NODE_ENV === \"test\" || process.env.VITEST === \"true\";\nconst { bold } = isTest ? { bold: (str: string) => str } : pico;\n\n/** Related table columns */\nexport interface ColumnGroup<T> {\n groupTitle?: string;\n columns: AnyColumn<T>[];\n}\n\nexport type AnyColumn<T> = Column<T> | DiffColumn<T>;\n\n/** Column with optional formatter */\nexport interface Column<T> extends ColumnFormat<T> {\n formatter?: (value: unknown) => string | null;\n diffKey?: undefined;\n}\n\n/** Comparison column against baseline */\ninterface DiffColumn<T> extends ColumnFormat<T> {\n diffFormatter?: (value: unknown, baseline: unknown) => string | null;\n formatter?: undefined;\n\n /** Key for comparison value against baseline */\n diffKey: keyof T;\n}\n\ninterface ColumnFormat<T> {\n key: keyof T;\n title: string;\n\n alignment?: Alignment;\n\n width?: number;\n}\n\n/** Table headers and configuration */\nexport interface TableSetup {\n headerRows: string[][];\n config: TableUserConfig;\n}\n\n/** Data rows with optional baseline */\nexport interface ResultGroup<T extends Record<string, any>> {\n results: T[];\n\n baseline?: T;\n}\n\n/** Build formatted table with column groups and baselines */\nexport function buildTable<T extends Record<string, any>>(\n columnGroups: ColumnGroup<T>[],\n resultGroups: ResultGroup<T>[],\n nameKey: keyof T = \"name\" as keyof T,\n): string {\n const allRecords = flattenGroups(columnGroups, resultGroups, nameKey);\n return createTable(columnGroups, allRecords);\n}\n\n/** Convert columns and records to formatted table */\nfunction createTable<T extends Record<string, any>>(\n groups: ColumnGroup<T>[],\n records: T[],\n): string {\n const dataRows = toRows(records, groups);\n const { headerRows, config } = setup(groups, dataRows);\n const allRows = [...headerRows, ...dataRows];\n return table(allRows, config);\n}\n\n/** Create header rows with group titles */\nfunction createGroupHeaders<T>(\n groups: ColumnGroup<T>[],\n numColumns: number,\n): string[][] {\n if (!groups.some(g => g.groupTitle)) return [];\n\n const sectionRow = groups.flatMap(g => {\n const title = g.groupTitle ? [bold(g.groupTitle)] : [];\n return padWithBlanks(title, g.columns.length);\n });\n const blankRow = padWithBlanks([], numColumns);\n return [sectionRow, blankRow];\n}\n\ninterface Lines {\n drawHorizontalLine: (index: number, size: number) => boolean;\n drawVerticalLine: (index: number, size: number) => boolean;\n}\n\n/** @return draw functions for horizontal/vertical table borders */\nfunction createLines<T>(groups: ColumnGroup<T>[]): Lines {\n const { sectionBorders, headerBottom } = calcBorders(groups);\n\n function drawVerticalLine(index: number, size: number): boolean {\n return index === 0 || index === size || sectionBorders.includes(index);\n }\n function drawHorizontalLine(index: number, size: number): boolean {\n return index === 0 || index === size || index === headerBottom;\n }\n return { drawHorizontalLine, drawVerticalLine };\n}\n\n/** @return spanning cell configs for group title headers */\nfunction createSectionSpans<T>(groups: ColumnGroup<T>[]): SpanningCellConfig[] {\n let col = 0;\n const alignment: Alignment = \"center\";\n return groups.map(g => {\n const colSpan = g.columns.length;\n const span = { row: 0, col, colSpan, alignment };\n col += colSpan;\n return span;\n });\n}\n\n/** @return bolded column title strings */\nfunction getTitles<T>(groups: ColumnGroup<T>[]): string[] {\n return groups.flatMap(g => g.columns.map(c => bold(c.title || \" \")));\n}\n\n/** @return array padded with blank strings to the given length */\nfunction padWithBlanks(arr: string[], length: number): string[] {\n if (arr.length >= length) return arr;\n return [...arr, ...Array(length - arr.length).fill(\" \")];\n}\n\n/** Convert records to string arrays for table */\nexport function toRows<T extends Record<string, any>>(\n records: T[],\n groups: ColumnGroup<T>[],\n): string[][] {\n const allColumns = groups.flatMap(group => group.columns);\n\n const rawRows = records.map(record =>\n allColumns.map(col => {\n const value = record[col.key];\n return col.formatter ? col.formatter(value) : value;\n }),\n );\n\n return rawRows.map(row => row.map(cell => cell ?? \" \"));\n}\n\n/** Add comparison values for diff columns */\nfunction addComparisons<T extends Record<string, any>>(\n groups: ColumnGroup<T>[],\n mainRecord: T,\n baselineRecord: T,\n): T {\n const diffColumns = groups.flatMap(g => g.columns).filter(col => col.diffKey);\n const updatedMain = { ...mainRecord };\n\n for (const col of diffColumns) {\n const dcol = col as DiffColumn<T>;\n const diffKey = dcol.diffKey;\n const mainValue = mainRecord[diffKey];\n const baselineValue = baselineRecord[diffKey];\n const diffFormat = dcol.diffFormatter ?? diffPercent;\n const diffStr = diffFormat(mainValue, baselineValue);\n (updatedMain as any)[col.key] = diffStr;\n }\n\n return updatedMain;\n}\n\n/** Flatten groups with spacing */\nfunction flattenGroups<T extends Record<string, any>>(\n columnGroups: ColumnGroup<T>[],\n resultGroups: ResultGroup<T>[],\n nameKey: keyof T,\n): T[] {\n return resultGroups.flatMap((group, i) => {\n const groupRecords = addBaseline(columnGroups, group, nameKey);\n\n const isLast = i === resultGroups.length - 1;\n return isLast ? groupRecords : [...groupRecords, {} as T];\n });\n}\n\n/** Process results with baseline comparisons */\nfunction addBaseline<T extends Record<string, any>>(\n columnGroups: ColumnGroup<T>[],\n group: ResultGroup<T>,\n nameKey: keyof T,\n): T[] {\n const { results, baseline } = group;\n\n if (!baseline) return results;\n\n const diffResults = results.map(result =>\n addComparisons(columnGroups, result, baseline),\n );\n\n const markedBaseline = {\n ...baseline,\n [nameKey]: `--> ${baseline[nameKey]}`,\n };\n\n return [...diffResults, markedBaseline];\n}\n\n/** Calculate vertical lines between sections and header bottom position */\nfunction calcBorders<T>(groups: ColumnGroup<T>[]): {\n sectionBorders: number[];\n headerBottom: number;\n} {\n if (groups.length === 0) return { sectionBorders: [], headerBottom: 1 };\n\n const sectionBorders: number[] = [];\n let border = 0;\n for (const g of groups) {\n border += g.columns.length;\n sectionBorders.push(border);\n }\n return { sectionBorders, headerBottom: 3 };\n}\n\n/** Create headers and table configuration */\nfunction setup<T>(groups: ColumnGroup<T>[], dataRows: string[][]): TableSetup {\n const titles = getTitles(groups);\n const numColumns = titles.length;\n\n const sectionRows = createGroupHeaders(groups, numColumns);\n const headerRows = [...sectionRows, titles];\n const spanningCells = createSectionSpans(groups);\n const columnWidths = calcColumnWidths(groups, titles, dataRows);\n const config: TableUserConfig = {\n spanningCells,\n columns: columnWidths,\n ...createLines(groups),\n };\n\n return { headerRows, config };\n}\n\n/** Calculate column widths based on content, including group titles */\nfunction calcColumnWidths<T>(\n groups: ColumnGroup<T>[],\n titles: string[],\n dataRows: unknown[][],\n): Record<number, { width: number; wrapWord: boolean }> {\n // First pass: calculate base widths from titles and data\n const widths: number[] = [];\n for (let i = 0; i < titles.length; i++) {\n const titleW = cellWidth(titles[i]);\n const maxDataW = dataRows.reduce(\n (max, row) => Math.max(max, cellWidth(row[i])),\n 0,\n );\n widths.push(Math.max(titleW, maxDataW));\n }\n\n // Second pass: ensure group titles fit (accounting for column separators)\n let colIndex = 0;\n for (const group of groups) {\n const groupW = cellWidth(group.groupTitle);\n if (groupW > 0) {\n const numCols = group.columns.length;\n const separatorWidth = (numCols - 1) * 3; // \" | \" between columns\n const currentWidth = widths\n .slice(colIndex, colIndex + numCols)\n .reduce((a, b) => a + b, 0);\n const needed = groupW - currentWidth - separatorWidth;\n if (needed > 0) {\n // Distribute extra width to last column in group\n widths[colIndex + numCols - 1] += needed;\n }\n }\n colIndex += group.columns.length;\n }\n\n // Convert to table config format\n return Object.fromEntries(\n widths.map((w, i) => [i, { width: w, wrapWord: false }]),\n );\n}\n\n// Regex to strip ANSI escape codes (ESC [ ... m sequences)\nconst ansiEscapeRegex = new RegExp(\n String.fromCharCode(27) + \"\\\\[[0-9;]*m\",\n \"g\",\n);\n\n/** Get visible length of a cell value (strips ANSI escape codes) */\nfunction cellWidth(value: unknown): number {\n if (value == null) return 0;\n const str = String(value);\n return str.replace(ansiEscapeRegex, \"\").length;\n}\n","import type { MeasuredResults } from \"./MeasuredResults.ts\";\nimport { bootstrapDifferenceCI } from \"./StatisticalUtils.ts\";\nimport type { UnionToIntersection } from \"./TypeUtil.ts\";\nimport {\n formatDiffWithCI,\n formatDiffWithCIHigherIsBetter,\n truncate,\n} from \"./table-util/Formatters.ts\";\nimport {\n type AnyColumn,\n buildTable,\n type ColumnGroup,\n type ResultGroup,\n} from \"./table-util/TableReport.ts\";\n\n/** Benchmark results with optional baseline for comparison */\nexport interface ReportGroup {\n name: string;\n reports: BenchmarkReport[];\n baseline?: BenchmarkReport;\n}\n\n/** Results from a single benchmark run */\nexport interface BenchmarkReport {\n name: string;\n measuredResults: MeasuredResults;\n metadata?: UnknownRecord;\n}\n\nexport interface ReportColumnGroup<T> {\n groupTitle?: string;\n columns: ReportColumn<T>[];\n}\n\nexport type ReportColumn<T> = AnyColumn<T> & {\n /** Add diff column after this column when baseline exists */\n comparable?: boolean;\n /** Set true for throughput metrics where higher values are better (e.g., lines/sec) */\n higherIsBetter?: boolean;\n};\n\n/** Maps benchmark results to table columns */\nexport interface ResultsMapper<\n T extends Record<string, any> = Record<string, any>,\n> {\n extract(results: MeasuredResults, metadata?: UnknownRecord): T;\n columns(): ReportColumnGroup<T>[];\n}\nexport type UnknownRecord = Record<string, unknown>;\n\ntype SectionStats<S> = S extends ResultsMapper<infer T> ? T : never;\n\ninterface ReportRowBase {\n name: string;\n}\n\n/** Row data combining all section statistics */\ntype ReportRowData<S extends ReadonlyArray<ResultsMapper<any>>> =\n ReportRowBase & UnionToIntersection<SectionStats<S[number]>>;\n\n/** @return formatted table report with optional baseline comparisons */\nexport function reportResults<S extends ReadonlyArray<ResultsMapper<any>>>(\n groups: ReportGroup[],\n sections: S,\n): string {\n const results = groups.map(group => resultGroupValues(group, sections));\n const hasBaseline = results.some(g => g.baseline);\n return buildTable(createColumnGroups(sections, hasBaseline), results);\n}\n\n/** @return values for report group */\nfunction resultGroupValues<S extends ReadonlyArray<ResultsMapper<any>>>(\n group: ReportGroup,\n sections: S,\n): ResultGroup<ReportRowData<S>> {\n const { reports, baseline } = group;\n const baselineSamples = baseline?.measuredResults.samples;\n\n const results = reports.map(report => {\n const row = {\n name: truncate(report.name),\n ...extractReportValues(report, sections),\n } as ReportRowData<S>;\n\n if (baselineSamples && report.measuredResults.samples) {\n (row as any).diffCI = bootstrapDifferenceCI(\n baselineSamples,\n report.measuredResults.samples,\n );\n }\n return row;\n });\n\n const baselineRow = baseline && valuesForReports([baseline], sections)[0];\n return { results, baseline: baselineRow };\n}\n\n/** @return rows with stats from sections */\nexport function valuesForReports<S extends ReadonlyArray<ResultsMapper<any>>>(\n reports: BenchmarkReport[],\n sections: S,\n): ReportRowData<S>[] {\n return reports.map(report => ({\n name: truncate(report.name),\n ...extractReportValues(report, sections),\n })) as ReportRowData<S>[];\n}\n\n/** @return merged statistics from all sections */\nfunction extractReportValues(\n report: BenchmarkReport,\n sections: ReadonlyArray<ResultsMapper<any>>,\n): UnknownRecord {\n const { measuredResults, metadata } = report;\n const entries = sections.flatMap(s =>\n Object.entries(s.extract(measuredResults, metadata)),\n );\n return Object.fromEntries(entries);\n}\n\n/** @return column groups with diff columns if baseline exists */\nfunction createColumnGroups<S extends ReadonlyArray<ResultsMapper<any>>>(\n sections: S,\n hasBaseline: boolean,\n): ColumnGroup<ReportRowData<S>>[] {\n const nameColumn: ColumnGroup<ReportRowData<S>> = {\n columns: [{ key: \"name\" as keyof ReportRowData<S>, title: \"name\" }],\n };\n\n const groups = sections.flatMap(section => section.columns());\n return [nameColumn, ...(hasBaseline ? injectDiffColumns(groups) : groups)];\n}\n\n/** @return groups with single CI column after first comparable field */\nexport function injectDiffColumns<T>(\n reportGroups: ReportColumnGroup<T>[],\n): ColumnGroup<T>[] {\n let ciAdded = false;\n\n return reportGroups.map(group => ({\n groupTitle: group.groupTitle,\n columns: group.columns.flatMap(col => {\n if (col.comparable && !ciAdded) {\n ciAdded = true;\n const fmt = col.higherIsBetter\n ? formatDiffWithCIHigherIsBetter\n : formatDiffWithCI;\n return [\n col,\n { title: \"Δ% CI\", key: \"diffCI\" as keyof T, formatter: fmt },\n ];\n }\n return [col];\n }),\n }));\n}\n","import type { Argv } from \"yargs\";\nimport yargs from \"yargs\";\n\nexport const defaultTime = 0.642;\nexport const defaultAdaptiveMaxTime = 20;\nexport const defaultPauseInterval = 0;\nexport const defaultPauseDuration = 100;\n\nexport type Configure<T> = (yargs: Argv) => Argv<T>;\n\n/** @return CLI args type from builder function */\nexport type DefaultCliArgs =\n ReturnType<typeof defaultCliArgs> extends Argv<infer T> ? T : never;\n\n// biome-ignore format: compact option definitions\nconst cliOptions = {\n time: { type: \"number\", default: defaultTime, requiresArg: true, describe: \"test duration in seconds\" },\n cpu: { type: \"boolean\", default: false, describe: \"CPU counter measurements (requires root)\" },\n collect: { type: \"boolean\", default: false, describe: \"force GC after each iteration\" },\n \"gc-stats\": { type: \"boolean\", default: false, describe: \"collect GC statistics (Node: --trace-gc-nvp, browser: CDP tracing)\" },\n profile: { type: \"boolean\", default: false, describe: \"run once for profiling\" },\n filter: { type: \"string\", requiresArg: true, describe: \"filter benchmarks by regex or substring\" },\n all: { type: \"boolean\", default: false, describe: \"run all cases (ignore defaultCases)\" },\n worker: { type: \"boolean\", default: true, describe: \"run in worker process for isolation (default: true)\" },\n adaptive: { type: \"boolean\", default: false, describe: \"use adaptive sampling mode\" },\n \"min-time\": { type: \"number\", default: 1, describe: \"minimum time in seconds before adaptive convergence can stop\" },\n convergence: { type: \"number\", default: 95, describe: \"confidence threshold (0-100)\" },\n warmup: { type: \"number\", default: 0, describe: \"warmup iterations before measurement\" },\n html: { type: \"boolean\", default: false, describe: \"generate HTML report and open in browser\" },\n \"export-html\": { type: \"string\", requiresArg: true, describe: \"export HTML report to specified file\" },\n json: { type: \"string\", requiresArg: true, describe: \"export benchmark data to JSON file\" },\n perfetto: { type: \"string\", requiresArg: true, describe: \"export Perfetto trace file (view at ui.perfetto.dev)\" },\n \"trace-opt\": { type: \"boolean\", default: false, describe: \"trace V8 optimization tiers (requires --allow-natives-syntax)\" },\n \"skip-settle\": { type: \"boolean\", default: false, describe: \"skip post-warmup settle time (see V8 optimization cold start)\" },\n \"pause-first\": { type: \"number\", describe: \"iterations before first pause (then pause-interval applies)\" },\n \"pause-interval\": { type: \"number\", default: defaultPauseInterval, describe: \"iterations between pauses for V8 optimization (0 to disable)\" },\n \"pause-duration\": { type: \"number\", default: defaultPauseDuration, describe: \"pause duration in ms for V8 optimization\" },\n batches: { type: \"number\", default: 1, describe: \"divide time into N batches, alternating baseline/current order\" },\n iterations: { type: \"number\", requiresArg: true, describe: \"exact number of iterations (overrides --time)\" },\n \"heap-sample\": { type: \"boolean\", default: false, describe: \"heap sampling allocation attribution (includes garbage)\" },\n \"heap-interval\": { type: \"number\", default: 32768, describe: \"heap sampling interval in bytes\" },\n \"heap-depth\": { type: \"number\", default: 64, describe: \"heap sampling stack depth\" },\n \"heap-rows\": { type: \"number\", default: 20, describe: \"top allocation sites to show\" },\n \"heap-stack\": { type: \"number\", default: 3, describe: \"call stack depth to display\" },\n \"heap-verbose\": { type: \"boolean\", default: false, describe: \"verbose output with file:// paths and line numbers\" },\n \"heap-user-only\": { type: \"boolean\", default: false, describe: \"filter to user code only (hide node internals)\" },\n url: { type: \"string\", requiresArg: true, describe: \"page URL for browser profiling (enables browser mode)\" },\n headless: { type: \"boolean\", default: true, describe: \"run browser in headless mode\" },\n timeout: { type: \"number\", default: 60, describe: \"browser page timeout in seconds\" },\n} as const;\n\n/** @return yargs with standard benchmark options */\nexport function defaultCliArgs(yargsInstance: Argv) {\n return yargsInstance.options(cliOptions).help().strict();\n}\n\n/** @return parsed command line arguments */\nexport function parseCliArgs<T = DefaultCliArgs>(\n args: string[],\n configure: Configure<T> = defaultCliArgs as Configure<T>,\n): T {\n const yargsInstance = configure(yargs(args));\n return yargsInstance.parseSync() as T;\n}\n","import {\n aggregateGcStats,\n type GcEvent,\n type GcStats,\n} from \"../runners/GcStats.ts\";\n\n/** CDP trace event from Tracing.dataCollected */\nexport interface TraceEvent {\n cat: string;\n name: string;\n ph: string;\n dur?: number; // microseconds\n args?: Record<string, any>;\n}\n\n/** Parse CDP trace events (MinorGC/MajorGC) into GcEvent[] */\nexport function parseGcTraceEvents(traceEvents: TraceEvent[]): GcEvent[] {\n return traceEvents.flatMap(e => {\n if (e.ph !== \"X\") return [];\n const type = gcType(e.name);\n if (!type) return [];\n const durUs = e.dur ?? 0;\n const heapBefore: number = e.args?.usedHeapSizeBefore ?? 0;\n const heapAfter: number = e.args?.usedHeapSizeAfter ?? 0;\n return [\n {\n type,\n pauseMs: durUs / 1000,\n collected: Math.max(0, heapBefore - heapAfter),\n },\n ];\n });\n}\n\nfunction gcType(name: string): GcEvent[\"type\"] | undefined {\n if (name === \"MinorGC\") return \"scavenge\";\n if (name === \"MajorGC\") return \"mark-compact\";\n return undefined;\n}\n\n/** Parse CDP trace events and aggregate into GcStats */\nexport function browserGcStats(traceEvents: TraceEvent[]): GcStats {\n return aggregateGcStats(parseGcTraceEvents(traceEvents));\n}\n","import { type CDPSession, chromium, type Page } from \"playwright\";\nimport type {\n HeapProfile,\n HeapSampleOptions,\n} from \"../heap-sample/HeapSampler.ts\";\nimport type { GcStats } from \"../runners/GcStats.ts\";\nimport { browserGcStats, type TraceEvent } from \"./BrowserGcStats.ts\";\n\nexport interface BrowserProfileParams {\n url: string;\n heapSample?: boolean;\n heapOptions?: HeapSampleOptions;\n gcStats?: boolean;\n headless?: boolean;\n timeout?: number; // seconds\n maxTime?: number; // ms, bench function iteration time limit\n maxIterations?: number; // exact iteration count (bench function mode)\n}\n\nexport interface BrowserProfileResult {\n heapProfile?: HeapProfile;\n gcStats?: GcStats;\n /** Wall-clock ms (lap mode: first start to done, bench function: total loop) */\n wallTimeMs?: number;\n /** Per-iteration timing samples (ms) from bench function or lap mode */\n samples?: number[];\n}\n\ninterface LapModeHandle {\n promise: Promise<BrowserProfileResult>;\n cancel: () => void;\n}\n\n/** Run browser benchmark, auto-detecting page API mode.\n * Bench function (window.__bench): CLI controls iteration and timing.\n * Lap mode (__start/__lap/__done): page controls the measured region. */\nexport async function profileBrowser(\n params: BrowserProfileParams,\n): Promise<BrowserProfileResult> {\n const { url, headless = true, timeout = 60 } = params;\n const { gcStats: collectGc } = params;\n const { samplingInterval = 32768 } = params.heapOptions ?? {};\n\n const browser = await chromium.launch({ headless });\n try {\n const page = await browser.newPage();\n page.setDefaultTimeout(timeout * 1000);\n const cdp = await page.context().newCDPSession(page);\n\n const pageErrors: string[] = [];\n page.on(\"pageerror\", err => pageErrors.push(err.message));\n\n const traceEvents = collectGc ? await startGcTracing(cdp) : [];\n const lapMode = await setupLapMode(\n page,\n cdp,\n params,\n samplingInterval,\n timeout,\n pageErrors,\n );\n\n await page.goto(url, { waitUntil: \"load\" });\n const hasBench = await page.evaluate(\n () => typeof (globalThis as any).__bench === \"function\",\n );\n\n let result: BrowserProfileResult;\n if (hasBench) {\n lapMode.cancel();\n lapMode.promise.catch(() => {}); // suppress unused rejection\n result = await runBenchLoop(page, cdp, params, samplingInterval);\n } else {\n result = await lapMode.promise;\n lapMode.cancel();\n }\n\n if (collectGc) {\n result = { ...result, gcStats: await collectTracing(cdp, traceEvents) };\n }\n return result;\n } finally {\n await browser.close();\n }\n}\n\n/** Inject __start/__lap as in-page functions, expose __done for results collection.\n * __start/__lap are pure in-page (zero CDP overhead). First __start() triggers\n * instrument start. __done() stops instruments and collects timing data. */\nasync function setupLapMode(\n page: Page,\n cdp: CDPSession,\n params: BrowserProfileParams,\n samplingInterval: number,\n timeout: number,\n pageErrors: string[],\n): Promise<LapModeHandle> {\n const { heapSample } = params;\n const { promise, resolve, reject } =\n Promise.withResolvers<BrowserProfileResult>();\n let instrumentsStarted = false;\n\n await page.exposeFunction(\"__benchInstrumentStart\", async () => {\n if (instrumentsStarted) return;\n instrumentsStarted = true;\n if (heapSample) {\n await cdp.send(\n \"HeapProfiler.startSampling\",\n heapSamplingParams(samplingInterval),\n );\n }\n });\n\n await page.exposeFunction(\n \"__benchCollect\",\n async (samples: number[], wallTimeMs: number) => {\n let heapProfile: HeapProfile | undefined;\n if (heapSample && instrumentsStarted) {\n const result = await cdp.send(\"HeapProfiler.stopSampling\");\n heapProfile = result.profile as unknown as HeapProfile;\n }\n resolve({ samples, heapProfile, wallTimeMs });\n },\n );\n\n await page.addInitScript(injectLapFunctions);\n\n const timer = setTimeout(() => {\n const lines = [`Timed out after ${timeout}s`];\n if (pageErrors.length) {\n lines.push(\"Page JS errors:\", ...pageErrors.map(e => ` ${e}`));\n } else {\n lines.push(\"Page did not call __done() or define window.__bench\");\n }\n reject(new Error(lines.join(\"\\n\")));\n }, timeout * 1000);\n\n return { promise, cancel: () => clearTimeout(timer) };\n}\n\n/** In-page timing functions injected via addInitScript (zero CDP overhead).\n * __start/__lap collect timestamps, __done delegates to exposed __benchCollect. */\nfunction injectLapFunctions(): void {\n const g = globalThis as any;\n g.__benchSamples = [];\n g.__benchLastTime = 0;\n g.__benchFirstStart = 0;\n\n g.__start = () => {\n const now = performance.now();\n g.__benchLastTime = now;\n if (!g.__benchFirstStart) {\n g.__benchFirstStart = now;\n return g.__benchInstrumentStart();\n }\n };\n\n g.__lap = () => {\n const now = performance.now();\n g.__benchSamples.push(now - g.__benchLastTime);\n g.__benchLastTime = now;\n };\n\n g.__done = () => {\n const wall = g.__benchFirstStart\n ? performance.now() - g.__benchFirstStart\n : 0;\n return g.__benchCollect(g.__benchSamples.slice(), wall);\n };\n}\n\nfunction heapSamplingParams(samplingInterval: number) {\n return {\n samplingInterval,\n includeObjectsCollectedByMajorGC: true,\n includeObjectsCollectedByMinorGC: true,\n };\n}\n\n/** Start CDP GC tracing, returns the event collector array. */\nasync function startGcTracing(cdp: CDPSession): Promise<TraceEvent[]> {\n const events: TraceEvent[] = [];\n cdp.on(\"Tracing.dataCollected\", ({ value }) => {\n for (const e of value) events.push(e as unknown as TraceEvent);\n });\n await cdp.send(\"Tracing.start\", {\n traceConfig: { includedCategories: [\"v8\", \"v8.gc\"] },\n });\n return events;\n}\n\n/** Bench function mode: run window.__bench in a timed iteration loop. */\nasync function runBenchLoop(\n page: Page,\n cdp: CDPSession,\n params: BrowserProfileParams,\n samplingInterval: number,\n): Promise<BrowserProfileResult> {\n const { heapSample } = params;\n const maxTime = params.maxTime ?? 642;\n const maxIter = params.maxIterations ?? Number.MAX_SAFE_INTEGER;\n\n if (heapSample) {\n await cdp.send(\n \"HeapProfiler.startSampling\",\n heapSamplingParams(samplingInterval),\n );\n }\n\n const { samples, totalMs } = await page.evaluate(\n async ({ maxTime, maxIter }) => {\n const bench = (globalThis as any).__bench;\n const samples: number[] = [];\n const startAll = performance.now();\n const deadline = startAll + maxTime;\n for (let i = 0; i < maxIter && performance.now() < deadline; i++) {\n const t0 = performance.now();\n await bench();\n samples.push(performance.now() - t0);\n }\n return { samples, totalMs: performance.now() - startAll };\n },\n { maxTime, maxIter },\n );\n\n let heapProfile: HeapProfile | undefined;\n if (heapSample) {\n const result = await cdp.send(\"HeapProfiler.stopSampling\");\n heapProfile = result.profile as unknown as HeapProfile;\n }\n\n return { samples, heapProfile, wallTimeMs: totalMs };\n}\n\n/** Stop CDP tracing and parse GC events into GcStats. */\nasync function collectTracing(\n cdp: CDPSession,\n traceEvents: TraceEvent[],\n): Promise<GcStats> {\n const complete = new Promise<void>(resolve =>\n cdp.once(\"Tracing.tracingComplete\", () => resolve()),\n );\n await cdp.send(\"Tracing.end\");\n await complete;\n return browserGcStats(traceEvents);\n}\n\nexport { profileBrowser as profileBrowserHeap };\n","import { writeFile } from \"node:fs/promises\";\nimport type { ReportGroup } from \"../BenchmarkReport.ts\";\nimport type { DefaultCliArgs } from \"../cli/CliArgs.ts\";\nimport type {\n BenchmarkGroup,\n BenchmarkJsonData,\n BenchmarkResult,\n} from \"./JsonFormat.ts\";\n\n/** Export benchmark results to JSON file */\nexport async function exportBenchmarkJson(\n groups: ReportGroup[],\n outputPath: string,\n args: DefaultCliArgs,\n suiteName = \"Benchmark Suite\",\n): Promise<void> {\n const jsonData = prepareJsonData(groups, args, suiteName);\n const jsonString = JSON.stringify(jsonData, null, 2);\n\n await writeFile(outputPath, jsonString, \"utf-8\");\n console.log(`Benchmark data exported to: ${outputPath}`);\n}\n\n/** Convert ReportGroup data to JSON format */\nfunction prepareJsonData(\n groups: ReportGroup[],\n args: DefaultCliArgs,\n suiteName: string,\n): BenchmarkJsonData {\n return {\n meta: {\n timestamp: new Date().toISOString(),\n version: process.env.npm_package_version || \"unknown\",\n args: cleanCliArgs(args),\n environment: {\n node: process.version,\n platform: process.platform,\n arch: process.arch,\n },\n },\n suites: [\n {\n name: suiteName,\n groups: groups.map(convertGroup),\n },\n ],\n };\n}\n\n/** Convert a report group, mapping each report to the JSON result format */\nfunction convertGroup(group: ReportGroup): BenchmarkGroup {\n return {\n name: \"Benchmark Group\", // Could be enhanced to include actual group names\n baseline: group.baseline ? convertReport(group.baseline) : undefined,\n benchmarks: group.reports.map(convertReport),\n };\n}\n\n/** Extract measured stats and optional metrics into JSON result shape */\nfunction convertReport(report: any): BenchmarkResult {\n const { name, measuredResults: m } = report;\n const { time, heapSize, gcTime, cpu } = m;\n const minMaxMean = (s: any) =>\n s ? { min: s.min, max: s.max, mean: s.avg } : undefined;\n\n return {\n name,\n status: \"completed\",\n samples: m.samples || [],\n time: {\n ...minMaxMean(time)!,\n p50: time.p50,\n p75: time.p75,\n p99: time.p99,\n p999: time.p999,\n },\n heapSize: minMaxMean(heapSize),\n gcTime: minMaxMean(gcTime),\n cpu: cpu\n ? {\n instructions: cpu.instructions,\n cycles: cpu.cycles,\n cacheMisses: m.cpuCacheMiss,\n branchMisses: cpu.branchMisses,\n }\n : undefined,\n execution: {\n iterations: m.samples?.length || 0,\n totalTime: m.totalTime || 0,\n warmupRuns: undefined, // Not available in current data structure\n },\n };\n}\n\n/** Clean CLI args for JSON export (remove undefined values) */\nfunction cleanCliArgs(args: DefaultCliArgs): Record<string, any> {\n const toCamel = (k: string) =>\n k.replace(/-([a-z])/g, (_, l) => l.toUpperCase());\n const entries = Object.entries(args)\n .filter(([, v]) => v !== undefined && v !== null)\n .map(([k, v]) => [toCamel(k), v]);\n return Object.fromEntries(entries);\n}\n","import { spawn } from \"node:child_process\";\nimport { readdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { ReportGroup } from \"../BenchmarkReport.ts\";\nimport type { DefaultCliArgs } from \"../cli/CliArgs.ts\";\nimport type { MeasuredResults } from \"../MeasuredResults.ts\";\n\n/** Chrome Trace Event format event */\ninterface TraceEvent {\n ph: string; // event type: M=metadata, C=counter, i=instant, B/E=begin/end\n ts: number; // timestamp in microseconds\n pid?: number;\n tid?: number;\n cat?: string;\n name: string;\n args?: Record<string, unknown>;\n s?: string; // scope for instant events: \"t\"=thread, \"p\"=process, \"g\"=global\n dur?: number; // duration for complete events\n}\n\n/** Chrome Trace Event format file structure */\ninterface TraceFile {\n traceEvents: TraceEvent[];\n}\n\nconst pid = 1;\nconst tid = 1;\n\n/** Export benchmark results to Perfetto-compatible trace file */\nexport function exportPerfettoTrace(\n groups: ReportGroup[],\n outputPath: string,\n args: DefaultCliArgs,\n): void {\n const absPath = resolve(outputPath);\n const events = buildTraceEvents(groups, args);\n\n // Try to merge any existing V8 trace from a previous run\n const merged = mergeV8Trace(events);\n writeTraceFile(absPath, merged);\n console.log(`Perfetto trace exported to: ${outputPath}`);\n\n // V8 writes trace files after process exit, so spawn a child to merge later\n scheduleDeferredMerge(absPath);\n}\n\n/** Build trace events from benchmark results */\nfunction buildTraceEvents(\n groups: ReportGroup[],\n args: DefaultCliArgs,\n): TraceEvent[] {\n const meta = (name: string, a: Record<string, unknown>): TraceEvent => ({\n ph: \"M\",\n ts: 0,\n pid,\n tid,\n name,\n args: a,\n });\n const events: TraceEvent[] = [\n meta(\"process_name\", { name: \"wesl-bench\" }),\n meta(\"thread_name\", { name: \"MainThread\" }),\n meta(\"bench_settings\", cleanArgs(args)),\n ];\n\n for (const group of groups) {\n for (const report of group.reports) {\n const results = report.measuredResults as MeasuredResults;\n events.push(...buildBenchmarkEvents(results));\n }\n }\n\n return events;\n}\n\nfunction instant(\n ts: number,\n name: string,\n args: Record<string, unknown>,\n): TraceEvent {\n return { ph: \"i\", ts, pid, tid, cat: \"bench\", name, s: \"t\", args };\n}\n\nfunction counter(\n ts: number,\n name: string,\n args: Record<string, unknown>,\n): TraceEvent {\n return { ph: \"C\", ts, pid, tid, cat: \"bench\", name, args };\n}\n\n/** Build events for a single benchmark run */\nfunction buildBenchmarkEvents(results: MeasuredResults): TraceEvent[] {\n const { samples, heapSamples, timestamps, pausePoints } = results;\n if (!timestamps?.length) return [];\n\n const events: TraceEvent[] = [];\n for (let i = 0; i < samples.length; i++) {\n const ts = timestamps[i];\n const ms = Math.round(samples[i] * 100) / 100;\n events.push(instant(ts, results.name, { n: i, ms }));\n events.push(counter(ts, \"duration\", { ms }));\n if (heapSamples?.[i] !== undefined) {\n const MB = Math.round((heapSamples[i] / 1024 / 1024) * 10) / 10;\n events.push(counter(ts, \"heap\", { MB }));\n }\n }\n\n for (const pause of pausePoints ?? []) {\n const ts = timestamps[pause.sampleIndex];\n if (ts) events.push(instant(ts, \"pause\", { ms: pause.durationMs }));\n }\n return events;\n}\n\n/** Normalize timestamps so events start at 0 */\nfunction normalizeTimestamps(events: TraceEvent[]): void {\n const times = events.filter(e => e.ts > 0).map(e => e.ts);\n if (times.length === 0) return;\n const minTs = Math.min(...times);\n for (const e of events) if (e.ts > 0) e.ts -= minTs;\n}\n\n/** Merge V8 trace events from a previous run, aligning timestamps */\nfunction mergeV8Trace(customEvents: TraceEvent[]): TraceEvent[] {\n const traceFiles = readdirSync(\".\").filter(\n f => f.startsWith(\"node_trace.\") && f.endsWith(\".log\"),\n );\n\n const v8Events = loadV8Events(traceFiles[0]);\n normalizeTimestamps(customEvents);\n if (!v8Events) return customEvents;\n\n normalizeTimestamps(v8Events);\n return [...v8Events, ...customEvents];\n}\n\n/** Load V8 trace events from file, or undefined if unavailable */\nfunction loadV8Events(\n v8TracePath: string | undefined,\n): TraceEvent[] | undefined {\n if (!v8TracePath) return undefined;\n try {\n const v8Data = JSON.parse(readFileSync(v8TracePath, \"utf-8\")) as TraceFile;\n console.log(\n `Merged ${v8Data.traceEvents.length} V8 events from ${v8TracePath}`,\n );\n return v8Data.traceEvents;\n } catch {\n console.warn(`Could not parse V8 trace file: ${v8TracePath}`);\n return undefined;\n }\n}\n\n/** Write trace events to JSON file */\nfunction writeTraceFile(outputPath: string, events: TraceEvent[]): void {\n const traceFile: TraceFile = { traceEvents: events };\n writeFileSync(outputPath, JSON.stringify(traceFile));\n}\n\n/** Clean CLI args for metadata */\nfunction cleanArgs(args: DefaultCliArgs): Record<string, unknown> {\n const skip = new Set([\"_\", \"$0\"]);\n const entries = Object.entries(args).filter(\n ([k, v]) => v !== undefined && !skip.has(k),\n );\n return Object.fromEntries(entries);\n}\n\n/** Spawn a detached child to merge V8 trace after process exit */\nfunction scheduleDeferredMerge(outputPath: string): void {\n const cwd = process.cwd();\n const mergeScript = `\n const { readdirSync, readFileSync, writeFileSync } = require('fs');\n function normalize(events) {\n const times = events.filter(e => e.ts > 0).map(e => e.ts);\n if (!times.length) return;\n const min = Math.min(...times);\n for (const e of events) if (e.ts > 0) e.ts -= min;\n }\n setTimeout(() => {\n const traceFiles = readdirSync('.').filter(f => f.startsWith('node_trace.') && f.endsWith('.log'));\n if (traceFiles.length === 0) process.exit(0);\n try {\n const v8Data = JSON.parse(readFileSync(traceFiles[0], 'utf-8'));\n const ourData = JSON.parse(readFileSync('${outputPath}', 'utf-8'));\n normalize(v8Data.traceEvents);\n const merged = { traceEvents: [...v8Data.traceEvents, ...ourData.traceEvents] };\n writeFileSync('${outputPath}', JSON.stringify(merged));\n console.log('Merged ' + v8Data.traceEvents.length + ' V8 events into ' + '${outputPath}');\n } catch (e) { console.error('Merge failed:', e.message); }\n }, 100);\n `;\n\n process.on(\"exit\", () => {\n const child = spawn(\"node\", [\"-e\", mergeScript], {\n detached: true,\n stdio: \"inherit\",\n cwd,\n });\n child.unref();\n });\n}\n","import type {\n ReportColumnGroup,\n ReportGroup,\n ResultsMapper,\n} from \"./BenchmarkReport.ts\";\nimport type { GitVersion } from \"./GitUtils.ts\";\nimport type {\n BenchmarkData,\n DifferenceCI,\n FormattedStat,\n GroupData,\n ReportData,\n} from \"./html/index.ts\";\nimport { bootstrapDifferenceCI } from \"./StatisticalUtils.ts\";\n\nexport interface PrepareHtmlOptions {\n cliArgs?: Record<string, unknown>;\n sections?: ResultsMapper[];\n currentVersion?: GitVersion;\n baselineVersion?: GitVersion;\n}\n\n/** Find higherIsBetter from first comparable column in sections */\nfunction findHigherIsBetter(sections?: ResultsMapper[]): boolean {\n const cols = sections?.flatMap(s => s.columns().flatMap(g => g.columns));\n return cols?.find(c => c.comparable)?.higherIsBetter ?? false;\n}\n\n/** Flip CI percent for metrics where higher is better (e.g., lines/sec) */\nfunction flipCI(ci: DifferenceCI): DifferenceCI {\n return {\n percent: -ci.percent,\n ci: [-ci.ci[1], -ci.ci[0]],\n direction: ci.direction,\n histogram: ci.histogram?.map(bin => ({ x: -bin.x, count: bin.count })),\n };\n}\n\n/** Prepare ReportData from benchmark results for HTML rendering */\nexport function prepareHtmlData(\n groups: ReportGroup[],\n options: PrepareHtmlOptions,\n): ReportData {\n const { cliArgs, sections, currentVersion, baselineVersion } = options;\n const higherIsBetter = findHigherIsBetter(sections);\n return {\n groups: groups.map(group =>\n prepareGroupData(group, sections, higherIsBetter),\n ),\n metadata: {\n timestamp: new Date().toISOString(),\n bencherVersion: process.env.npm_package_version || \"unknown\",\n cliArgs,\n gcTrackingEnabled: cliArgs?.[\"gc-stats\"] === true,\n currentVersion,\n baselineVersion,\n },\n };\n}\n\n/** @return group data with bootstrap CI comparisons against baseline */\nfunction prepareGroupData(\n group: ReportGroup,\n sections?: ResultsMapper[],\n higherIsBetter?: boolean,\n): GroupData {\n const baselineSamples = group.baseline?.measuredResults.samples;\n return {\n name: group.name,\n baseline: group.baseline\n ? prepareBenchmarkData(group.baseline, sections)\n : undefined,\n benchmarks: group.reports.map(report => {\n const samples = report.measuredResults.samples;\n const rawCI =\n baselineSamples && samples\n ? bootstrapDifferenceCI(baselineSamples, samples)\n : undefined;\n const comparisonCI = rawCI && higherIsBetter ? flipCI(rawCI) : rawCI;\n return { ...prepareBenchmarkData(report, sections), comparisonCI };\n }),\n };\n}\n\n/** @return benchmark data with samples, stats, and formatted section values */\nfunction prepareBenchmarkData(\n report: {\n name: string;\n measuredResults: any;\n metadata?: Record<string, unknown>;\n },\n sections?: ResultsMapper[],\n): Omit<BenchmarkData, \"comparisonCI\"> {\n const { measuredResults } = report;\n return {\n name: report.name,\n samples: measuredResults.samples,\n warmupSamples: measuredResults.warmupSamples,\n allocationSamples: measuredResults.allocationSamples,\n heapSamples: measuredResults.heapSamples,\n gcEvents: measuredResults.nodeGcTime?.events,\n optSamples: measuredResults.optSamples,\n pausePoints: measuredResults.pausePoints,\n stats: measuredResults.time,\n heapSize: measuredResults.heapSize,\n sectionStats: sections ? extractSectionStats(report, sections) : undefined,\n };\n}\n\n/** @return formatted stats from all sections for tooltip display */\nfunction extractSectionStats(\n report: { measuredResults: any; metadata?: Record<string, unknown> },\n sections: ResultsMapper[],\n): FormattedStat[] {\n return sections.flatMap(section => {\n const vals = section.extract(report.measuredResults, report.metadata);\n return section.columns().flatMap(g => formatGroupStats(vals, g));\n });\n}\n\n/** @return formatted stats for one column group, skipping undefined values */\nfunction formatGroupStats(\n values: Record<string, unknown>,\n group: ReportColumnGroup<Record<string, unknown>>,\n): FormattedStat[] {\n return group.columns\n .map(c => formatColumnStat(values, c, group.groupTitle))\n .filter((s): s is FormattedStat => s !== undefined);\n}\n\ntype ColumnLike = {\n key: string;\n title: string;\n formatter?: (v: unknown) => string | null;\n};\n\n/** @return formatted stat for a single column, or undefined if empty/placeholder */\nfunction formatColumnStat(\n values: Record<string, unknown>,\n col: ColumnLike,\n groupTitle?: string,\n): FormattedStat | undefined {\n const raw = values[col.key];\n if (raw === undefined) return undefined;\n const formatted = col.formatter ? col.formatter(raw) : String(raw);\n if (!formatted || formatted === \"—\" || formatted === \"\") return undefined;\n return { label: col.title, value: formatted, groupTitle };\n}\n","import pc from \"picocolors\";\nimport type { HeapProfile, ProfileNode } from \"./HeapSampler.ts\";\n\n/** Sum selfSize across all nodes in profile (before any filtering) */\nexport function totalProfileBytes(profile: HeapProfile): number {\n let total = 0;\n function walk(node: ProfileNode): void {\n total += node.selfSize;\n for (const child of node.children || []) walk(child);\n }\n walk(profile.head);\n return total;\n}\n\nexport interface CallFrame {\n fn: string;\n url: string;\n line: number; // 1-indexed for display\n col: number;\n}\n\nexport interface HeapSite {\n fn: string;\n url: string;\n line: number; // 1-indexed for display\n col: number;\n bytes: number;\n stack?: CallFrame[]; // call stack from root to this frame\n}\n\n/** Flatten profile tree into sorted list of allocation sites with call stacks */\nexport function flattenProfile(profile: HeapProfile): HeapSite[] {\n const sites: HeapSite[] = [];\n\n function walk(node: ProfileNode, stack: CallFrame[]): void {\n const { functionName, url, lineNumber, columnNumber } = node.callFrame;\n const fn = functionName || \"(anonymous)\";\n const col = columnNumber ?? 0;\n const frame: CallFrame = { fn, url: url || \"\", line: lineNumber + 1, col };\n const newStack = [...stack, frame];\n\n if (node.selfSize > 0) {\n sites.push({\n ...frame,\n bytes: node.selfSize,\n stack: newStack,\n });\n }\n for (const child of node.children || []) walk(child, newStack);\n }\n\n walk(profile.head, []);\n return sites.sort((a, b) => b.bytes - a.bytes);\n}\n\nexport type UserCodeFilter = (site: CallFrame) => boolean;\n\n/** Check if site is user code (not node internals) */\nexport function isNodeUserCode(site: CallFrame): boolean {\n if (!site.url) return false;\n if (site.url.startsWith(\"node:\")) return false;\n if (site.url.includes(\"(native)\")) return false;\n if (site.url.includes(\"internal/\")) return false;\n return true;\n}\n\n/** Check if site is user code (not browser internals) */\nexport function isBrowserUserCode(site: CallFrame): boolean {\n if (!site.url) return false;\n if (site.url.startsWith(\"chrome-extension://\")) return false;\n if (site.url.startsWith(\"devtools://\")) return false;\n if (site.url.includes(\"(native)\")) return false;\n return true;\n}\n\n/** Filter sites to user code only */\nexport function filterSites(\n sites: HeapSite[],\n isUser: UserCodeFilter = isNodeUserCode,\n): HeapSite[] {\n return sites.filter(isUser);\n}\n\n/** Aggregate sites by location (combine same file:line:col) */\nexport function aggregateSites(sites: HeapSite[]): HeapSite[] {\n const byLocation = new Map<string, HeapSite>();\n\n for (const site of sites) {\n const key = `${site.url}:${site.line}:${site.col}`;\n const existing = byLocation.get(key);\n if (existing) {\n existing.bytes += site.bytes;\n } else {\n byLocation.set(key, { ...site });\n }\n }\n\n return [...byLocation.values()].sort((a, b) => b.bytes - a.bytes);\n}\n\nfunction fmtBytes(bytes: number): string {\n if (bytes >= 1024 * 1024) return `${(bytes / 1024 / 1024).toFixed(2)} MB`;\n if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${bytes} B`;\n}\n\nexport interface HeapReportOptions {\n topN: number;\n stackDepth?: number;\n verbose?: boolean;\n userOnly?: boolean; // filter to user code only (hide node internals)\n isUserCode?: UserCodeFilter; // predicate for user vs internal code\n totalAll?: number; // total across all nodes (before filtering)\n totalUserCode?: number; // total for user code only\n sampleCount?: number; // number of samples taken\n}\n\n/** Format heap report for console output */\nexport function formatHeapReport(\n sites: HeapSite[],\n options: HeapReportOptions,\n): string {\n const { topN, stackDepth = 3, verbose = false } = options;\n const { totalAll, totalUserCode, sampleCount } = options;\n const isUser = options.isUserCode ?? isNodeUserCode;\n const lines: string[] = [];\n lines.push(`Heap allocation sites (top ${topN}, garbage included):`);\n\n for (const site of sites.slice(0, topN)) {\n if (verbose) {\n formatVerboseSite(lines, site, stackDepth, isUser);\n } else {\n formatCompactSite(lines, site, stackDepth, isUser);\n }\n }\n\n lines.push(\"\");\n if (totalAll !== undefined)\n lines.push(`Total (all): ${fmtBytes(totalAll)}`);\n if (totalUserCode !== undefined)\n lines.push(`Total (user-code): ${fmtBytes(totalUserCode)}`);\n if (sampleCount !== undefined)\n lines.push(`Samples: ${sampleCount.toLocaleString()}`);\n\n return lines.join(\"\\n\");\n}\n\n/** Compact single-line format: `49 MB fn1 <- fn2 <- fn3` */\nfunction formatCompactSite(\n lines: string[],\n site: HeapSite,\n stackDepth: number,\n isUser: UserCodeFilter,\n): void {\n const bytes = fmtBytes(site.bytes).padStart(10);\n const fns = [site.fn];\n\n if (site.stack && site.stack.length > 1) {\n const callers = site.stack.slice(0, -1).reverse().slice(0, stackDepth);\n for (const frame of callers) {\n if (!frame.url || !isUser(frame)) continue;\n fns.push(frame.fn);\n }\n }\n\n const line = `${bytes} ${fns.join(\" <- \")}`;\n lines.push(isUser(site) ? line : pc.dim(line));\n}\n\n/** Verbose multi-line format with file:// paths and line numbers */\nfunction formatVerboseSite(\n lines: string[],\n site: HeapSite,\n stackDepth: number,\n isUser: UserCodeFilter,\n): void {\n const bytes = fmtBytes(site.bytes).padStart(10);\n const loc = site.url ? `${site.url}:${site.line}:${site.col}` : \"(unknown)\";\n const dimFn = isUser(site) ? (s: string) => s : pc.dim;\n\n lines.push(dimFn(`${bytes} ${site.fn} ${loc}`));\n\n if (site.stack && site.stack.length > 1) {\n const callers = site.stack.slice(0, -1).reverse().slice(0, stackDepth);\n for (const frame of callers) {\n if (!frame.url || !isUser(frame)) continue;\n const callerLoc = `${frame.url}:${frame.line}:${frame.col}`;\n lines.push(dimFn(` <- ${frame.fn} ${callerLoc}`));\n }\n }\n}\n\n/** Get total bytes from sites */\nexport function totalBytes(sites: HeapSite[]): number {\n return sites.reduce((sum, s) => sum + s.bytes, 0);\n}\n","import type { GitVersion, GroupData, ReportData } from \"./Types.ts\";\n\nconst skipArgs = new Set([\"_\", \"$0\", \"html\", \"export-html\"]);\n\n/** Format ISO date as local time with UTC: \"Jan 9, 2026, 3:45 PM (2026-01-09T23:45:00Z)\" */\nexport function formatDateWithTimezone(isoDate: string): string {\n const date = new Date(isoDate);\n const local = date.toLocaleString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n });\n const utc = date.toISOString().replace(\".000Z\", \"Z\");\n return `${local} (${utc})`;\n}\n\n/** Format relative time: \"5m ago\", \"2h ago\", \"yesterday\", \"3 days ago\" */\nexport function formatRelativeTime(isoDate: string): string {\n const date = new Date(isoDate);\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n const diffDays = Math.floor(diffMs / 86400000);\n\n if (diffMins < 1) return \"just now\";\n if (diffMins < 60) return `${diffMins}m ago`;\n if (diffHours < 24) return `${diffHours}h ago`;\n if (diffDays === 1) return \"yesterday\";\n if (diffDays < 30) return `${diffDays} days ago`;\n return date.toLocaleDateString(\"en-US\", { month: \"short\", day: \"numeric\" });\n}\n\n/** Format git version for display: \"abc1234* (5m ago)\" */\nfunction formatVersion(version?: GitVersion): string {\n if (!version || version.hash === \"unknown\") return \"unknown\";\n const hashDisplay = version.dirty ? `${version.hash}*` : version.hash;\n const timeDisplay = version.date ? formatRelativeTime(version.date) : \"\";\n return timeDisplay ? `${hashDisplay} (${timeDisplay})` : hashDisplay;\n}\n\n/** Render current/baseline version info as an HTML div */\nfunction versionInfoHtml(data: ReportData): string {\n const { currentVersion, baselineVersion } = data.metadata;\n if (!currentVersion && !baselineVersion) return \"\";\n const parts: string[] = [];\n if (currentVersion) parts.push(`Current: ${formatVersion(currentVersion)}`);\n if (baselineVersion)\n parts.push(`Baseline: ${formatVersion(baselineVersion)}`);\n return `<div class=\"version-info\">${parts.join(\" | \")}</div>`;\n}\n\nconst badgeLabels = {\n faster: \"Faster\",\n slower: \"Slower\",\n uncertain: \"Inconclusive\",\n};\n\n/** Render faster/slower/uncertain badge with CI plot container */\nfunction comparisonBadge(group: GroupData, groupIndex: number): string {\n const ci = group.benchmarks[0]?.comparisonCI;\n if (!ci) return \"\";\n const label = badgeLabels[ci.direction];\n return `\n <span class=\"badge badge-${ci.direction}\">${label}</span>\n <div id=\"ci-plot-${groupIndex}\" class=\"ci-plot-container\"></div>\n `;\n}\nconst defaultArgs: Record<string, unknown> = {\n worker: true,\n time: 5,\n warmup: 500,\n \"pause-interval\": 0,\n \"pause-duration\": 100,\n};\n\n/** @return true if this CLI arg should be hidden from the report header */\nfunction shouldSkipArg(\n key: string,\n value: unknown,\n adaptive: unknown,\n): boolean {\n if (skipArgs.has(key) || value === undefined || value === false) return true;\n if (defaultArgs[key] === value) return true;\n if (!key.includes(\"-\") && key !== key.toLowerCase()) return true; // skip yargs camelCase aliases\n if (key === \"convergence\" && !adaptive) return true;\n return false;\n}\n\n/** Reconstruct the CLI invocation string, omitting default/internal args */\nfunction formatCliArgs(args?: Record<string, unknown>): string {\n if (!args) return \"bb bench\";\n const parts = [\"bb bench\"];\n for (const [key, value] of Object.entries(args)) {\n if (shouldSkipArg(key, value, args.adaptive)) continue;\n parts.push(value === true ? `--${key}` : `--${key} ${value}`);\n }\n return parts.join(\" \");\n}\n\n/** Generate complete HTML document with embedded data and visualizations */\nexport function generateHtmlDocument(data: ReportData): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Benchmark Report - ${new Date().toLocaleDateString()}</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n background: #f5f5f5;\n padding: 20px;\n line-height: 1.6;\n }\n .header {\n background: white;\n padding: 10px 15px;\n border-radius: 8px;\n margin-bottom: 20px;\n box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n h1 { display: none; }\n h2 {\n color: #555;\n margin: 30px 0 20px;\n font-size: 20px;\n border-bottom: 2px solid #e0e0e0;\n padding-bottom: 10px;\n }\n .metadata { color: #666; font-size: 12px; }\n .cli-args {\n font-family: \"SF Mono\", Monaco, \"Consolas\", monospace;\n font-size: 11px;\n color: #555;\n background: #f0f0f0;\n padding: 6px 10px;\n border-radius: 4px;\n word-break: break-word;\n }\n .comparison-mode {\n background: #fff3cd;\n color: #856404;\n padding: 8px 12px;\n border-radius: 4px;\n display: inline-block;\n margin-top: 10px;\n font-weight: 500;\n }\n .plot-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 20px;\n margin-bottom: 30px;\n }\n .plot-grid.second-row { grid-template-columns: 1fr; }\n .plot-container {\n background: white;\n padding: 20px;\n border-radius: 8px;\n box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n }\n .plot-container.full-width { grid-column: 1 / -1; }\n .plot-title { font-size: 18px; font-weight: 600; margin-bottom: 8px; color: #333; }\n .plot-description { font-size: 14px; color: #666; margin-bottom: 15px; }\n .plot-area {\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 300px;\n }\n .plot-area svg { overflow: visible; }\n .plot-area svg g[aria-label=\"x-axis label\"] text { font-size: 14px; }\n .summary-stats { background: #f8f9fa; padding: 15px; border-radius: 6px; margin-top: 20px; }\n .stats-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));\n gap: 10px;\n margin-top: 10px;\n }\n .stat-item { background: white; padding: 10px; border-radius: 4px; text-align: center; }\n .stat-label { font-size: 12px; color: #666; text-transform: uppercase; letter-spacing: 0.5px; }\n .stat-value { font-size: 18px; font-weight: 600; color: #333; margin-top: 4px; }\n .loading { color: #666; font-style: italic; padding: 20px; text-align: center; }\n .error { color: #d32f2f; background: #ffebee; padding: 15px; border-radius: 4px; margin: 10px 0; }\n .ci-faster { color: #22c55e; }\n .ci-slower { color: #ef4444; }\n .ci-uncertain { color: #6b7280; }\n .group-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin: 30px 0 20px;\n padding-bottom: 10px;\n border-bottom: 2px solid #e0e0e0;\n }\n .group-header h2 { margin: 0; border: none; padding: 0; }\n .badge {\n font-size: 12px;\n font-weight: 600;\n padding: 4px 10px;\n border-radius: 12px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n .badge-faster { background: #dcfce7; color: #166534; }\n .badge-slower { background: #fee2e2; color: #991b1b; }\n .badge-uncertain { background: #dbeafe; color: #1e40af; }\n .version-info { font-size: 12px; color: #666; margin-top: 6px; }\n .header-right { text-align: right; }\n .ci-plot-container { display: inline-block; vertical-align: middle; margin-left: 8px; }\n .ci-plot-container svg { display: block; }\n </style>\n</head>\n<body>\n <div class=\"header\">\n <div class=\"cli-args\">${formatCliArgs(data.metadata.cliArgs)}</div>\n <div class=\"header-right\">\n <div class=\"metadata\">Generated: ${formatDateWithTimezone(new Date().toISOString())}</div>\n ${versionInfoHtml(data)}\n </div>\n </div>\n\n ${data.groups\n .map(\n (group, i) => `\n <div id=\"group-${i}\">\n ${\n group.benchmarks.length > 0\n ? `\n <div class=\"group-header\">\n <h2>${group.name}</h2>\n ${comparisonBadge(group, i)}\n </div>\n\n <div class=\"plot-grid\">\n <div class=\"plot-container\">\n <div class=\"plot-title\">Time per Sample</div>\n <div class=\"plot-description\">Execution time for each sample in collection order</div>\n <div id=\"sample-timeseries-${i}\" class=\"plot-area\">\n <div class=\"loading\">Loading time series...</div>\n </div>\n </div>\n\n <div class=\"plot-container\">\n <div class=\"plot-title\">Time Distribution</div>\n <div class=\"plot-description\">Frequency distribution of execution times</div>\n <div id=\"histogram-${i}\" class=\"plot-area\">\n <div class=\"loading\">Loading histogram...</div>\n </div>\n </div>\n </div>\n\n <div id=\"stats-${i}\"></div>\n `\n : '<div class=\"error\">No benchmark data available for this group</div>'\n }\n </div>\n `,\n )\n .join(\"\")}\n\n <script type=\"importmap\">\n {\n \"imports\": {\n \"d3\": \"https://cdn.jsdelivr.net/npm/d3@7/+esm\",\n \"@observablehq/plot\": \"https://cdn.jsdelivr.net/npm/@observablehq/plot@0.6/+esm\"\n }\n }\n </script>\n <script type=\"module\">\n import { renderPlots } from \"./plots.js\";\n const benchmarkData = ${JSON.stringify(data, null, 2)};\n renderPlots(benchmarkData);\n </script>\n</body>\n</html>`;\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { createServer, type Server } from \"node:http\";\nimport { dirname, extname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport open from \"open\";\nimport { generateHtmlDocument } from \"./HtmlTemplate.ts\";\nimport type {\n HtmlReportOptions,\n HtmlReportResult,\n ReportData,\n} from \"./Types.ts\";\n\n/** Generate HTML report from prepared data and optionally open in browser */\nexport async function generateHtmlReport(\n data: ReportData,\n options: HtmlReportOptions,\n): Promise<HtmlReportResult> {\n const html = generateHtmlDocument(data);\n\n const reportDir = options.outputPath || (await createReportDir());\n await mkdir(reportDir, { recursive: true });\n\n await writeFile(join(reportDir, \"index.html\"), html, \"utf-8\");\n const plots = await loadPlotsBundle();\n await writeFile(join(reportDir, \"plots.js\"), plots, \"utf-8\");\n await writeLatestRedirect(reportDir);\n\n let server: Server | undefined;\n let closeServer: (() => void) | undefined;\n\n if (options.openBrowser) {\n const baseDir = dirname(reportDir);\n const reportName = reportDir.split(\"/\").pop();\n const result = await startReportServer(baseDir, 7979, 7978, 7977);\n server = result.server;\n closeServer = () => result.server.close();\n const openUrl = `http://localhost:${result.port}/${reportName}/`;\n await open(openUrl);\n console.log(`Report opened in browser: ${openUrl}`);\n } else {\n console.log(`Report saved to: ${reportDir}/`);\n }\n\n return { reportDir, server, closeServer };\n}\n\n/** Start HTTP server for report directory, trying fallback ports if needed */\nasync function startReportServer(\n baseDir: string,\n ...ports: number[]\n): Promise<{ server: Server; port: number }> {\n const mimeTypes: Record<string, string> = {\n \".html\": \"text/html\",\n \".js\": \"application/javascript\",\n \".css\": \"text/css\",\n \".json\": \"application/json\",\n };\n\n const server = createServer(async (req, res) => {\n const url = req.url || \"/\";\n const suffix = url.endsWith(\"/\") ? url + \"index.html\" : url;\n const filePath = join(baseDir, suffix);\n try {\n const content = await readFile(filePath);\n const mime = mimeTypes[extname(filePath)] || \"application/octet-stream\";\n res.setHeader(\"Content-Type\", mime);\n res.end(content);\n } catch {\n res.statusCode = 404;\n res.end(\"Not found\");\n }\n });\n\n for (const port of ports) {\n try {\n return await tryListen(server, port);\n } catch {\n // Port in use, try next\n }\n }\n return tryListen(server, 0);\n}\n\n/** Listen on a port, resolving with the actual port or rejecting on error */\nfunction tryListen(\n server: Server,\n port: number,\n): Promise<{ server: Server; port: number }> {\n return new Promise((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(port, () => {\n server.removeListener(\"error\", reject);\n const addr = server.address();\n const actualPort = typeof addr === \"object\" && addr ? addr.port : port;\n resolve({ server, port: actualPort });\n });\n });\n}\n\n/** Create a timestamped report directory under ./bench-report/ */\nasync function createReportDir(): Promise<string> {\n const base = \"./bench-report\";\n await mkdir(base, { recursive: true });\n const ts = new Date().toISOString().replace(/[:.]/g, \"-\").slice(0, 19);\n return join(base, `report-${ts}`);\n}\n\n/** Read the pre-built browser plots bundle from dist/ */\nasync function loadPlotsBundle(): Promise<string> {\n const thisDir = dirname(fileURLToPath(import.meta.url));\n const builtPath = join(thisDir, \"browser/index.js\");\n const devPath = join(thisDir, \"../../dist/browser/index.js\");\n try {\n return await readFile(builtPath, \"utf-8\");\n } catch {}\n return readFile(devPath, \"utf-8\");\n}\n\n/** Write an index.html in the parent dir that redirects to this report */\nasync function writeLatestRedirect(reportDir: string): Promise<void> {\n const baseDir = dirname(reportDir);\n const reportName = reportDir.split(\"/\").pop();\n const html = `<!DOCTYPE html>\n<html><head>\n <meta http-equiv=\"refresh\" content=\"0; url=./${reportName}/\">\n <script>location.href = \"./${reportName}/\";</script>\n</head><body>\n <a href=\"./${reportName}/\">Latest report</a>\n</body></html>`;\n await writeFile(join(baseDir, \"index.html\"), html, \"utf-8\");\n}\n","import type { BenchMatrix } from \"../BenchMatrix.ts\";\nimport { loadCasesModule } from \"./CaseLoader.ts\";\nimport { discoverVariants } from \"./VariantLoader.ts\";\n\n/** Filter for matrix case/variant selection */\nexport interface MatrixFilter {\n case?: string;\n variant?: string;\n}\n\n/** Parse filter string: \"case/variant\", \"case/\", \"/variant\", or \"case\" */\nexport function parseMatrixFilter(filter: string): MatrixFilter {\n if (filter.includes(\"/\")) {\n const [casePart, variantPart] = filter.split(\"/\", 2);\n return {\n case: casePart || undefined,\n variant: variantPart || undefined,\n };\n }\n return { case: filter };\n}\n\n/** Filtered matrix with explicit case and variant lists */\nexport interface FilteredMatrix<T = unknown> extends BenchMatrix<T> {\n filteredCases?: string[];\n filteredVariants?: string[];\n}\n\n/** Apply filter to a matrix, merging with existing filters via intersection */\nexport async function filterMatrix<T>(\n matrix: FilteredMatrix<T>,\n filter?: MatrixFilter,\n): Promise<FilteredMatrix<T>> {\n if (!filter || (!filter.case && !filter.variant)) return matrix;\n\n const caseList = await getFilteredCases(matrix, filter.case);\n const variantList = await getFilteredVariants(matrix, filter.variant);\n\n const filteredCases =\n caseList && matrix.filteredCases\n ? caseList.filter(c => matrix.filteredCases!.includes(c))\n : (caseList ?? matrix.filteredCases);\n\n const filteredVariants =\n variantList && matrix.filteredVariants\n ? variantList.filter(v => matrix.filteredVariants!.includes(v))\n : (variantList ?? matrix.filteredVariants);\n\n return { ...matrix, filteredCases, filteredVariants };\n}\n\n/** Get case IDs matching filter pattern */\nasync function getFilteredCases<T>(\n matrix: BenchMatrix<T>,\n casePattern?: string,\n): Promise<string[] | undefined> {\n if (!casePattern) return undefined;\n\n const caseIds = matrix.casesModule\n ? (await loadCasesModule(matrix.casesModule)).cases\n : matrix.cases;\n if (!caseIds) return [\"default\"]; // implicit single case\n\n const filtered = caseIds.filter(id => matchPattern(id, casePattern));\n if (filtered.length === 0) {\n throw new Error(`No cases match filter: \"${casePattern}\"`);\n }\n return filtered;\n}\n\n/** Get variant IDs matching filter pattern */\nasync function getFilteredVariants<T>(\n matrix: BenchMatrix<T>,\n variantPattern?: string,\n): Promise<string[] | undefined> {\n if (!variantPattern) return undefined;\n\n if (matrix.variants) {\n const ids = Object.keys(matrix.variants).filter(id =>\n matchPattern(id, variantPattern),\n );\n if (ids.length === 0) {\n throw new Error(`No variants match filter: \"${variantPattern}\"`);\n }\n return ids;\n }\n\n if (matrix.variantDir) {\n const allIds = await discoverVariants(matrix.variantDir);\n const filtered = allIds.filter(id => matchPattern(id, variantPattern));\n if (filtered.length === 0) {\n throw new Error(`No variants match filter: \"${variantPattern}\"`);\n }\n return filtered;\n }\n\n throw new Error(\"BenchMatrix requires 'variants' or 'variantDir'\");\n}\n\n/** Match id against pattern (case-insensitive substring) */\nfunction matchPattern(id: string, pattern: string): boolean {\n return id.toLowerCase().includes(pattern.toLowerCase());\n}\n","import pico from \"picocolors\";\n\nconst isTest = process.env.NODE_ENV === \"test\" || process.env.VITEST === \"true\";\nconst { red } = isTest ? { red: (str: string) => str } : pico;\n\nconst lowConfidence = 80;\n\n/** @return convergence percentage with color for low values */\nexport function formatConvergence(v: unknown): string {\n if (typeof v !== \"number\") return \"—\";\n const pct = `${Math.round(v)}%`;\n return v < lowConfidence ? red(pct) : pct;\n}\n\n/** @return coefficient of variation as ±percentage */\nexport function formatCV(v: unknown): string {\n if (typeof v !== \"number\") return \"\";\n return `±${(v * 100).toFixed(1)}%`;\n}\n","import type { ReportColumnGroup, ResultsMapper } from \"./BenchmarkReport.ts\";\nimport type { MeasuredResults } from \"./MeasuredResults.ts\";\nimport { formatConvergence } from \"./table-util/ConvergenceFormatters.ts\";\nimport {\n formatBytes,\n integer,\n percent,\n percentPrecision,\n timeMs,\n} from \"./table-util/Formatters.ts\";\n\nexport interface TimeStats {\n mean?: number;\n p50?: number;\n p99?: number;\n convergence?: number;\n}\n\n/** Section: mean, p50, p99 timing with convergence */\nexport const timeSection: ResultsMapper<TimeStats> = {\n extract: (results: MeasuredResults) => ({\n mean: results.time?.avg,\n p50: results.time?.p50,\n p99: results.time?.p99,\n convergence: results.convergence?.confidence,\n }),\n columns: (): ReportColumnGroup<TimeStats>[] => [\n {\n groupTitle: \"time\",\n columns: [\n { key: \"mean\", title: \"mean\", formatter: timeMs, comparable: true },\n { key: \"p50\", title: \"p50\", formatter: timeMs, comparable: true },\n { key: \"p99\", title: \"p99\", formatter: timeMs, comparable: true },\n ],\n },\n {\n columns: [\n { key: \"convergence\", title: \"conv%\", formatter: formatConvergence },\n ],\n },\n ],\n};\n\nexport interface GcSectionStats {\n gc?: number; // GC time as fraction of total bench time\n}\n\n/** Section: GC time as fraction of total benchmark time (Node performance hooks) */\nexport const gcSection: ResultsMapper<GcSectionStats> = {\n extract: (results: MeasuredResults) => {\n const { nodeGcTime, time, samples } = results;\n if (!nodeGcTime || !time?.avg) return { gc: undefined };\n const totalBenchTime = time.avg * samples.length;\n if (totalBenchTime <= 0) return { gc: undefined };\n const gcTime = nodeGcTime.inRun / totalBenchTime;\n // GC time can't exceed total time\n return { gc: gcTime <= 1 ? gcTime : undefined };\n },\n columns: (): ReportColumnGroup<GcSectionStats>[] => [\n {\n groupTitle: \"gc\",\n columns: [\n { key: \"gc\", title: \"mean\", formatter: percent, comparable: true },\n ],\n },\n ],\n};\n\nexport interface GcStatsInfo {\n allocPerIter?: number;\n collected?: number;\n scavenges?: number;\n fullGCs?: number;\n promoPercent?: number;\n pausePerIter?: number;\n}\n\n/** Section: detailed GC stats from --trace-gc-nvp (allocation, promotion, pauses) */\nexport const gcStatsSection: ResultsMapper<GcStatsInfo> = {\n extract: (results: MeasuredResults) => {\n const { gcStats, samples } = results;\n if (!gcStats) return {};\n const iterations = samples.length || 1;\n const { totalAllocated, totalPromoted } = gcStats;\n const hasAlloc = totalAllocated && totalAllocated > 0;\n const promoPercent = hasAlloc\n ? (totalPromoted ?? 0) / totalAllocated\n : undefined;\n return {\n allocPerIter:\n totalAllocated != null ? totalAllocated / iterations : undefined,\n collected: gcStats.totalCollected || undefined,\n scavenges: gcStats.scavenges,\n fullGCs: gcStats.markCompacts,\n promoPercent,\n pausePerIter: gcStats.gcPauseTime / iterations,\n };\n },\n columns: (): ReportColumnGroup<GcStatsInfo>[] => [\n {\n groupTitle: \"gc\",\n columns: [\n { key: \"allocPerIter\", title: \"alloc/iter\", formatter: formatBytes },\n { key: \"collected\", title: \"collected\", formatter: formatBytes },\n { key: \"scavenges\", title: \"scav\", formatter: integer },\n { key: \"fullGCs\", title: \"full\", formatter: integer },\n { key: \"promoPercent\", title: \"promo%\", formatter: percent },\n { key: \"pausePerIter\", title: \"pause/iter\", formatter: timeMs },\n ],\n },\n ],\n};\n\n/** Browser GC section: only fields available from CDP tracing */\nexport const browserGcStatsSection: ResultsMapper<GcStatsInfo> = {\n extract: gcStatsSection.extract,\n columns: (): ReportColumnGroup<GcStatsInfo>[] => [\n {\n groupTitle: \"gc\",\n columns: [\n { key: \"collected\", title: \"collected\", formatter: formatBytes },\n { key: \"scavenges\", title: \"scav\", formatter: integer },\n { key: \"fullGCs\", title: \"full\", formatter: integer },\n { key: \"pausePerIter\", title: \"pause\", formatter: timeMs },\n ],\n },\n ],\n};\n\nexport interface CpuStats {\n cpuCacheMiss?: number;\n cpuStall?: number;\n}\n\n/** Section: CPU L1 cache miss rate and stall rate (requires @mitata/counters) */\nexport const cpuSection: ResultsMapper<CpuStats> = {\n extract: (results: MeasuredResults) => ({\n cpuCacheMiss: results.cpuCacheMiss,\n cpuStall: results.cpuStall,\n }),\n columns: (): ReportColumnGroup<CpuStats>[] => [\n {\n groupTitle: \"cpu\",\n columns: [\n { key: \"cpuCacheMiss\", title: \"L1 miss\", formatter: percent },\n { key: \"cpuStall\", title: \"stalls\", formatter: percentPrecision(2) },\n ],\n },\n ],\n};\n\nexport interface RunStats {\n runs?: number;\n}\n\n/** Section: number of sample iterations */\nexport const runsSection: ResultsMapper<RunStats> = {\n extract: (results: MeasuredResults) => ({\n runs: results.samples.length,\n }),\n columns: (): ReportColumnGroup<RunStats>[] => [\n { columns: [{ key: \"runs\", title: \"runs\", formatter: integer }] },\n ],\n};\n\n/** Section: total sampling duration in seconds (brackets if >= 30s) */\nexport const totalTimeSection: ResultsMapper<{ totalTime?: number }> = {\n extract: (results: MeasuredResults) => ({\n totalTime: results.totalTime,\n }),\n columns: (): ReportColumnGroup<{ totalTime?: number }>[] => [\n {\n columns: [\n {\n key: \"totalTime\",\n title: \"time\",\n formatter: v => {\n if (typeof v !== \"number\") return \"\";\n return v >= 30 ? `[${v.toFixed(1)}s]` : `${v.toFixed(1)}s`;\n },\n },\n ],\n },\n ],\n};\n\nexport interface AdaptiveStats {\n median?: number;\n mean?: number;\n p99?: number;\n convergence?: number;\n}\n\n/** Section: median, mean, p99, and convergence for adaptive mode */\nexport const adaptiveSection: ResultsMapper<AdaptiveStats> = {\n extract: (results: MeasuredResults) => ({\n median: results.time?.p50,\n mean: results.time?.avg,\n p99: results.time?.p99,\n convergence: results.convergence?.confidence,\n }),\n columns: (): ReportColumnGroup<AdaptiveStats>[] => [\n {\n groupTitle: \"time\",\n columns: [\n { key: \"median\", title: \"median\", formatter: timeMs, comparable: true },\n { key: \"mean\", title: \"mean\", formatter: timeMs, comparable: true },\n { key: \"p99\", title: \"p99\", formatter: timeMs },\n ],\n },\n {\n columns: [\n { key: \"convergence\", title: \"conv%\", formatter: formatConvergence },\n ],\n },\n ],\n};\n\n/** Build generic sections based on CLI flags */\nexport function buildGenericSections(args: {\n \"gc-stats\"?: boolean;\n \"heap-sample\"?: boolean;\n}): ResultsMapper[] {\n const sections: ResultsMapper[] = [];\n if (args[\"gc-stats\"]) sections.push(gcStatsSection);\n sections.push(runsSection);\n return sections;\n}\n\nexport interface OptStats {\n tiers?: string; // tier distribution summary\n deopt?: number; // deopt count\n}\n\n/** Section: V8 optimization tier distribution and deopt count */\nexport const optSection: ResultsMapper<OptStats> = {\n extract: (results: MeasuredResults) => {\n const opt = results.optStatus;\n if (!opt) return {};\n\n const total = Object.values(opt.byTier).reduce((s, t) => s + t.count, 0);\n const tierParts = Object.entries(opt.byTier)\n .sort((a, b) => b[1].count - a[1].count)\n .map(([name, t]) => `${name}:${((t.count / total) * 100).toFixed(0)}%`);\n\n return {\n tiers: tierParts.join(\" \"),\n deopt: opt.deoptCount > 0 ? opt.deoptCount : undefined,\n };\n },\n columns: (): ReportColumnGroup<OptStats>[] => [\n {\n groupTitle: \"v8 opt\",\n columns: [\n {\n key: \"tiers\",\n title: \"tiers\",\n formatter: v => (typeof v === \"string\" ? v : \"\"),\n },\n {\n key: \"deopt\",\n title: \"deopt\",\n formatter: v => (typeof v === \"number\" ? String(v) : \"\"),\n },\n ],\n },\n ],\n};\n","import type { CaseResult, MatrixResults } from \"../BenchMatrix.ts\";\nimport { injectDiffColumns, type ResultsMapper } from \"../BenchmarkReport.ts\";\nimport { totalProfileBytes } from \"../heap-sample/HeapSampleReport.ts\";\nimport { type GcStatsInfo, gcStatsSection } from \"../StandardSections.ts\";\nimport {\n average,\n bootstrapDifferenceCI,\n type DifferenceCI,\n} from \"../StatisticalUtils.ts\";\nimport {\n duration,\n formatBytes,\n formatDiffWithCI,\n truncate,\n} from \"../table-util/Formatters.ts\";\nimport {\n buildTable,\n type ColumnGroup,\n type ResultGroup,\n} from \"../table-util/TableReport.ts\";\n\n/** Custom column definition for extra computed metrics */\nexport interface ExtraColumn {\n key: string;\n title: string;\n groupTitle?: string; // optional column group header\n extract: (caseResult: CaseResult) => unknown;\n formatter?: (value: unknown) => string;\n}\n\n/** Options for matrix report generation */\nexport interface MatrixReportOptions {\n extraColumns?: ExtraColumn[];\n sections?: ResultsMapper[]; // ResultsMapper sections (like BenchSuite)\n variantTitle?: string; // custom title for the variant column (default: \"variant\")\n}\n\n/** Row data for matrix report table */\ninterface MatrixReportRow extends Record<string, unknown> {\n name: string;\n time: number;\n samples: number;\n diffCI?: DifferenceCI;\n}\n\n/** Format matrix results as one table per case */\nexport function reportMatrixResults(\n results: MatrixResults,\n options?: MatrixReportOptions,\n): string {\n const tables = buildCaseTables(results, options);\n const header = `Matrix: ${results.name}`;\n return [header, ...tables].join(\"\\n\\n\");\n}\n\n/** Build one table for each case showing all variants */\nfunction buildCaseTables(\n results: MatrixResults,\n options?: MatrixReportOptions,\n): string[] {\n if (results.variants.length === 0) return [];\n\n // Get all case IDs from first variant (all variants have same cases)\n const caseIds = results.variants[0].cases.map(c => c.caseId);\n return caseIds.map(caseId => buildCaseTable(results, caseId, options));\n}\n\n/** Build table for a single case showing all variants */\nfunction buildCaseTable(\n results: MatrixResults,\n caseId: string,\n options?: MatrixReportOptions,\n): string {\n const caseTitle = formatCaseTitle(results, caseId);\n\n if (options?.sections?.length) {\n return buildSectionTable(results, caseId, options, caseTitle);\n }\n\n const rows = buildCaseRows(results, caseId, options?.extraColumns);\n const hasBaseline = rows.some(r => r.diffCI);\n const columns = buildColumns(hasBaseline, options);\n\n const resultGroup: ResultGroup<MatrixReportRow> = { results: rows };\n const table = buildTable(columns, [resultGroup]);\n return `${caseTitle}\\n${table}`;\n}\n\n/** Build table using ResultsMapper sections */\nfunction buildSectionTable(\n results: MatrixResults,\n caseId: string,\n options: MatrixReportOptions,\n caseTitle: string,\n): string {\n const sections = options.sections!;\n const variantTitle = options.variantTitle ?? \"name\";\n\n const rows: Record<string, unknown>[] = [];\n let hasBaseline = false;\n\n for (const variant of results.variants) {\n const caseResult = variant.cases.find(c => c.caseId === caseId);\n if (!caseResult) continue;\n\n const row: Record<string, unknown> = { name: truncate(variant.id, 25) };\n\n for (const section of sections) {\n Object.assign(\n row,\n section.extract(caseResult.measured, caseResult.metadata),\n );\n }\n\n if (caseResult.baseline) {\n hasBaseline = true;\n const { samples: base } = caseResult.baseline;\n row.diffCI = bootstrapDifferenceCI(base, caseResult.measured.samples);\n }\n\n rows.push(row);\n }\n\n const columnGroups = buildSectionColumns(sections, variantTitle, hasBaseline);\n const resultGroup: ResultGroup<Record<string, unknown>> = { results: rows };\n const table = buildTable(columnGroups, [resultGroup]);\n return `${caseTitle}\\n${table}`;\n}\n\n/** Build column groups from ResultsMapper sections */\nfunction buildSectionColumns(\n sections: ResultsMapper[],\n variantTitle: string,\n hasBaseline: boolean,\n): ColumnGroup<Record<string, unknown>>[] {\n const nameCol: ColumnGroup<Record<string, unknown>> = {\n columns: [{ key: \"name\", title: variantTitle }],\n };\n\n const sectionColumns = sections.flatMap(s => s.columns());\n const columnGroups = hasBaseline\n ? injectDiffColumns(sectionColumns)\n : (sectionColumns as ColumnGroup<Record<string, unknown>>[]);\n\n return [nameCol, ...columnGroups];\n}\n\n/** Build rows for all variants for a given case */\nfunction buildCaseRows(\n results: MatrixResults,\n caseId: string,\n extraColumns?: ExtraColumn[],\n): MatrixReportRow[] {\n return results.variants.flatMap(variant => {\n const caseResult = variant.cases.find(c => c.caseId === caseId);\n return caseResult ? [buildRow(variant.id, caseResult, extraColumns)] : [];\n });\n}\n\n/** Build a single row from case result */\nfunction buildRow(\n variantId: string,\n caseResult: CaseResult,\n extraColumns?: ExtraColumn[],\n): MatrixReportRow {\n const { measured, baseline } = caseResult;\n const samples = measured.samples;\n const time = measured.time?.avg ?? average(samples);\n\n const row: MatrixReportRow = {\n name: truncate(variantId, 25),\n time,\n samples: samples.length,\n };\n\n if (baseline) {\n row.diffCI = bootstrapDifferenceCI(baseline.samples, samples);\n }\n\n if (extraColumns) {\n for (const col of extraColumns) {\n row[col.key] = col.extract(caseResult);\n }\n }\n\n return row;\n}\n\n/** Build column configuration */\nfunction buildColumns(\n hasBaseline: boolean,\n options?: MatrixReportOptions,\n): ColumnGroup<MatrixReportRow>[] {\n const variantTitle = options?.variantTitle ?? \"variant\";\n const nameCol: ColumnGroup<MatrixReportRow> = {\n columns: [{ key: \"name\", title: variantTitle }],\n };\n\n const ciKey = \"diffCI\" as keyof MatrixReportRow;\n const diffCol = { key: ciKey, title: \"Δ% CI\", formatter: formatDiff };\n const timeCol: ColumnGroup<MatrixReportRow> = {\n columns: [\n { key: \"time\", title: \"time\", formatter: duration },\n ...(hasBaseline ? [diffCol] : []),\n ],\n };\n\n const groups: ColumnGroup<MatrixReportRow>[] = [nameCol, timeCol];\n\n // Add extra columns, grouped by groupTitle\n const extraColumns = options?.extraColumns;\n if (extraColumns?.length) {\n const byGroup = new Map<string | undefined, ExtraColumn[]>();\n for (const col of extraColumns) {\n const group = byGroup.get(col.groupTitle) ?? [];\n group.push(col);\n byGroup.set(col.groupTitle, group);\n }\n for (const [groupTitle, cols] of byGroup) {\n groups.push({\n groupTitle,\n columns: cols.map(col => ({\n key: col.key as keyof MatrixReportRow,\n title: col.title,\n formatter: col.formatter ?? String,\n })),\n });\n }\n }\n\n return groups;\n}\n\n/** Format diff with CI, or \"baseline\" marker */\nfunction formatDiff(value: unknown): string | null {\n if (!value) return null;\n return formatDiffWithCI(value as DifferenceCI);\n}\n\n/** Format case title with metadata if available */\nfunction formatCaseTitle(results: MatrixResults, caseId: string): string {\n const caseResult = results.variants[0]?.cases.find(c => c.caseId === caseId);\n const metadata = caseResult?.metadata;\n\n if (metadata && Object.keys(metadata).length > 0) {\n const metaParts = Object.entries(metadata)\n .map(([k, v]) => `${v} ${k}`)\n .join(\", \");\n return `${caseId} (${metaParts})`;\n }\n return caseId;\n}\n\n/** GC statistics columns - derived from gcStatsSection for consistency */\nexport const gcStatsColumns: ExtraColumn[] = gcStatsSection\n .columns()[0]\n .columns.map(col => ({\n key: col.key as string,\n title: col.title,\n groupTitle: \"GC\",\n extract: (r: CaseResult) =>\n gcStatsSection.extract(r.measured)[col.key as keyof GcStatsInfo],\n formatter: (v: unknown) => col.formatter?.(v) ?? \"-\",\n }));\n\n/** Format bytes with fallback to \"-\" for missing values */\nfunction formatBytesOrDash(value: unknown): string {\n return formatBytes(value) ?? \"-\";\n}\n\n/** GC pause time column */\nexport const gcPauseColumn: ExtraColumn = {\n key: \"gcPause\",\n title: \"pause\",\n groupTitle: \"GC\",\n extract: r => r.measured.gcStats?.gcPauseTime,\n formatter: v => (v != null ? `${(v as number).toFixed(1)}ms` : \"-\"),\n};\n\n/** Heap sampling total bytes column */\nexport const heapTotalColumn: ExtraColumn = {\n key: \"heapTotal\",\n title: \"heap\",\n extract: r => {\n const profile = r.measured.heapProfile;\n if (!profile?.head) return undefined;\n return totalProfileBytes(profile);\n },\n formatter: formatBytesOrDash,\n};\n","import type { BenchGroup, BenchSuite } from \"../Benchmark.ts\";\n\n/** Filter benchmarks by name pattern */\nexport function filterBenchmarks(\n suite: BenchSuite,\n filter?: string,\n removeEmpty = true,\n): BenchSuite {\n if (!filter) return suite;\n const regex = createFilterRegex(filter);\n const groups = suite.groups\n .map(group => ({\n ...group,\n benchmarks: group.benchmarks.filter(bench =>\n regex.test(stripCaseSuffix(bench.name)),\n ),\n baseline:\n group.baseline && regex.test(stripCaseSuffix(group.baseline.name))\n ? group.baseline\n : undefined,\n }))\n .filter(group => !removeEmpty || group.benchmarks.length > 0);\n validateFilteredSuite(groups, filter);\n return { name: suite.name, groups };\n}\n\n/** Create regex from filter (literal unless regex-like) */\nfunction createFilterRegex(filter: string): RegExp {\n const looksLikeRegex =\n (filter.startsWith(\"/\") && filter.endsWith(\"/\")) ||\n filter.includes(\"*\") ||\n filter.includes(\"?\") ||\n filter.includes(\"[\") ||\n filter.includes(\"|\") ||\n filter.startsWith(\"^\") ||\n filter.endsWith(\"$\");\n\n if (looksLikeRegex) {\n const pattern =\n filter.startsWith(\"/\") && filter.endsWith(\"/\")\n ? filter.slice(1, -1)\n : filter;\n try {\n return new RegExp(pattern, \"i\");\n } catch {\n return new RegExp(escapeRegex(filter), \"i\");\n }\n }\n\n return new RegExp(\"^\" + escapeRegex(filter), \"i\");\n}\n\n/** Strip case suffix like \" [large]\" from benchmark name for filtering */\nfunction stripCaseSuffix(name: string): string {\n return name.replace(/ \\[.*?\\]$/, \"\");\n}\n\n/** Escape regex special characters */\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/** Ensure at least one benchmark matches filter */\nfunction validateFilteredSuite(groups: BenchGroup[], filter?: string): void {\n if (groups.every(g => g.benchmarks.length === 0)) {\n throw new Error(`No benchmarks match filter: \"${filter}\"`);\n }\n}\n","import pico from \"picocolors\";\nimport { hideBin } from \"yargs/helpers\";\nimport type {\n MatrixResults,\n MatrixSuite,\n RunMatrixOptions,\n} from \"../BenchMatrix.ts\";\nimport { runMatrix } from \"../BenchMatrix.ts\";\nimport type { BenchGroup, BenchmarkSpec, BenchSuite } from \"../Benchmark.ts\";\nimport type { BenchmarkReport, ReportGroup } from \"../BenchmarkReport.ts\";\nimport { reportResults } from \"../BenchmarkReport.ts\";\nimport {\n type BrowserProfileResult,\n profileBrowser,\n} from \"../browser/BrowserHeapSampler.ts\";\nimport { exportBenchmarkJson } from \"../export/JsonExport.ts\";\nimport { exportPerfettoTrace } from \"../export/PerfettoExport.ts\";\nimport type { GitVersion } from \"../GitUtils.ts\";\nimport { prepareHtmlData } from \"../HtmlDataPrep.ts\";\nimport {\n aggregateSites,\n filterSites,\n flattenProfile,\n formatHeapReport,\n type HeapReportOptions,\n isBrowserUserCode,\n totalProfileBytes,\n} from \"../heap-sample/HeapSampleReport.ts\";\nimport { generateHtmlReport } from \"../html/index.ts\";\nimport type { MeasuredResults } from \"../MeasuredResults.ts\";\nimport { loadCasesModule } from \"../matrix/CaseLoader.ts\";\nimport {\n type FilteredMatrix,\n filterMatrix,\n parseMatrixFilter,\n} from \"../matrix/MatrixFilter.ts\";\nimport {\n type MatrixReportOptions,\n reportMatrixResults,\n} from \"../matrix/MatrixReport.ts\";\nimport { checkConvergence } from \"../runners/AdaptiveWrapper.ts\";\nimport { computeStats } from \"../runners/BasicRunner.ts\";\nimport type { RunnerOptions } from \"../runners/BenchRunner.ts\";\nimport type { KnownRunner } from \"../runners/CreateRunner.ts\";\nimport { runBenchmark } from \"../runners/RunnerOrchestrator.ts\";\nimport { msToNs } from \"../runners/RunnerUtils.ts\";\nimport {\n adaptiveSection,\n browserGcStatsSection,\n cpuSection,\n gcStatsSection,\n optSection,\n runsSection,\n timeSection,\n totalTimeSection,\n} from \"../StandardSections.ts\";\nimport {\n type Configure,\n type DefaultCliArgs,\n defaultAdaptiveMaxTime,\n parseCliArgs,\n} from \"./CliArgs.ts\";\nimport { filterBenchmarks } from \"./FilterBenchmarks.ts\";\n\n/** Validate CLI argument combinations */\nfunction validateArgs(args: DefaultCliArgs): void {\n if (args[\"gc-stats\"] && !args.worker && !args.url) {\n throw new Error(\n \"--gc-stats requires worker mode (the default). Remove --no-worker flag.\",\n );\n }\n}\n\n/** Warn about Node-only flags that are ignored in browser mode. */\nfunction warnBrowserFlags(args: DefaultCliArgs): void {\n const ignored: string[] = [];\n if (!args.worker) ignored.push(\"--no-worker\");\n if (args.cpu) ignored.push(\"--cpu\");\n if (args[\"trace-opt\"]) ignored.push(\"--trace-opt\");\n if (args.collect) ignored.push(\"--collect\");\n if (args.adaptive) ignored.push(\"--adaptive\");\n if (args.batches > 1) ignored.push(\"--batches\");\n if (ignored.length) {\n console.warn(yellow(`Ignored in browser mode: ${ignored.join(\", \")}`));\n }\n}\n\ntype RunParams = {\n runner: KnownRunner;\n options: RunnerOptions;\n useWorker: boolean;\n params: unknown;\n metadata?: Record<string, any>;\n};\n\ntype SuiteParams = {\n runner: KnownRunner;\n options: RunnerOptions;\n useWorker: boolean;\n suite: BenchSuite;\n batches: number;\n};\n\n/** Parse CLI with custom configuration */\nexport function parseBenchArgs<T = DefaultCliArgs>(\n configureArgs?: Configure<T>,\n): T & DefaultCliArgs {\n const argv = hideBin(process.argv);\n return parseCliArgs(argv, configureArgs) as T & DefaultCliArgs;\n}\n\n/** Run suite with CLI arguments */\nexport async function runBenchmarks(\n suite: BenchSuite,\n args: DefaultCliArgs,\n): Promise<ReportGroup[]> {\n validateArgs(args);\n const { filter, worker: useWorker, batches = 1 } = args;\n const options = cliToRunnerOptions(args);\n const filtered = filterBenchmarks(suite, filter);\n\n return runSuite({\n suite: filtered,\n runner: \"basic\",\n options,\n useWorker,\n batches,\n });\n}\n\n/** Execute all groups in suite */\nasync function runSuite(params: SuiteParams): Promise<ReportGroup[]> {\n const { suite, runner, options, useWorker, batches } = params;\n const results: ReportGroup[] = [];\n for (const group of suite.groups) {\n results.push(await runGroup(group, runner, options, useWorker, batches));\n }\n return results;\n}\n\n/** Execute group with shared setup, optionally batching to reduce ordering bias */\nasync function runGroup(\n group: BenchGroup,\n runner: KnownRunner,\n options: RunnerOptions,\n useWorker: boolean,\n batches = 1,\n): Promise<ReportGroup> {\n const { name, benchmarks, baseline, setup, metadata } = group;\n const setupParams = await setup?.();\n validateBenchmarkParameters(group);\n\n const runParams = {\n runner,\n options,\n useWorker,\n params: setupParams,\n metadata,\n };\n if (batches === 1) {\n return runSingleBatch(name, benchmarks, baseline, runParams);\n }\n return runMultipleBatches(name, benchmarks, baseline, runParams, batches);\n}\n\n/** Run benchmarks in a single batch */\nasync function runSingleBatch(\n name: string,\n benchmarks: BenchmarkSpec[],\n baseline: BenchmarkSpec | undefined,\n runParams: RunParams,\n): Promise<ReportGroup> {\n const baselineReport = baseline\n ? await runSingleBenchmark(baseline, runParams)\n : undefined;\n const reports = await serialMap(benchmarks, b =>\n runSingleBenchmark(b, runParams),\n );\n return { name, reports, baseline: baselineReport };\n}\n\n/** Run benchmarks in multiple batches, alternating order to reduce bias */\nasync function runMultipleBatches(\n name: string,\n benchmarks: BenchmarkSpec[],\n baseline: BenchmarkSpec | undefined,\n runParams: RunParams,\n batches: number,\n): Promise<ReportGroup> {\n const timePerBatch = (runParams.options.maxTime || 5000) / batches;\n const batchParams = {\n ...runParams,\n options: { ...runParams.options, maxTime: timePerBatch },\n };\n const baselineBatches: MeasuredResults[] = [];\n const benchmarkBatches = new Map<string, MeasuredResults[]>();\n\n for (let i = 0; i < batches; i++) {\n const reverseOrder = i % 2 === 1;\n await runBatchIteration(\n benchmarks,\n baseline,\n batchParams,\n reverseOrder,\n baselineBatches,\n benchmarkBatches,\n );\n }\n\n const meta = runParams.metadata;\n return mergeBatchResults(\n name,\n benchmarks,\n baseline,\n baselineBatches,\n benchmarkBatches,\n meta,\n );\n}\n\n/** Run one batch iteration in either order */\nasync function runBatchIteration(\n benchmarks: BenchmarkSpec[],\n baseline: BenchmarkSpec | undefined,\n runParams: RunParams,\n reverseOrder: boolean,\n baselineBatches: MeasuredResults[],\n benchmarkBatches: Map<string, MeasuredResults[]>,\n): Promise<void> {\n const runBaseline = async () => {\n if (baseline) {\n const r = await runSingleBenchmark(baseline, runParams);\n baselineBatches.push(r.measuredResults);\n }\n };\n const runBenches = async () => {\n for (const b of benchmarks) {\n const r = await runSingleBenchmark(b, runParams);\n appendToMap(benchmarkBatches, b.name, r.measuredResults);\n }\n };\n\n if (reverseOrder) {\n await runBenches();\n await runBaseline();\n } else {\n await runBaseline();\n await runBenches();\n }\n}\n\n/** Merge batch results into final ReportGroup */\nfunction mergeBatchResults(\n name: string,\n benchmarks: BenchmarkSpec[],\n baseline: BenchmarkSpec | undefined,\n baselineBatches: MeasuredResults[],\n benchmarkBatches: Map<string, MeasuredResults[]>,\n metadata?: Record<string, unknown>,\n): ReportGroup {\n const mergedBaseline = baseline\n ? {\n name: baseline.name,\n measuredResults: mergeResults(baselineBatches),\n metadata,\n }\n : undefined;\n const reports = benchmarks.map(b => ({\n name: b.name,\n measuredResults: mergeResults(benchmarkBatches.get(b.name) || []),\n metadata,\n }));\n return { name, reports, baseline: mergedBaseline };\n}\n\n/** Run single benchmark and create report */\nasync function runSingleBenchmark(\n spec: BenchmarkSpec,\n runParams: RunParams,\n): Promise<BenchmarkReport> {\n const { runner, options, useWorker, params, metadata } = runParams;\n const benchmarkParams = { spec, runner, options, useWorker, params };\n const [result] = await runBenchmark(benchmarkParams);\n return { name: spec.name, measuredResults: result, metadata };\n}\n\n/** Warn if parameterized benchmarks lack setup */\nfunction validateBenchmarkParameters(group: BenchGroup): void {\n const { name, setup, benchmarks, baseline } = group;\n if (setup) return;\n\n const allBenchmarks = baseline ? [...benchmarks, baseline] : benchmarks;\n for (const benchmark of allBenchmarks) {\n if (benchmark.fn.length > 0) {\n console.warn(\n `Benchmark \"${benchmark.name}\" in group \"${name}\" expects parameters but no setup() provided.`,\n );\n }\n }\n}\n\n/** Merge multiple batch results into a single MeasuredResults */\nfunction mergeResults(results: MeasuredResults[]): MeasuredResults {\n if (results.length === 0) {\n throw new Error(\"Cannot merge empty results array\");\n }\n if (results.length === 1) return results[0];\n\n const allSamples = results.flatMap(r => r.samples);\n const allWarmup = results.flatMap(r => r.warmupSamples || []);\n const time = computeStats(allSamples);\n const convergence = checkConvergence(allSamples.map(s => s * msToNs));\n\n let offset = 0;\n const allPausePoints = results.flatMap(r => {\n const pts = (r.pausePoints ?? []).map(p => ({\n sampleIndex: p.sampleIndex + offset,\n durationMs: p.durationMs,\n }));\n offset += r.samples.length;\n return pts;\n });\n\n return {\n name: results[0].name,\n samples: allSamples,\n warmupSamples: allWarmup.length ? allWarmup : undefined,\n time,\n totalTime: results.reduce((sum, r) => sum + (r.totalTime || 0), 0),\n convergence,\n pausePoints: allPausePoints.length ? allPausePoints : undefined,\n };\n}\n\nfunction appendToMap(\n map: Map<string, MeasuredResults[]>,\n key: string,\n value: MeasuredResults,\n) {\n if (!map.has(key)) map.set(key, []);\n map.get(key)!.push(value);\n}\n\n/** Generate table with standard sections */\nexport function defaultReport(\n groups: ReportGroup[],\n args: DefaultCliArgs,\n): string {\n const { adaptive, \"gc-stats\": gcStats, \"trace-opt\": traceOpt } = args;\n const hasCpu = hasField(groups, \"cpu\");\n const hasOpt = hasField(groups, \"optStatus\");\n const sections = buildReportSections(\n adaptive,\n gcStats,\n hasCpu,\n traceOpt && hasOpt,\n );\n return reportResults(groups, sections);\n}\n\n/** Build report sections based on CLI options */\nfunction buildReportSections(\n adaptive: boolean,\n gcStats: boolean,\n hasCpuData: boolean,\n hasOptData: boolean,\n) {\n const sections = adaptive\n ? [adaptiveSection, runsSection, totalTimeSection]\n : [timeSection, runsSection];\n\n if (gcStats) sections.push(gcStatsSection);\n if (hasCpuData) sections.push(cpuSection);\n if (hasOptData) sections.push(optSection);\n\n return sections;\n}\n\n/** Run benchmarks, display table, and optionally generate HTML report */\nexport async function benchExports(\n suite: BenchSuite,\n args: DefaultCliArgs,\n): Promise<void> {\n const results = await runBenchmarks(suite, args);\n const report = defaultReport(results, args);\n console.log(report);\n await finishReports(results, args, suite.name);\n}\n\n/** Run browser profiling via Playwright + CDP, report with standard pipeline */\nexport async function browserBenchExports(args: DefaultCliArgs): Promise<void> {\n warnBrowserFlags(args);\n const url = args.url!;\n const { iterations, time } = args;\n const result = await profileBrowser({\n url,\n heapSample: args[\"heap-sample\"],\n heapOptions: {\n samplingInterval: args[\"heap-interval\"],\n stackDepth: args[\"heap-depth\"],\n },\n headless: args.headless,\n timeout: args.timeout,\n gcStats: args[\"gc-stats\"],\n maxTime: iterations ? Number.MAX_SAFE_INTEGER : time * 1000,\n maxIterations: iterations,\n });\n\n const name = new URL(url).pathname.split(\"/\").pop() || \"browser\";\n const hasSamples = result.samples && result.samples.length > 0;\n const results = browserResultGroups(name, result);\n\n // Time report\n if (hasSamples || result.wallTimeMs != null) {\n console.log(reportResults(results, [timeSection, runsSection]));\n }\n\n // GC stats table\n if (result.gcStats) {\n console.log(reportResults(results, [browserGcStatsSection]));\n }\n\n // Heap allocation report\n if (result.heapProfile) {\n printHeapReports(results, {\n ...cliHeapReportOptions(args),\n isUserCode: isBrowserUserCode,\n });\n }\n\n await exportReports({ results, args });\n}\n\n/** Wrap browser profile result as ReportGroup[] for the standard pipeline */\nfunction browserResultGroups(\n name: string,\n result: BrowserProfileResult,\n): ReportGroup[] {\n const { gcStats, heapProfile } = result;\n let measured: MeasuredResults;\n\n // Bench function mode: multiple timing samples with real statistics\n if (result.samples && result.samples.length > 0) {\n const { samples } = result;\n const totalTime = result.wallTimeMs ? result.wallTimeMs / 1000 : undefined;\n measured = {\n name,\n samples,\n time: computeStats(samples),\n totalTime,\n gcStats,\n heapProfile,\n };\n } else {\n // Lap mode: 0 laps = single wall-clock, N laps handled above\n const wallMs = result.wallTimeMs ?? 0;\n const time = {\n min: wallMs,\n max: wallMs,\n avg: wallMs,\n p50: wallMs,\n p75: wallMs,\n p99: wallMs,\n p999: wallMs,\n };\n measured = { name, samples: [wallMs], time, gcStats, heapProfile };\n }\n\n return [{ name, reports: [{ name, measuredResults: measured }] }];\n}\n\n/** Print heap allocation reports for benchmarks with heap profiles */\nexport function printHeapReports(\n groups: ReportGroup[],\n options: HeapReportOptions,\n): void {\n for (const group of groups) {\n const allReports = group.baseline\n ? [...group.reports, group.baseline]\n : group.reports;\n\n for (const report of allReports) {\n const { heapProfile } = report.measuredResults;\n if (!heapProfile) continue;\n\n console.log(dim(`\\n─── Heap profile: ${report.name} ───`));\n const totalAll = totalProfileBytes(heapProfile);\n const sites = flattenProfile(heapProfile);\n const userSites = filterSites(sites, options.isUserCode);\n const totalUserCode = userSites.reduce((sum, s) => sum + s.bytes, 0);\n const aggregated = aggregateSites(options.userOnly ? userSites : sites);\n const extra = {\n totalAll,\n totalUserCode,\n sampleCount: heapProfile.samples?.length,\n };\n console.log(formatHeapReport(aggregated, { ...options, ...extra }));\n }\n }\n}\n\n/** Run benchmarks and display table. Suite is optional with --url (browser mode). */\nexport async function runDefaultBench(\n suite?: BenchSuite,\n configureArgs?: Configure<any>,\n): Promise<void> {\n const args = parseBenchArgs(configureArgs);\n if (args.url) {\n await browserBenchExports(args);\n } else if (suite) {\n await benchExports(suite, args);\n } else {\n throw new Error(\"Either --url or a BenchSuite is required.\");\n }\n}\n\n/** Convert CLI args to runner options */\nexport function cliToRunnerOptions(args: DefaultCliArgs): RunnerOptions {\n const { profile, collect, iterations } = args;\n if (profile)\n return { maxIterations: iterations ?? 1, warmupTime: 0, collect };\n if (args.adaptive) return createAdaptiveOptions(args);\n\n return {\n maxTime: iterations ? Number.POSITIVE_INFINITY : args.time * 1000,\n maxIterations: iterations,\n ...cliCommonOptions(args),\n };\n}\n\n/** Create options for adaptive mode */\nfunction createAdaptiveOptions(args: DefaultCliArgs): RunnerOptions {\n return {\n minTime: (args[\"min-time\"] ?? 1) * 1000,\n maxTime: defaultAdaptiveMaxTime * 1000,\n targetConfidence: args.convergence,\n adaptive: true,\n ...cliCommonOptions(args),\n } as any;\n}\n\n/** Runner/matrix options shared across all CLI modes */\nfunction cliCommonOptions(args: DefaultCliArgs) {\n const { collect, cpu, warmup } = args;\n const { \"trace-opt\": traceOpt, \"skip-settle\": noSettle } = args;\n const { \"pause-first\": pauseFirst, \"pause-interval\": pauseInterval } = args;\n const { \"pause-duration\": pauseDuration, \"gc-stats\": gcStats } = args;\n const { \"heap-sample\": heapSample, \"heap-interval\": heapInterval } = args;\n const { \"heap-depth\": heapDepth } = args;\n return {\n collect,\n cpuCounters: cpu,\n warmup,\n traceOpt,\n noSettle,\n pauseFirst,\n pauseInterval,\n pauseDuration,\n gcStats,\n heapSample,\n heapInterval,\n heapDepth,\n };\n}\n\nconst isTest = process.env.NODE_ENV === \"test\" || process.env.VITEST === \"true\";\nconst { yellow, dim } = isTest\n ? { yellow: (s: string) => s, dim: (s: string) => s }\n : pico;\n\n/** Log V8 optimization tier distribution and deoptimizations */\nexport function reportOptStatus(groups: ReportGroup[]): void {\n const optData = groups.flatMap(({ reports, baseline }) => {\n const all = baseline ? [...reports, baseline] : reports;\n return all\n .filter(r => r.measuredResults.optStatus)\n .map(r => ({\n name: r.name,\n opt: r.measuredResults.optStatus!,\n samples: r.measuredResults.samples.length,\n }));\n });\n if (optData.length === 0) return;\n\n console.log(dim(\"\\nV8 optimization:\"));\n for (const { name, opt, samples } of optData) {\n const total = Object.values(opt.byTier).reduce((s, t) => s + t.count, 0);\n const tierParts = Object.entries(opt.byTier)\n .sort((a, b) => b[1].count - a[1].count)\n .map(\n ([tier, info]) => `${tier} ${((info.count / total) * 100).toFixed(0)}%`,\n )\n .join(\", \");\n console.log(` ${name}: ${tierParts} ${dim(`(${samples} samples)`)}`);\n }\n\n const totalDeopts = optData.reduce((s, d) => s + d.opt.deoptCount, 0);\n if (totalDeopts > 0) {\n console.log(\n yellow(\n ` ⚠ ${totalDeopts} deoptimization${totalDeopts > 1 ? \"s\" : \"\"} detected`,\n ),\n );\n }\n}\n\n/** @return true if any result has the specified field with a defined value */\nexport function hasField(\n results: ReportGroup[],\n field: keyof MeasuredResults,\n): boolean {\n return results.some(({ reports, baseline }) => {\n const all = baseline ? [...reports, baseline] : reports;\n return all.some(\n ({ measuredResults }) => measuredResults[field] !== undefined,\n );\n });\n}\n\nexport interface ExportOptions {\n results: ReportGroup[];\n args: DefaultCliArgs;\n sections?: any[];\n suiteName?: string;\n currentVersion?: GitVersion;\n baselineVersion?: GitVersion;\n}\n\n/** Print heap reports (if enabled) and export results */\nasync function finishReports(\n results: ReportGroup[],\n args: DefaultCliArgs,\n suiteName?: string,\n exportOptions?: MatrixExportOptions,\n): Promise<void> {\n if (args[\"heap-sample\"]) {\n printHeapReports(results, cliHeapReportOptions(args));\n }\n await exportReports({ results, args, suiteName, ...exportOptions });\n}\n\n/** Export reports (HTML, JSON, Perfetto) based on CLI args */\nexport async function exportReports(options: ExportOptions): Promise<void> {\n const { results, args, sections, suiteName } = options;\n const { currentVersion, baselineVersion } = options;\n const openInBrowser = args.html && !args[\"export-html\"];\n let closeServer: (() => void) | undefined;\n\n if (args.html || args[\"export-html\"]) {\n const htmlOpts = {\n cliArgs: args,\n sections,\n currentVersion,\n baselineVersion,\n };\n const reportData = prepareHtmlData(results, htmlOpts);\n const result = await generateHtmlReport(reportData, {\n openBrowser: openInBrowser,\n outputPath: args[\"export-html\"],\n });\n closeServer = result.closeServer;\n }\n\n if (args.json) {\n await exportBenchmarkJson(results, args.json, args, suiteName);\n }\n\n if (args.perfetto) {\n exportPerfettoTrace(results, args.perfetto, args);\n }\n\n // Keep process running when HTML report is opened in browser\n if (openInBrowser) {\n await waitForCtrlC();\n closeServer?.();\n }\n}\n\n/** Wait for Ctrl+C before exiting */\nfunction waitForCtrlC(): Promise<void> {\n return new Promise(resolve => {\n console.log(dim(\"\\nPress Ctrl+C to exit\"));\n process.on(\"SIGINT\", () => {\n console.log();\n resolve();\n });\n });\n}\n\n/** Run matrix suite with CLI arguments.\n * no options ==> defaultCases/defaultVariants, --filter ==> subset of defaults,\n * --all --filter ==> subset of all, --all ==> all cases/variants */\nexport async function runMatrixSuite(\n suite: MatrixSuite,\n args: DefaultCliArgs,\n): Promise<MatrixResults[]> {\n validateArgs(args);\n const filter = args.filter ? parseMatrixFilter(args.filter) : undefined;\n const options = cliToMatrixOptions(args);\n\n const results: MatrixResults[] = [];\n for (const matrix of suite.matrices) {\n const casesModule = matrix.casesModule\n ? await loadCasesModule(matrix.casesModule)\n : undefined;\n\n let filtered: FilteredMatrix<any> = matrix;\n if (!args.all && casesModule) {\n filtered = {\n ...matrix,\n filteredCases: casesModule.defaultCases,\n filteredVariants: casesModule.defaultVariants,\n };\n }\n\n // filter merges via intersection with defaults\n if (filter) {\n filtered = await filterMatrix(filtered, filter);\n }\n\n const { filteredCases, filteredVariants } = filtered;\n results.push(\n await runMatrix(filtered, {\n ...options,\n filteredCases,\n filteredVariants,\n }),\n );\n }\n return results;\n}\n\n/** Convert CLI args to matrix run options */\nexport function cliToMatrixOptions(args: DefaultCliArgs): RunMatrixOptions {\n const { time, iterations, worker } = args;\n return {\n iterations,\n maxTime: iterations ? undefined : time * 1000,\n useWorker: worker,\n ...cliCommonOptions(args),\n };\n}\n\n/** Generate report for matrix results. Uses same sections as regular benchmarks. */\nexport function defaultMatrixReport(\n results: MatrixResults[],\n reportOptions?: MatrixReportOptions,\n args?: DefaultCliArgs,\n): string {\n const options = args\n ? mergeMatrixDefaults(reportOptions, args, results)\n : reportOptions;\n return results.map(r => reportMatrixResults(r, options)).join(\"\\n\\n\");\n}\n\n/** @return HeapReportOptions from CLI args */\nfunction cliHeapReportOptions(args: DefaultCliArgs): HeapReportOptions {\n return {\n topN: args[\"heap-rows\"],\n stackDepth: args[\"heap-stack\"],\n verbose: args[\"heap-verbose\"],\n userOnly: args[\"heap-user-only\"],\n };\n}\n\n/** Apply default sections and extra columns for matrix reports */\nfunction mergeMatrixDefaults(\n reportOptions: MatrixReportOptions | undefined,\n args: DefaultCliArgs,\n results: MatrixResults[],\n): MatrixReportOptions {\n const result: MatrixReportOptions = { ...reportOptions };\n\n if (!result.sections?.length) {\n const groups = matrixToReportGroups(results);\n result.sections = buildReportSections(\n args.adaptive,\n args[\"gc-stats\"],\n hasField(groups, \"cpu\"),\n args[\"trace-opt\"] && hasField(groups, \"optStatus\"),\n );\n }\n\n return result;\n}\n\n/** Run matrix suite with full CLI handling (parse, run, report, export) */\nexport async function runDefaultMatrixBench(\n suite: MatrixSuite,\n configureArgs?: Configure<any>,\n reportOptions?: MatrixReportOptions,\n): Promise<void> {\n const args = parseBenchArgs(configureArgs);\n await matrixBenchExports(suite, args, reportOptions);\n}\n\n/** Convert MatrixResults to ReportGroup[] for export compatibility */\nexport function matrixToReportGroups(results: MatrixResults[]): ReportGroup[] {\n return results.flatMap(matrix =>\n matrix.variants.flatMap(variant =>\n variant.cases.map(c => {\n const { metadata } = c;\n const report = {\n name: variant.id,\n measuredResults: c.measured,\n metadata,\n };\n const baseline = c.baseline\n ? {\n name: `${variant.id} (baseline)`,\n measuredResults: c.baseline,\n metadata,\n }\n : undefined;\n return {\n name: `${variant.id} / ${c.caseId}`,\n reports: [report],\n baseline,\n };\n }),\n ),\n );\n}\n\nexport interface MatrixExportOptions {\n sections?: any[];\n currentVersion?: GitVersion;\n baselineVersion?: GitVersion;\n}\n\n/** Sequential map - like Promise.all(arr.map(fn)) but runs one at a time */\nasync function serialMap<T, R>(\n arr: T[],\n fn: (item: T) => Promise<R>,\n): Promise<R[]> {\n const results: R[] = [];\n for (const item of arr) {\n results.push(await fn(item));\n }\n return results;\n}\n\n/** Run matrix benchmarks, display table, and generate exports */\nexport async function matrixBenchExports(\n suite: MatrixSuite,\n args: DefaultCliArgs,\n reportOptions?: MatrixReportOptions,\n exportOptions?: MatrixExportOptions,\n): Promise<void> {\n const results = await runMatrixSuite(suite, args);\n const report = defaultMatrixReport(results, reportOptions, args);\n console.log(report);\n\n const reportGroups = matrixToReportGroups(results);\n await finishReports(reportGroups, args, suite.name, exportOptions);\n}\n","import { execSync } from \"node:child_process\";\nimport { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { GitVersion } from \"./html/index.ts\";\nimport { formatDateWithTimezone } from \"./html/index.ts\";\n\nexport type { GitVersion } from \"./html/index.ts\";\nexport { formatDateWithTimezone, formatRelativeTime } from \"./html/index.ts\";\n\n/** Get current git version info. For dirty repos, uses most recent modified file date. */\nexport function getCurrentGitVersion(): GitVersion | undefined {\n try {\n const exec = (cmd: string) => execSync(cmd, { encoding: \"utf-8\" }).trim();\n const hash = exec(\"git rev-parse --short HEAD\");\n const commitDate = exec(\"git log -1 --format=%aI\");\n const dirty = exec(\"git status --porcelain\").length > 0;\n\n const date = dirty\n ? (getMostRecentModifiedDate(\".\") ?? commitDate)\n : commitDate;\n return { hash, date, dirty };\n } catch {\n return undefined;\n }\n}\n\n/** Read baseline version from .baseline-version file */\nexport function getBaselineVersion(\n baselineDir = \"_baseline\",\n): GitVersion | undefined {\n const versionFile = join(baselineDir, \".baseline-version\");\n if (!existsSync(versionFile)) return undefined;\n\n try {\n const content = readFileSync(versionFile, \"utf-8\");\n const data = JSON.parse(content);\n return { hash: data.hash, date: data.date };\n } catch {\n return undefined;\n }\n}\n\n/** Format git version for display: \"abc1234 (Jan 9, 2026, 3:45 PM)\" or \"abc1234*\" if dirty */\nexport function formatGitVersion(version: GitVersion): string {\n const hashDisplay = version.dirty ? `${version.hash}*` : version.hash;\n const dateDisplay = formatDateWithTimezone(version.date);\n return `${hashDisplay} (${dateDisplay})`;\n}\n\n/** Get most recent modified file date in a directory (for dirty repos) */\nexport function getMostRecentModifiedDate(dir: string): string | undefined {\n try {\n const raw = execSync(\"git status --porcelain\", {\n encoding: \"utf-8\",\n cwd: dir,\n });\n const modifiedFiles = raw\n .trim()\n .split(\"\\n\")\n .filter(line => line.length > 0)\n .map(line => line.slice(3));\n\n if (modifiedFiles.length === 0) return undefined;\n\n let mostRecent = 0;\n for (const file of modifiedFiles) {\n try {\n const filePath = join(dir, file);\n if (!existsSync(filePath)) continue;\n const mtime = statSync(filePath).mtimeMs;\n if (mtime > mostRecent) mostRecent = mtime;\n } catch {}\n }\n\n return mostRecent > 0 ? new Date(mostRecent).toISOString() : undefined;\n } catch {\n return undefined;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAWA,eAAsB,gBACpB,WACyB;CACzB,MAAM,SAAS,MAAM,OAAO;AAC5B,KAAI,CAAC,MAAM,QAAQ,OAAO,MAAM,CAC9B,OAAM,IAAI,MAAM,mBAAmB,UAAU,4BAA4B;AAE3E,QAAO;EACL,OAAO,OAAO;EACd,cAAc,OAAO;EACrB,iBAAiB,OAAO;EACxB,UAAU,OAAO;EAClB;;;AAIH,eAAsB,aACpB,aACA,QACwB;AACxB,KAAI,aAAa,SACf,QAAO,YAAY,SAAS,OAAO;AAErC,QAAO,EAAE,MAAM,QAAa;;;;;;AC7B9B,eAAsB,iBAAiB,QAAmC;CACxE,MAAM,UAAU,cAAc,OAAO;AAErC,SADgB,MAAM,GAAG,QAAQ,SAAS,EAAE,eAAe,MAAM,CAAC,EAE/D,QAAO,MAAK,EAAE,QAAQ,IAAI,EAAE,KAAK,SAAS,MAAM,CAAC,CACjD,KAAI,MAAK,EAAE,KAAK,MAAM,GAAG,GAAG,CAAC,CAC7B,MAAM;;;;;ACVX,MAAM,mBAAmB;AACzB,MAAM,aAAa;;AAgBnB,SAAgB,uBAAuB,SAA2B;CAChE,MAAM,OAAO,QAAQ,QAAQ;AAC7B,KAAI,SAAS,EAAG,QAAO;AAEvB,QADe,kBAAkB,QAAQ,GACzB;;;AAIlB,SAAgB,wBAAwB,SAA2B;CACjE,MAAM,SAASA,aAAW,SAAS,GAAI;AAEvC,QAAOA,aADY,QAAQ,KAAI,MAAK,KAAK,IAAI,IAAI,OAAO,CAAC,EAC3B,GAAI;;;AAsCpC,SAAgB,QAAQ,QAA0B;AAEhD,QADY,OAAO,QAAQ,GAAG,MAAM,IAAI,GAAG,EAAE,GAChC,OAAO;;;AAItB,SAAgB,kBAAkB,SAA2B;AAC3D,KAAI,QAAQ,UAAU,EAAG,QAAO;CAChC,MAAM,OAAO,QAAQ,QAAQ;CAC7B,MAAM,WACJ,QAAQ,QAAQ,KAAK,MAAM,OAAO,IAAI,SAAS,GAAG,EAAE,IAAI,QAAQ,SAAS;AAC3E,QAAO,KAAK,KAAK,SAAS;;;AAI5B,SAAgBA,aAAW,QAAkB,GAAmB;CAC9D,MAAM,SAAS,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,IAAI,EAAE;CAChD,MAAM,QAAQ,KAAK,KAAK,OAAO,SAAS,EAAE,GAAG;AAC7C,QAAO,OAAO,KAAK,IAAI,GAAG,MAAM;;;AAWlC,SAAgB,eAAe,SAA6B;CAC1D,MAAM,IAAI,QAAQ;CAClB,MAAM,aAAa,QAAQ,KAAK,MAAM,KAAK,QAAQ,GAAG,EAAE;AACxD,QAAO,MAAM,KAAK,EAAE,QAAQ,GAAG,EAAE,KAAK;;;AAIxC,SAAS,gBACP,SACA,YACkB;CAClB,MAAM,SAAS,IAAI,cAAc;AAGjC,QAAO,CAFOA,aAAW,SAAS,MAAM,EAC1BA,aAAW,SAAS,IAAI,MAAM,CACvB;;;AAqBvB,SAAS,UAAU,QAAkB,WAAW,IAAoB;CAClE,MAAM,SAAS,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,IAAI,EAAE;CAChD,MAAM,MAAM,OAAO;CACnB,MAAM,MAAM,OAAO,OAAO,SAAS;AACnC,KAAI,QAAQ,IAAK,QAAO,CAAC;EAAE,GAAG;EAAK,OAAO,OAAO;EAAQ,CAAC;CAE1D,MAAM,QAAQ,MAAM,OAAO;CAC3B,MAAM,SAAS,IAAI,MAAM,SAAS,CAAC,KAAK,EAAE;AAC1C,MAAK,MAAM,KAAK,QAAQ;EACtB,MAAM,MAAM,KAAK,IAAI,KAAK,OAAO,IAAI,OAAO,KAAK,EAAE,WAAW,EAAE;AAChE,SAAO;;AAET,QAAO,OAAO,KAAK,OAAO,OAAO;EAAE,GAAG,OAAO,IAAI,MAAO;EAAM;EAAO,EAAE;;;AAIzE,SAAgB,sBACd,UACA,SACA,UAA4B,EAAE,EAChB;CACd,MAAM,EAAE,YAAY,kBAAkB,YAAY,OAAO,eACvD;CAEF,MAAM,iBAAiBA,aAAW,UAAU,GAAI;CAEhD,MAAM,mBADgBA,aAAW,SAAS,GAAI,GAE1B,kBAAkB,iBAAkB;CAExD,MAAM,QAAkB,EAAE;AAC1B,MAAK,IAAI,IAAI,GAAG,IAAI,WAAW,KAAK;EAClC,MAAM,OAAO,eAAe,SAAS;EACrC,MAAM,OAAO,eAAe,QAAQ;EACpC,MAAM,OAAOA,aAAW,MAAM,GAAI;EAClC,MAAM,OAAOA,aAAW,MAAM,GAAI;AAClC,QAAM,MAAO,OAAO,QAAQ,OAAQ,IAAI;;CAG1C,MAAM,KAAK,gBAAgB,OAAO,KAAK;CACvC,MAAM,eAAe,GAAG,KAAK,KAAK,GAAG,KAAK;CAC1C,IAAI,YAAyB;AAC7B,KAAI,aAAc,aAAY,kBAAkB,IAAI,WAAW;CAC/D,MAAM,YAAY,UAAU,MAAM;AAClC,QAAO;EAAE,SAAS;EAAiB;EAAI;EAAW;EAAW;;;;;AC9K/D,MAAa,SAAS;;;;ACUtB,MAAM,UAAU;AAChB,MAAM,UAAU;AAChB,MAAM,mBAAmB;AACzB,MAAM,oBAAoB;AAC1B,MAAM,aAAa;AACnB,MAAM,YAAY;AAClB,MAAM,eAAe;AACrB,MAAM,gBAAgB;AACtB,MAAM,qBAAqB;;AAwB3B,SAAgB,sBACd,YACA,SACa;AACb,QAAO,EACL,MAAM,SACJ,WACA,eACA,QAC4B;AAC5B,SAAO,iBACL,YACA,WACA,eACA,SACA,OACD;IAEJ;;;AAIH,eAAe,iBACb,YACA,WACA,eACA,SACA,QAC4B;CAC5B,MAAM,EACJ,SAAS,MAAM,QAAQ,WAAW,SAClC,SAAS,MAAM,QAAQ,WAAW,SAClC,kBAAkB,SAAS,QAAQ,eAAe,qBAChD;CACJ,MAAM,aAAuB,EAAE;CAG/B,MAAM,SAAS,MAAM,eACnB,YACA,WACA,eACA,QACA,WACD;CAGD,MAAM,YAAY,YAAY,KAAK;AAQnC,OAAM,gBACJ,YACA,WACA,eACA,QACA,YAXa;EACb,SAAS;EACT,SAAS;EACT,kBAAkB;EAClB;EACD,CAQA;AAGD,QAAO,aACL,YACA,WAHkB,iBAAiB,WAAW,KAAI,MAAK,IAAI,OAAO,CAAC,EAKnE,UAAU,MACV,OACD;;;AAIH,eAAe,eACb,YACA,WACA,eACA,QACA,YAC+B;CAE/B,MAAM,OAAO;EACX,GAAI;EACJ,SAAS;EACT,eAAe;EAChB;CACD,MAAM,UAAU,MAAM,WAAW,SAAS,WAAW,MAAM,OAAO;AAClE,eAAc,QAAQ,IAAI,WAAW;AACrC,QAAO,QAAQ,GAAG;;;AAIpB,eAAe,gBACb,YACA,WACA,eACA,QACA,YACA,QAMe;CACf,MAAM,EAAE,SAAS,SAAS,kBAAkB,cAAc;CAC1D,IAAI,UAAU;AACd,QAAO,YAAY,KAAK,GAAG,YAAY,SAAS;EAE9C,MAAM,cAAc,iBADF,WAAW,KAAI,MAAK,IAAI,OAAO,CACF;EAC/C,MAAM,UAAU,YAAY,KAAK,GAAG;AAEpC,MAAI,UAAU,UAAU,KAAM;GAC5B,MAAM,cAAc,UAAU,KAAM,QAAQ,EAAE;GAC9C,MAAM,OAAO,YAAY,WAAW,QAAQ,EAAE;AAC9C,WAAQ,OAAO,MACb,OAAO,UAAU,KAAK,IAAI,KAAK,eAAe,WAAW,OAC1D;AACD,aAAU;;AAGZ,MAAI,WAAW,aAAa,kBAAkB,SAAS,QAAQ,CAC7D;EAIF,MAAM,OAAO;GACX,GAAI;GACJ,SAAS;GACT,eAAe;GACf,YAAY;GACb;AAED,iBADqB,MAAM,WAAW,SAAS,WAAW,MAAM,OAAO,EAC5C,IAAI,WAAW;;AAE5C,SAAQ,OAAO,MAAM,OAAO,IAAI,OAAO,GAAG,GAAG,KAAK;;;AAIpD,SAAS,cAAc,QAAyB,SAAyB;AACvE,KAAI,CAAC,OAAO,SAAS,OAAQ;AAC7B,MAAK,MAAM,UAAU,OAAO,QAAS,SAAQ,KAAK,OAAO;;;AAI3D,SAAS,WACP,aACA,kBACA,aACA,SACS;AACT,KAAI,YAAY,aAAa,YAAY,cAAc,iBACrD,QAAO;CAGT,MAAM,YAAY,KAAK,IAAI,kBAAkB,kBAAkB;AAC/D,QAAO,eAAe,WAAW,YAAY,cAAc;;;AAI7D,SAAS,aACP,WACA,WACA,aACA,MACA,eACmB;CACnB,MAAM,aAAa,YAAY,KAAK,GAAG,aAAa;AAIpD,QAAO,CACL;EACE;EACA,SAAS;EACT;EACA,MAPc,iBADA,UAAU,KAAI,MAAK,IAAI,OAAO,CACH;EAQzC;EACA;EACD,CACF;;;AAIH,SAAS,iBAAiB,WAAqB;CAC7C,MAAM,YAAY,UAAU,KAAI,MAAK,IAAI,OAAO;CAChD,MAAM,EAAE,KAAK,KAAK,QAAQ,aAAa,UAAU;CACjD,MAAM,cAAc,eAAe,UAAU;CAC7C,MAAM,SAAS,iBAAiB,UAAU;AAE1C,QAAO;EACL,KAAK,MAAM;EACX,KAAK,MAAM;EACX,KAAK,MAAM,UAAU,SAAS;EAC9B,GAAG;EACH,GAAG;EACJ;;;AAIH,SAAS,aAAa,SAAmB;AAUvC,QAAO;EAAE,KATG,QAAQ,QACjB,GAAG,MAAM,KAAK,IAAI,GAAG,EAAE,EACxB,OAAO,kBACR;EAMa,KALF,QAAQ,QACjB,GAAG,MAAM,KAAK,IAAI,GAAG,EAAE,EACxB,OAAO,kBACR;EAEkB,KADP,QAAQ,QAAQ,GAAG,MAAM,IAAI,GAAG,EAAE;EACtB;;;AAI1B,SAAS,eAAe,SAAmB;AACzC,QAAO;EACL,KAAKC,aAAW,SAAS,IAAK,GAAG;EACjC,KAAKA,aAAW,SAAS,GAAI,GAAG;EAChC,KAAKA,aAAW,SAAS,IAAK,GAAG;EACjC,KAAKA,aAAW,SAAS,IAAK,GAAG;EACjC,KAAKA,aAAW,SAAS,IAAK,GAAG;EACjC,MAAMA,aAAW,SAAS,KAAM,GAAG;EACpC;;;AAIH,SAAS,iBAAiB,WAAqB;CAC7C,MAAM,SAAS,iBAAiB,UAAU;AAC1C,QAAO;EACL,IAAI,uBAAuB,UAAU;EACrC,KAAK,wBAAwB,UAAU;EACvC,aAAa,OAAO;EACrB;;;AAIH,SAAS,iBAAiB,SAAqD;AAC7E,KAAI,QAAQ,WAAW,EAAG,QAAO;EAAE,OAAO;EAAG,OAAO;EAAG;CAEvD,MAAM,SAASA,aAAW,SAAS,GAAI;CAEvC,MAAM,YAAY,SAAS,OADfA,aAAW,SAAS,IAAK,GACG;CAExC,IAAI,aAAa;CACjB,IAAI,QAAQ;AAEZ,MAAK,MAAM,UAAU,QACnB,KAAI,SAAS,WAAW;AACtB,gBAAc,SAAS;AACvB;;CAIJ,MAAM,YAAY,QAAQ,QAAQ,GAAG,MAAM,IAAI,GAAG,EAAE;AACpD,QAAO;EACL,OAAO,YAAY,IAAI,aAAa,YAAY;EAChD;EACD;;;AAIH,SAAgB,iBAAiB,SAAsC;CACrE,MAAM,aAAa,cAAc,QAAQ;CACzC,MAAM,aAAa,aAAa;AAEhC,KAAI,QAAQ,SAAS,WACnB,QAAO,oBAAoB,QAAQ,QAAQ,WAAW;AAIxD,QAAO,iBADS,aAAa,SAAS,WAAW,CACjB;;;AAIlC,SAAS,oBACP,gBACA,YACmB;AACnB,QAAO;EACL,WAAW;EACX,YAAa,iBAAiB,aAAc;EAC5C,QAAQ,uBAAuB,eAAe,GAAG;EAClD;;;AAIH,SAAS,aAAa,SAAmB,YAA6B;CACpE,MAAM,SAAS,QAAQ,MAAM,CAAC,WAAW;CACzC,MAAM,WAAW,QAAQ,MAAM,CAAC,aAAa,GAAG,CAAC,WAAW;CAE5D,MAAM,WAAW,OAAO,KAAI,MAAK,IAAI,OAAO;CAC5C,MAAM,aAAa,SAAS,KAAI,MAAK,IAAI,OAAO;CAEhD,MAAM,eAAeA,aAAW,UAAU,GAAI;CAC9C,MAAM,iBAAiBA,aAAW,YAAY,GAAI;CAClD,MAAM,cAAc,KAAK,IAAI,eAAe,eAAe,GAAG;CAE9D,MAAM,eAAe,iBAAiB,SAAS;CAC/C,MAAM,iBAAiB,iBAAiB,WAAW;CACnD,MAAM,cAAc,KAAK,IAAI,aAAa,QAAQ,eAAe,MAAM;AAEvE,QAAO;EACL;EACA;EACA,cAAc,cAAc;EAC5B,cAAc,cAAc;EAC7B;;;AAIH,SAAS,iBAAiB,SAAqC;CAC7D,MAAM,EAAE,aAAa,aAAa,cAAc,iBAAiB;AAEjE,KAAI,gBAAgB,aAClB,QAAO;EACL,WAAW;EACX,YAAY;EACZ,QAAQ;EACT;CAGH,MAAM,aAAa,KAAK,IACtB,MACC,IAAI,cAAc,aAAa,MAAM,IAAI,cAAc,aAAa,GACtE;CAED,MAAM,SACJ,cAAc,cACV,qBAAqB,cAAc,KAAK,QAAQ,EAAE,CAAC,KACnD,6BAA6B,cAAc,KAAK,QAAQ,EAAE,CAAC;AAEjE,QAAO;EAAE,WAAW;EAAO,YAAY,KAAK,IAAI,GAAG,WAAW;EAAE;EAAQ;;;AAI1E,SAAS,cAAc,SAA2B;AAChD,KAAI,QAAQ,SAAS,GAAI,QAAO;CAGhC,MAAM,eAAeA,aADJ,QAAQ,MAAM,IAAI,CAAC,KAAI,MAAK,IAAI,OAAO,EACd,GAAI;AAG9C,KAAI,eAAe,IAAM,QAAO;AAChC,KAAI,eAAe,GAAK,QAAO;AAC/B,KAAI,eAAe,EAAG,QAAO;AAC7B,KAAI,eAAe,GAAI,QAAO;AAC9B,QAAO;;;;;;ACjYT,SAAgB,iBACd,WACA,QACM;AACN,CAAC,UAAU,GAA4B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;ACyBhD,MAAM,eAAe;;AAsCrB,IAAa,cAAb,MAAgD;CAC9C,MAAM,SACJ,WACA,SACA,QAC4B;EAE5B,MAAM,YAAY,MAAM,eAAe;GAAE;GAAW;GADrC,GAAG;GAAuB,GAAI;GACwB,CAAC;AACtE,SAAO,CAAC,qBAAqB,UAAU,MAAM,UAAU,CAAC;;;AAI5D,MAAM,wBAAwB;CAC5B,SAAS;CACT,eAAe;CACf,QAAQ;CACR,UAAU;CACV,UAAU;CACX;AAED,SAAS,qBAAqB,MAAc,GAAmC;CAC7E,MAAM,OAAO,aAAa,EAAE,QAAQ;CACpC,MAAM,cAAc,iBAAiB,EAAE,QAAQ,KAAI,MAAK,IAAI,OAAO,CAAC;AACpE,QAAO;EACL;EACA,SAAS,EAAE;EACX,eAAe,EAAE;EACjB,aAAa,EAAE;EACf,YAAY,EAAE;EACd;EACA,UAAU;GAAE,KAAK,EAAE;GAAY,KAAK,EAAE;GAAY,KAAK,EAAE;GAAY;EACrE;EACA,WAAW,EAAE;EACb,YAAY,EAAE;EACd,aAAa,EAAE;EAChB;;;AAIH,eAAe,eAAkB,GAA6C;AAC5E,KAAI,CAAC,EAAE,iBAAiB,CAAC,EAAE,QACzB,OAAM,IAAI,MAAM,uDAAuD;CAEzE,MAAM,gBAAgB,EAAE,aAAa,EAAE,GAAG,MAAM,UAAU,EAAE;CAC5D,MAAM,aAAa,QAAQ,aAAa,CAAC;CACzC,MAAM,EAAE,SAAS,aAAa,YAAY,aAAa,gBACrD,MAAM,cAAc,EAAE;CACxB,MAAM,aACJ,KAAK,IAAI,GAAG,QAAQ,aAAa,CAAC,WAAW,WAAW,GACxD,OACA,QAAQ;AACV,KAAI,QAAQ,WAAW,EACrB,OAAM,IAAI,MAAM,uCAAuC,EAAE,UAAU,OAAO;AAO5E,QAAO;EACL;EACA;EACA;EACA;EACA;EACA,WAXgB,EAAE,WAChB,iBAAiB,SAAS,YAAY,GACtC;EAUF,YARA,EAAE,YAAY,YAAY,SAAS,IAAI,cAAc;EASrD;EACD;;;AAIH,eAAe,UAAa,GAAwC;CAClE,MAAM,KAAK,YAAY;CACvB,MAAM,UAAU,IAAI,MAAc,EAAE,OAAO;AAC3C,MAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;EACjC,MAAM,QAAQ,YAAY,KAAK;AAC/B,mBAAiB,EAAE,WAAW,EAAE,OAAO;AACvC,UAAQ,KAAK,YAAY,KAAK,GAAG;;AAEnC,KAAI;AACJ,KAAI,CAAC,EAAE,UAAU;AACf,QAAM,IAAI,SAAQ,MAAK,WAAW,GAAG,aAAa,CAAC;AACnD,MAAI;;AAEN,QAAO;;;AAYT,SAAS,oBAAoB,SAAiB,eAA+B;AAC3E,QAAO,iBAAiB,KAAK,KAAK,UAAU,GAAI;;;AAYlD,SAAS,mBACP,GACA,WACA,UACc;CACd,MAAM,OAAO,UAAoB,QAAQ,IAAI,MAAc,EAAE,GAAG,EAAE;AAClE,QAAO;EACL,SAAS,IAAI,MAAc,EAAE;EAC7B,YAAY,IAAI,MAAc,EAAE;EAChC,aAAa,IAAI,UAAU;EAC3B,aAAa,IAAI,SAAS;EAC1B,aAAa,EAAE;EAChB;;;AAIH,SAAS,WACP,GACA,OACA,WACA,UACM;AACN,GAAE,QAAQ,SAAS,EAAE,WAAW,SAAS;AACzC,KAAI,UAAW,GAAE,YAAY,SAAS;AACtC,KAAI,SAAU,GAAE,YAAY,SAAS;;;AAIvC,eAAe,cACb,GAC2B;CAC3B,MAAM,EACJ,SACA,eACA,YACA,gBAAgB,GAChB,gBAAgB,QACd;CACJ,MAAM,YAAY;CAClB,MAAM,eAAe,EAAE,WAAW,uBAAuB,GAAG;CAE5D,MAAM,IAAI,mBADQ,oBAAoB,SAAS,cAAc,EACrB,WAAW,CAAC,CAAC,aAAa;CAElE,IAAI,QAAQ;CACZ,IAAI,UAAU;CACd,IAAI,iBAAiB;CACrB,MAAM,YAAY,YAAY,KAAK;AAEnC,SACG,CAAC,iBAAiB,QAAQ,mBAC1B,CAAC,WAAW,UAAU,UACvB;EACA,MAAM,QAAQ,YAAY,KAAK;AAC/B,mBAAiB,EAAE,WAAW,EAAE,OAAO;EACvC,MAAM,MAAM,YAAY,KAAK;AAC7B,IAAE,QAAQ,SAAS,MAAM;AACzB,IAAE,WAAW,SAAS,OAAO,QAAQ,OAAO,QAAQ,GAAG,MAAM;AAC9C,IAAE,YAAY,SAAS,mBAAmB,CAAC;AAC1D,MAAI,aAAc,GAAE,YAAY,SAAS,aAAa,EAAE,UAAU,GAAG;AACrE;AAEA,MAAI,YAAY,OAAO,YAAY,cAAc,EAAE;AACjD,KAAE,YAAY,KAAK;IAAE,aAAa,QAAQ;IAAG,YAAY;IAAe,CAAC;GACzE,MAAM,aAAa,YAAY,KAAK;AACpC,SAAM,IAAI,SAAQ,MAAK,WAAW,GAAG,cAAc,CAAC;AACpD,qBAAkB,YAAY,KAAK,GAAG;;AAExC,YAAU,YAAY,KAAK,GAAG,YAAY;;AAG5C,YAAW,GAAG,OAAO,WAAW,CAAC,CAAC,aAAa;AAC/C,QAAO;EACL,SAAS,EAAE;EACX,aAAyB,EAAE;EAC3B,YAAY,EAAE;EACd,aAAa,EAAE;EACf,aAAa,EAAE;EAChB;;;AAIH,SAAS,YACP,MACA,OACA,UACS;AACT,KAAI,UAAU,UAAa,SAAS,MAAO,QAAO;AAClD,KAAI,YAAY,EAAG,QAAO;AAC1B,KAAI,UAAU,OAAW,QAAO,OAAO,aAAa;AACpD,SAAQ,OAAO,SAAS,aAAa;;;AAIvC,SAAgB,aAAa,SAAoC;CAC/D,MAAM,SAAS,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,MAAM,IAAI,EAAE;CACjD,MAAM,MAAM,QAAQ,QAAQ,KAAK,MAAM,MAAM,GAAG,EAAE,GAAG,QAAQ;AAC7D,QAAO;EACL,KAAK,OAAO;EACZ,KAAK,OAAO,OAAO,SAAS;EAC5B;EACA,KAAK,WAAW,QAAQ,GAAI;EAC5B,KAAK,WAAW,QAAQ,IAAK;EAC7B,KAAK,WAAW,QAAQ,IAAK;EAC7B,MAAM,WAAW,QAAQ,KAAM;EAChC;;;AAIH,SAAS,WAAW,aAAuB,GAAmB;CAC5D,MAAM,SAAS,YAAY,SAAS,KAAK;CACzC,MAAM,QAAQ,KAAK,MAAM,MAAM;CAC/B,MAAM,QAAQ,KAAK,KAAK,MAAM;CAC9B,MAAM,SAAS,QAAQ;AAEvB,KAAI,SAAS,YAAY,OAAQ,QAAO,YAAY,YAAY,SAAS;AAEzE,QAAO,YAAY,UAAU,IAAI,UAAU,YAAY,SAAS;;;AAIlE,SAAS,aAAyB;CAChC,MAAM,KAAK,WAAW,MAAO,WAAmB;AAChD,KAAI,GAAI,QAAO;AACf,SAAQ,KAAK,oDAAoD;AACjE,cAAa;;;AAIf,SAAS,wBAA+D;AACtE,KAAI;EAEF,MAAM,SAAS,IAAI,SAAS,KAAK,mCAAmC;AACpE,eAAa,GAAG;AAChB,SAAO;SACD;AACN;;;;;;;;;;;AAYJ,MAAM,cAAsC;CAC1C,GAAG;CACH,KAAK;CACL,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,OAAO;CACR;;AAGD,SAAS,iBACP,SACA,UAC2B;AAC3B,KAAI,SAAS,WAAW,KAAK,SAAS,OAAO,OAAW,QAAO;CAE/D,MAAM,+BAAe,IAAI,KAAuB;CAChD,IAAI,aAAa;AAEjB,MAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;EACvC,MAAM,SAAS,SAAS;AACxB,MAAI,WAAW,OAAW;AAG1B,MAAI,SAAS,EAAG;AAEhB,MAAI,CAAC,aAAa,IAAI,OAAO,CAAE,cAAa,IAAI,QAAQ,EAAE,CAAC;AAC3D,eAAa,IAAI,OAAO,CAAE,KAAK,QAAQ,GAAG;;CAG5C,MAAM,SAA8D,EAAE;AACtE,MAAK,MAAM,CAAC,QAAQ,UAAU,cAAc;EAC1C,MAAM,OAAO,YAAY,WAAW,UAAU;EAC9C,MAAM,SAAS,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,IAAI,EAAE;EAC/C,MAAM,SAAS,OAAO,KAAK,MAAM,OAAO,SAAS,EAAE;AACnD,SAAO,QAAQ;GAAE,OAAO,MAAM;GAAQ,UAAU;GAAQ;;AAG1D,QAAO;EAAE;EAAQ;EAAY;;;;;;ACxW/B,eAAsB,aACpB,aACsB;AACtB,QAAO,IAAI,aAAa;;;;;;ACe1B,SAAgB,YAAY,MAAmC;AAE7D,KAAI,CAAC,KAAK,SAAS,SAAS,CAAE,QAAO;CAErC,MAAM,SAAS,eAAe,KAAK;AACnC,KAAI,CAAC,OAAO,GAAI,QAAO;CAEvB,MAAM,OAAO,MAAc,OAAO,SAAS,OAAO,MAAM,KAAK,GAAG;CAChE,MAAM,OAAO,YAAY,OAAO,GAAG;CACnC,MAAM,UAAU,OAAO,WAAW,OAAO,SAAS,IAAI;CACtD,MAAM,YAAY,IAAI,YAAY;CAClC,MAAM,WAAW,IAAI,WAAW;CAEhC,MAAM,WAAW,IAAI,qBAAqB,IAAI,IAAI,WAAW;CAE7D,MAAM,YAAY,IAAI,oBAAoB;CAC1C,MAAM,UAAU,IAAI,kBAAkB;CACtC,MAAM,YAAY,YAAY,UAAU,YAAY,UAAU;AAE9D,KAAI,OAAO,MAAM,QAAQ,CAAE,QAAO;AAElC,QAAO;EAAE;EAAM;EAAS;EAAW;EAAW;EAAU;EAAU;;;AAIpE,SAAS,eAAe,MAAsC;CAC5D,MAAM,SAAiC,EAAE;CAEzC,MAAM,UAAU,KAAK,SAAS,mBAAmB;AACjD,MAAK,MAAM,GAAG,KAAK,UAAU,QAC3B,QAAO,OAAO;AAEhB,QAAO;;;AAIT,SAAS,YAAY,SAAkC;AAErD,KAAI,YAAY,OAAO,YAAY,WAAY,QAAO;AACtD,KAAI,YAAY,QAAQ,YAAY,QAAQ,YAAY,eACtD,QAAO;AACT,KAAI,YAAY,SAAS,YAAY,cAAc,YAAY,WAC7D,QAAO;AACT,QAAO;;;AAIT,SAAgB,iBAAiB,QAA4B;CAC3D,IAAI,YAAY;CAChB,IAAI,eAAe;CACnB,IAAI,cAAc;CAClB,IAAI,iBAAiB;CACrB,IAAI,gBAAgB;CACpB,IAAI,iBAAiB;CACrB,IAAI,gBAAgB;CACpB,IAAI,gBAAgB;AAEpB,MAAK,MAAM,KAAK,QAAQ;AACtB,MAAI,EAAE,SAAS,cAAc,EAAE,SAAS,WAAY;WAC3C,EAAE,SAAS,eAAgB;AACpC,iBAAe,EAAE;AACjB,oBAAkB,EAAE;AACpB,MAAI,EAAE,aAAa,MAAM;AACvB,mBAAgB;AAChB,qBAAkB,EAAE;AACpB,oBAAiB,EAAE,YAAY;AAC/B,oBAAiB,EAAE,YAAY;;;AAInC,QAAO;EACL;EACA;EACA;EACA;EACA,GAAI,iBAAiB;GAAE;GAAgB;GAAe;GAAe;EACtE;;;;;ACpGH,MAAa,oBAAoB;;AAGjC,SAAgB,aAAqB;AACnC,QAA+C;;;AAIjD,SAAgB,WAAW,WAAmB,SAA0B;AAC9C,QAAO;;;;;ACUjC,MAAM,YAAY,qBACb,YAAoB,QAAQ,IAAI,wBAAwB,UAAU,SAC7D;;AAuBV,eAAsB,aAA0B,EAC9C,MACA,QACA,SACA,YAAY,OACZ,UACoD;AACpD,KAAI,CAAC,WAAW;EACd,MAAM,eAAe,KAAK,aACtB,MAAM,kBAAkB,MAAM,OAAO,GACrC;GAAE;GAAM;GAAQ;EAEpB,MAAM,OAAO,MAAM,aAAa,OAAO;AAIvC,UAHqB,QAAgB,WACjC,sBAAsB,MAAM,QAA2B,GACvD,MACe,SACjB,aAAa,MACb,SACA,aAAa,OACd;;AAGH,QAAO,YAAY;EAAE;EAAM;EAAQ;EAAS;EAAQ,CAAC;;;AAIvD,eAAe,kBACb,MACA,QAC4D;CAC5D,MAAM,SAAS,MAAM,OAAO,KAAK;CAEjC,MAAM,KAAK,KAAK,aACZ,OAAO,KAAK,cACZ,OAAO,WAAW;AAEtB,KAAI,OAAO,OAAO,YAAY;EAC5B,MAAM,OAAO,KAAK,cAAc;AAChC,QAAM,IAAI,MACR,WAAW,KAAK,SAAS,KAAK,WAAW,oBAC1C;;CAGH,IAAI,iBAAiB;AACrB,KAAI,KAAK,iBAAiB;EACxB,MAAM,UAAU,OAAO,KAAK;AAC5B,MAAI,OAAO,YAAY,YAAY;GACjC,MAAM,MAAM,iBAAiB,KAAK,gBAAgB,SAAS,KAAK,WAAW;AAC3E,SAAM,IAAI,MAAM,IAAI;;AAEtB,mBAAiB,MAAM,QAAQ,OAAO;;AAGxC,QAAO;EAAE,MAAM;GAAE,GAAG;GAAM;GAAI;EAAE,QAAQ;EAAgB;;;AAI1D,eAAe,YACb,cAC4B;CAC5B,MAAM,EAAE,MAAM,QAAQ,SAAS,WAAW;CAC1C,MAAM,MAAM,iBAAiB,MAAM,QAAQ,SAAS,OAAO;AAC3D,QAAO,qBAAqB,KAAK,MAAM,SAAS,IAAI;;;AAItD,SAAS,uBAAuB,SAAkB;CAChD,MAAM,cAAc,YAAY;CAChC,MAAM,WAAsB,EAAE;CAC9B,MAAM,SAAS,oBAAoB,QAAQ;CAC3C,MAAM,aAAa,YAAY;AAC/B,KAAI,WAAW,OAAO,OAAQ,gBAAe,QAAQ,SAAS;AAC9D,WACE,6BAA6B,WAAW,aAAa,WAAW,CAAC,QAAQ,EAAE,CAAC,IAC7E;AACD,QAAO;EAAE;EAAQ;EAAY;EAAU;;;AAIzC,SAAS,eAAe,QAAsB,UAA2B;CACvE,IAAI,SAAS;AACb,QAAO,OAAQ,GAAG,SAAS,SAAiB;AAC1C,YAAU,KAAK,UAAU;EACzB,MAAM,QAAQ,OAAO,MAAM,KAAK;AAChC,WAAS,MAAM,KAAK,IAAI;AACxB,OAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,QAAQ,YAAY,KAAK;AAC/B,OAAI,MACF,UAAS,KAAK,MAAM;YACX,KAAK,MAAM,CAEpB,SAAQ,OAAO,MAAM,OAAO,KAAK;;GAGrC;;;AAIJ,SAAS,qBACP,MACA,SACA,SAC4B;CAC5B,MAAM,YAAY,YAAY;CAC9B,MAAM,iBAAiB,QAAQ,WAAW;AAC1C,WAAU,uBAAuB,OAAO;AAExC,QAAO,IAAI,SAAS,SAAS,WAAW;EACtC,MAAM,EAAE,QAAQ,YAAY,aAC1B,uBAAuB,eAAe;AAQxC,sBAAoB,QAAQ,MAPX,qBACf,MACA,WACA,UACA,SACA,OACD,CAC0C;AAC3C,oBAAkB,QAAQ,SAAS,WAAW;GAC9C;;;AAIJ,SAAS,kBACP,QACA,SACA,YACM;CACN,MAAM,cAAc,YAAY;AAChC,QAAO,KAAK,QAAQ;AACpB,WACE,6BAA6B,WAAW,YAAY,YAAY,CAAC,QAAQ,EAAE,CAAC,IAC7E;;;AAIH,SAAS,oBACP,QACA,UACA,UACA;CACA,MAAM,EAAE,SAAS,WAAW;CAC5B,MAAM,UAAU,cAAc,QAAQ,UAAU,OAAO;AACvD,QAAO,GACL,WACA,qBAAqB,UAAU,SAAS,SAAS,OAAO,CACzD;AACD,QAAO,GAAG,SAAS,mBAAmB,UAAU,SAAS,OAAO,CAAC;AACjE,QAAO,GAAG,QAAQ,kBAAkB,UAAU,SAAS,OAAO,CAAC;;;AAIjE,SAAS,qBACP,UACA,SACA,SACA,QACA;AACA,SAAQ,QAAsC;AAC5C,WAAS;AACT,MAAI,IAAI,SAAS,SACf,SAAQ,IAAI,SAAS,IAAI,YAAY;WAC5B,IAAI,SAAS,SAAS;GAC/B,MAAM,wBAAQ,IAAI,MAAM,cAAc,SAAS,YAAY,IAAI,QAAQ;AACvE,OAAI,IAAI,MAAO,OAAM,QAAQ,IAAI;AACjC,UAAO,MAAM;;;;;AAMnB,SAAS,mBACP,UACA,SACA,QACA;AACA,SAAQ,UAAiB;AACvB,WAAS;AACT,yBACE,IAAI,MACF,wCAAwC,SAAS,KAAK,MAAM,UAC7D,CACF;;;;AAKL,SAAS,kBACP,UACA,SACA,QACA;AACA,SAAQ,MAAqB,YAAmC;AAC9D,MAAI,SAAS,KAAK,SAAS,MAAM;AAC/B,YAAS;GACT,MAAM,MAAM,2BAA2B,KAAK,kBAAkB,SAAS;AACvE,UAAO,IAAI,MAAM,IAAI,CAAC;;;;;AAM5B,SAAS,cACP,QACA,UACA,QACA;CACA,MAAM,YAAY,iBAAiB;AACjC,WAAS;AACT,yBAAO,IAAI,MAAM,cAAc,SAAS,8BAA8B,CAAC;IACtE,IAAM;CACT,MAAM,gBAAgB;AACpB,eAAa,UAAU;AACvB,MAAI,CAAC,OAAO,OAAQ,QAAO,KAAK,UAAU;;AAE5C,QAAO;;;AAIT,SAAS,oBAAoB,SAAkB;CAC7C,MAAM,aAAa,KAAK,KAAK,OAAO,KAAK,SAAU,kBAAkB;CACrE,MAAM,WAAW;EACf;EACA;EACA;EACA;EACD;AACD,KAAI,QAAS,UAAS,KAAK,iBAAiB;AAE5C,QAAO,KAAK,YAAY,EAAE,EAAE;EAC1B;EACA,QAAQ;EACR,KAAK;GACH,GAAG,QAAQ;GACX,cAAc;GACf;EACF,CAAC;;;AAOJ,SAAS,qBACP,UACA,WACA,UACA,SACA,QACgB;AAChB,QAAO;EACL,UAAU,SAA4B,gBAA8B;AAClE,aACE,yBAAyB,SAAS,IAAI,WAAW,UAAU,CAAC,QAAQ,EAAE,CAAC,IACxE;AACD,OAAI,UAAU,QAAQ;IACpB,MAAM,UAAU,iBAAiB,SAAS;AAC1C,SAAK,MAAM,KAAK,QAAS,GAAE,UAAU;;AAEvC,OAAI,YAAa,MAAK,MAAM,KAAK,QAAS,GAAE,cAAc;AAC1D,WAAQ,QAAQ;;EAElB;EACD;;;AAIH,SAAS,iBACP,MACA,YACA,SACA,QACY;CACZ,MAAM,EAAE,IAAI,GAAG,SAAS;CACxB,MAAM,UAAsB;EAC1B,MAAM;EACN,MAAM;EACN;EACA;EACA;EACD;AACD,KAAI,KAAK,YAAY;AACnB,UAAQ,aAAa,KAAK;AAC1B,UAAQ,aAAa,KAAK;AAC1B,MAAI,KAAK,gBAAiB,SAAQ,kBAAkB,KAAK;OAEzD,SAAQ,SAAS,GAAG,UAAU;AAEhC,QAAO;;;AAeT,eAAsB,iBACpB,QAC4B;CAC5B,MAAM,EACJ,YACA,WACA,QACA,UACA,aACA,QACA,YACE;CACJ,MAAM,OAAO,GAAG,UAAU,GAAG;AAY7B,QAAO,qBAAqB,MAAM,SAXN;EAC1B,MAAM;EACN,MAAM;GAAE;GAAM,UAAU;GAAI;EAC5B,YAAY;EACZ;EACA;EACA;EACA;EACA;EACA;EACD,CACkD;;;;;;ACvSrD,SAAgB,kBACd,GAC4B;AAC5B,QAAO,OAAO,MAAM,YAAY,WAAW,KAAK,SAAS;;;AA0B3D,eAAsB,UACpB,QACA,UAA4B,EAAE,EACN;AACxB,kBAAiB,OAAO;CACxB,MAAM,mBAAmB;EAAE,GAAG,OAAO;EAAU,GAAG;EAAS;AAE3D,KAAI,OAAO,WACT,QAAO,iBAAiB,QAAQ,iBAAiB;AAEnD,KAAI,OAAO,SACT,QAAO,gBAAgB,QAAQ,iBAAiB;AAElD,OAAM,IAAI,MAAM,yDAAyD;;;AAI3E,SAAS,iBAAoB,QAA8B;CACzD,MAAM,MACJ;AACF,KAAI,OAAO,eAAe,OAAO,gBAAiB,OAAM,IAAI,MAAM,IAAI;;AAGxE,SAAS,mBAAmB,SAA0C;AACpE,QAAO;EACL,eAAe,QAAQ;EACvB,SAAS,QAAQ,WAAW;EAC5B,QAAQ,QAAQ,UAAU;EAC1B,SAAS,QAAQ;EACjB,aAAa,QAAQ;EACrB,UAAU,QAAQ;EAClB,UAAU,QAAQ;EAClB,YAAY,QAAQ;EACpB,eAAe,QAAQ;EACvB,eAAe,QAAQ;EACvB,SAAS,QAAQ;EACjB,YAAY,QAAQ;EACpB,cAAc,QAAQ;EACtB,WAAW,QAAQ;EACpB;;;AAIH,eAAe,aACb,QACA,SACA;CACA,MAAM,cAAc,OAAO,cACvB,MAAM,gBAAmB,OAAO,YAAY,GAC5C;CACJ,MAAM,aAAa,aAAa,SAAS,OAAO,SAAS,CAAC,UAAU;AAEpE,QAAO;EAAE;EAAa,SADN,QAAQ,iBAAiB;EACV;;;AAIjC,eAAe,gBACb,QACA,SACwB;CAExB,MAAM,MACJ;AACF,KAAI,OAAO,YAAa,OAAM,IAAI,MAAM,IAAI;CAE5C,MAAM,EAAE,aAAa,YAAY,MAAM,aAAa,QAAQ,QAAQ;CACpE,MAAM,SAAS,IAAI,aAAa;CAChC,MAAM,aAAa,mBAAmB,QAAQ;CAE9C,MAAM,iBAAiB,QAAQ,mBAC3B,OAAO,QAAQ,OAAO,SAAU,CAAC,QAAQ,CAAC,QACxC,QAAQ,iBAAkB,SAAS,GAAG,CACvC,GACD,OAAO,QAAQ,OAAO,SAAU;CAEpC,MAAM,WAA4B,EAAE;AACpC,MAAK,MAAM,CAAC,WAAW,YAAY,gBAAgB;EACjD,MAAM,QAAsB,EAAE;AAC9B,OAAK,MAAM,UAAU,SAAS;GAC5B,MAAM,SAAS,MAAM,aAAa,aAAa,OAAO;GAGtD,MAAM,WAAW,MAAM,WACrB,SAFA,eAAe,OAAO,QAAQ,OAAO,OAAQ,QAI7C,WACA,QACA,WACD;AACD,SAAM,KAAK;IAAE;IAAQ;IAAU,UAAU,OAAO;IAAU,CAAC;;AAE7D,WAAS,KAAK;GAAE,IAAI;GAAW;GAAO,CAAC;;AAGzC,KAAI,OAAO,gBACT,sBAAqB,UAAU,OAAO,gBAAgB;AAGxD,QAAO;EAAE,MAAM,OAAO;EAAM;EAAU;;;AAaxC,eAAe,iBACb,QACA,SACwB;CACxB,MAAM,gBAAgB,MAAM,iBAAiB,OAAO,WAAY;AAChE,KAAI,cAAc,WAAW,EAC3B,OAAM,IAAI,MAAM,wBAAwB,OAAO,aAAa;CAK9D,MAAM,WAAW,MAAM,eAHJ,QAAQ,oBAAoB,eAEnC,MAAM,iBAAiB,QAAQ,QAAQ,CACG;AAEtD,KAAI,OAAO,gBACT,sBAAqB,UAAU,OAAO,gBAAgB;AAExD,QAAO;EAAE,MAAM,OAAO;EAAM;EAAU;;;AAIxC,eAAe,iBACb,QACA,SAC8B;CAC9B,MAAM,cAAc,OAAO,cACvB,MAAM,iBAAiB,OAAO,YAAY,GAC1C,EAAE;CACN,MAAM,EAAE,aAAa,YAAY,MAAM,aAAa,QAAQ,QAAQ;AAEpE,QAAO;EAAE;EAAQ;EAAa;EAAa;EAAS,YADjC,mBAAmB,QAAQ;EACkB;;;AAIlE,eAAe,eACb,YACA,KAC0B;CAC1B,MAAM,WAA4B,EAAE;AACpC,MAAK,MAAM,aAAa,YAAY;EAClC,MAAM,QAAQ,MAAM,mBAAmB,WAAW,IAAI;AACtD,WAAS,KAAK;GAAE,IAAI;GAAW;GAAO,CAAC;;AAEzC,QAAO;;;AAIT,eAAe,mBACb,WACA,KACuB;CACvB,MAAM,EAAE,QAAQ,aAAa,SAAS,eAAe;CACrD,MAAM,QAAsB,EAAE;AAE9B,MAAK,MAAM,UAAU,SAAS;EAC5B,MAAM,WAAW,CAAC,OAAO,eAAe,OAAO,QAAQ,SAAS;EAChE,MAAM,CAAC,YAAY,MAAM,iBAAiB;GACxC,YAAY,OAAO;GACnB;GACA;GACA;GACA,aAAa,OAAO;GACpB,QAAQ;GACR,SAAS;GACV,CAAC;EAEF,MAAM,SAAS,MAAM,aAAa,aAAa,OAAO;EACtD,MAAM,WAAW,MAAM,oBACrB,WACA,QACA,UACA,IACD;EACD,MAAM,eAAe,WACjB,oBAAoB,UAAU,SAAS,GACvC;EACJ,MAAM,WAAW,OAAO;AACxB,QAAM,KAAK;GAAE;GAAQ;GAAU;GAAU;GAAU;GAAc,CAAC;;AAEpE,QAAO;;;AAIT,eAAe,oBACb,WACA,QACA,UACA,KACsC;CACtC,MAAM,EAAE,QAAQ,aAAa,eAAe;AAC5C,KAAI,CAAC,OAAO,eAAe,CAAC,YAAY,SAAS,UAAU,CAAE,QAAO;CAEpE,MAAM,CAAC,YAAY,MAAM,iBAAiB;EACxC,YAAY,OAAO;EACnB;EACA;EACA;EACA,aAAa,OAAO;EACpB,QAAQ;EACR,SAAS;EACV,CAAC;AACF,QAAO;;;AAIT,SAAS,oBACP,UACA,SACQ;CACR,MAAM,UAAU,QAAQ,SAAS,QAAQ;AACzC,KAAI,YAAY,EAAG,QAAO;AAC1B,SAAS,QAAQ,QAAQ,QAAQ,GAAG,WAAW,UAAW;;;AAI5D,SAAS,qBACP,UACA,mBACM;CACN,MAAM,kBAAkB,SAAS,MAAK,MAAK,EAAE,OAAO,kBAAkB;AACtE,KAAI,CAAC,gBAAiB;CAEtB,MAAM,iCAAiB,IAAI,KAA8B;AACzD,MAAK,MAAM,KAAK,gBAAgB,MAC9B,gBAAe,IAAI,EAAE,QAAQ,EAAE,SAAS;AAG1C,MAAK,MAAM,WAAW,UAAU;AAC9B,MAAI,QAAQ,OAAO,kBAAmB;AACtC,OAAK,MAAM,cAAc,QAAQ,OAAO;GACtC,MAAM,WAAW,eAAe,IAAI,WAAW,OAAO;AACtD,OAAI,UAAU;AACZ,eAAW,WAAW;AACtB,eAAW,eAAe,oBACxB,UACA,WAAW,SACZ;;;;;;AAOT,eAAe,WACb,SACA,UACA,MACA,QACA,SAC0B;AAC1B,KAAI,kBAAkB,QAAQ,EAAE;EAC9B,MAAM,QAAQ,MAAM,QAAQ,MAAM,SAAS;EAC3C,MAAM,CAAC,UAAU,MAAM,OAAO,SAC5B;GAAE;GAAM,UAAU,QAAQ,IAAI,MAAM;GAAE,EACtC,QACD;AACD,SAAO;;CAET,MAAM,CAAC,UAAU,MAAM,OAAO,SAC5B;EAAE;EAAM,UAAU,QAAQ,SAAS;EAAE,EACrC,QACD;AACD,QAAO;;;;;ACtXT,MAAM,EAAE,YAAK,UADE,QAAQ,IAAI,aAAa,UAAU,QAAQ,IAAI,WAAW,SAErE;CAAE,MAAM,QAAgB;CAAK,QAAQ,QAAgB;CAAK,GAC1D;;AAWJ,SAAgB,iBAAiB,WAAmB;AAClD,SAAQ,MAA8B;AACpC,MAAI,OAAO,MAAM,SAAU,QAAO;AAClC,SAAO,QAAQ,GAAG,UAAU;;;;AAKhC,SAAgB,SAAS,IAA4B;AACnD,KAAI,OAAO,OAAO,SAAU,QAAO;AACnC,KAAI,KAAK,KAAO,QAAO,IAAI,KAAK,KAAS,QAAQ,EAAE,CAAC;AACpD,KAAI,KAAK,EAAG,QAAO,IAAI,KAAK,KAAM,QAAQ,EAAE,CAAC;AAC7C,KAAI,KAAK,IAAM,QAAO,GAAG,GAAG,QAAQ,EAAE,CAAC;AACvC,QAAO,IAAI,KAAK,KAAM,QAAQ,EAAE,CAAC;;;AAInC,SAAgB,OAAO,IAA4B;AACjD,KAAI,OAAO,OAAO,SAAU,QAAO;AACnC,KAAI,KAAK,KAAO,QAAO,IAAI,KAAK,KAAS,QAAQ,EAAE,CAAC;AACpD,KAAI,KAAK,IAAM,QAAO,IAAI,KAAK,KAAM,QAAQ,EAAE,CAAC;AAChD,KAAI,MAAM,GAAI,QAAO,GAAG,QAAQ,EAAE;AAClC,QAAO,GAAG,QAAQ,EAAE;;;AAYtB,SAAgB,QAAQ,GAA2B;AACjD,KAAI,OAAO,MAAM,SAAU,QAAO;AAClC,QAAO,IAAI,KAAK,aAAa,QAAQ,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;;;AAI7D,SAAgB,QAAQ,UAAmB,YAAY,GAAkB;AACvE,KAAI,OAAO,aAAa,SAAU,QAAO;AACzC,QAAO,GAAG,KAAK,IAAI,WAAW,IAAI,CAAC,QAAQ,UAAU,CAAC;;;AAIxD,SAAgB,YAAY,MAAe,MAAuB;AAChE,KAAI,OAAO,SAAS,YAAY,OAAO,SAAS,SAAU,QAAO;AAEjE,QAAO,eADM,OAAO,MACQ,KAAK;;;AAWnC,SAAS,eACP,WACA,aACA,kBAAkB,MACV;CACR,MAAM,WAAW,YAAY;AAC7B,KAAI,OAAO,MAAM,SAAS,IAAI,CAAC,OAAO,SAAS,SAAS,CACtD,QAAO;CAET,MAAM,WAAW,YAAY;CAE7B,MAAM,aAAa,GADN,WAAW,MAAM,MACD,QAAQ,SAAS;AAE9C,QADe,aAAa,kBACZ,MAAM,WAAW,GAAGC,MAAI,WAAW;;;AAWrD,SAAgB,YAAY,OAA+B;AACzD,KAAI,OAAO,UAAU,SAAU,QAAO;AACtC,KAAI,QAAQ,KAAM,QAAO,GAAG,MAAM,QAAQ,EAAE,CAAC;AAC7C,KAAI,QAAQ,OAAO,KAAM,QAAO,IAAI,QAAQ,MAAM,QAAQ,EAAE,CAAC;AAC7D,KAAI,QAAQ,OAAO,OAAO,KACxB,QAAO,IAAI,QAAQ,OAAO,MAAM,QAAQ,EAAE,CAAC;AAC7C,QAAO,IAAI,QAAQ,OAAO,OAAO,MAAM,QAAQ,EAAE,CAAC;;;AAIpD,SAAgB,iBAAiB,OAA+B;AAC9D,KAAI,CAAC,eAAe,MAAM,CAAE,QAAO;CACnC,MAAM,EAAE,SAAS,IAAI,cAAc;AACnC,QAAO,iBAAiB,WAAW,SAAS,GAAG,EAAE,UAAU;;;AAI7D,SAAgB,+BAA+B,OAA+B;AAC5E,KAAI,CAAC,eAAe,MAAM,CAAE,QAAO;CACnC,MAAM,EAAE,SAAS,IAAI,cAAc;AAEnC,QAAO,iBAAiB,WAAW,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,EAAE,UAAU;;;AAI5E,SAAS,WAAW,KAAa,IAA8B;AAC7D,QAAO,GAAG,YAAY,IAAI,CAAC,IAAI,YAAY,GAAG,GAAG,CAAC,IAAI,YAAY,GAAG,GAAG,CAAC;;;AAI3E,SAAS,iBAAiB,MAAc,WAAgC;AACtE,KAAI,cAAc,SAAU,QAAO,MAAM,KAAK;AAC9C,KAAI,cAAc,SAAU,QAAOA,MAAI,KAAK;AAC5C,QAAO;;;AAIT,SAAS,YAAY,GAAmB;AAEtC,QAAO,GADM,KAAK,IAAI,MAAM,KACX,EAAE,QAAQ,EAAE,CAAC;;;AAIhC,SAAS,eAAe,GAA+B;AACrD,QAAO,OAAO,MAAM,YAAY,MAAM,QAAQ,QAAQ,KAAK,eAAe;;;AAI5E,SAAgB,SAAS,KAAa,SAAS,IAAY;AACzD,QAAO,IAAI,SAAS,SAAS,IAAI,MAAM,GAAG,SAAS,EAAE,GAAG,QAAQ;;;;;AChJlE,MAAM,EAAE,SADO,QAAQ,IAAI,aAAa,UAAU,QAAQ,IAAI,WAAW,SAC/C,EAAE,OAAO,QAAgB,KAAK,GAAG;;AAgD3D,SAAgB,WACd,cACA,cACA,UAAmB,QACX;AAER,QAAO,YAAY,cADA,cAAc,cAAc,cAAc,QAAQ,CACzB;;;AAI9C,SAAS,YACP,QACA,SACQ;CACR,MAAM,WAAW,OAAO,SAAS,OAAO;CACxC,MAAM,EAAE,YAAY,WAAW,MAAM,QAAQ,SAAS;AAEtD,QAAO,MADS,CAAC,GAAG,YAAY,GAAG,SAAS,EACtB,OAAO;;;AAI/B,SAAS,mBACP,QACA,YACY;AACZ,KAAI,CAAC,OAAO,MAAK,MAAK,EAAE,WAAW,CAAE,QAAO,EAAE;AAO9C,QAAO,CALY,OAAO,SAAQ,MAAK;AAErC,SAAO,cADO,EAAE,aAAa,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,EAAE,EAC1B,EAAE,QAAQ,OAAO;GAC7C,EACe,cAAc,EAAE,EAAE,WAAW,CACjB;;;AAS/B,SAAS,YAAe,QAAiC;CACvD,MAAM,EAAE,gBAAgB,iBAAiB,YAAY,OAAO;CAE5D,SAAS,iBAAiB,OAAe,MAAuB;AAC9D,SAAO,UAAU,KAAK,UAAU,QAAQ,eAAe,SAAS,MAAM;;CAExE,SAAS,mBAAmB,OAAe,MAAuB;AAChE,SAAO,UAAU,KAAK,UAAU,QAAQ,UAAU;;AAEpD,QAAO;EAAE;EAAoB;EAAkB;;;AAIjD,SAAS,mBAAsB,QAAgD;CAC7E,IAAI,MAAM;CACV,MAAM,YAAuB;AAC7B,QAAO,OAAO,KAAI,MAAK;EACrB,MAAM,UAAU,EAAE,QAAQ;EAC1B,MAAM,OAAO;GAAE,KAAK;GAAG;GAAK;GAAS;GAAW;AAChD,SAAO;AACP,SAAO;GACP;;;AAIJ,SAAS,UAAa,QAAoC;AACxD,QAAO,OAAO,SAAQ,MAAK,EAAE,QAAQ,KAAI,MAAK,KAAK,EAAE,SAAS,IAAI,CAAC,CAAC;;;AAItE,SAAS,cAAc,KAAe,QAA0B;AAC9D,KAAI,IAAI,UAAU,OAAQ,QAAO;AACjC,QAAO,CAAC,GAAG,KAAK,GAAG,MAAM,SAAS,IAAI,OAAO,CAAC,KAAK,IAAI,CAAC;;;AAI1D,SAAgB,OACd,SACA,QACY;CACZ,MAAM,aAAa,OAAO,SAAQ,UAAS,MAAM,QAAQ;AASzD,QAPgB,QAAQ,KAAI,WAC1B,WAAW,KAAI,QAAO;EACpB,MAAM,QAAQ,OAAO,IAAI;AACzB,SAAO,IAAI,YAAY,IAAI,UAAU,MAAM,GAAG;GAC9C,CACH,CAEc,KAAI,QAAO,IAAI,KAAI,SAAQ,QAAQ,IAAI,CAAC;;;AAIzD,SAAS,eACP,QACA,YACA,gBACG;CACH,MAAM,cAAc,OAAO,SAAQ,MAAK,EAAE,QAAQ,CAAC,QAAO,QAAO,IAAI,QAAQ;CAC7E,MAAM,cAAc,EAAE,GAAG,YAAY;AAErC,MAAK,MAAM,OAAO,aAAa;EAC7B,MAAM,OAAO;EACb,MAAM,UAAU,KAAK;EACrB,MAAM,YAAY,WAAW;EAC7B,MAAM,gBAAgB,eAAe;EAErC,MAAM,WADa,KAAK,iBAAiB,aACd,WAAW,cAAc;AACpD,EAAC,YAAoB,IAAI,OAAO;;AAGlC,QAAO;;;AAIT,SAAS,cACP,cACA,cACA,SACK;AACL,QAAO,aAAa,SAAS,OAAO,MAAM;EACxC,MAAM,eAAe,YAAY,cAAc,OAAO,QAAQ;AAG9D,SADe,MAAM,aAAa,SAAS,IAC3B,eAAe,CAAC,GAAG,cAAc,EAAE,CAAM;GACzD;;;AAIJ,SAAS,YACP,cACA,OACA,SACK;CACL,MAAM,EAAE,SAAS,aAAa;AAE9B,KAAI,CAAC,SAAU,QAAO;CAEtB,MAAM,cAAc,QAAQ,KAAI,WAC9B,eAAe,cAAc,QAAQ,SAAS,CAC/C;CAED,MAAM,iBAAiB;EACrB,GAAG;GACF,UAAU,OAAO,SAAS;EAC5B;AAED,QAAO,CAAC,GAAG,aAAa,eAAe;;;AAIzC,SAAS,YAAe,QAGtB;AACA,KAAI,OAAO,WAAW,EAAG,QAAO;EAAE,gBAAgB,EAAE;EAAE,cAAc;EAAG;CAEvE,MAAM,iBAA2B,EAAE;CACnC,IAAI,SAAS;AACb,MAAK,MAAM,KAAK,QAAQ;AACtB,YAAU,EAAE,QAAQ;AACpB,iBAAe,KAAK,OAAO;;AAE7B,QAAO;EAAE;EAAgB,cAAc;EAAG;;;AAI5C,SAAS,MAAS,QAA0B,UAAkC;CAC5E,MAAM,SAAS,UAAU,OAAO;CAChC,MAAM,aAAa,OAAO;AAY1B,QAAO;EAAE,YATU,CAAC,GADA,mBAAmB,QAAQ,WAAW,EACtB,OAAO;EAStB,QANW;GAC9B,eAHoB,mBAAmB,OAAO;GAI9C,SAHmB,iBAAiB,QAAQ,QAAQ,SAAS;GAI7D,GAAG,YAAY,OAAO;GACvB;EAE4B;;;AAI/B,SAAS,iBACP,QACA,QACA,UACsD;CAEtD,MAAM,SAAmB,EAAE;AAC3B,MAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;EACtC,MAAM,SAAS,UAAU,OAAO,GAAG;EACnC,MAAM,WAAW,SAAS,QACvB,KAAK,QAAQ,KAAK,IAAI,KAAK,UAAU,IAAI,GAAG,CAAC,EAC9C,EACD;AACD,SAAO,KAAK,KAAK,IAAI,QAAQ,SAAS,CAAC;;CAIzC,IAAI,WAAW;AACf,MAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,SAAS,UAAU,MAAM,WAAW;AAC1C,MAAI,SAAS,GAAG;GACd,MAAM,UAAU,MAAM,QAAQ;GAC9B,MAAM,kBAAkB,UAAU,KAAK;GAIvC,MAAM,SAAS,SAHM,OAClB,MAAM,UAAU,WAAW,QAAQ,CACnC,QAAQ,GAAG,MAAM,IAAI,GAAG,EAAE,GACU;AACvC,OAAI,SAAS,EAEX,QAAO,WAAW,UAAU,MAAM;;AAGtC,cAAY,MAAM,QAAQ;;AAI5B,QAAO,OAAO,YACZ,OAAO,KAAK,GAAG,MAAM,CAAC,GAAG;EAAE,OAAO;EAAG,UAAU;EAAO,CAAC,CAAC,CACzD;;AAIH,MAAM,kBAAkB,IAAI,OAC1B,OAAO,aAAa,GAAG,GAAG,eAC1B,IACD;;AAGD,SAAS,UAAU,OAAwB;AACzC,KAAI,SAAS,KAAM,QAAO;AAE1B,QADY,OAAO,MAAM,CACd,QAAQ,iBAAiB,GAAG,CAAC;;;;;;ACtO1C,SAAgB,cACd,QACA,UACQ;CACR,MAAM,UAAU,OAAO,KAAI,UAAS,kBAAkB,OAAO,SAAS,CAAC;AAEvE,QAAO,WAAW,mBAAmB,UADjB,QAAQ,MAAK,MAAK,EAAE,SAAS,CACU,EAAE,QAAQ;;;AAIvE,SAAS,kBACP,OACA,UAC+B;CAC/B,MAAM,EAAE,SAAS,aAAa;CAC9B,MAAM,kBAAkB,UAAU,gBAAgB;AAkBlD,QAAO;EAAE,SAhBO,QAAQ,KAAI,WAAU;GACpC,MAAM,MAAM;IACV,MAAM,SAAS,OAAO,KAAK;IAC3B,GAAG,oBAAoB,QAAQ,SAAS;IACzC;AAED,OAAI,mBAAmB,OAAO,gBAAgB,QAC5C,CAAC,IAAY,SAAS,sBACpB,iBACA,OAAO,gBAAgB,QACxB;AAEH,UAAO;IACP;EAGgB,UADE,YAAY,iBAAiB,CAAC,SAAS,EAAE,SAAS,CAAC;EAC9B;;;AAI3C,SAAgB,iBACd,SACA,UACoB;AACpB,QAAO,QAAQ,KAAI,YAAW;EAC5B,MAAM,SAAS,OAAO,KAAK;EAC3B,GAAG,oBAAoB,QAAQ,SAAS;EACzC,EAAE;;;AAIL,SAAS,oBACP,QACA,UACe;CACf,MAAM,EAAE,iBAAiB,aAAa;CACtC,MAAM,UAAU,SAAS,SAAQ,MAC/B,OAAO,QAAQ,EAAE,QAAQ,iBAAiB,SAAS,CAAC,CACrD;AACD,QAAO,OAAO,YAAY,QAAQ;;;AAIpC,SAAS,mBACP,UACA,aACiC;CACjC,MAAM,aAA4C,EAChD,SAAS,CAAC;EAAE,KAAK;EAAkC,OAAO;EAAQ,CAAC,EACpE;CAED,MAAM,SAAS,SAAS,SAAQ,YAAW,QAAQ,SAAS,CAAC;AAC7D,QAAO,CAAC,YAAY,GAAI,cAAc,kBAAkB,OAAO,GAAG,OAAQ;;;AAI5E,SAAgB,kBACd,cACkB;CAClB,IAAI,UAAU;AAEd,QAAO,aAAa,KAAI,WAAU;EAChC,YAAY,MAAM;EAClB,SAAS,MAAM,QAAQ,SAAQ,QAAO;AACpC,OAAI,IAAI,cAAc,CAAC,SAAS;AAC9B,cAAU;AAIV,WAAO,CACL,KACA;KAAE,OAAO;KAAS,KAAK;KAAqB,WALlC,IAAI,iBACZ,iCACA;KAG0D,CAC7D;;AAEH,UAAO,CAAC,IAAI;IACZ;EACH,EAAE;;;;;ACvJL,MAAa,cAAc;AAC3B,MAAa,yBAAyB;AACtC,MAAa,uBAAuB;AACpC,MAAa,uBAAuB;AASpC,MAAM,aAAa;CACjB,MAAgB;EAAE,MAAM;EAAW,SAAS;EAAa,aAAa;EAAM,UAAU;EAA4B;CAClH,KAAgB;EAAE,MAAM;EAAW,SAAS;EAAO,UAAU;EAA4C;CACzG,SAAgB;EAAE,MAAM;EAAW,SAAS;EAAO,UAAU;EAAiC;CAC9F,YAAgB;EAAE,MAAM;EAAW,SAAS;EAAO,UAAU;EAAsE;CACnI,SAAgB;EAAE,MAAM;EAAW,SAAS;EAAO,UAAU;EAA0B;CACvF,QAAgB;EAAE,MAAM;EAAW,aAAa;EAAM,UAAU;EAA2C;CAC3G,KAAgB;EAAE,MAAM;EAAW,SAAS;EAAO,UAAU;EAAuC;CACpG,QAAgB;EAAE,MAAM;EAAW,SAAS;EAAM,UAAU;EAAuD;CACnH,UAAgB;EAAE,MAAM;EAAW,SAAS;EAAO,UAAU;EAA8B;CAC3F,YAAgB;EAAE,MAAM;EAAW,SAAS;EAAG,UAAU;EAAgE;CACzH,aAAgB;EAAE,MAAM;EAAW,SAAS;EAAI,UAAU;EAAgC;CAC1F,QAAgB;EAAE,MAAM;EAAW,SAAS;EAAG,UAAU;EAAwC;CACjG,MAAgB;EAAE,MAAM;EAAW,SAAS;EAAO,UAAU;EAA4C;CACzG,eAAgB;EAAE,MAAM;EAAW,aAAa;EAAM,UAAU;EAAwC;CACxG,MAAgB;EAAE,MAAM;EAAW,aAAa;EAAM,UAAU;EAAsC;CACtG,UAAgB;EAAE,MAAM;EAAW,aAAa;EAAM,UAAU;EAAwD;CACxH,aAAgB;EAAE,MAAM;EAAW,SAAS;EAAO,UAAU;EAAiE;CAC9H,eAAgB;EAAE,MAAM;EAAW,SAAS;EAAO,UAAU;EAAiE;CAC9H,eAAgB;EAAE,MAAM;EAAW,UAAU;EAA+D;CAC5G,kBAAkB;EAAE,MAAM;EAAU,SAAS;EAAsB,UAAU;EAAgE;CAC7I,kBAAkB;EAAE,MAAM;EAAU,SAAS;EAAsB,UAAU;EAA4C;CACzH,SAAkB;EAAE,MAAM;EAAW,SAAS;EAAG,UAAU;EAAkE;CAC7H,YAAkB;EAAE,MAAM;EAAW,aAAa;EAAM,UAAU;EAAiD;CACnH,eAAkB;EAAE,MAAM;EAAW,SAAS;EAAO,UAAU;EAA2D;CAC1H,iBAAkB;EAAE,MAAM;EAAW,SAAS;EAAO,UAAU;EAAmC;CAClG,cAAkB;EAAE,MAAM;EAAW,SAAS;EAAI,UAAU;EAA6B;CACzF,aAAkB;EAAE,MAAM;EAAW,SAAS;EAAI,UAAU;EAAgC;CAC5F,cAAkB;EAAE,MAAM;EAAW,SAAS;EAAG,UAAU;EAA+B;CAC1F,gBAAkB;EAAE,MAAM;EAAW,SAAS;EAAO,UAAU;EAAsD;CACrH,kBAAkB;EAAE,MAAM;EAAW,SAAS;EAAO,UAAU;EAAkD;CACjH,KAAkB;EAAE,MAAM;EAAW,aAAa;EAAM,UAAU;EAAyD;CAC3H,UAAkB;EAAE,MAAM;EAAW,SAAS;EAAM,UAAU;EAAgC;CAC9F,SAAkB;EAAE,MAAM;EAAW,SAAS;EAAI,UAAU;EAAmC;CAChG;;AAGD,SAAgB,eAAe,eAAqB;AAClD,QAAO,cAAc,QAAQ,WAAW,CAAC,MAAM,CAAC,QAAQ;;;AAI1D,SAAgB,aACd,MACA,YAA0B,gBACvB;AAEH,QADsB,UAAU,MAAM,KAAK,CAAC,CACvB,WAAW;;;;;;AC9ClC,SAAgB,mBAAmB,aAAsC;AACvE,QAAO,YAAY,SAAQ,MAAK;AAC9B,MAAI,EAAE,OAAO,IAAK,QAAO,EAAE;EAC3B,MAAM,OAAO,OAAO,EAAE,KAAK;AAC3B,MAAI,CAAC,KAAM,QAAO,EAAE;EACpB,MAAM,QAAQ,EAAE,OAAO;EACvB,MAAM,aAAqB,EAAE,MAAM,sBAAsB;EACzD,MAAM,YAAoB,EAAE,MAAM,qBAAqB;AACvD,SAAO,CACL;GACE;GACA,SAAS,QAAQ;GACjB,WAAW,KAAK,IAAI,GAAG,aAAa,UAAU;GAC/C,CACF;GACD;;AAGJ,SAAS,OAAO,MAA2C;AACzD,KAAI,SAAS,UAAW,QAAO;AAC/B,KAAI,SAAS,UAAW,QAAO;;;AAKjC,SAAgB,eAAe,aAAoC;AACjE,QAAO,iBAAiB,mBAAmB,YAAY,CAAC;;;;;;;;ACN1D,eAAsB,eACpB,QAC+B;CAC/B,MAAM,EAAE,KAAK,WAAW,MAAM,UAAU,OAAO;CAC/C,MAAM,EAAE,SAAS,cAAc;CAC/B,MAAM,EAAE,mBAAmB,UAAU,OAAO,eAAe,EAAE;CAE7D,MAAM,UAAU,MAAM,SAAS,OAAO,EAAE,UAAU,CAAC;AACnD,KAAI;EACF,MAAM,OAAO,MAAM,QAAQ,SAAS;AACpC,OAAK,kBAAkB,UAAU,IAAK;EACtC,MAAM,MAAM,MAAM,KAAK,SAAS,CAAC,cAAc,KAAK;EAEpD,MAAM,aAAuB,EAAE;AAC/B,OAAK,GAAG,cAAa,QAAO,WAAW,KAAK,IAAI,QAAQ,CAAC;EAEzD,MAAM,cAAc,YAAY,MAAM,eAAe,IAAI,GAAG,EAAE;EAC9D,MAAM,UAAU,MAAM,aACpB,MACA,KACA,QACA,kBACA,SACA,WACD;AAED,QAAM,KAAK,KAAK,KAAK,EAAE,WAAW,QAAQ,CAAC;EAC3C,MAAM,WAAW,MAAM,KAAK,eACpB,OAAQ,WAAmB,YAAY,WAC9C;EAED,IAAI;AACJ,MAAI,UAAU;AACZ,WAAQ,QAAQ;AAChB,WAAQ,QAAQ,YAAY,GAAG;AAC/B,YAAS,MAAM,aAAa,MAAM,KAAK,QAAQ,iBAAiB;SAC3D;AACL,YAAS,MAAM,QAAQ;AACvB,WAAQ,QAAQ;;AAGlB,MAAI,UACF,UAAS;GAAE,GAAG;GAAQ,SAAS,MAAM,eAAe,KAAK,YAAY;GAAE;AAEzE,SAAO;WACC;AACR,QAAM,QAAQ,OAAO;;;;;;AAOzB,eAAe,aACb,MACA,KACA,QACA,kBACA,SACA,YACwB;CACxB,MAAM,EAAE,eAAe;CACvB,MAAM,EAAE,SAAS,SAAS,WACxB,QAAQ,eAAqC;CAC/C,IAAI,qBAAqB;AAEzB,OAAM,KAAK,eAAe,0BAA0B,YAAY;AAC9D,MAAI,mBAAoB;AACxB,uBAAqB;AACrB,MAAI,WACF,OAAM,IAAI,KACR,8BACA,mBAAmB,iBAAiB,CACrC;GAEH;AAEF,OAAM,KAAK,eACT,kBACA,OAAO,SAAmB,eAAuB;EAC/C,IAAI;AACJ,MAAI,cAAc,mBAEhB,gBADe,MAAM,IAAI,KAAK,4BAA4B,EACrC;AAEvB,UAAQ;GAAE;GAAS;GAAa;GAAY,CAAC;GAEhD;AAED,OAAM,KAAK,cAAc,mBAAmB;CAE5C,MAAM,QAAQ,iBAAiB;EAC7B,MAAM,QAAQ,CAAC,mBAAmB,QAAQ,GAAG;AAC7C,MAAI,WAAW,OACb,OAAM,KAAK,mBAAmB,GAAG,WAAW,KAAI,MAAK,KAAK,IAAI,CAAC;MAE/D,OAAM,KAAK,sDAAsD;AAEnE,SAAO,IAAI,MAAM,MAAM,KAAK,KAAK,CAAC,CAAC;IAClC,UAAU,IAAK;AAElB,QAAO;EAAE;EAAS,cAAc,aAAa,MAAM;EAAE;;;;AAKvD,SAAS,qBAA2B;CAClC,MAAM,IAAI;AACV,GAAE,iBAAiB,EAAE;AACrB,GAAE,kBAAkB;AACpB,GAAE,oBAAoB;AAEtB,GAAE,gBAAgB;EAChB,MAAM,MAAM,YAAY,KAAK;AAC7B,IAAE,kBAAkB;AACpB,MAAI,CAAC,EAAE,mBAAmB;AACxB,KAAE,oBAAoB;AACtB,UAAO,EAAE,wBAAwB;;;AAIrC,GAAE,cAAc;EACd,MAAM,MAAM,YAAY,KAAK;AAC7B,IAAE,eAAe,KAAK,MAAM,EAAE,gBAAgB;AAC9C,IAAE,kBAAkB;;AAGtB,GAAE,eAAe;EACf,MAAM,OAAO,EAAE,oBACX,YAAY,KAAK,GAAG,EAAE,oBACtB;AACJ,SAAO,EAAE,eAAe,EAAE,eAAe,OAAO,EAAE,KAAK;;;AAI3D,SAAS,mBAAmB,kBAA0B;AACpD,QAAO;EACL;EACA,kCAAkC;EAClC,kCAAkC;EACnC;;;AAIH,eAAe,eAAe,KAAwC;CACpE,MAAM,SAAuB,EAAE;AAC/B,KAAI,GAAG,0BAA0B,EAAE,YAAY;AAC7C,OAAK,MAAM,KAAK,MAAO,QAAO,KAAK,EAA2B;GAC9D;AACF,OAAM,IAAI,KAAK,iBAAiB,EAC9B,aAAa,EAAE,oBAAoB,CAAC,MAAM,QAAQ,EAAE,EACrD,CAAC;AACF,QAAO;;;AAIT,eAAe,aACb,MACA,KACA,QACA,kBAC+B;CAC/B,MAAM,EAAE,eAAe;CACvB,MAAM,UAAU,OAAO,WAAW;CAClC,MAAM,UAAU,OAAO,iBAAiB,OAAO;AAE/C,KAAI,WACF,OAAM,IAAI,KACR,8BACA,mBAAmB,iBAAiB,CACrC;CAGH,MAAM,EAAE,SAAS,YAAY,MAAM,KAAK,SACtC,OAAO,EAAE,SAAS,cAAc;EAC9B,MAAM,QAAS,WAAmB;EAClC,MAAM,UAAoB,EAAE;EAC5B,MAAM,WAAW,YAAY,KAAK;EAClC,MAAM,WAAW,WAAW;AAC5B,OAAK,IAAI,IAAI,GAAG,IAAI,WAAW,YAAY,KAAK,GAAG,UAAU,KAAK;GAChE,MAAM,KAAK,YAAY,KAAK;AAC5B,SAAM,OAAO;AACb,WAAQ,KAAK,YAAY,KAAK,GAAG,GAAG;;AAEtC,SAAO;GAAE;GAAS,SAAS,YAAY,KAAK,GAAG;GAAU;IAE3D;EAAE;EAAS;EAAS,CACrB;CAED,IAAI;AACJ,KAAI,WAEF,gBADe,MAAM,IAAI,KAAK,4BAA4B,EACrC;AAGvB,QAAO;EAAE;EAAS;EAAa,YAAY;EAAS;;;AAItD,eAAe,eACb,KACA,aACkB;CAClB,MAAM,WAAW,IAAI,SAAc,YACjC,IAAI,KAAK,iCAAiC,SAAS,CAAC,CACrD;AACD,OAAM,IAAI,KAAK,cAAc;AAC7B,OAAM;AACN,QAAO,eAAe,YAAY;;;;;;AC1OpC,eAAsB,oBACpB,QACA,YACA,MACA,YAAY,mBACG;CACf,MAAM,WAAW,gBAAgB,QAAQ,MAAM,UAAU;AAGzD,OAAM,UAAU,YAFG,KAAK,UAAU,UAAU,MAAM,EAAE,EAEZ,QAAQ;AAChD,SAAQ,IAAI,+BAA+B,aAAa;;;AAI1D,SAAS,gBACP,QACA,MACA,WACmB;AACnB,QAAO;EACL,MAAM;GACJ,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC,SAAS,QAAQ,IAAI,uBAAuB;GAC5C,MAAM,aAAa,KAAK;GACxB,aAAa;IACX,MAAM,QAAQ;IACd,UAAU,QAAQ;IAClB,MAAM,QAAQ;IACf;GACF;EACD,QAAQ,CACN;GACE,MAAM;GACN,QAAQ,OAAO,IAAI,aAAa;GACjC,CACF;EACF;;;AAIH,SAAS,aAAa,OAAoC;AACxD,QAAO;EACL,MAAM;EACN,UAAU,MAAM,WAAW,cAAc,MAAM,SAAS,GAAG;EAC3D,YAAY,MAAM,QAAQ,IAAI,cAAc;EAC7C;;;AAIH,SAAS,cAAc,QAA8B;CACnD,MAAM,EAAE,MAAM,iBAAiB,MAAM;CACrC,MAAM,EAAE,MAAM,UAAU,QAAQ,QAAQ;CACxC,MAAM,cAAc,MAClB,IAAI;EAAE,KAAK,EAAE;EAAK,KAAK,EAAE;EAAK,MAAM,EAAE;EAAK,GAAG;AAEhD,QAAO;EACL;EACA,QAAQ;EACR,SAAS,EAAE,WAAW,EAAE;EACxB,MAAM;GACJ,GAAG,WAAW,KAAK;GACnB,KAAK,KAAK;GACV,KAAK,KAAK;GACV,KAAK,KAAK;GACV,MAAM,KAAK;GACZ;EACD,UAAU,WAAW,SAAS;EAC9B,QAAQ,WAAW,OAAO;EAC1B,KAAK,MACD;GACE,cAAc,IAAI;GAClB,QAAQ,IAAI;GACZ,aAAa,EAAE;GACf,cAAc,IAAI;GACnB,GACD;EACJ,WAAW;GACT,YAAY,EAAE,SAAS,UAAU;GACjC,WAAW,EAAE,aAAa;GAC1B,YAAY;GACb;EACF;;;AAIH,SAAS,aAAa,MAA2C;CAC/D,MAAM,WAAW,MACf,EAAE,QAAQ,cAAc,GAAG,MAAM,EAAE,aAAa,CAAC;CACnD,MAAM,UAAU,OAAO,QAAQ,KAAK,CACjC,QAAQ,GAAG,OAAO,MAAM,UAAa,MAAM,KAAK,CAChD,KAAK,CAAC,GAAG,OAAO,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC;AACnC,QAAO,OAAO,YAAY,QAAQ;;;;;AC5EpC,MAAM,MAAM;AACZ,MAAM,MAAM;;AAGZ,SAAgB,oBACd,QACA,YACA,MACM;CACN,MAAM,UAAU,QAAQ,WAAW;AAKnC,gBAAe,SADA,aAHA,iBAAiB,QAAQ,KAAK,CAGV,CACJ;AAC/B,SAAQ,IAAI,+BAA+B,aAAa;AAGxD,uBAAsB,QAAQ;;;AAIhC,SAAS,iBACP,QACA,MACc;CACd,MAAM,QAAQ,MAAc,OAA4C;EACtE,IAAI;EACJ,IAAI;EACJ;EACA;EACA;EACA,MAAM;EACP;CACD,MAAM,SAAuB;EAC3B,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;EAC5C,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;EAC3C,KAAK,kBAAkB,UAAU,KAAK,CAAC;EACxC;AAED,MAAK,MAAM,SAAS,OAClB,MAAK,MAAM,UAAU,MAAM,SAAS;EAClC,MAAM,UAAU,OAAO;AACvB,SAAO,KAAK,GAAG,qBAAqB,QAAQ,CAAC;;AAIjD,QAAO;;AAGT,SAAS,QACP,IACA,MACA,MACY;AACZ,QAAO;EAAE,IAAI;EAAK;EAAI;EAAK;EAAK,KAAK;EAAS;EAAM,GAAG;EAAK;EAAM;;AAGpE,SAAS,QACP,IACA,MACA,MACY;AACZ,QAAO;EAAE,IAAI;EAAK;EAAI;EAAK;EAAK,KAAK;EAAS;EAAM;EAAM;;;AAI5D,SAAS,qBAAqB,SAAwC;CACpE,MAAM,EAAE,SAAS,aAAa,YAAY,gBAAgB;AAC1D,KAAI,CAAC,YAAY,OAAQ,QAAO,EAAE;CAElC,MAAM,SAAuB,EAAE;AAC/B,MAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;EACvC,MAAM,KAAK,WAAW;EACtB,MAAM,KAAK,KAAK,MAAM,QAAQ,KAAK,IAAI,GAAG;AAC1C,SAAO,KAAK,QAAQ,IAAI,QAAQ,MAAM;GAAE,GAAG;GAAG;GAAI,CAAC,CAAC;AACpD,SAAO,KAAK,QAAQ,IAAI,YAAY,EAAE,IAAI,CAAC,CAAC;AAC5C,MAAI,cAAc,OAAO,QAAW;GAClC,MAAM,KAAK,KAAK,MAAO,YAAY,KAAK,OAAO,OAAQ,GAAG,GAAG;AAC7D,UAAO,KAAK,QAAQ,IAAI,QAAQ,EAAE,IAAI,CAAC,CAAC;;;AAI5C,MAAK,MAAM,SAAS,eAAe,EAAE,EAAE;EACrC,MAAM,KAAK,WAAW,MAAM;AAC5B,MAAI,GAAI,QAAO,KAAK,QAAQ,IAAI,SAAS,EAAE,IAAI,MAAM,YAAY,CAAC,CAAC;;AAErE,QAAO;;;AAIT,SAAS,oBAAoB,QAA4B;CACvD,MAAM,QAAQ,OAAO,QAAO,MAAK,EAAE,KAAK,EAAE,CAAC,KAAI,MAAK,EAAE,GAAG;AACzD,KAAI,MAAM,WAAW,EAAG;CACxB,MAAM,QAAQ,KAAK,IAAI,GAAG,MAAM;AAChC,MAAK,MAAM,KAAK,OAAQ,KAAI,EAAE,KAAK,EAAG,GAAE,MAAM;;;AAIhD,SAAS,aAAa,cAA0C;CAK9D,MAAM,WAAW,aAJE,YAAY,IAAI,CAAC,QAClC,MAAK,EAAE,WAAW,cAAc,IAAI,EAAE,SAAS,OAAO,CACvD,CAEwC,GAAG;AAC5C,qBAAoB,aAAa;AACjC,KAAI,CAAC,SAAU,QAAO;AAEtB,qBAAoB,SAAS;AAC7B,QAAO,CAAC,GAAG,UAAU,GAAG,aAAa;;;AAIvC,SAAS,aACP,aAC0B;AAC1B,KAAI,CAAC,YAAa,QAAO;AACzB,KAAI;EACF,MAAM,SAAS,KAAK,MAAM,aAAa,aAAa,QAAQ,CAAC;AAC7D,UAAQ,IACN,UAAU,OAAO,YAAY,OAAO,kBAAkB,cACvD;AACD,SAAO,OAAO;SACR;AACN,UAAQ,KAAK,kCAAkC,cAAc;AAC7D;;;;AAKJ,SAAS,eAAe,YAAoB,QAA4B;CACtE,MAAM,YAAuB,EAAE,aAAa,QAAQ;AACpD,eAAc,YAAY,KAAK,UAAU,UAAU,CAAC;;;AAItD,SAAS,UAAU,MAA+C;CAChE,MAAM,OAAO,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC;CACjC,MAAM,UAAU,OAAO,QAAQ,KAAK,CAAC,QAClC,CAAC,GAAG,OAAO,MAAM,UAAa,CAAC,KAAK,IAAI,EAAE,CAC5C;AACD,QAAO,OAAO,YAAY,QAAQ;;;AAIpC,SAAS,sBAAsB,YAA0B;CACvD,MAAM,MAAM,QAAQ,KAAK;CACzB,MAAM,cAAc;;;;;;;;;;;;;mDAa6B,WAAW;;;yBAGrC,WAAW;oFACgD,WAAW;;;;AAK7F,SAAQ,GAAG,cAAc;AAMvB,EALc,MAAM,QAAQ,CAAC,MAAM,YAAY,EAAE;GAC/C,UAAU;GACV,OAAO;GACP;GACD,CAAC,CACI,OAAO;GACb;;;;;;AClLJ,SAAS,mBAAmB,UAAqC;AAE/D,SADa,UAAU,SAAQ,MAAK,EAAE,SAAS,CAAC,SAAQ,MAAK,EAAE,QAAQ,CAAC,GAC3D,MAAK,MAAK,EAAE,WAAW,EAAE,kBAAkB;;;AAI1D,SAAS,OAAO,IAAgC;AAC9C,QAAO;EACL,SAAS,CAAC,GAAG;EACb,IAAI,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,GAAG,GAAG;EAC1B,WAAW,GAAG;EACd,WAAW,GAAG,WAAW,KAAI,SAAQ;GAAE,GAAG,CAAC,IAAI;GAAG,OAAO,IAAI;GAAO,EAAE;EACvE;;;AAIH,SAAgB,gBACd,QACA,SACY;CACZ,MAAM,EAAE,SAAS,UAAU,gBAAgB,oBAAoB;CAC/D,MAAM,iBAAiB,mBAAmB,SAAS;AACnD,QAAO;EACL,QAAQ,OAAO,KAAI,UACjB,iBAAiB,OAAO,UAAU,eAAe,CAClD;EACD,UAAU;GACR,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC,gBAAgB,QAAQ,IAAI,uBAAuB;GACnD;GACA,mBAAmB,UAAU,gBAAgB;GAC7C;GACA;GACD;EACF;;;AAIH,SAAS,iBACP,OACA,UACA,gBACW;CACX,MAAM,kBAAkB,MAAM,UAAU,gBAAgB;AACxD,QAAO;EACL,MAAM,MAAM;EACZ,UAAU,MAAM,WACZ,qBAAqB,MAAM,UAAU,SAAS,GAC9C;EACJ,YAAY,MAAM,QAAQ,KAAI,WAAU;GACtC,MAAM,UAAU,OAAO,gBAAgB;GACvC,MAAM,QACJ,mBAAmB,UACf,sBAAsB,iBAAiB,QAAQ,GAC/C;GACN,MAAM,eAAe,SAAS,iBAAiB,OAAO,MAAM,GAAG;AAC/D,UAAO;IAAE,GAAG,qBAAqB,QAAQ,SAAS;IAAE;IAAc;IAClE;EACH;;;AAIH,SAAS,qBACP,QAKA,UACqC;CACrC,MAAM,EAAE,oBAAoB;AAC5B,QAAO;EACL,MAAM,OAAO;EACb,SAAS,gBAAgB;EACzB,eAAe,gBAAgB;EAC/B,mBAAmB,gBAAgB;EACnC,aAAa,gBAAgB;EAC7B,UAAU,gBAAgB,YAAY;EACtC,YAAY,gBAAgB;EAC5B,aAAa,gBAAgB;EAC7B,OAAO,gBAAgB;EACvB,UAAU,gBAAgB;EAC1B,cAAc,WAAW,oBAAoB,QAAQ,SAAS,GAAG;EAClE;;;AAIH,SAAS,oBACP,QACA,UACiB;AACjB,QAAO,SAAS,SAAQ,YAAW;EACjC,MAAM,OAAO,QAAQ,QAAQ,OAAO,iBAAiB,OAAO,SAAS;AACrE,SAAO,QAAQ,SAAS,CAAC,SAAQ,MAAK,iBAAiB,MAAM,EAAE,CAAC;GAChE;;;AAIJ,SAAS,iBACP,QACA,OACiB;AACjB,QAAO,MAAM,QACV,KAAI,MAAK,iBAAiB,QAAQ,GAAG,MAAM,WAAW,CAAC,CACvD,QAAQ,MAA0B,MAAM,OAAU;;;AAUvD,SAAS,iBACP,QACA,KACA,YAC2B;CAC3B,MAAM,MAAM,OAAO,IAAI;AACvB,KAAI,QAAQ,OAAW,QAAO;CAC9B,MAAM,YAAY,IAAI,YAAY,IAAI,UAAU,IAAI,GAAG,OAAO,IAAI;AAClE,KAAI,CAAC,aAAa,cAAc,OAAO,cAAc,GAAI,QAAO;AAChE,QAAO;EAAE,OAAO,IAAI;EAAO,OAAO;EAAW;EAAY;;;;;;AC9I3D,SAAgB,kBAAkB,SAA8B;CAC9D,IAAI,QAAQ;CACZ,SAAS,KAAK,MAAyB;AACrC,WAAS,KAAK;AACd,OAAK,MAAM,SAAS,KAAK,YAAY,EAAE,CAAE,MAAK,MAAM;;AAEtD,MAAK,QAAQ,KAAK;AAClB,QAAO;;;AAoBT,SAAgB,eAAe,SAAkC;CAC/D,MAAM,QAAoB,EAAE;CAE5B,SAAS,KAAK,MAAmB,OAA0B;EACzD,MAAM,EAAE,cAAc,KAAK,YAAY,iBAAiB,KAAK;EAC7D,MAAM,KAAK,gBAAgB;EAC3B,MAAM,MAAM,gBAAgB;EAC5B,MAAM,QAAmB;GAAE;GAAI,KAAK,OAAO;GAAI,MAAM,aAAa;GAAG;GAAK;EAC1E,MAAM,WAAW,CAAC,GAAG,OAAO,MAAM;AAElC,MAAI,KAAK,WAAW,EAClB,OAAM,KAAK;GACT,GAAG;GACH,OAAO,KAAK;GACZ,OAAO;GACR,CAAC;AAEJ,OAAK,MAAM,SAAS,KAAK,YAAY,EAAE,CAAE,MAAK,OAAO,SAAS;;AAGhE,MAAK,QAAQ,MAAM,EAAE,CAAC;AACtB,QAAO,MAAM,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;;;AAMhD,SAAgB,eAAe,MAA0B;AACvD,KAAI,CAAC,KAAK,IAAK,QAAO;AACtB,KAAI,KAAK,IAAI,WAAW,QAAQ,CAAE,QAAO;AACzC,KAAI,KAAK,IAAI,SAAS,WAAW,CAAE,QAAO;AAC1C,KAAI,KAAK,IAAI,SAAS,YAAY,CAAE,QAAO;AAC3C,QAAO;;;AAIT,SAAgB,kBAAkB,MAA0B;AAC1D,KAAI,CAAC,KAAK,IAAK,QAAO;AACtB,KAAI,KAAK,IAAI,WAAW,sBAAsB,CAAE,QAAO;AACvD,KAAI,KAAK,IAAI,WAAW,cAAc,CAAE,QAAO;AAC/C,KAAI,KAAK,IAAI,SAAS,WAAW,CAAE,QAAO;AAC1C,QAAO;;;AAIT,SAAgB,YACd,OACA,SAAyB,gBACb;AACZ,QAAO,MAAM,OAAO,OAAO;;;AAI7B,SAAgB,eAAe,OAA+B;CAC5D,MAAM,6BAAa,IAAI,KAAuB;AAE9C,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,MAAM,GAAG,KAAK,IAAI,GAAG,KAAK,KAAK,GAAG,KAAK;EAC7C,MAAM,WAAW,WAAW,IAAI,IAAI;AACpC,MAAI,SACF,UAAS,SAAS,KAAK;MAEvB,YAAW,IAAI,KAAK,EAAE,GAAG,MAAM,CAAC;;AAIpC,QAAO,CAAC,GAAG,WAAW,QAAQ,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;;AAGnE,SAAS,SAAS,OAAuB;AACvC,KAAI,SAAS,OAAO,KAAM,QAAO,IAAI,QAAQ,OAAO,MAAM,QAAQ,EAAE,CAAC;AACrE,KAAI,SAAS,KAAM,QAAO,IAAI,QAAQ,MAAM,QAAQ,EAAE,CAAC;AACvD,QAAO,GAAG,MAAM;;;AAelB,SAAgB,iBACd,OACA,SACQ;CACR,MAAM,EAAE,MAAM,aAAa,GAAG,UAAU,UAAU;CAClD,MAAM,EAAE,UAAU,eAAe,gBAAgB;CACjD,MAAM,SAAS,QAAQ,cAAc;CACrC,MAAM,QAAkB,EAAE;AAC1B,OAAM,KAAK,8BAA8B,KAAK,sBAAsB;AAEpE,MAAK,MAAM,QAAQ,MAAM,MAAM,GAAG,KAAK,CACrC,KAAI,QACF,mBAAkB,OAAO,MAAM,YAAY,OAAO;KAElD,mBAAkB,OAAO,MAAM,YAAY,OAAO;AAItD,OAAM,KAAK,GAAG;AACd,KAAI,aAAa,OACf,OAAM,KAAK,sBAAsB,SAAS,SAAS,GAAG;AACxD,KAAI,kBAAkB,OACpB,OAAM,KAAK,sBAAsB,SAAS,cAAc,GAAG;AAC7D,KAAI,gBAAgB,OAClB,OAAM,KAAK,YAAY,YAAY,gBAAgB,GAAG;AAExD,QAAO,MAAM,KAAK,KAAK;;;AAIzB,SAAS,kBACP,OACA,MACA,YACA,QACM;CACN,MAAM,QAAQ,SAAS,KAAK,MAAM,CAAC,SAAS,GAAG;CAC/C,MAAM,MAAM,CAAC,KAAK,GAAG;AAErB,KAAI,KAAK,SAAS,KAAK,MAAM,SAAS,GAAG;EACvC,MAAM,UAAU,KAAK,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC,MAAM,GAAG,WAAW;AACtE,OAAK,MAAM,SAAS,SAAS;AAC3B,OAAI,CAAC,MAAM,OAAO,CAAC,OAAO,MAAM,CAAE;AAClC,OAAI,KAAK,MAAM,GAAG;;;CAItB,MAAM,OAAO,GAAG,MAAM,IAAI,IAAI,KAAK,OAAO;AAC1C,OAAM,KAAK,OAAO,KAAK,GAAG,OAAOC,KAAG,IAAI,KAAK,CAAC;;;AAIhD,SAAS,kBACP,OACA,MACA,YACA,QACM;CACN,MAAM,QAAQ,SAAS,KAAK,MAAM,CAAC,SAAS,GAAG;CAC/C,MAAM,MAAM,KAAK,MAAM,GAAG,KAAK,IAAI,GAAG,KAAK,KAAK,GAAG,KAAK,QAAQ;CAChE,MAAM,QAAQ,OAAO,KAAK,IAAI,MAAc,IAAIA,KAAG;AAEnD,OAAM,KAAK,MAAM,GAAG,MAAM,IAAI,KAAK,GAAG,IAAI,MAAM,CAAC;AAEjD,KAAI,KAAK,SAAS,KAAK,MAAM,SAAS,GAAG;EACvC,MAAM,UAAU,KAAK,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC,MAAM,GAAG,WAAW;AACtE,OAAK,MAAM,SAAS,SAAS;AAC3B,OAAI,CAAC,MAAM,OAAO,CAAC,OAAO,MAAM,CAAE;GAClC,MAAM,YAAY,GAAG,MAAM,IAAI,GAAG,MAAM,KAAK,GAAG,MAAM;AACtD,SAAM,KAAK,MAAM,kBAAkB,MAAM,GAAG,IAAI,YAAY,CAAC;;;;;;;ACzLnE,MAAM,WAAW,IAAI,IAAI;CAAC;CAAK;CAAM;CAAQ;CAAc,CAAC;;AAG5D,SAAgB,uBAAuB,SAAyB;CAC9D,MAAM,OAAO,IAAI,KAAK,QAAQ;AAS9B,QAAO,GARO,KAAK,eAAe,SAAS;EACzC,OAAO;EACP,KAAK;EACL,MAAM;EACN,MAAM;EACN,QAAQ;EACT,CAAC,CAEc,IADJ,KAAK,aAAa,CAAC,QAAQ,SAAS,IAAI,CAC5B;;;AAI1B,SAAgB,mBAAmB,SAAyB;CAC1D,MAAM,OAAO,IAAI,KAAK,QAAQ;CAE9B,MAAM,0BADM,IAAI,MAAM,EACH,SAAS,GAAG,KAAK,SAAS;CAC7C,MAAM,WAAW,KAAK,MAAM,SAAS,IAAM;CAC3C,MAAM,YAAY,KAAK,MAAM,SAAS,KAAQ;CAC9C,MAAM,WAAW,KAAK,MAAM,SAAS,MAAS;AAE9C,KAAI,WAAW,EAAG,QAAO;AACzB,KAAI,WAAW,GAAI,QAAO,GAAG,SAAS;AACtC,KAAI,YAAY,GAAI,QAAO,GAAG,UAAU;AACxC,KAAI,aAAa,EAAG,QAAO;AAC3B,KAAI,WAAW,GAAI,QAAO,GAAG,SAAS;AACtC,QAAO,KAAK,mBAAmB,SAAS;EAAE,OAAO;EAAS,KAAK;EAAW,CAAC;;;AAI7E,SAAS,cAAc,SAA8B;AACnD,KAAI,CAAC,WAAW,QAAQ,SAAS,UAAW,QAAO;CACnD,MAAM,cAAc,QAAQ,QAAQ,GAAG,QAAQ,KAAK,KAAK,QAAQ;CACjE,MAAM,cAAc,QAAQ,OAAO,mBAAmB,QAAQ,KAAK,GAAG;AACtE,QAAO,cAAc,GAAG,YAAY,IAAI,YAAY,KAAK;;;AAI3D,SAAS,gBAAgB,MAA0B;CACjD,MAAM,EAAE,gBAAgB,oBAAoB,KAAK;AACjD,KAAI,CAAC,kBAAkB,CAAC,gBAAiB,QAAO;CAChD,MAAM,QAAkB,EAAE;AAC1B,KAAI,eAAgB,OAAM,KAAK,YAAY,cAAc,eAAe,GAAG;AAC3E,KAAI,gBACF,OAAM,KAAK,aAAa,cAAc,gBAAgB,GAAG;AAC3D,QAAO,6BAA6B,MAAM,KAAK,MAAM,CAAC;;AAGxD,MAAM,cAAc;CAClB,QAAQ;CACR,QAAQ;CACR,WAAW;CACZ;;AAGD,SAAS,gBAAgB,OAAkB,YAA4B;CACrE,MAAM,KAAK,MAAM,WAAW,IAAI;AAChC,KAAI,CAAC,GAAI,QAAO;CAChB,MAAM,QAAQ,YAAY,GAAG;AAC7B,QAAO;+BACsB,GAAG,UAAU,IAAI,MAAM;uBAC/B,WAAW;;;AAGlC,MAAM,cAAuC;CAC3C,QAAQ;CACR,MAAM;CACN,QAAQ;CACR,kBAAkB;CAClB,kBAAkB;CACnB;;AAGD,SAAS,cACP,KACA,OACA,UACS;AACT,KAAI,SAAS,IAAI,IAAI,IAAI,UAAU,UAAa,UAAU,MAAO,QAAO;AACxE,KAAI,YAAY,SAAS,MAAO,QAAO;AACvC,KAAI,CAAC,IAAI,SAAS,IAAI,IAAI,QAAQ,IAAI,aAAa,CAAE,QAAO;AAC5D,KAAI,QAAQ,iBAAiB,CAAC,SAAU,QAAO;AAC/C,QAAO;;;AAIT,SAAS,cAAc,MAAwC;AAC7D,KAAI,CAAC,KAAM,QAAO;CAClB,MAAM,QAAQ,CAAC,WAAW;AAC1B,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,EAAE;AAC/C,MAAI,cAAc,KAAK,OAAO,KAAK,SAAS,CAAE;AAC9C,QAAM,KAAK,UAAU,OAAO,KAAK,QAAQ,KAAK,IAAI,GAAG,QAAQ;;AAE/D,QAAO,MAAM,KAAK,IAAI;;;AAIxB,SAAgB,qBAAqB,MAA0B;AAC7D,QAAO;;;;;+CAKqB,IAAI,MAAM,EAAC,oBAAoB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAiHlC,cAAc,KAAK,SAAS,QAAQ,CAAC;;yCAExB,wCAAuB,IAAI,MAAM,EAAC,aAAa,CAAC,CAAC;QAClF,gBAAgB,KAAK,CAAC;;;;IAI1B,KAAK,OACJ,KACE,OAAO,MAAM;qBACC,EAAE;QAEf,MAAM,WAAW,SAAS,IACtB;;gBAEI,MAAM,KAAK;YACf,gBAAgB,OAAO,EAAE,CAAC;;;;;;;yCAOG,EAAE;;;;;;;;iCAQV,EAAE;;;;;;yBAMV,EAAE;UAEf,wEACL;;IAGF,CACA,KAAK,GAAG,CAAC;;;;;;;;;;;;4BAYc,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC;;;;;;;;;;ACzQ1D,eAAsB,mBACpB,MACA,SAC2B;CAC3B,MAAM,OAAO,qBAAqB,KAAK;CAEvC,MAAM,YAAY,QAAQ,cAAe,MAAM,iBAAiB;AAChE,OAAM,MAAM,WAAW,EAAE,WAAW,MAAM,CAAC;AAE3C,OAAM,UAAU,KAAK,WAAW,aAAa,EAAE,MAAM,QAAQ;CAC7D,MAAM,QAAQ,MAAM,iBAAiB;AACrC,OAAM,UAAU,KAAK,WAAW,WAAW,EAAE,OAAO,QAAQ;AAC5D,OAAM,oBAAoB,UAAU;CAEpC,IAAI;CACJ,IAAI;AAEJ,KAAI,QAAQ,aAAa;EACvB,MAAM,UAAU,QAAQ,UAAU;EAClC,MAAM,aAAa,UAAU,MAAM,IAAI,CAAC,KAAK;EAC7C,MAAM,SAAS,MAAM,kBAAkB,SAAS,MAAM,MAAM,KAAK;AACjE,WAAS,OAAO;AAChB,sBAAoB,OAAO,OAAO,OAAO;EACzC,MAAM,UAAU,oBAAoB,OAAO,KAAK,GAAG,WAAW;AAC9D,QAAM,KAAK,QAAQ;AACnB,UAAQ,IAAI,6BAA6B,UAAU;OAEnD,SAAQ,IAAI,oBAAoB,UAAU,GAAG;AAG/C,QAAO;EAAE;EAAW;EAAQ;EAAa;;;AAI3C,eAAe,kBACb,SACA,GAAG,OACwC;CAC3C,MAAM,YAAoC;EACxC,SAAS;EACT,OAAO;EACP,QAAQ;EACR,SAAS;EACV;CAED,MAAM,SAAS,aAAa,OAAO,KAAK,QAAQ;EAC9C,MAAM,MAAM,IAAI,OAAO;EAEvB,MAAM,WAAW,KAAK,SADP,IAAI,SAAS,IAAI,GAAG,MAAM,eAAe,IAClB;AACtC,MAAI;GACF,MAAM,UAAU,MAAM,SAAS,SAAS;GACxC,MAAM,OAAO,UAAU,QAAQ,SAAS,KAAK;AAC7C,OAAI,UAAU,gBAAgB,KAAK;AACnC,OAAI,IAAI,QAAQ;UACV;AACN,OAAI,aAAa;AACjB,OAAI,IAAI,YAAY;;GAEtB;AAEF,MAAK,MAAM,QAAQ,MACjB,KAAI;AACF,SAAO,MAAM,UAAU,QAAQ,KAAK;SAC9B;AAIV,QAAO,UAAU,QAAQ,EAAE;;;AAI7B,SAAS,UACP,QACA,MAC2C;AAC3C,QAAO,IAAI,SAAS,SAAS,WAAW;AACtC,SAAO,KAAK,SAAS,OAAO;AAC5B,SAAO,OAAO,YAAY;AACxB,UAAO,eAAe,SAAS,OAAO;GACtC,MAAM,OAAO,OAAO,SAAS;AAE7B,WAAQ;IAAE;IAAQ,MADC,OAAO,SAAS,YAAY,OAAO,KAAK,OAAO;IAC9B,CAAC;IACrC;GACF;;;AAIJ,eAAe,kBAAmC;CAChD,MAAM,OAAO;AACb,OAAM,MAAM,MAAM,EAAE,WAAW,MAAM,CAAC;AAEtC,QAAO,KAAK,MAAM,2BADP,IAAI,MAAM,EAAC,aAAa,CAAC,QAAQ,SAAS,IAAI,CAAC,MAAM,GAAG,GAAG,GACrC;;;AAInC,eAAe,kBAAmC;CAChD,MAAM,UAAU,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;CACvD,MAAM,YAAY,KAAK,SAAS,mBAAmB;CACnD,MAAM,UAAU,KAAK,SAAS,8BAA8B;AAC5D,KAAI;AACF,SAAO,MAAM,SAAS,WAAW,QAAQ;SACnC;AACR,QAAO,SAAS,SAAS,QAAQ;;;AAInC,eAAe,oBAAoB,WAAkC;CACnE,MAAM,UAAU,QAAQ,UAAU;CAClC,MAAM,aAAa,UAAU,MAAM,IAAI,CAAC,KAAK;CAC7C,MAAM,OAAO;;iDAEkC,WAAW;+BAC7B,WAAW;;eAE3B,WAAW;;AAExB,OAAM,UAAU,KAAK,SAAS,aAAa,EAAE,MAAM,QAAQ;;;;;;ACtH7D,SAAgB,kBAAkB,QAA8B;AAC9D,KAAI,OAAO,SAAS,IAAI,EAAE;EACxB,MAAM,CAAC,UAAU,eAAe,OAAO,MAAM,KAAK,EAAE;AACpD,SAAO;GACL,MAAM,YAAY;GAClB,SAAS,eAAe;GACzB;;AAEH,QAAO,EAAE,MAAM,QAAQ;;;AAUzB,eAAsB,aACpB,QACA,QAC4B;AAC5B,KAAI,CAAC,UAAW,CAAC,OAAO,QAAQ,CAAC,OAAO,QAAU,QAAO;CAEzD,MAAM,WAAW,MAAM,iBAAiB,QAAQ,OAAO,KAAK;CAC5D,MAAM,cAAc,MAAM,oBAAoB,QAAQ,OAAO,QAAQ;CAErE,MAAM,gBACJ,YAAY,OAAO,gBACf,SAAS,QAAO,MAAK,OAAO,cAAe,SAAS,EAAE,CAAC,GACtD,YAAY,OAAO;CAE1B,MAAM,mBACJ,eAAe,OAAO,mBAClB,YAAY,QAAO,MAAK,OAAO,iBAAkB,SAAS,EAAE,CAAC,GAC5D,eAAe,OAAO;AAE7B,QAAO;EAAE,GAAG;EAAQ;EAAe;EAAkB;;;AAIvD,eAAe,iBACb,QACA,aAC+B;AAC/B,KAAI,CAAC,YAAa,QAAO;CAEzB,MAAM,UAAU,OAAO,eAClB,MAAM,gBAAgB,OAAO,YAAY,EAAE,QAC5C,OAAO;AACX,KAAI,CAAC,QAAS,QAAO,CAAC,UAAU;CAEhC,MAAM,WAAW,QAAQ,QAAO,OAAM,aAAa,IAAI,YAAY,CAAC;AACpE,KAAI,SAAS,WAAW,EACtB,OAAM,IAAI,MAAM,2BAA2B,YAAY,GAAG;AAE5D,QAAO;;;AAIT,eAAe,oBACb,QACA,gBAC+B;AAC/B,KAAI,CAAC,eAAgB,QAAO;AAE5B,KAAI,OAAO,UAAU;EACnB,MAAM,MAAM,OAAO,KAAK,OAAO,SAAS,CAAC,QAAO,OAC9C,aAAa,IAAI,eAAe,CACjC;AACD,MAAI,IAAI,WAAW,EACjB,OAAM,IAAI,MAAM,8BAA8B,eAAe,GAAG;AAElE,SAAO;;AAGT,KAAI,OAAO,YAAY;EAErB,MAAM,YADS,MAAM,iBAAiB,OAAO,WAAW,EAChC,QAAO,OAAM,aAAa,IAAI,eAAe,CAAC;AACtE,MAAI,SAAS,WAAW,EACtB,OAAM,IAAI,MAAM,8BAA8B,eAAe,GAAG;AAElE,SAAO;;AAGT,OAAM,IAAI,MAAM,kDAAkD;;;AAIpE,SAAS,aAAa,IAAY,SAA0B;AAC1D,QAAO,GAAG,aAAa,CAAC,SAAS,QAAQ,aAAa,CAAC;;;;;AClGzD,MAAM,EAAE,QADO,QAAQ,IAAI,aAAa,UAAU,QAAQ,IAAI,WAAW,SAChD,EAAE,MAAM,QAAgB,KAAK,GAAG;AAEzD,MAAM,gBAAgB;;AAGtB,SAAgB,kBAAkB,GAAoB;AACpD,KAAI,OAAO,MAAM,SAAU,QAAO;CAClC,MAAM,MAAM,GAAG,KAAK,MAAM,EAAE,CAAC;AAC7B,QAAO,IAAI,gBAAgB,IAAI,IAAI,GAAG;;;;;;ACQxC,MAAa,cAAwC;CACnD,UAAU,aAA8B;EACtC,MAAM,QAAQ,MAAM;EACpB,KAAK,QAAQ,MAAM;EACnB,KAAK,QAAQ,MAAM;EACnB,aAAa,QAAQ,aAAa;EACnC;CACD,eAA+C,CAC7C;EACE,YAAY;EACZ,SAAS;GACP;IAAE,KAAK;IAAQ,OAAO;IAAQ,WAAW;IAAQ,YAAY;IAAM;GACnE;IAAE,KAAK;IAAO,OAAO;IAAO,WAAW;IAAQ,YAAY;IAAM;GACjE;IAAE,KAAK;IAAO,OAAO;IAAO,WAAW;IAAQ,YAAY;IAAM;GAClE;EACF,EACD,EACE,SAAS,CACP;EAAE,KAAK;EAAe,OAAO;EAAS,WAAW;EAAmB,CACrE,EACF,CACF;CACF;;AAOD,MAAa,YAA2C;CACtD,UAAU,YAA6B;EACrC,MAAM,EAAE,YAAY,MAAM,YAAY;AACtC,MAAI,CAAC,cAAc,CAAC,MAAM,IAAK,QAAO,EAAE,IAAI,QAAW;EACvD,MAAM,iBAAiB,KAAK,MAAM,QAAQ;AAC1C,MAAI,kBAAkB,EAAG,QAAO,EAAE,IAAI,QAAW;EACjD,MAAM,SAAS,WAAW,QAAQ;AAElC,SAAO,EAAE,IAAI,UAAU,IAAI,SAAS,QAAW;;CAEjD,eAAoD,CAClD;EACE,YAAY;EACZ,SAAS,CACP;GAAE,KAAK;GAAM,OAAO;GAAQ,WAAW;GAAS,YAAY;GAAM,CACnE;EACF,CACF;CACF;;AAYD,MAAa,iBAA6C;CACxD,UAAU,YAA6B;EACrC,MAAM,EAAE,SAAS,YAAY;AAC7B,MAAI,CAAC,QAAS,QAAO,EAAE;EACvB,MAAM,aAAa,QAAQ,UAAU;EACrC,MAAM,EAAE,gBAAgB,kBAAkB;EAE1C,MAAM,eADW,kBAAkB,iBAAiB,KAE/C,iBAAiB,KAAK,iBACvB;AACJ,SAAO;GACL,cACE,kBAAkB,OAAO,iBAAiB,aAAa;GACzD,WAAW,QAAQ,kBAAkB;GACrC,WAAW,QAAQ;GACnB,SAAS,QAAQ;GACjB;GACA,cAAc,QAAQ,cAAc;GACrC;;CAEH,eAAiD,CAC/C;EACE,YAAY;EACZ,SAAS;GACP;IAAE,KAAK;IAAgB,OAAO;IAAc,WAAW;IAAa;GACpE;IAAE,KAAK;IAAa,OAAO;IAAa,WAAW;IAAa;GAChE;IAAE,KAAK;IAAa,OAAO;IAAQ,WAAW;IAAS;GACvD;IAAE,KAAK;IAAW,OAAO;IAAQ,WAAW;IAAS;GACrD;IAAE,KAAK;IAAgB,OAAO;IAAU,WAAW;IAAS;GAC5D;IAAE,KAAK;IAAgB,OAAO;IAAc,WAAW;IAAQ;GAChE;EACF,CACF;CACF;;AAGD,MAAa,wBAAoD;CAC/D,SAAS,eAAe;CACxB,eAAiD,CAC/C;EACE,YAAY;EACZ,SAAS;GACP;IAAE,KAAK;IAAa,OAAO;IAAa,WAAW;IAAa;GAChE;IAAE,KAAK;IAAa,OAAO;IAAQ,WAAW;IAAS;GACvD;IAAE,KAAK;IAAW,OAAO;IAAQ,WAAW;IAAS;GACrD;IAAE,KAAK;IAAgB,OAAO;IAAS,WAAW;IAAQ;GAC3D;EACF,CACF;CACF;;AAQD,MAAa,aAAsC;CACjD,UAAU,aAA8B;EACtC,cAAc,QAAQ;EACtB,UAAU,QAAQ;EACnB;CACD,eAA8C,CAC5C;EACE,YAAY;EACZ,SAAS,CACP;GAAE,KAAK;GAAgB,OAAO;GAAW,WAAW;GAAS,EAC7D;GAAE,KAAK;GAAY,OAAO;GAAU,WAAW,iBAAiB,EAAE;GAAE,CACrE;EACF,CACF;CACF;;AAOD,MAAa,cAAuC;CAClD,UAAU,aAA8B,EACtC,MAAM,QAAQ,QAAQ,QACvB;CACD,eAA8C,CAC5C,EAAE,SAAS,CAAC;EAAE,KAAK;EAAQ,OAAO;EAAQ,WAAW;EAAS,CAAC,EAAE,CAClE;CACF;;AAGD,MAAa,mBAA0D;CACrE,UAAU,aAA8B,EACtC,WAAW,QAAQ,WACpB;CACD,eAA4D,CAC1D,EACE,SAAS,CACP;EACE,KAAK;EACL,OAAO;EACP,YAAW,MAAK;AACd,OAAI,OAAO,MAAM,SAAU,QAAO;AAClC,UAAO,KAAK,KAAK,IAAI,EAAE,QAAQ,EAAE,CAAC,MAAM,GAAG,EAAE,QAAQ,EAAE,CAAC;;EAE3D,CACF,EACF,CACF;CACF;;AAUD,MAAa,kBAAgD;CAC3D,UAAU,aAA8B;EACtC,QAAQ,QAAQ,MAAM;EACtB,MAAM,QAAQ,MAAM;EACpB,KAAK,QAAQ,MAAM;EACnB,aAAa,QAAQ,aAAa;EACnC;CACD,eAAmD,CACjD;EACE,YAAY;EACZ,SAAS;GACP;IAAE,KAAK;IAAU,OAAO;IAAU,WAAW;IAAQ,YAAY;IAAM;GACvE;IAAE,KAAK;IAAQ,OAAO;IAAQ,WAAW;IAAQ,YAAY;IAAM;GACnE;IAAE,KAAK;IAAO,OAAO;IAAO,WAAW;IAAQ;GAChD;EACF,EACD,EACE,SAAS,CACP;EAAE,KAAK;EAAe,OAAO;EAAS,WAAW;EAAmB,CACrE,EACF,CACF;CACF;;AAGD,SAAgB,qBAAqB,MAGjB;CAClB,MAAM,WAA4B,EAAE;AACpC,KAAI,KAAK,YAAa,UAAS,KAAK,eAAe;AACnD,UAAS,KAAK,YAAY;AAC1B,QAAO;;;AAST,MAAa,aAAsC;CACjD,UAAU,YAA6B;EACrC,MAAM,MAAM,QAAQ;AACpB,MAAI,CAAC,IAAK,QAAO,EAAE;EAEnB,MAAM,QAAQ,OAAO,OAAO,IAAI,OAAO,CAAC,QAAQ,GAAG,MAAM,IAAI,EAAE,OAAO,EAAE;AAKxE,SAAO;GACL,OALgB,OAAO,QAAQ,IAAI,OAAO,CACzC,MAAM,GAAG,MAAM,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,CACvC,KAAK,CAAC,MAAM,OAAO,GAAG,KAAK,IAAK,EAAE,QAAQ,QAAS,KAAK,QAAQ,EAAE,CAAC,GAAG,CAGtD,KAAK,IAAI;GAC1B,OAAO,IAAI,aAAa,IAAI,IAAI,aAAa;GAC9C;;CAEH,eAA8C,CAC5C;EACE,YAAY;EACZ,SAAS,CACP;GACE,KAAK;GACL,OAAO;GACP,YAAW,MAAM,OAAO,MAAM,WAAW,IAAI;GAC9C,EACD;GACE,KAAK;GACL,OAAO;GACP,YAAW,MAAM,OAAO,MAAM,WAAW,OAAO,EAAE,GAAG;GACtD,CACF;EACF,CACF;CACF;;;;;AC7ND,SAAgB,oBACd,SACA,SACQ;CACR,MAAM,SAAS,gBAAgB,SAAS,QAAQ;AAEhD,QAAO,CADQ,WAAW,QAAQ,QAClB,GAAG,OAAO,CAAC,KAAK,OAAO;;;AAIzC,SAAS,gBACP,SACA,SACU;AACV,KAAI,QAAQ,SAAS,WAAW,EAAG,QAAO,EAAE;AAI5C,QADgB,QAAQ,SAAS,GAAG,MAAM,KAAI,MAAK,EAAE,OAAO,CAC7C,KAAI,WAAU,eAAe,SAAS,QAAQ,QAAQ,CAAC;;;AAIxE,SAAS,eACP,SACA,QACA,SACQ;CACR,MAAM,YAAY,gBAAgB,SAAS,OAAO;AAElD,KAAI,SAAS,UAAU,OACrB,QAAO,kBAAkB,SAAS,QAAQ,SAAS,UAAU;CAG/D,MAAM,OAAO,cAAc,SAAS,QAAQ,SAAS,aAAa;AAMlE,QAAO,GAAG,UAAU,IADN,WAHE,aADI,KAAK,MAAK,MAAK,EAAE,OAAO,EACF,QAAQ,EAGhB,CADgB,EAAE,SAAS,MAAM,CACpB,CAAC;;;AAKlD,SAAS,kBACP,SACA,QACA,SACA,WACQ;CACR,MAAM,WAAW,QAAQ;CACzB,MAAM,eAAe,QAAQ,gBAAgB;CAE7C,MAAM,OAAkC,EAAE;CAC1C,IAAI,cAAc;AAElB,MAAK,MAAM,WAAW,QAAQ,UAAU;EACtC,MAAM,aAAa,QAAQ,MAAM,MAAK,MAAK,EAAE,WAAW,OAAO;AAC/D,MAAI,CAAC,WAAY;EAEjB,MAAM,MAA+B,EAAE,MAAM,SAAS,QAAQ,IAAI,GAAG,EAAE;AAEvE,OAAK,MAAM,WAAW,SACpB,QAAO,OACL,KACA,QAAQ,QAAQ,WAAW,UAAU,WAAW,SAAS,CAC1D;AAGH,MAAI,WAAW,UAAU;AACvB,iBAAc;GACd,MAAM,EAAE,SAAS,SAAS,WAAW;AACrC,OAAI,SAAS,sBAAsB,MAAM,WAAW,SAAS,QAAQ;;AAGvE,OAAK,KAAK,IAAI;;AAMhB,QAAO,GAAG,UAAU,IADN,WAFO,oBAAoB,UAAU,cAAc,YAAY,EAEtC,CADmB,EAAE,SAAS,MAAM,CACvB,CAAC;;;AAKvD,SAAS,oBACP,UACA,cACA,aACwC;CACxC,MAAM,UAAgD,EACpD,SAAS,CAAC;EAAE,KAAK;EAAQ,OAAO;EAAc,CAAC,EAChD;CAED,MAAM,iBAAiB,SAAS,SAAQ,MAAK,EAAE,SAAS,CAAC;AAKzD,QAAO,CAAC,SAAS,GAJI,cACjB,kBAAkB,eAAe,GAChC,eAE4B;;;AAInC,SAAS,cACP,SACA,QACA,cACmB;AACnB,QAAO,QAAQ,SAAS,SAAQ,YAAW;EACzC,MAAM,aAAa,QAAQ,MAAM,MAAK,MAAK,EAAE,WAAW,OAAO;AAC/D,SAAO,aAAa,CAAC,SAAS,QAAQ,IAAI,YAAY,aAAa,CAAC,GAAG,EAAE;GACzE;;;AAIJ,SAAS,SACP,WACA,YACA,cACiB;CACjB,MAAM,EAAE,UAAU,aAAa;CAC/B,MAAM,UAAU,SAAS;CACzB,MAAM,OAAO,SAAS,MAAM,OAAO,QAAQ,QAAQ;CAEnD,MAAM,MAAuB;EAC3B,MAAM,SAAS,WAAW,GAAG;EAC7B;EACA,SAAS,QAAQ;EAClB;AAED,KAAI,SACF,KAAI,SAAS,sBAAsB,SAAS,SAAS,QAAQ;AAG/D,KAAI,aACF,MAAK,MAAM,OAAO,aAChB,KAAI,IAAI,OAAO,IAAI,QAAQ,WAAW;AAI1C,QAAO;;;AAIT,SAAS,aACP,aACA,SACgC;CAehC,MAAM,SAAyC,CAbD,EAC5C,SAAS,CAAC;EAAE,KAAK;EAAQ,OAFN,SAAS,gBAAgB;EAEE,CAAC,EAChD,EAI6C,EAC5C,SAAS,CACP;EAAE,KAAK;EAAQ,OAAO;EAAQ,WAAW;EAAU,EACnD,GAAI,cAAc,CAJN;EAAE,KADJ;EACgB,OAAO;EAAS,WAAW;EAAY,CAItC,GAAG,EAAE,CACjC,EACF,CAEgE;CAGjE,MAAM,eAAe,SAAS;AAC9B,KAAI,cAAc,QAAQ;EACxB,MAAM,0BAAU,IAAI,KAAwC;AAC5D,OAAK,MAAM,OAAO,cAAc;GAC9B,MAAM,QAAQ,QAAQ,IAAI,IAAI,WAAW,IAAI,EAAE;AAC/C,SAAM,KAAK,IAAI;AACf,WAAQ,IAAI,IAAI,YAAY,MAAM;;AAEpC,OAAK,MAAM,CAAC,YAAY,SAAS,QAC/B,QAAO,KAAK;GACV;GACA,SAAS,KAAK,KAAI,SAAQ;IACxB,KAAK,IAAI;IACT,OAAO,IAAI;IACX,WAAW,IAAI,aAAa;IAC7B,EAAE;GACJ,CAAC;;AAIN,QAAO;;;AAIT,SAAS,WAAW,OAA+B;AACjD,KAAI,CAAC,MAAO,QAAO;AACnB,QAAO,iBAAiB,MAAsB;;;AAIhD,SAAS,gBAAgB,SAAwB,QAAwB;CAEvE,MAAM,YADa,QAAQ,SAAS,IAAI,MAAM,MAAK,MAAK,EAAE,WAAW,OAAO,GAC/C;AAE7B,KAAI,YAAY,OAAO,KAAK,SAAS,CAAC,SAAS,EAI7C,QAAO,GAAG,OAAO,IAHC,OAAO,QAAQ,SAAS,CACvC,KAAK,CAAC,GAAG,OAAO,GAAG,EAAE,GAAG,IAAI,CAC5B,KAAK,KAAK,CACkB;AAEjC,QAAO;;;AAIT,MAAa,iBAAgC,eAC1C,SAAS,CAAC,GACV,QAAQ,KAAI,SAAQ;CACnB,KAAK,IAAI;CACT,OAAO,IAAI;CACX,YAAY;CACZ,UAAU,MACR,eAAe,QAAQ,EAAE,SAAS,CAAC,IAAI;CACzC,YAAY,MAAe,IAAI,YAAY,EAAE,IAAI;CAClD,EAAE;;AAGL,SAAS,kBAAkB,OAAwB;AACjD,QAAO,YAAY,MAAM,IAAI;;;AAI/B,MAAa,gBAA6B;CACxC,KAAK;CACL,OAAO;CACP,YAAY;CACZ,UAAS,MAAK,EAAE,SAAS,SAAS;CAClC,YAAW,MAAM,KAAK,OAAO,GAAI,EAAa,QAAQ,EAAE,CAAC,MAAM;CAChE;;AAGD,MAAa,kBAA+B;CAC1C,KAAK;CACL,OAAO;CACP,UAAS,MAAK;EACZ,MAAM,UAAU,EAAE,SAAS;AAC3B,MAAI,CAAC,SAAS,KAAM,QAAO;AAC3B,SAAO,kBAAkB,QAAQ;;CAEnC,WAAW;CACZ;;;;;AC9RD,SAAgB,iBACd,OACA,QACA,cAAc,MACF;AACZ,KAAI,CAAC,OAAQ,QAAO;CACpB,MAAM,QAAQ,kBAAkB,OAAO;CACvC,MAAM,SAAS,MAAM,OAClB,KAAI,WAAU;EACb,GAAG;EACH,YAAY,MAAM,WAAW,QAAO,UAClC,MAAM,KAAK,gBAAgB,MAAM,KAAK,CAAC,CACxC;EACD,UACE,MAAM,YAAY,MAAM,KAAK,gBAAgB,MAAM,SAAS,KAAK,CAAC,GAC9D,MAAM,WACN;EACP,EAAE,CACF,QAAO,UAAS,CAAC,eAAe,MAAM,WAAW,SAAS,EAAE;AAC/D,uBAAsB,QAAQ,OAAO;AACrC,QAAO;EAAE,MAAM,MAAM;EAAM;EAAQ;;;AAIrC,SAAS,kBAAkB,QAAwB;AAUjD,KARG,OAAO,WAAW,IAAI,IAAI,OAAO,SAAS,IAAI,IAC/C,OAAO,SAAS,IAAI,IACpB,OAAO,SAAS,IAAI,IACpB,OAAO,SAAS,IAAI,IACpB,OAAO,SAAS,IAAI,IACpB,OAAO,WAAW,IAAI,IACtB,OAAO,SAAS,IAAI,EAEF;EAClB,MAAM,UACJ,OAAO,WAAW,IAAI,IAAI,OAAO,SAAS,IAAI,GAC1C,OAAO,MAAM,GAAG,GAAG,GACnB;AACN,MAAI;AACF,UAAO,IAAI,OAAO,SAAS,IAAI;UACzB;AACN,UAAO,IAAI,OAAO,YAAY,OAAO,EAAE,IAAI;;;AAI/C,QAAO,IAAI,OAAO,MAAM,YAAY,OAAO,EAAE,IAAI;;;AAInD,SAAS,gBAAgB,MAAsB;AAC7C,QAAO,KAAK,QAAQ,aAAa,GAAG;;;AAItC,SAAS,YAAY,KAAqB;AACxC,QAAO,IAAI,QAAQ,uBAAuB,OAAO;;;AAInD,SAAS,sBAAsB,QAAsB,QAAuB;AAC1E,KAAI,OAAO,OAAM,MAAK,EAAE,WAAW,WAAW,EAAE,CAC9C,OAAM,IAAI,MAAM,gCAAgC,OAAO,GAAG;;;;;;ACA9D,SAAS,aAAa,MAA4B;AAChD,KAAI,KAAK,eAAe,CAAC,KAAK,UAAU,CAAC,KAAK,IAC5C,OAAM,IAAI,MACR,0EACD;;;AAKL,SAAS,iBAAiB,MAA4B;CACpD,MAAM,UAAoB,EAAE;AAC5B,KAAI,CAAC,KAAK,OAAQ,SAAQ,KAAK,cAAc;AAC7C,KAAI,KAAK,IAAK,SAAQ,KAAK,QAAQ;AACnC,KAAI,KAAK,aAAc,SAAQ,KAAK,cAAc;AAClD,KAAI,KAAK,QAAS,SAAQ,KAAK,YAAY;AAC3C,KAAI,KAAK,SAAU,SAAQ,KAAK,aAAa;AAC7C,KAAI,KAAK,UAAU,EAAG,SAAQ,KAAK,YAAY;AAC/C,KAAI,QAAQ,OACV,SAAQ,KAAK,OAAO,4BAA4B,QAAQ,KAAK,KAAK,GAAG,CAAC;;;AAqB1E,SAAgB,eACd,eACoB;AAEpB,QAAO,aADM,QAAQ,QAAQ,KAAK,EACR,cAAc;;;AAI1C,eAAsB,cACpB,OACA,MACwB;AACxB,cAAa,KAAK;CAClB,MAAM,EAAE,QAAQ,QAAQ,WAAW,UAAU,MAAM;CACnD,MAAM,UAAU,mBAAmB,KAAK;AAGxC,QAAO,SAAS;EACd,OAHe,iBAAiB,OAAO,OAAO;EAI9C,QAAQ;EACR;EACA;EACA;EACD,CAAC;;;AAIJ,eAAe,SAAS,QAA6C;CACnE,MAAM,EAAE,OAAO,QAAQ,SAAS,WAAW,YAAY;CACvD,MAAM,UAAyB,EAAE;AACjC,MAAK,MAAM,SAAS,MAAM,OACxB,SAAQ,KAAK,MAAM,SAAS,OAAO,QAAQ,SAAS,WAAW,QAAQ,CAAC;AAE1E,QAAO;;;AAIT,eAAe,SACb,OACA,QACA,SACA,WACA,UAAU,GACY;CACtB,MAAM,EAAE,MAAM,YAAY,UAAU,OAAO,aAAa;CACxD,MAAM,cAAc,MAAM,SAAS;AACnC,6BAA4B,MAAM;CAElC,MAAM,YAAY;EAChB;EACA;EACA;EACA,QAAQ;EACR;EACD;AACD,KAAI,YAAY,EACd,QAAO,eAAe,MAAM,YAAY,UAAU,UAAU;AAE9D,QAAO,mBAAmB,MAAM,YAAY,UAAU,WAAW,QAAQ;;;AAI3E,eAAe,eACb,MACA,YACA,UACA,WACsB;CACtB,MAAM,iBAAiB,WACnB,MAAM,mBAAmB,UAAU,UAAU,GAC7C;AAIJ,QAAO;EAAE;EAAM,SAHC,MAAM,UAAU,aAAY,MAC1C,mBAAmB,GAAG,UAAU,CACjC;EACuB,UAAU;EAAgB;;;AAIpD,eAAe,mBACb,MACA,YACA,UACA,WACA,SACsB;CACtB,MAAM,gBAAgB,UAAU,QAAQ,WAAW,OAAQ;CAC3D,MAAM,cAAc;EAClB,GAAG;EACH,SAAS;GAAE,GAAG,UAAU;GAAS,SAAS;GAAc;EACzD;CACD,MAAM,kBAAqC,EAAE;CAC7C,MAAM,mCAAmB,IAAI,KAAgC;AAE7D,MAAK,IAAI,IAAI,GAAG,IAAI,SAAS,IAE3B,OAAM,kBACJ,YACA,UACA,aAJmB,IAAI,MAAM,GAM7B,iBACA,iBACD;CAGH,MAAM,OAAO,UAAU;AACvB,QAAO,kBACL,MACA,YACA,UACA,iBACA,kBACA,KACD;;;AAIH,eAAe,kBACb,YACA,UACA,WACA,cACA,iBACA,kBACe;CACf,MAAM,cAAc,YAAY;AAC9B,MAAI,UAAU;GACZ,MAAM,IAAI,MAAM,mBAAmB,UAAU,UAAU;AACvD,mBAAgB,KAAK,EAAE,gBAAgB;;;CAG3C,MAAM,aAAa,YAAY;AAC7B,OAAK,MAAM,KAAK,YAAY;GAC1B,MAAM,IAAI,MAAM,mBAAmB,GAAG,UAAU;AAChD,eAAY,kBAAkB,EAAE,MAAM,EAAE,gBAAgB;;;AAI5D,KAAI,cAAc;AAChB,QAAM,YAAY;AAClB,QAAM,aAAa;QACd;AACL,QAAM,aAAa;AACnB,QAAM,YAAY;;;;AAKtB,SAAS,kBACP,MACA,YACA,UACA,iBACA,kBACA,UACa;CACb,MAAM,iBAAiB,WACnB;EACE,MAAM,SAAS;EACf,iBAAiB,aAAa,gBAAgB;EAC9C;EACD,GACD;AAMJ,QAAO;EAAE;EAAM,SALC,WAAW,KAAI,OAAM;GACnC,MAAM,EAAE;GACR,iBAAiB,aAAa,iBAAiB,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;GACjE;GACD,EAAE;EACqB,UAAU;EAAgB;;;AAIpD,eAAe,mBACb,MACA,WAC0B;CAC1B,MAAM,EAAE,QAAQ,SAAS,WAAW,QAAQ,aAAa;CAEzD,MAAM,CAAC,UAAU,MAAM,aADC;EAAE;EAAM;EAAQ;EAAS;EAAW;EAAQ,CAChB;AACpD,QAAO;EAAE,MAAM,KAAK;EAAM,iBAAiB;EAAQ;EAAU;;;AAI/D,SAAS,4BAA4B,OAAyB;CAC5D,MAAM,EAAE,MAAM,OAAO,YAAY,aAAa;AAC9C,KAAI,MAAO;CAEX,MAAM,gBAAgB,WAAW,CAAC,GAAG,YAAY,SAAS,GAAG;AAC7D,MAAK,MAAM,aAAa,cACtB,KAAI,UAAU,GAAG,SAAS,EACxB,SAAQ,KACN,cAAc,UAAU,KAAK,cAAc,KAAK,+CACjD;;;AAMP,SAAS,aAAa,SAA6C;AACjE,KAAI,QAAQ,WAAW,EACrB,OAAM,IAAI,MAAM,mCAAmC;AAErD,KAAI,QAAQ,WAAW,EAAG,QAAO,QAAQ;CAEzC,MAAM,aAAa,QAAQ,SAAQ,MAAK,EAAE,QAAQ;CAClD,MAAM,YAAY,QAAQ,SAAQ,MAAK,EAAE,iBAAiB,EAAE,CAAC;CAC7D,MAAM,OAAO,aAAa,WAAW;CACrC,MAAM,cAAc,iBAAiB,WAAW,KAAI,MAAK,IAAI,OAAO,CAAC;CAErE,IAAI,SAAS;CACb,MAAM,iBAAiB,QAAQ,SAAQ,MAAK;EAC1C,MAAM,OAAO,EAAE,eAAe,EAAE,EAAE,KAAI,OAAM;GAC1C,aAAa,EAAE,cAAc;GAC7B,YAAY,EAAE;GACf,EAAE;AACH,YAAU,EAAE,QAAQ;AACpB,SAAO;GACP;AAEF,QAAO;EACL,MAAM,QAAQ,GAAG;EACjB,SAAS;EACT,eAAe,UAAU,SAAS,YAAY;EAC9C;EACA,WAAW,QAAQ,QAAQ,KAAK,MAAM,OAAO,EAAE,aAAa,IAAI,EAAE;EAClE;EACA,aAAa,eAAe,SAAS,iBAAiB;EACvD;;AAGH,SAAS,YACP,KACA,KACA,OACA;AACA,KAAI,CAAC,IAAI,IAAI,IAAI,CAAE,KAAI,IAAI,KAAK,EAAE,CAAC;AACnC,KAAI,IAAI,IAAI,CAAE,KAAK,MAAM;;;AAI3B,SAAgB,cACd,QACA,MACQ;CACR,MAAM,EAAE,UAAU,YAAY,SAAS,aAAa,aAAa;CACjE,MAAM,SAAS,SAAS,QAAQ,MAAM;CACtC,MAAM,SAAS,SAAS,QAAQ,YAAY;AAO5C,QAAO,cAAc,QANJ,oBACf,UACA,SACA,QACA,YAAY,OACb,CACqC;;;AAIxC,SAAS,oBACP,UACA,SACA,YACA,YACA;CACA,MAAM,WAAW,WACb;EAAC;EAAiB;EAAa;EAAiB,GAChD,CAAC,aAAa,YAAY;AAE9B,KAAI,QAAS,UAAS,KAAK,eAAe;AAC1C,KAAI,WAAY,UAAS,KAAK,WAAW;AACzC,KAAI,WAAY,UAAS,KAAK,WAAW;AAEzC,QAAO;;;AAIT,eAAsB,aACpB,OACA,MACe;CACf,MAAM,UAAU,MAAM,cAAc,OAAO,KAAK;CAChD,MAAM,SAAS,cAAc,SAAS,KAAK;AAC3C,SAAQ,IAAI,OAAO;AACnB,OAAM,cAAc,SAAS,MAAM,MAAM,KAAK;;;AAIhD,eAAsB,oBAAoB,MAAqC;AAC7E,kBAAiB,KAAK;CACtB,MAAM,MAAM,KAAK;CACjB,MAAM,EAAE,YAAY,SAAS;CAC7B,MAAM,SAAS,MAAM,eAAe;EAClC;EACA,YAAY,KAAK;EACjB,aAAa;GACX,kBAAkB,KAAK;GACvB,YAAY,KAAK;GAClB;EACD,UAAU,KAAK;EACf,SAAS,KAAK;EACd,SAAS,KAAK;EACd,SAAS,aAAa,OAAO,mBAAmB,OAAO;EACvD,eAAe;EAChB,CAAC;CAEF,MAAM,OAAO,IAAI,IAAI,IAAI,CAAC,SAAS,MAAM,IAAI,CAAC,KAAK,IAAI;CACvD,MAAM,aAAa,OAAO,WAAW,OAAO,QAAQ,SAAS;CAC7D,MAAM,UAAU,oBAAoB,MAAM,OAAO;AAGjD,KAAI,cAAc,OAAO,cAAc,KACrC,SAAQ,IAAI,cAAc,SAAS,CAAC,aAAa,YAAY,CAAC,CAAC;AAIjE,KAAI,OAAO,QACT,SAAQ,IAAI,cAAc,SAAS,CAAC,sBAAsB,CAAC,CAAC;AAI9D,KAAI,OAAO,YACT,kBAAiB,SAAS;EACxB,GAAG,qBAAqB,KAAK;EAC7B,YAAY;EACb,CAAC;AAGJ,OAAM,cAAc;EAAE;EAAS;EAAM,CAAC;;;AAIxC,SAAS,oBACP,MACA,QACe;CACf,MAAM,EAAE,SAAS,gBAAgB;CACjC,IAAI;AAGJ,KAAI,OAAO,WAAW,OAAO,QAAQ,SAAS,GAAG;EAC/C,MAAM,EAAE,YAAY;EACpB,MAAM,YAAY,OAAO,aAAa,OAAO,aAAa,MAAO;AACjE,aAAW;GACT;GACA;GACA,MAAM,aAAa,QAAQ;GAC3B;GACA;GACA;GACD;QACI;EAEL,MAAM,SAAS,OAAO,cAAc;AAUpC,aAAW;GAAE;GAAM,SAAS,CAAC,OAAO;GAAE,MATzB;IACX,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,MAAM;IACP;GAC2C;GAAS;GAAa;;AAGpE,QAAO,CAAC;EAAE;EAAM,SAAS,CAAC;GAAE;GAAM,iBAAiB;GAAU,CAAC;EAAE,CAAC;;;AAInE,SAAgB,iBACd,QACA,SACM;AACN,MAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,aAAa,MAAM,WACrB,CAAC,GAAG,MAAM,SAAS,MAAM,SAAS,GAClC,MAAM;AAEV,OAAK,MAAM,UAAU,YAAY;GAC/B,MAAM,EAAE,gBAAgB,OAAO;AAC/B,OAAI,CAAC,YAAa;AAElB,WAAQ,IAAI,IAAI,uBAAuB,OAAO,KAAK,MAAM,CAAC;GAC1D,MAAM,WAAW,kBAAkB,YAAY;GAC/C,MAAM,QAAQ,eAAe,YAAY;GACzC,MAAM,YAAY,YAAY,OAAO,QAAQ,WAAW;GACxD,MAAM,gBAAgB,UAAU,QAAQ,KAAK,MAAM,MAAM,EAAE,OAAO,EAAE;GACpE,MAAM,aAAa,eAAe,QAAQ,WAAW,YAAY,MAAM;GACvE,MAAM,QAAQ;IACZ;IACA;IACA,aAAa,YAAY,SAAS;IACnC;AACD,WAAQ,IAAI,iBAAiB,YAAY;IAAE,GAAG;IAAS,GAAG;IAAO,CAAC,CAAC;;;;;AAMzE,eAAsB,gBACpB,OACA,eACe;CACf,MAAM,OAAO,eAAe,cAAc;AAC1C,KAAI,KAAK,IACP,OAAM,oBAAoB,KAAK;UACtB,MACT,OAAM,aAAa,OAAO,KAAK;KAE/B,OAAM,IAAI,MAAM,4CAA4C;;;AAKhE,SAAgB,mBAAmB,MAAqC;CACtE,MAAM,EAAE,SAAS,SAAS,eAAe;AACzC,KAAI,QACF,QAAO;EAAE,eAAe,cAAc;EAAG,YAAY;EAAG;EAAS;AACnE,KAAI,KAAK,SAAU,QAAO,sBAAsB,KAAK;AAErD,QAAO;EACL,SAAS,aAAa,OAAO,oBAAoB,KAAK,OAAO;EAC7D,eAAe;EACf,GAAG,iBAAiB,KAAK;EAC1B;;;AAIH,SAAS,sBAAsB,MAAqC;AAClE,QAAO;EACL,UAAU,KAAK,eAAe,KAAK;EACnC,SAAS,yBAAyB;EAClC,kBAAkB,KAAK;EACvB,UAAU;EACV,GAAG,iBAAiB,KAAK;EAC1B;;;AAIH,SAAS,iBAAiB,MAAsB;CAC9C,MAAM,EAAE,SAAS,KAAK,WAAW;CACjC,MAAM,EAAE,aAAa,UAAU,eAAe,aAAa;CAC3D,MAAM,EAAE,eAAe,YAAY,kBAAkB,kBAAkB;CACvE,MAAM,EAAE,kBAAkB,eAAe,YAAY,YAAY;CACjE,MAAM,EAAE,eAAe,YAAY,iBAAiB,iBAAiB;CACrE,MAAM,EAAE,cAAc,cAAc;AACpC,QAAO;EACL;EACA,aAAa;EACb;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD;;AAIH,MAAM,EAAE,QAAQ,QADD,QAAQ,IAAI,aAAa,UAAU,QAAQ,IAAI,WAAW,SAErE;CAAE,SAAS,MAAc;CAAG,MAAM,MAAc;CAAG,GACnD;;AAGJ,SAAgB,gBAAgB,QAA6B;CAC3D,MAAM,UAAU,OAAO,SAAS,EAAE,SAAS,eAAe;AAExD,UADY,WAAW,CAAC,GAAG,SAAS,SAAS,GAAG,SAE7C,QAAO,MAAK,EAAE,gBAAgB,UAAU,CACxC,KAAI,OAAM;GACT,MAAM,EAAE;GACR,KAAK,EAAE,gBAAgB;GACvB,SAAS,EAAE,gBAAgB,QAAQ;GACpC,EAAE;GACL;AACF,KAAI,QAAQ,WAAW,EAAG;AAE1B,SAAQ,IAAI,IAAI,qBAAqB,CAAC;AACtC,MAAK,MAAM,EAAE,MAAM,KAAK,aAAa,SAAS;EAC5C,MAAM,QAAQ,OAAO,OAAO,IAAI,OAAO,CAAC,QAAQ,GAAG,MAAM,IAAI,EAAE,OAAO,EAAE;EACxE,MAAM,YAAY,OAAO,QAAQ,IAAI,OAAO,CACzC,MAAM,GAAG,MAAM,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,CACvC,KACE,CAAC,MAAM,UAAU,GAAG,KAAK,IAAK,KAAK,QAAQ,QAAS,KAAK,QAAQ,EAAE,CAAC,GACtE,CACA,KAAK,KAAK;AACb,UAAQ,IAAI,KAAK,KAAK,IAAI,UAAU,GAAG,IAAI,IAAI,QAAQ,WAAW,GAAG;;CAGvE,MAAM,cAAc,QAAQ,QAAQ,GAAG,MAAM,IAAI,EAAE,IAAI,YAAY,EAAE;AACrE,KAAI,cAAc,EAChB,SAAQ,IACN,OACE,OAAO,YAAY,iBAAiB,cAAc,IAAI,MAAM,GAAG,WAChE,CACF;;;AAKL,SAAgB,SACd,SACA,OACS;AACT,QAAO,QAAQ,MAAM,EAAE,SAAS,eAAe;AAE7C,UADY,WAAW,CAAC,GAAG,SAAS,SAAS,GAAG,SACrC,MACR,EAAE,sBAAsB,gBAAgB,WAAW,OACrD;GACD;;;AAaJ,eAAe,cACb,SACA,MACA,WACA,eACe;AACf,KAAI,KAAK,eACP,kBAAiB,SAAS,qBAAqB,KAAK,CAAC;AAEvD,OAAM,cAAc;EAAE;EAAS;EAAM;EAAW,GAAG;EAAe,CAAC;;;AAIrE,eAAsB,cAAc,SAAuC;CACzE,MAAM,EAAE,SAAS,MAAM,UAAU,cAAc;CAC/C,MAAM,EAAE,gBAAgB,oBAAoB;CAC5C,MAAM,gBAAgB,KAAK,QAAQ,CAAC,KAAK;CACzC,IAAI;AAEJ,KAAI,KAAK,QAAQ,KAAK,eAYpB,gBAJe,MAAM,mBADF,gBAAgB,SANlB;EACf,SAAS;EACT;EACA;EACA;EACD,CACoD,EACD;EAClD,aAAa;EACb,YAAY,KAAK;EAClB,CAAC,EACmB;AAGvB,KAAI,KAAK,KACP,OAAM,oBAAoB,SAAS,KAAK,MAAM,MAAM,UAAU;AAGhE,KAAI,KAAK,SACP,qBAAoB,SAAS,KAAK,UAAU,KAAK;AAInD,KAAI,eAAe;AACjB,QAAM,cAAc;AACpB,iBAAe;;;;AAKnB,SAAS,eAA8B;AACrC,QAAO,IAAI,SAAQ,YAAW;AAC5B,UAAQ,IAAI,IAAI,yBAAyB,CAAC;AAC1C,UAAQ,GAAG,gBAAgB;AACzB,WAAQ,KAAK;AACb,YAAS;IACT;GACF;;;;;AAMJ,eAAsB,eACpB,OACA,MAC0B;AAC1B,cAAa,KAAK;CAClB,MAAM,SAAS,KAAK,SAAS,kBAAkB,KAAK,OAAO,GAAG;CAC9D,MAAM,UAAU,mBAAmB,KAAK;CAExC,MAAM,UAA2B,EAAE;AACnC,MAAK,MAAM,UAAU,MAAM,UAAU;EACnC,MAAM,cAAc,OAAO,cACvB,MAAM,gBAAgB,OAAO,YAAY,GACzC;EAEJ,IAAI,WAAgC;AACpC,MAAI,CAAC,KAAK,OAAO,YACf,YAAW;GACT,GAAG;GACH,eAAe,YAAY;GAC3B,kBAAkB,YAAY;GAC/B;AAIH,MAAI,OACF,YAAW,MAAM,aAAa,UAAU,OAAO;EAGjD,MAAM,EAAE,eAAe,qBAAqB;AAC5C,UAAQ,KACN,MAAM,UAAU,UAAU;GACxB,GAAG;GACH;GACA;GACD,CAAC,CACH;;AAEH,QAAO;;;AAIT,SAAgB,mBAAmB,MAAwC;CACzE,MAAM,EAAE,MAAM,YAAY,WAAW;AACrC,QAAO;EACL;EACA,SAAS,aAAa,SAAY,OAAO;EACzC,WAAW;EACX,GAAG,iBAAiB,KAAK;EAC1B;;;AAIH,SAAgB,oBACd,SACA,eACA,MACQ;CACR,MAAM,UAAU,OACZ,oBAAoB,eAAe,MAAM,QAAQ,GACjD;AACJ,QAAO,QAAQ,KAAI,MAAK,oBAAoB,GAAG,QAAQ,CAAC,CAAC,KAAK,OAAO;;;AAIvE,SAAS,qBAAqB,MAAyC;AACrE,QAAO;EACL,MAAM,KAAK;EACX,YAAY,KAAK;EACjB,SAAS,KAAK;EACd,UAAU,KAAK;EAChB;;;AAIH,SAAS,oBACP,eACA,MACA,SACqB;CACrB,MAAM,SAA8B,EAAE,GAAG,eAAe;AAExD,KAAI,CAAC,OAAO,UAAU,QAAQ;EAC5B,MAAM,SAAS,qBAAqB,QAAQ;AAC5C,SAAO,WAAW,oBAChB,KAAK,UACL,KAAK,aACL,SAAS,QAAQ,MAAM,EACvB,KAAK,gBAAgB,SAAS,QAAQ,YAAY,CACnD;;AAGH,QAAO;;;AAIT,eAAsB,sBACpB,OACA,eACA,eACe;AAEf,OAAM,mBAAmB,OADZ,eAAe,cAAc,EACJ,cAAc;;;AAItD,SAAgB,qBAAqB,SAAyC;AAC5E,QAAO,QAAQ,SAAQ,WACrB,OAAO,SAAS,SAAQ,YACtB,QAAQ,MAAM,KAAI,MAAK;EACrB,MAAM,EAAE,aAAa;EACrB,MAAM,SAAS;GACb,MAAM,QAAQ;GACd,iBAAiB,EAAE;GACnB;GACD;EACD,MAAM,WAAW,EAAE,WACf;GACE,MAAM,GAAG,QAAQ,GAAG;GACpB,iBAAiB,EAAE;GACnB;GACD,GACD;AACJ,SAAO;GACL,MAAM,GAAG,QAAQ,GAAG,KAAK,EAAE;GAC3B,SAAS,CAAC,OAAO;GACjB;GACD;GACD,CACH,CACF;;;AAUH,eAAe,UACb,KACA,IACc;CACd,MAAM,UAAe,EAAE;AACvB,MAAK,MAAM,QAAQ,IACjB,SAAQ,KAAK,MAAM,GAAG,KAAK,CAAC;AAE9B,QAAO;;;AAIT,eAAsB,mBACpB,OACA,MACA,eACA,eACe;CACf,MAAM,UAAU,MAAM,eAAe,OAAO,KAAK;CACjD,MAAM,SAAS,oBAAoB,SAAS,eAAe,KAAK;AAChE,SAAQ,IAAI,OAAO;AAGnB,OAAM,cADe,qBAAqB,QAAQ,EAChB,MAAM,MAAM,MAAM,cAAc;;;;;;AC50BpE,SAAgB,uBAA+C;AAC7D,KAAI;EACF,MAAM,QAAQ,QAAgB,SAAS,KAAK,EAAE,UAAU,SAAS,CAAC,CAAC,MAAM;EACzE,MAAM,OAAO,KAAK,6BAA6B;EAC/C,MAAM,aAAa,KAAK,0BAA0B;EAClD,MAAM,QAAQ,KAAK,yBAAyB,CAAC,SAAS;AAKtD,SAAO;GAAE;GAAM,MAHF,QACR,0BAA0B,IAAI,IAAI,aACnC;GACiB;GAAO;SACtB;AACN;;;;AAKJ,SAAgB,mBACd,cAAc,aACU;CACxB,MAAM,cAAc,KAAK,aAAa,oBAAoB;AAC1D,KAAI,CAAC,WAAW,YAAY,CAAE,QAAO;AAErC,KAAI;EACF,MAAM,UAAU,aAAa,aAAa,QAAQ;EAClD,MAAM,OAAO,KAAK,MAAM,QAAQ;AAChC,SAAO;GAAE,MAAM,KAAK;GAAM,MAAM,KAAK;GAAM;SACrC;AACN;;;;AAKJ,SAAgB,iBAAiB,SAA6B;AAG5D,QAAO,GAFa,QAAQ,QAAQ,GAAG,QAAQ,KAAK,KAAK,QAAQ,KAE3C,IADF,uBAAuB,QAAQ,KAAK,CAClB;;;AAIxC,SAAgB,0BAA0B,KAAiC;AACzE,KAAI;EAKF,MAAM,gBAJM,SAAS,0BAA0B;GAC7C,UAAU;GACV,KAAK;GACN,CAAC,CAEC,MAAM,CACN,MAAM,KAAK,CACX,QAAO,SAAQ,KAAK,SAAS,EAAE,CAC/B,KAAI,SAAQ,KAAK,MAAM,EAAE,CAAC;AAE7B,MAAI,cAAc,WAAW,EAAG,QAAO;EAEvC,IAAI,aAAa;AACjB,OAAK,MAAM,QAAQ,cACjB,KAAI;GACF,MAAM,WAAW,KAAK,KAAK,KAAK;AAChC,OAAI,CAAC,WAAW,SAAS,CAAE;GAC3B,MAAM,QAAQ,SAAS,SAAS,CAAC;AACjC,OAAI,QAAQ,WAAY,cAAa;UAC/B;AAGV,SAAO,aAAa,IAAI,IAAI,KAAK,WAAW,CAAC,aAAa,GAAG;SACvD;AACN"}
|