(path: string)
| 53 | } |
| 54 | |
| 55 | async function getLanguageForFile(path: string) { |
| 56 | if (!parser) await initParser(); |
| 57 | const extMatch = path.match(/\.([a-zA-Z0-9]+)$/); |
| 58 | if (!extMatch) return null; |
| 59 | const ext = extMatch[1].toLowerCase(); |
| 60 | |
| 61 | let wasmName = ''; |
| 62 | switch (ext) { |
| 63 | case 'py': wasmName = 'tree-sitter-python.wasm'; break; |
| 64 | case 'js': |
| 65 | case 'jsx': wasmName = 'tree-sitter-javascript.wasm'; break; |
| 66 | case 'ts': wasmName = 'tree-sitter-typescript.wasm'; break; |
| 67 | case 'tsx': wasmName = 'tree-sitter-tsx.wasm'; break; |
| 68 | case 'java': wasmName = 'tree-sitter-java.wasm'; break; |
| 69 | case 'c': |
| 70 | case 'h': wasmName = 'tree-sitter-c.wasm'; break; |
| 71 | case 'cpp': |
| 72 | case 'hpp': |
| 73 | case 'cc': wasmName = 'tree-sitter-cpp.wasm'; break; |
| 74 | case 'cs': wasmName = 'tree-sitter-c_sharp.wasm'; break; |
| 75 | case 'go': wasmName = 'tree-sitter-go.wasm'; break; |
| 76 | case 'rs': wasmName = 'tree-sitter-rust.wasm'; break; |
| 77 | case 'rb': wasmName = 'tree-sitter-ruby.wasm'; break; |
| 78 | case 'php': wasmName = 'tree-sitter-php.wasm'; break; |
| 79 | case 'swift': wasmName = 'tree-sitter-swift.wasm'; break; |
| 80 | case 'kt': |
| 81 | case 'kts': wasmName = 'tree-sitter-kotlin.wasm'; break; |
| 82 | case 'dart': wasmName = 'tree-sitter-dart.wasm'; break; |
| 83 | case 'pl': |
| 84 | case 'pm': wasmName = 'tree-sitter-perl.wasm'; break; |
| 85 | default: return null; |
| 86 | } |
| 87 | |
| 88 | if (wasmLanguageCache.has(wasmName)) { |
| 89 | const lang = wasmLanguageCache.get(wasmName); |
| 90 | wasmLanguageCache.delete(wasmName); |
| 91 | wasmLanguageCache.set(wasmName, lang); |
| 92 | return lang; |
| 93 | } |
| 94 | |
| 95 | // Set CACHE_LIMIT to accommodate all supported languages (we support 15 languages in the web app). |
| 96 | // CRITICAL MEMORY NOTE: Keeping this limit high (e.g., 20) prevents fatal WebAssembly compilation memory leaks. |
| 97 | // In V8/Chromium, deleting a JS reference to a compiled WASM Language does not free the native WASM machine code. |
| 98 | // If this limit is low (e.g., 3) and we index a multi-language repo (like the tests folder), the LRU cache will |
| 99 | // constantly evict and re-compile the same WASM files, leaking memory infinitely and crashing the worker. |
| 100 | // Keeping them in cache ensures each language is compiled EXACTLY ONCE. |
| 101 | const CACHE_LIMIT = 20; |
| 102 | if (wasmLanguageCache.size >= CACHE_LIMIT) { |
| 103 | const oldestKey = wasmLanguageCache.keys().next().value; |
| 104 | if (oldestKey) { |
| 105 | wasmLanguageCache.delete(oldestKey); |
| 106 | console.log(`[Worker LRU Cache] Evicted parser to free WASM heap: ${oldestKey}`); |
| 107 | } |
| 108 | } |
| 109 | |
| 110 | try { |
| 111 | const response = await fetch(`${location.origin}/wasm/${wasmName}`); |
| 112 | if (!response.ok) { |
no test coverage detected