Download packages/tree-sitter-bash/src/budget.ts from SaylorTwift/kimi-code: direct link, hf CLI and curl.
- Browser
- Download file 2.28 kB
-
https://huggingface.co/SaylorTwift/kimi-code/resolve/main/packages/tree-sitter-bash/src/budget.ts
- Command line
-
hf download hf://SaylorTwift/kimi-code/packages/tree-sitter-bash/src/budget.ts
-
curl -L -o budget.ts https://huggingface.co/SaylorTwift/kimi-code/resolve/main/packages/tree-sitter-bash/src/budget.ts
2.28 kB
| // src/budget.ts | |
| // | |
| // Parse budget: a hard cap on wall-clock time and on the number of syntax | |
| // nodes a single parse may create. The parser calls `budget.tick()` every | |
| // time it creates a node; long scan loops (word runs, strings, heredoc | |
| // bodies) call `budget.progress()` periodically so a pathological single | |
| // token still hits the deadline without inflating the node count. When | |
| // either limit is exceeded the methods throw `Aborted`, which the `parse` | |
| // entry point catches and reports as `{ ok: false, reason: 'aborted' }`. | |
| export const DEFAULT_TIMEOUT_MS = 50; | |
| export const DEFAULT_MAX_NODES = 50_000; | |
| /** Internal control-flow error. Never escapes the `parse` entry point. */ | |
| export class Aborted extends Error { | |
| constructor(message: string) { | |
| super(message); | |
| this.name = 'Aborted'; | |
| } | |
| } | |
| export interface BudgetOptions { | |
| /** Wall-clock limit in milliseconds. `Infinity` disables the time check. */ | |
| timeoutMs?: number; | |
| /** Maximum number of nodes the parse may create. */ | |
| maxNodes?: number; | |
| } | |
| export class ParseBudget { | |
| private readonly deadline: number; | |
| private readonly maxNodes: number; | |
| private nodeCount = 0; | |
| constructor(options: BudgetOptions = {}) { | |
| const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS; | |
| this.deadline = Date.now() + timeoutMs; | |
| this.maxNodes = options.maxNodes ?? DEFAULT_MAX_NODES; | |
| } | |
| /** Number of nodes created so far. */ | |
| get nodesUsed(): number { | |
| return this.nodeCount; | |
| } | |
| /** | |
| * Account for one created node and re-check the deadline. Throws `Aborted` | |
| * when the node cap is exceeded or the deadline has been reached. | |
| */ | |
| tick(): void { | |
| this.nodeCount++; | |
| if (this.nodeCount > this.maxNodes) { | |
| throw new Aborted(`parse aborted: node budget exceeded (${this.nodeCount} > ${this.maxNodes})`); | |
| } | |
| if (Date.now() >= this.deadline) { | |
| throw new Aborted(`parse aborted: timeout`); | |
| } | |
| } | |
| /** | |
| * Re-check the deadline WITHOUT counting a node. For long scan loops that | |
| * run many iterations per produced node (character-level scanning), called | |
| * at intervals so the deadline is still enforced promptly. | |
| */ | |
| progress(): void { | |
| if (Date.now() >= this.deadline) { | |
| throw new Aborted(`parse aborted: timeout`); | |
| } | |
| } | |
| } | |