Skip to content

Commit 331cdb7

Browse files
spewRob Leidle
and
Rob Leidle
authored
Change treeSitter to cache the Language objects it loads from wasm (#1672)
Without this change, for a repository with 600 typescript files, the indexer would fail to finish correctly and there would be many of the following errors in the webview console log: 'Unable to load language for file ${path} RuntimeError: table index is out of bounds' The following bash will create a repo that reproduces the problem: current_path="." for ((i=1; i<=20; i++)); do new_folder="folder-$i" mkdir -p "$current_path/$new_folder" current_path="$current_path/$new_folder" for ((a=1; a<=30; a++)); do head -c 10000 /dev/urandom | base64 > "$current_path/file-$a.ts" done done Co-authored-by: Rob Leidle <[email protected]>
1 parent b6fb456 commit 331cdb7

File tree

1 file changed

+23
-10
lines changed

1 file changed

+23
-10
lines changed

core/util/treeSitter.ts

+23-10
Original file line numberDiff line numberDiff line change
@@ -93,25 +93,27 @@ export async function getParserForFile(filepath: string) {
9393
}
9494
}
9595

96+
// Loading the wasm files to create a Language object is an expensive operation and with
97+
// sufficient number of files can result in errors, instead keep a map of language name
98+
// to Language object
99+
const nameToLanguage = new Map<string, Language>();
100+
96101
export async function getLanguageForFile(
97102
filepath: string,
98103
): Promise<Language | undefined> {
99104
try {
100105
await Parser.init();
101106
const extension = path.extname(filepath).slice(1);
102107

103-
if (!supportedLanguages[extension]) {
108+
const languageName = supportedLanguages[extension];
109+
if (!languageName) {
104110
return undefined;
105111
}
106-
107-
const wasmPath = path.join(
108-
__dirname,
109-
...(process.env.NODE_ENV === "test"
110-
? ["node_modules", "tree-sitter-wasms", "out"]
111-
: ["tree-sitter-wasms"]),
112-
`tree-sitter-${supportedLanguages[extension]}.wasm`,
113-
);
114-
const language = await Parser.Language.load(wasmPath);
112+
let language = nameToLanguage.get(languageName);
113+
if (!language) {
114+
language = await loadLanguageForFileExt(extension);
115+
nameToLanguage.set(languageName, language);
116+
}
115117
return language;
116118
} catch (e) {
117119
console.error("Unable to load language for file", filepath, e);
@@ -149,3 +151,14 @@ export async function getQueryForFile(
149151
const query = language.query(querySource);
150152
return query;
151153
}
154+
155+
async function loadLanguageForFileExt(fileExtension: string): Promise<Language> {
156+
const wasmPath = path.join(
157+
__dirname,
158+
...(process.env.NODE_ENV === "test"
159+
? ["node_modules", "tree-sitter-wasms", "out"]
160+
: ["tree-sitter-wasms"]),
161+
`tree-sitter-${supportedLanguages[fileExtension]}.wasm`,
162+
);
163+
return await Parser.Language.load(wasmPath);
164+
}

0 commit comments

Comments
 (0)