mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-10-17 05:07:37 +08:00
f416357b93
* fix(cobol): a file ending inside the sequence area no longer hangs the parser The vendored COBOL grammar's external scanner skips the fixed-format sequence area (columns 1-6) with `while (get_column() <= 5) advance()`. At end of input advance() is a no-op, so a file whose last line stops in that area (` .`, `X\n .`, a sentence closed by a short ` .` line) never reached column 7 and the scanner spun forever inside wasm. Indexing hit the parse worker's hard timeout three times (~93 s) and stored the file with zero symbols; the viewer's highlighter froze on the same text. The loop now also stops at eof(). It is upstream code (present at e99dbdc3), so the change is a standalone upstreamable fix; inputs that parsed before are unaffected (412 NIST + ocesql test sources give byte-identical trees with the old and new wasm, and the upstream corpus keeps its single pre-existing failure). Regenerates docs/grammars/tree-sitter-cobol.patch, rebuilds the wasm per docs/grammars/tree-sitter-cobol.md, and adds an out-of-process regression test under a hard deadline (a regression is an uninterruptible wasm loop). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(viewer): force the highlight deadline instead of relying on a grammar bug The bounded-highlight test used the COBOL ` .` slice as its slice that never finishes; the grammar fix makes it parse, so the deadline is now forced through tokenizeBounded's deadline parameter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
37 lines
1.8 KiB
TypeScript
37 lines
1.8 KiB
TypeScript
/**
|
|
* A grammar that never finishes a slice must not take the viewer's server
|
|
* down. The COBOL grammar's scanner once looped forever on a slice ending in a
|
|
* line like ` .` (fixed in the grammar since), which froze cobolcraft's Flow
|
|
* strip and every request behind it: a parse inside WebAssembly cannot be
|
|
* interrupted from JavaScript. Slices are classified in a worker the server
|
|
* ends past a deadline; the slice is served plain, and the next one gets a
|
|
* fresh worker. The deadline is forced here rather than found in a grammar.
|
|
*/
|
|
import { describe, it, expect, afterAll } from 'vitest';
|
|
import { highlightLines, clearHighlightCache } from '../src/ui-server/highlight';
|
|
import { stopHighlightWorker, tokenizeBounded } from '../src/ui-server/highlight/bounded-tokenize';
|
|
|
|
afterAll(() => stopHighlightWorker());
|
|
|
|
describe('highlighting a slice', () => {
|
|
it('gives up on a slice past the deadline, and the next slice gets a fresh worker', async () => {
|
|
const big = 'export const value: number = 1;\n'.repeat(2000);
|
|
const started = Date.now();
|
|
const timedOut = await tokenizeBounded(big, 'typescript', 1);
|
|
expect('timedOut' in timedOut).toBe(true);
|
|
expect(Date.now() - started).toBeLessThan(5_000);
|
|
|
|
const fine = await tokenizeBounded('const y = 2;', 'typescript');
|
|
expect('result' in fine && (fine.result?.spans.length ?? 0) > 0).toBe(true);
|
|
}, 20_000);
|
|
|
|
it('still highlights through the worker', async () => {
|
|
clearHighlightCache();
|
|
const fine = await highlightLines(['export const x: number = 1;'], { language: 'typescript' });
|
|
expect(fine.engine).toBe('tree-sitter');
|
|
// The slice that used to hang the COBOL grammar is classified now.
|
|
const cobol = await highlightLines([' PERFORM AssertOk', ' .'], { language: 'cobol' });
|
|
expect(cobol.reason ?? '').not.toMatch(/took too long/);
|
|
}, 20_000);
|
|
});
|