feat(web)!: use the WASM module in the bindings, and not the other way around
Parser is no longer the default export, but you *must* call `Parser.init()` before doing anything still
This commit is contained in:
parent
b1e39d2dba
commit
be7716dfa7
29 changed files with 613 additions and 662 deletions
1
lib/binding_web/.gitattributes
vendored
Normal file
1
lib/binding_web/.gitattributes
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/lib/tree-sitter.d.ts linguist-generated
|
||||
3
lib/binding_web/.gitignore
vendored
3
lib/binding_web/.gitignore
vendored
|
|
@ -1,5 +1,8 @@
|
|||
debug/
|
||||
dist/
|
||||
/lib/tree-sitter.js
|
||||
/lib/tree-sitter.wasm
|
||||
/lib/tree-sitter.wasm.map
|
||||
/tree-sitter.js
|
||||
/tree-sitter.js.map
|
||||
/tree-sitter.wasm
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ mergeInto(LibraryManager.library, {
|
|||
lengthAddress,
|
||||
) {
|
||||
const INPUT_BUFFER_SIZE = 10 * 1024;
|
||||
const string = currentParseCallback(index, { row, column });
|
||||
const string = Module.currentParseCallback(index, { row, column });
|
||||
if (typeof string === 'string') {
|
||||
setValue(lengthAddress, string.length, 'i32');
|
||||
stringToUTF16(string, inputBufferAddress, INPUT_BUFFER_SIZE);
|
||||
|
|
@ -17,22 +17,22 @@ mergeInto(LibraryManager.library, {
|
|||
},
|
||||
|
||||
tree_sitter_log_callback(isLexMessage, messageAddress) {
|
||||
if (currentLogCallback) {
|
||||
if (Module.currentLogCallback) {
|
||||
const message = UTF8ToString(messageAddress);
|
||||
currentLogCallback(message, isLexMessage !== 0);
|
||||
Module.currentLogCallback(message, isLexMessage !== 0);
|
||||
}
|
||||
},
|
||||
|
||||
tree_sitter_progress_callback(currentOffset) {
|
||||
if (currentProgressCallback) {
|
||||
return currentProgressCallback({ currentOffset });
|
||||
if (Module.currentProgressCallback) {
|
||||
return Module.currentProgressCallback({ currentOffset });
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
tree_sitter_query_progress_callback(currentOffset) {
|
||||
if (currentQueryProgressCallback) {
|
||||
return currentQueryProgressCallback({ currentOffset });
|
||||
if (Module.currentQueryProgressCallback) {
|
||||
return Module.currentQueryProgressCallback({ currentOffset });
|
||||
}
|
||||
return false;
|
||||
},
|
||||
4
lib/binding_web/lib/prefix.js
Normal file
4
lib/binding_web/lib/prefix.js
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
Module.currentQueryProgressCallback = null;
|
||||
Module.currentProgressCallback = null;
|
||||
Module.currentLogCallback = null;
|
||||
Module.currentParseCallback = null;
|
||||
217
lib/binding_web/lib/tree-sitter.d.ts
generated
vendored
Normal file
217
lib/binding_web/lib/tree-sitter.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
// TypeScript bindings for emscripten-generated code. Automatically generated at compile time.
|
||||
declare namespace RuntimeExports {
|
||||
function AsciiToString(ptr: number): string;
|
||||
function stringToUTF8(str: string, outPtr: number, maxBytesToWrite: number): number;
|
||||
/**
|
||||
* Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the
|
||||
* emscripten HEAP, returns a copy of that string as a Javascript String object.
|
||||
*
|
||||
* @param {number} ptr
|
||||
* @param {number=} maxBytesToRead - An optional length that specifies the
|
||||
* maximum number of bytes to read. You can omit this parameter to scan the
|
||||
* string until the first 0 byte. If maxBytesToRead is passed, and the string
|
||||
* at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the
|
||||
* string will cut short at that byte index (i.e. maxBytesToRead will not
|
||||
* produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing
|
||||
* frequent uses of UTF8ToString() with and without maxBytesToRead may throw
|
||||
* JS JIT optimizations off, so it is worth to consider consistently using one
|
||||
* @return {string}
|
||||
*/
|
||||
function UTF8ToString(ptr: number, maxBytesToRead?: number): string;
|
||||
function lengthBytesUTF8(str: string): number;
|
||||
function stringToUTF16(str: string, outPtr: number, maxBytesToWrite: number): number;
|
||||
/**
|
||||
* @param {string=} libName
|
||||
* @param {Object=} localScope
|
||||
* @param {number=} handle
|
||||
*/
|
||||
function loadWebAssemblyModule(
|
||||
binary: Uint8Array,
|
||||
flags: {
|
||||
allowUndefined?: boolean,
|
||||
loadAsync?: boolean,
|
||||
global?: boolean,
|
||||
nodelete?: boolean;
|
||||
},
|
||||
libName?: string,
|
||||
localScope?: Record<string, any>,
|
||||
handle?: number
|
||||
): Promise<Record<string, () => number>>;
|
||||
/**
|
||||
* @param {number} ptr
|
||||
* @param {string} type
|
||||
*/
|
||||
function getValue(ptr: number, type?: string): number;
|
||||
/**
|
||||
* @param {number} ptr
|
||||
* @param {number} value
|
||||
* @param {string} type
|
||||
*/
|
||||
function setValue(ptr: number, value: number, type?: string): void;
|
||||
let currentParseCallback: ((index: number, position: {row: number, column: number}) => string | undefined) | null;
|
||||
let currentLogCallback: ((message: string, isLex: boolean) => void) | null;
|
||||
let currentProgressCallback: ((state: {currentOffset: number}) => void) | null;
|
||||
let currentQueryProgressCallback: ((state: {currentOffset: number}) => void) | null;
|
||||
let HEAPF32: Float32Array;
|
||||
let HEAPF64: Float64Array;
|
||||
let HEAP_DATA_VIEW: DataView;
|
||||
let HEAP8: Int8Array
|
||||
let HEAPU8: Uint8Array;
|
||||
let HEAP16: Int16Array;
|
||||
let HEAPU16: Uint16Array;
|
||||
let HEAP32: Int32Array;
|
||||
let HEAPU32: Uint32Array;
|
||||
let HEAP64: BigInt64Array;
|
||||
let HEAPU64: BigUint64Array;
|
||||
}
|
||||
interface WasmModule {
|
||||
_malloc(_0: number): number;
|
||||
_calloc(_0: number, _1: number): number;
|
||||
_realloc(_0: number, _1: number): number;
|
||||
_free(_0: number): void;
|
||||
_ts_language_symbol_count(_0: number): number;
|
||||
_ts_language_state_count(_0: number): number;
|
||||
_ts_language_version(_0: number): number;
|
||||
_ts_language_name(_0: number): number;
|
||||
_ts_language_field_count(_0: number): number;
|
||||
_ts_language_next_state(_0: number, _1: number, _2: number): number;
|
||||
_ts_language_symbol_name(_0: number, _1: number): number;
|
||||
_ts_language_symbol_for_name(_0: number, _1: number, _2: number, _3: number): number;
|
||||
_strncmp(_0: number, _1: number, _2: number): number;
|
||||
_ts_language_symbol_type(_0: number, _1: number): number;
|
||||
_ts_language_field_name_for_id(_0: number, _1: number): number;
|
||||
_ts_lookahead_iterator_new(_0: number, _1: number): number;
|
||||
_ts_lookahead_iterator_delete(_0: number): void;
|
||||
_ts_lookahead_iterator_reset_state(_0: number, _1: number): number;
|
||||
_ts_lookahead_iterator_reset(_0: number, _1: number, _2: number): number;
|
||||
_ts_lookahead_iterator_next(_0: number): number;
|
||||
_ts_lookahead_iterator_current_symbol(_0: number): number;
|
||||
_memset(_0: number, _1: number, _2: number): number;
|
||||
_memcpy(_0: number, _1: number, _2: number): number;
|
||||
_ts_parser_delete(_0: number): void;
|
||||
_ts_parser_reset(_0: number): void;
|
||||
_ts_parser_set_language(_0: number, _1: number): number;
|
||||
_ts_parser_timeout_micros(_0: number): number;
|
||||
_ts_parser_set_timeout_micros(_0: number, _1: number, _2: number): void;
|
||||
_ts_parser_set_included_ranges(_0: number, _1: number, _2: number): number;
|
||||
_memmove(_0: number, _1: number, _2: number): number;
|
||||
_memcmp(_0: number, _1: number, _2: number): number;
|
||||
_ts_query_new(_0: number, _1: number, _2: number, _3: number, _4: number): number;
|
||||
_ts_query_delete(_0: number): void;
|
||||
_iswspace(_0: number): number;
|
||||
_iswalnum(_0: number): number;
|
||||
_ts_query_pattern_count(_0: number): number;
|
||||
_ts_query_capture_count(_0: number): number;
|
||||
_ts_query_string_count(_0: number): number;
|
||||
_ts_query_capture_name_for_id(_0: number, _1: number, _2: number): number;
|
||||
_ts_query_capture_quantifier_for_id(_0: number, _1: number, _2: number): number;
|
||||
_ts_query_string_value_for_id(_0: number, _1: number, _2: number): number;
|
||||
_ts_query_predicates_for_pattern(_0: number, _1: number, _2: number): number;
|
||||
_ts_query_start_byte_for_pattern(_0: number, _1: number): number;
|
||||
_ts_query_end_byte_for_pattern(_0: number, _1: number): number;
|
||||
_ts_query_is_pattern_rooted(_0: number, _1: number): number;
|
||||
_ts_query_is_pattern_non_local(_0: number, _1: number): number;
|
||||
_ts_query_is_pattern_guaranteed_at_step(_0: number, _1: number): number;
|
||||
_ts_query_disable_capture(_0: number, _1: number, _2: number): void;
|
||||
_ts_query_disable_pattern(_0: number, _1: number): void;
|
||||
_ts_tree_copy(_0: number): number;
|
||||
_ts_tree_delete(_0: number): void;
|
||||
_ts_init(): number;
|
||||
_ts_parser_new_wasm(): void;
|
||||
_ts_parser_enable_logger_wasm(_0: number, _1: number): void;
|
||||
_ts_parser_parse_wasm(_0: number, _1: number, _2: number, _3: number, _4: number): number;
|
||||
_ts_parser_included_ranges_wasm(_0: number): void;
|
||||
_ts_language_type_is_named_wasm(_0: number, _1: number): number;
|
||||
_ts_language_type_is_visible_wasm(_0: number, _1: number): number;
|
||||
_ts_language_supertypes_wasm(_0: number): void;
|
||||
_ts_language_subtypes_wasm(_0: number, _1: number): void;
|
||||
_ts_tree_root_node_wasm(_0: number): void;
|
||||
_ts_tree_root_node_with_offset_wasm(_0: number): void;
|
||||
_ts_tree_edit_wasm(_0: number): void;
|
||||
_ts_tree_included_ranges_wasm(_0: number): void;
|
||||
_ts_tree_get_changed_ranges_wasm(_0: number, _1: number): void;
|
||||
_ts_tree_cursor_new_wasm(_0: number): void;
|
||||
_ts_tree_cursor_copy_wasm(_0: number): void;
|
||||
_ts_tree_cursor_delete_wasm(_0: number): void;
|
||||
_ts_tree_cursor_reset_wasm(_0: number): void;
|
||||
_ts_tree_cursor_reset_to_wasm(_0: number, _1: number): void;
|
||||
_ts_tree_cursor_goto_first_child_wasm(_0: number): number;
|
||||
_ts_tree_cursor_goto_last_child_wasm(_0: number): number;
|
||||
_ts_tree_cursor_goto_first_child_for_index_wasm(_0: number): number;
|
||||
_ts_tree_cursor_goto_first_child_for_position_wasm(_0: number): number;
|
||||
_ts_tree_cursor_goto_next_sibling_wasm(_0: number): number;
|
||||
_ts_tree_cursor_goto_previous_sibling_wasm(_0: number): number;
|
||||
_ts_tree_cursor_goto_descendant_wasm(_0: number, _1: number): void;
|
||||
_ts_tree_cursor_goto_parent_wasm(_0: number): number;
|
||||
_ts_tree_cursor_current_node_type_id_wasm(_0: number): number;
|
||||
_ts_tree_cursor_current_node_state_id_wasm(_0: number): number;
|
||||
_ts_tree_cursor_current_node_is_named_wasm(_0: number): number;
|
||||
_ts_tree_cursor_current_node_is_missing_wasm(_0: number): number;
|
||||
_ts_tree_cursor_current_node_id_wasm(_0: number): number;
|
||||
_ts_tree_cursor_start_position_wasm(_0: number): void;
|
||||
_ts_tree_cursor_end_position_wasm(_0: number): void;
|
||||
_ts_tree_cursor_start_index_wasm(_0: number): number;
|
||||
_ts_tree_cursor_end_index_wasm(_0: number): number;
|
||||
_ts_tree_cursor_current_field_id_wasm(_0: number): number;
|
||||
_ts_tree_cursor_current_depth_wasm(_0: number): number;
|
||||
_ts_tree_cursor_current_descendant_index_wasm(_0: number): number;
|
||||
_ts_tree_cursor_current_node_wasm(_0: number): void;
|
||||
_ts_node_symbol_wasm(_0: number): number;
|
||||
_ts_node_field_name_for_child_wasm(_0: number, _1: number): number;
|
||||
_ts_node_field_name_for_named_child_wasm(_0: number, _1: number): number;
|
||||
_ts_node_children_by_field_id_wasm(_0: number, _1: number): void;
|
||||
_ts_node_first_child_for_byte_wasm(_0: number): void;
|
||||
_ts_node_first_named_child_for_byte_wasm(_0: number): void;
|
||||
_ts_node_grammar_symbol_wasm(_0: number): number;
|
||||
_ts_node_child_count_wasm(_0: number): number;
|
||||
_ts_node_named_child_count_wasm(_0: number): number;
|
||||
_ts_node_child_wasm(_0: number, _1: number): void;
|
||||
_ts_node_named_child_wasm(_0: number, _1: number): void;
|
||||
_ts_node_child_by_field_id_wasm(_0: number, _1: number): void;
|
||||
_ts_node_next_sibling_wasm(_0: number): void;
|
||||
_ts_node_prev_sibling_wasm(_0: number): void;
|
||||
_ts_node_next_named_sibling_wasm(_0: number): void;
|
||||
_ts_node_prev_named_sibling_wasm(_0: number): void;
|
||||
_ts_node_descendant_count_wasm(_0: number): number;
|
||||
_ts_node_parent_wasm(_0: number): void;
|
||||
_ts_node_descendant_for_index_wasm(_0: number): void;
|
||||
_ts_node_named_descendant_for_index_wasm(_0: number): void;
|
||||
_ts_node_descendant_for_position_wasm(_0: number): void;
|
||||
_ts_node_named_descendant_for_position_wasm(_0: number): void;
|
||||
_ts_node_start_point_wasm(_0: number): void;
|
||||
_ts_node_end_point_wasm(_0: number): void;
|
||||
_ts_node_start_index_wasm(_0: number): number;
|
||||
_ts_node_end_index_wasm(_0: number): number;
|
||||
_ts_node_to_string_wasm(_0: number): number;
|
||||
_ts_node_children_wasm(_0: number): void;
|
||||
_ts_node_named_children_wasm(_0: number): void;
|
||||
_ts_node_descendants_of_type_wasm(_0: number, _1: number, _2: number, _3: number, _4: number, _5: number, _6: number): void;
|
||||
_ts_node_is_named_wasm(_0: number): number;
|
||||
_ts_node_has_changes_wasm(_0: number): number;
|
||||
_ts_node_has_error_wasm(_0: number): number;
|
||||
_ts_node_is_error_wasm(_0: number): number;
|
||||
_ts_node_is_missing_wasm(_0: number): number;
|
||||
_ts_node_is_extra_wasm(_0: number): number;
|
||||
_ts_node_parse_state_wasm(_0: number): number;
|
||||
_ts_node_next_parse_state_wasm(_0: number): number;
|
||||
_ts_query_matches_wasm(_0: number, _1: number, _2: number, _3: number, _4: number, _5: number, _6: number, _7: number, _8: number, _9: number, _10: number): void;
|
||||
_ts_query_captures_wasm(_0: number, _1: number, _2: number, _3: number, _4: number, _5: number, _6: number, _7: number, _8: number, _9: number, _10: number): void;
|
||||
_iswalpha(_0: number): number;
|
||||
_iswblank(_0: number): number;
|
||||
_iswdigit(_0: number): number;
|
||||
_iswlower(_0: number): number;
|
||||
_iswupper(_0: number): number;
|
||||
_iswxdigit(_0: number): number;
|
||||
_memchr(_0: number, _1: number, _2: number): number;
|
||||
_strlen(_0: number): number;
|
||||
_strcmp(_0: number, _1: number): number;
|
||||
_strncat(_0: number, _1: number, _2: number): number;
|
||||
_strncpy(_0: number, _1: number, _2: number): number;
|
||||
_towlower(_0: number): number;
|
||||
_towupper(_0: number): number;
|
||||
_orig$ts_parser_timeout_micros(_0: number): bigint;
|
||||
_orig$ts_parser_set_timeout_micros(_0: number, _1: bigint): void;
|
||||
}
|
||||
|
||||
export type MainModule = WasmModule & typeof RuntimeExports;
|
||||
export default function MainModuleFactory (options?: EmscriptenModule): Promise<MainModule>;
|
||||
|
|
@ -50,12 +50,11 @@
|
|||
"vitest": "^3.0.2"
|
||||
},
|
||||
"scripts": {
|
||||
"build:ts": "esbuild src/index.ts --bundle --platform=neutral --format=cjs --global-name=TreeSitterImpl --outfile=dist/tree-sitter.js --external:fs/* --external:fs/promises --sourcemap --sources-content=true --keep-names",
|
||||
"build:ts": "esbuild src/index.ts --bundle --format=esm --platform=node --global-name=TreeSitterImpl --outfile=tree-sitter.js --external:fs/* --external:fs/promises --sourcemap --sources-content=true --keep-names && cp lib/*wasm* .",
|
||||
"build:wasm": "cd ../../ && cargo xtask build-wasm",
|
||||
"build:wasm:debug": "cd ../../ && cargo xtask build-wasm --debug",
|
||||
"build:sourcemap": "tsx script/build-sourcemap.ts",
|
||||
"build": "npm run build:ts && npm run build:wasm && npm run build:sourcemap",
|
||||
"build:debug": "npm run build:ts && npm run build:wasm:debug && cp debug/* . && npm run build:sourcemap",
|
||||
"build": "npm run build:wasm && npm run build:ts",
|
||||
"build:debug": "npm run build:wasm:debug && npm run build:ts && cp debug/* .",
|
||||
"lint": "eslint src/*.ts script/*.ts",
|
||||
"lint:fix": "eslint src/*.ts script/*.ts --fix",
|
||||
"test": "vitest run",
|
||||
|
|
|
|||
|
|
@ -1,64 +0,0 @@
|
|||
import { readFileSync, writeFileSync } from 'fs';
|
||||
import { SourceMapGenerator, SourceMapConsumer, RawSourceMap } from 'source-map';
|
||||
|
||||
async function fixSourceMap() {
|
||||
const distMap = JSON.parse(readFileSync('dist/tree-sitter.js.map', 'utf8')) as RawSourceMap;
|
||||
const distJs = readFileSync('dist/tree-sitter.js', 'utf8').split('\n');
|
||||
const finalJs = readFileSync('tree-sitter.js', 'utf8').split('\n');
|
||||
|
||||
const lineMap = new Map<number, number>();
|
||||
|
||||
let currentFinalLine = 0;
|
||||
for (let distLine = 0; distLine < distJs.length; distLine++) {
|
||||
const line = distJs[distLine].trim();
|
||||
if (!line) continue;
|
||||
|
||||
for (let finalLine = currentFinalLine; finalLine < finalJs.length; finalLine++) {
|
||||
if (finalJs[finalLine].trim() === line) {
|
||||
lineMap.set(distLine + 1, finalLine + 1);
|
||||
currentFinalLine = finalLine;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const consumer = await new SourceMapConsumer(distMap);
|
||||
const generator = new SourceMapGenerator({
|
||||
file: 'tree-sitter.js',
|
||||
sourceRoot: '',
|
||||
});
|
||||
|
||||
consumer.eachMapping(mapping => {
|
||||
const finalLine = lineMap.get(mapping.generatedLine);
|
||||
if (finalLine) {
|
||||
generator.addMapping({
|
||||
generated: {
|
||||
line: finalLine,
|
||||
column: mapping.generatedColumn,
|
||||
},
|
||||
original: {
|
||||
line: mapping.originalLine,
|
||||
column: mapping.originalColumn,
|
||||
},
|
||||
// Fix the source path to be relative to binding_web
|
||||
source: `src/${mapping.source.split('/').pop()}`,
|
||||
name: mapping.name,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
for (const source of consumer.sources) {
|
||||
const content = consumer.sourceContentFor(source);
|
||||
if (content) {
|
||||
generator.setSourceContent(
|
||||
`src/${source.split('/').pop()}`,
|
||||
content,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
consumer.destroy();
|
||||
writeFileSync('tree-sitter.js.map', generator.toString());
|
||||
}
|
||||
|
||||
fixSourceMap().catch(console.error);
|
||||
|
|
@ -17,9 +17,9 @@ const inputFiles = [
|
|||
'../src/tree.ts',
|
||||
'../src/tree_cursor.ts',
|
||||
'../dist/tree-sitter.js',
|
||||
'../wasm/exports.txt',
|
||||
'../wasm/imports.js',
|
||||
'../wasm/prefix.js',
|
||||
'../lib/exports.txt',
|
||||
'../lib/imports.js',
|
||||
'../lib/prefix.js',
|
||||
...listFiles('../../include/tree_sitter'),
|
||||
...listFiles('../../src'),
|
||||
];
|
||||
|
|
|
|||
14
lib/binding_web/src/bindings.ts
Normal file
14
lib/binding_web/src/bindings.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import createModule, { type MainModule } from '../lib/tree-sitter';
|
||||
|
||||
export let Module: MainModule | null = null;
|
||||
|
||||
export async function initializeBinding(moduleOptions: EmscriptenModule): Promise<MainModule> {
|
||||
if (!Module) {
|
||||
Module = await createModule(moduleOptions);
|
||||
}
|
||||
return Module;
|
||||
}
|
||||
|
||||
export function checkModule(): boolean {
|
||||
return !!Module;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { CaptureQuantifier } from './query';
|
||||
import { type MainModule } from '../lib/tree-sitter';
|
||||
|
||||
export interface Point {
|
||||
row: number;
|
||||
|
|
@ -56,183 +56,8 @@ export function isPoint(point?: Point): point is Point {
|
|||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
export const C: EmscriptenModule & {
|
||||
// Global
|
||||
_ts_init(): number;
|
||||
export function setModule(module: MainModule) {
|
||||
C = module;
|
||||
}
|
||||
|
||||
// Libc
|
||||
_malloc(size: number): number;
|
||||
_calloc(count: number, size: number): number;
|
||||
_free(ptr: number): void;
|
||||
|
||||
// Parser
|
||||
_ts_parser_new_wasm(): void;
|
||||
_ts_parser_delete(address: number): void;
|
||||
_ts_parser_set_language(parserAddress: number, languageAddress: number): void;
|
||||
_ts_parser_enable_logger_wasm(address: number, enabled: number): void;
|
||||
_ts_parser_parse_wasm(
|
||||
address: number,
|
||||
payload: number,
|
||||
oldTreeAddress: number,
|
||||
rangeAddress: number,
|
||||
rangeCount: number
|
||||
): number;
|
||||
_ts_parser_reset(address: number): void;
|
||||
_ts_parser_timeout_micros(address: number): number;
|
||||
_ts_parser_set_timeout_micros(address: number, timeout: number): void;
|
||||
_ts_parser_included_ranges_wasm(address: number): void;
|
||||
|
||||
// Language
|
||||
_ts_language_symbol_count(address: number): number;
|
||||
_ts_language_symbol_name(address: number, index: number): number;
|
||||
_ts_language_symbol_type(address: number, index: number): number;
|
||||
_ts_language_field_count(address: number): number;
|
||||
_ts_language_field_name_for_id(address: number, id: number): number;
|
||||
_ts_language_name(address: number): number;
|
||||
_ts_language_version(address: number): number;
|
||||
_ts_language_state_count(address: number): number;
|
||||
_ts_language_symbol_for_name(address: number, typeAddress: number, typeLength: number, named: boolean): number;
|
||||
_ts_language_type_is_named_wasm(address: number, typeId: number): number;
|
||||
_ts_language_type_is_visible_wasm(address: number, typeId: number): number;
|
||||
_ts_language_next_state(address: number, stateId: number, typeId: number): number;
|
||||
_ts_language_supertypes_wasm(address: number): void;
|
||||
_ts_language_subtypes_wasm(address: number, supertype: number): void;
|
||||
|
||||
// Tree
|
||||
_ts_tree_copy(tree: number): number;
|
||||
_ts_tree_delete(tree: number): void;
|
||||
_ts_tree_edit_wasm(tree: number): void;
|
||||
_ts_tree_root_node_wasm(tree: number): void;
|
||||
_ts_tree_root_node_with_offset_wasm(tree: number): void;
|
||||
_ts_tree_get_changed_ranges_wasm(self: number, other: number): void;
|
||||
_ts_tree_included_ranges_wasm(self: number): void;
|
||||
|
||||
// Node
|
||||
_ts_node_symbol_wasm(tree: number): number;
|
||||
_ts_node_grammar_symbol_wasm(tree: number): number;
|
||||
_ts_node_end_point_wasm(tree: number): void;
|
||||
_ts_node_end_index_wasm(tree: number): number;
|
||||
_ts_node_parse_state_wasm(tree: number): number;
|
||||
_ts_node_next_parse_state_wasm(tree: number): number;
|
||||
_ts_node_is_named_wasm(tree: number): number;
|
||||
_ts_node_has_error_wasm(tree: number): number;
|
||||
_ts_node_has_changes_wasm(tree: number): number;
|
||||
_ts_node_is_error_wasm(tree: number): number;
|
||||
_ts_node_is_missing_wasm(tree: number): number;
|
||||
_ts_node_is_extra_wasm(tree: number): number;
|
||||
_ts_node_child_wasm(tree: number, index: number): void;
|
||||
_ts_node_named_child_wasm(tree: number, index: number): void;
|
||||
_ts_node_child_by_field_id_wasm(tree: number, fieldId: number): void;
|
||||
_ts_node_field_name_for_child_wasm(tree: number, index: number): number;
|
||||
_ts_node_field_name_for_named_child_wasm(tree: number, index: number): number;
|
||||
_ts_node_children_by_field_id_wasm(tree: number, fieldId: number): void;
|
||||
_ts_node_first_child_for_byte_wasm(tree: number): void;
|
||||
_ts_node_first_named_child_for_byte_wasm(tree: number): void;
|
||||
_ts_node_child_count_wasm(tree: number): number;
|
||||
_ts_node_named_child_count_wasm(tree: number): number;
|
||||
_ts_node_children_wasm(tree: number): void;
|
||||
_ts_node_named_children_wasm(tree: number): void;
|
||||
_ts_node_descendants_of_type_wasm(
|
||||
tree: number,
|
||||
symbolsAddress: number,
|
||||
symbolCount: number,
|
||||
startRow: number,
|
||||
startColumn: number,
|
||||
endRow: number,
|
||||
endColumn: number
|
||||
): void;
|
||||
_ts_node_next_sibling_wasm(tree: number): void;
|
||||
_ts_node_prev_sibling_wasm(tree: number): void;
|
||||
_ts_node_next_named_sibling_wasm(tree: number): void;
|
||||
_ts_node_prev_named_sibling_wasm(tree: number): void;
|
||||
_ts_node_descendant_count_wasm(tree: number): number;
|
||||
_ts_node_parent_wasm(tree: number): void;
|
||||
_ts_node_descendant_for_index_wasm(tree: number): void;
|
||||
_ts_node_named_descendant_for_index_wasm(tree: number): void;
|
||||
_ts_node_descendant_for_position_wasm(tree: number): void;
|
||||
_ts_node_named_descendant_for_position_wasm(tree: number): void;
|
||||
_ts_tree_cursor_new_wasm(tree: number): void;
|
||||
_ts_node_to_string_wasm(tree: number): number;
|
||||
|
||||
// TreeCursor
|
||||
_ts_tree_cursor_copy_wasm(cursor: number): void;
|
||||
_ts_tree_cursor_delete_wasm(cursor: number): void;
|
||||
_ts_tree_cursor_reset_wasm(cursor: number): void;
|
||||
_ts_tree_cursor_reset_to_wasm(cursor: number, other: number): void;
|
||||
_ts_tree_cursor_current_node_type_id_wasm(cursor: number): number;
|
||||
_ts_tree_cursor_current_node_state_id_wasm(cursor: number): number;
|
||||
_ts_tree_cursor_current_node_id_wasm(cursor: number): number;
|
||||
_ts_tree_cursor_current_node_is_named_wasm(cursor: number): number;
|
||||
_ts_tree_cursor_current_node_is_missing_wasm(cursor: number): number;
|
||||
_ts_tree_cursor_start_index_wasm(cursor: number): number;
|
||||
_ts_tree_cursor_end_index_wasm(cursor: number): number;
|
||||
_ts_tree_cursor_start_position_wasm(cursor: number): void;
|
||||
_ts_tree_cursor_end_position_wasm(cursor: number): void;
|
||||
_ts_tree_cursor_current_node_wasm(cursor: number): void;
|
||||
_ts_tree_cursor_current_field_id_wasm(cursor: number): number;
|
||||
_ts_tree_cursor_current_depth_wasm(cursor: number): number;
|
||||
_ts_tree_cursor_current_descendant_index_wasm(cursor: number): number;
|
||||
_ts_tree_cursor_goto_first_child_wasm(cursor: number): number;
|
||||
_ts_tree_cursor_goto_last_child_wasm(cursor: number): number;
|
||||
_ts_tree_cursor_goto_first_child_for_index_wasm(cursor: number): number;
|
||||
_ts_tree_cursor_goto_first_child_for_position_wasm(cursor: number): number;
|
||||
_ts_tree_cursor_goto_next_sibling_wasm(cursor: number): number;
|
||||
_ts_tree_cursor_goto_previous_sibling_wasm(cursor: number): number;
|
||||
_ts_tree_cursor_goto_descendant_wasm(cursor: number, index: number): void;
|
||||
_ts_tree_cursor_goto_parent_wasm(cursor: number): number;
|
||||
|
||||
// Query
|
||||
_ts_query_new(languageAddress: number, sourceAddress: number, sourceLength: number, errorOffset: number, errorType: number): number;
|
||||
_ts_query_string_count(address: number): number;
|
||||
_ts_query_capture_count(address: number): number;
|
||||
_ts_query_pattern_count(address: number): number;
|
||||
_ts_query_capture_name_for_id(address: number, id: number, buffer: number): number;
|
||||
_ts_query_capture_quantifier_for_id(address: number, patternId: number, captureId: number): CaptureQuantifier;
|
||||
_ts_query_string_value_for_id(address: number, id: number, buffer: number): number;
|
||||
_ts_query_predicates_for_pattern(address: number, patternId: number, buffer: number): number;
|
||||
_ts_query_delete(address: number): void;
|
||||
_ts_query_matches_wasm(
|
||||
address: number,
|
||||
treeAddress: number,
|
||||
startRow: number,
|
||||
startColumn: number,
|
||||
endRow: number,
|
||||
endColumn: number,
|
||||
startIndex: number,
|
||||
endIndex: number,
|
||||
matchLimit: number,
|
||||
maxStartDepth: number,
|
||||
timeoutMicros: number
|
||||
): void;
|
||||
_ts_query_captures_wasm(
|
||||
address: number,
|
||||
treeAddress: number,
|
||||
startRow: number,
|
||||
startColumn: number,
|
||||
endRow: number,
|
||||
endColumn: number,
|
||||
startIndex: number,
|
||||
endIndex: number,
|
||||
matchLimit: number,
|
||||
maxStartDepth: number,
|
||||
timeoutMicros: number
|
||||
): void;
|
||||
_ts_query_disable_capture(address: number, nameAddress: number, nameLength: number): void;
|
||||
_ts_query_disable_pattern(address: number, patternIndex: number): void;
|
||||
_ts_query_start_byte_for_pattern(address: number, patternIndex: number): number;
|
||||
_ts_query_end_byte_for_pattern(address: number, patternIndex: number): number;
|
||||
_ts_query_is_pattern_non_local(address: number, patternIndex: number): number;
|
||||
_ts_query_is_pattern_rooted(address: number, patternIndex: number): number;
|
||||
_ts_query_is_pattern_guaranteed_at_step(address: number, patternIndex: number, stepIndex: number): number;
|
||||
|
||||
// LookaheadIterator
|
||||
_ts_lookahead_iterator_new(address: number, stateId: number): number;
|
||||
_ts_lookahead_iterator_current_symbol(address: number): number;
|
||||
_ts_lookahead_iterator_delete(address: number): void;
|
||||
_ts_lookahead_iterator_reset_state(address: number, stateId: number): boolean;
|
||||
_ts_lookahead_iterator_reset(address: number, languageAddress: number, stateId: number): boolean;
|
||||
_ts_lookahead_iterator_next(address: number): boolean;
|
||||
|
||||
// @ts-expect-error Module is defined after compilation
|
||||
} = Module;
|
||||
export let C: MainModule;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
import { INTERNAL, Internal, assertInternal, SIZE_OF_INT, SIZE_OF_SHORT, C } from './constants';
|
||||
import { C, INTERNAL, Internal, assertInternal, SIZE_OF_INT, SIZE_OF_SHORT } from './constants';
|
||||
import { LookaheadIterator } from './lookahead_iterator';
|
||||
import { Node } from './node';
|
||||
import { TRANSFER_BUFFER } from './parser';
|
||||
import { CaptureQuantifier, Predicate, PredicateStep, Properties, Query, TextPredicate } from './query';
|
||||
|
||||
declare const loadWebAssemblyModule: (bytes: Uint8Array, options: { loadAsync: boolean }) => Promise<Record<string, () => number>>;
|
||||
|
||||
const PREDICATE_STEP_TYPE_CAPTURE = 1;
|
||||
const PREDICATE_STEP_TYPE_STRING = 2;
|
||||
|
||||
|
|
@ -23,14 +21,14 @@ export class Language {
|
|||
this.types = new Array<string>(C._ts_language_symbol_count(this[0]));
|
||||
for (let i = 0, n = this.types.length; i < n; i++) {
|
||||
if (C._ts_language_symbol_type(this[0], i) < 2) {
|
||||
this.types[i] = UTF8ToString(C._ts_language_symbol_name(this[0], i));
|
||||
this.types[i] = C.UTF8ToString(C._ts_language_symbol_name(this[0], i));
|
||||
}
|
||||
}
|
||||
this.fields = new Array<string>(C._ts_language_field_count(this[0]) + 1);
|
||||
for (let i = 0, n = this.fields.length; i < n; i++) {
|
||||
const fieldName = C._ts_language_field_name_for_id(this[0], i);
|
||||
if (fieldName !== 0) {
|
||||
this.fields[i] = UTF8ToString(fieldName);
|
||||
this.fields[i] = C.UTF8ToString(fieldName);
|
||||
} else {
|
||||
this.fields[i] = null;
|
||||
}
|
||||
|
|
@ -40,7 +38,7 @@ export class Language {
|
|||
get name(): string | null {
|
||||
const ptr = C._ts_language_name(this[0]);
|
||||
if (ptr === 0) return null;
|
||||
return UTF8ToString(ptr);
|
||||
return C.UTF8ToString(ptr);
|
||||
}
|
||||
|
||||
get version(): number {
|
||||
|
|
@ -65,10 +63,10 @@ export class Language {
|
|||
}
|
||||
|
||||
idForNodeType(type: string, named: boolean): number | null {
|
||||
const typeLength = lengthBytesUTF8(type);
|
||||
const typeLength = C.lengthBytesUTF8(type);
|
||||
const typeAddress = C._malloc(typeLength + 1);
|
||||
stringToUTF8(type, typeAddress, typeLength + 1);
|
||||
const result = C._ts_language_symbol_for_name(this[0], typeAddress, typeLength, named);
|
||||
C.stringToUTF8(type, typeAddress, typeLength + 1);
|
||||
const result = C._ts_language_symbol_for_name(this[0], typeAddress, typeLength, named ? 1 : 0);
|
||||
C._free(typeAddress);
|
||||
return result || null;
|
||||
}
|
||||
|
|
@ -79,7 +77,7 @@ export class Language {
|
|||
|
||||
nodeTypeForId(typeId: number): string | null {
|
||||
const name = C._ts_language_symbol_name(this[0], typeId);
|
||||
return name ? UTF8ToString(name) : null;
|
||||
return name ? C.UTF8ToString(name) : null;
|
||||
}
|
||||
|
||||
nodeTypeIsNamed(typeId: number): boolean {
|
||||
|
|
@ -92,14 +90,14 @@ export class Language {
|
|||
|
||||
get supertypes(): number[] {
|
||||
C._ts_language_supertypes_wasm(this[0]);
|
||||
const count = getValue(TRANSFER_BUFFER, 'i32');
|
||||
const buffer = getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const count = C.getValue(TRANSFER_BUFFER, 'i32');
|
||||
const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const result = new Array<number>(count);
|
||||
|
||||
if (count > 0) {
|
||||
let address = buffer;
|
||||
for (let i = 0; i < count; i++) {
|
||||
result[i] = getValue(address, 'i16');
|
||||
result[i] = C.getValue(address, 'i16');
|
||||
address += SIZE_OF_SHORT;
|
||||
}
|
||||
}
|
||||
|
|
@ -109,14 +107,14 @@ export class Language {
|
|||
|
||||
subtypes(supertype: number): number[] {
|
||||
C._ts_language_subtypes_wasm(this[0], supertype);
|
||||
const count = getValue(TRANSFER_BUFFER, 'i32');
|
||||
const buffer = getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const count = C.getValue(TRANSFER_BUFFER, 'i32');
|
||||
const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const result = new Array<number>(count);
|
||||
|
||||
if (count > 0) {
|
||||
let address = buffer;
|
||||
for (let i = 0; i < count; i++) {
|
||||
result[i] = getValue(address, 'i16');
|
||||
result[i] = C.getValue(address, 'i16');
|
||||
address += SIZE_OF_SHORT;
|
||||
}
|
||||
}
|
||||
|
|
@ -135,9 +133,9 @@ export class Language {
|
|||
}
|
||||
|
||||
query(source: string): Query {
|
||||
const sourceLength = lengthBytesUTF8(source);
|
||||
const sourceLength = C.lengthBytesUTF8(source);
|
||||
const sourceAddress = C._malloc(sourceLength + 1);
|
||||
stringToUTF8(source, sourceAddress, sourceLength + 1);
|
||||
C.stringToUTF8(source, sourceAddress, sourceLength + 1);
|
||||
const address = C._ts_query_new(
|
||||
this[0],
|
||||
sourceAddress,
|
||||
|
|
@ -147,9 +145,9 @@ export class Language {
|
|||
);
|
||||
|
||||
if (!address) {
|
||||
const errorId = getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const errorByte = getValue(TRANSFER_BUFFER, 'i32');
|
||||
const errorIndex = UTF8ToString(sourceAddress, errorByte).length;
|
||||
const errorId = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const errorByte = C.getValue(TRANSFER_BUFFER, 'i32');
|
||||
const errorIndex = C.UTF8ToString(sourceAddress, errorByte).length;
|
||||
const suffix = source.slice(errorIndex, errorIndex + 100).split('\n')[0];
|
||||
let word = suffix.match(QUERY_WORD_REGEX)?.[0] ?? '';
|
||||
let error: Error;
|
||||
|
|
@ -195,15 +193,15 @@ export class Language {
|
|||
i,
|
||||
TRANSFER_BUFFER
|
||||
);
|
||||
const nameLength = getValue(TRANSFER_BUFFER, 'i32');
|
||||
captureNames[i] = UTF8ToString(nameAddress, nameLength);
|
||||
const nameLength = C.getValue(TRANSFER_BUFFER, 'i32');
|
||||
captureNames[i] = C.UTF8ToString(nameAddress, nameLength);
|
||||
}
|
||||
|
||||
for (let i = 0; i < patternCount; i++) {
|
||||
const captureQuantifiersArray = new Array<CaptureQuantifier>(captureCount);
|
||||
for (let j = 0; j < captureCount; j++) {
|
||||
const quantifier = C._ts_query_capture_quantifier_for_id(address, i, j);
|
||||
captureQuantifiersArray[j] = quantifier;
|
||||
captureQuantifiersArray[j] = quantifier as CaptureQuantifier;
|
||||
}
|
||||
captureQuantifiers[i] = captureQuantifiersArray;
|
||||
}
|
||||
|
|
@ -214,8 +212,8 @@ export class Language {
|
|||
i,
|
||||
TRANSFER_BUFFER
|
||||
);
|
||||
const nameLength = getValue(TRANSFER_BUFFER, 'i32');
|
||||
stringValues[i] = UTF8ToString(valueAddress, nameLength);
|
||||
const nameLength = C.getValue(TRANSFER_BUFFER, 'i32');
|
||||
stringValues[i] = C.UTF8ToString(valueAddress, nameLength);
|
||||
}
|
||||
|
||||
const setProperties = new Array<Properties>(patternCount);
|
||||
|
|
@ -230,7 +228,7 @@ export class Language {
|
|||
i,
|
||||
TRANSFER_BUFFER
|
||||
);
|
||||
const stepCount = getValue(TRANSFER_BUFFER, 'i32');
|
||||
const stepCount = C.getValue(TRANSFER_BUFFER, 'i32');
|
||||
|
||||
predicates[i] = [];
|
||||
textPredicates[i] = [];
|
||||
|
|
@ -238,9 +236,9 @@ export class Language {
|
|||
const steps: PredicateStep[] = [];
|
||||
let stepAddress = predicatesAddress;
|
||||
for (let j = 0; j < stepCount; j++) {
|
||||
const stepType = getValue(stepAddress, 'i32');
|
||||
const stepType = C.getValue(stepAddress, 'i32');
|
||||
stepAddress += SIZE_OF_INT;
|
||||
const stepValueId: number = getValue(stepAddress, 'i32');
|
||||
const stepValueId: number = C.getValue(stepAddress, 'i32');
|
||||
stepAddress += SIZE_OF_INT;
|
||||
|
||||
if (stepType === PREDICATE_STEP_TYPE_CAPTURE) {
|
||||
|
|
@ -469,7 +467,7 @@ export class Language {
|
|||
}
|
||||
}
|
||||
|
||||
const mod = await loadWebAssemblyModule(await bytes, { loadAsync: true });
|
||||
const mod = await C.loadWebAssemblyModule(await bytes, { loadAsync: true });
|
||||
const symbolNames = Object.keys(mod);
|
||||
const functionName = symbolNames.find((key) => LANGUAGE_FUNCTION_REGEX.test(key) &&
|
||||
!key.includes('external_scanner_'));
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Edit, INTERNAL, Point, Range, SIZE_OF_INT, SIZE_OF_NODE, SIZE_OF_POINT } from "./constants";
|
||||
import { Edit, INTERNAL, Point, Range, SIZE_OF_INT, SIZE_OF_NODE, SIZE_OF_POINT, C } from "./constants";
|
||||
import { Node } from "./node";
|
||||
import { Tree } from "./tree";
|
||||
import { Query } from "./query";
|
||||
|
|
@ -7,7 +7,7 @@ import { TRANSFER_BUFFER } from "./parser";
|
|||
|
||||
export function unmarshalCaptures(query: Query, tree: Tree, address: number, result: {name: string, node: Node}[]) {
|
||||
for (let i = 0, n = result.length; i < n; i++) {
|
||||
const captureIndex = getValue(address, 'i32');
|
||||
const captureIndex = C.getValue(address, 'i32');
|
||||
address += SIZE_OF_INT;
|
||||
const node = unmarshalNode(tree, address)!;
|
||||
address += SIZE_OF_NODE;
|
||||
|
|
@ -18,29 +18,29 @@ export function unmarshalCaptures(query: Query, tree: Tree, address: number, res
|
|||
|
||||
export function marshalNode(node: Node) {
|
||||
let address = TRANSFER_BUFFER;
|
||||
setValue(address, node.id, 'i32');
|
||||
C.setValue(address, node.id, 'i32');
|
||||
address += SIZE_OF_INT;
|
||||
setValue(address, node.startIndex, 'i32');
|
||||
C.setValue(address, node.startIndex, 'i32');
|
||||
address += SIZE_OF_INT;
|
||||
setValue(address, node.startPosition.row, 'i32');
|
||||
C.setValue(address, node.startPosition.row, 'i32');
|
||||
address += SIZE_OF_INT;
|
||||
setValue(address, node.startPosition.column, 'i32');
|
||||
C.setValue(address, node.startPosition.column, 'i32');
|
||||
address += SIZE_OF_INT;
|
||||
setValue(address, node[0], 'i32');
|
||||
C.setValue(address, node[0], 'i32');
|
||||
}
|
||||
|
||||
export function unmarshalNode(tree: Tree, address = TRANSFER_BUFFER): Node | null {
|
||||
const id = getValue(address, 'i32');
|
||||
const id = C.getValue(address, 'i32');
|
||||
address += SIZE_OF_INT;
|
||||
if (id === 0) return null;
|
||||
|
||||
const index = getValue(address, 'i32');
|
||||
const index = C.getValue(address, 'i32');
|
||||
address += SIZE_OF_INT;
|
||||
const row = getValue(address, 'i32');
|
||||
const row = C.getValue(address, 'i32');
|
||||
address += SIZE_OF_INT;
|
||||
const column = getValue(address, 'i32');
|
||||
const column = C.getValue(address, 'i32');
|
||||
address += SIZE_OF_INT;
|
||||
const other = getValue(address, 'i32');
|
||||
const other = C.getValue(address, 'i32');
|
||||
|
||||
const result = new Node(INTERNAL, {
|
||||
id,
|
||||
|
|
@ -54,28 +54,28 @@ export function unmarshalNode(tree: Tree, address = TRANSFER_BUFFER): Node | nul
|
|||
}
|
||||
|
||||
export function marshalTreeCursor(cursor: TreeCursor, address = TRANSFER_BUFFER) {
|
||||
setValue(address + 0 * SIZE_OF_INT, cursor[0], 'i32');
|
||||
setValue(address + 1 * SIZE_OF_INT, cursor[1], 'i32');
|
||||
setValue(address + 2 * SIZE_OF_INT, cursor[2], 'i32');
|
||||
setValue(address + 3 * SIZE_OF_INT, cursor[3], 'i32');
|
||||
C.setValue(address + 0 * SIZE_OF_INT, cursor[0], 'i32');
|
||||
C.setValue(address + 1 * SIZE_OF_INT, cursor[1], 'i32');
|
||||
C.setValue(address + 2 * SIZE_OF_INT, cursor[2], 'i32');
|
||||
C.setValue(address + 3 * SIZE_OF_INT, cursor[3], 'i32');
|
||||
}
|
||||
|
||||
export function unmarshalTreeCursor(cursor: TreeCursor) {
|
||||
cursor[0] = getValue(TRANSFER_BUFFER + 0 * SIZE_OF_INT, 'i32');
|
||||
cursor[1] = getValue(TRANSFER_BUFFER + 1 * SIZE_OF_INT, 'i32');
|
||||
cursor[2] = getValue(TRANSFER_BUFFER + 2 * SIZE_OF_INT, 'i32');
|
||||
cursor[3] = getValue(TRANSFER_BUFFER + 3 * SIZE_OF_INT, 'i32');
|
||||
cursor[0] = C.getValue(TRANSFER_BUFFER + 0 * SIZE_OF_INT, 'i32');
|
||||
cursor[1] = C.getValue(TRANSFER_BUFFER + 1 * SIZE_OF_INT, 'i32');
|
||||
cursor[2] = C.getValue(TRANSFER_BUFFER + 2 * SIZE_OF_INT, 'i32');
|
||||
cursor[3] = C.getValue(TRANSFER_BUFFER + 3 * SIZE_OF_INT, 'i32');
|
||||
}
|
||||
|
||||
export function marshalPoint(address: number, point: Point): void {
|
||||
setValue(address, point.row, 'i32');
|
||||
setValue(address + SIZE_OF_INT, point.column, 'i32');
|
||||
C.setValue(address, point.row, 'i32');
|
||||
C.setValue(address + SIZE_OF_INT, point.column, 'i32');
|
||||
}
|
||||
|
||||
export function unmarshalPoint(address: number): Point {
|
||||
const result = {
|
||||
row: getValue(address, 'i32') >>> 0,
|
||||
column: getValue(address + SIZE_OF_INT, 'i32') >>> 0,
|
||||
row: C.getValue(address, 'i32') >>> 0,
|
||||
column: C.getValue(address + SIZE_OF_INT, 'i32') >>> 0,
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
|
@ -83,16 +83,16 @@ export function unmarshalPoint(address: number): Point {
|
|||
export function marshalRange(address: number, range: Range): void {
|
||||
marshalPoint(address, range.startPosition); address += SIZE_OF_POINT;
|
||||
marshalPoint(address, range.endPosition); address += SIZE_OF_POINT;
|
||||
setValue(address, range.startIndex, 'i32'); address += SIZE_OF_INT;
|
||||
setValue(address, range.endIndex, 'i32'); address += SIZE_OF_INT;
|
||||
C.setValue(address, range.startIndex, 'i32'); address += SIZE_OF_INT;
|
||||
C.setValue(address, range.endIndex, 'i32'); address += SIZE_OF_INT;
|
||||
}
|
||||
|
||||
export function unmarshalRange(address: number): Range {
|
||||
const result = {} as Range;
|
||||
result.startPosition = unmarshalPoint(address); address += SIZE_OF_POINT;
|
||||
result.endPosition = unmarshalPoint(address); address += SIZE_OF_POINT;
|
||||
result.startIndex = getValue(address, 'i32') >>> 0; address += SIZE_OF_INT;
|
||||
result.endIndex = getValue(address, 'i32') >>> 0;
|
||||
result.startIndex = C.getValue(address, 'i32') >>> 0; address += SIZE_OF_INT;
|
||||
result.endIndex = C.getValue(address, 'i32') >>> 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ export function marshalEdit(edit: Edit, address = TRANSFER_BUFFER) {
|
|||
marshalPoint(address, edit.startPosition); address += SIZE_OF_POINT;
|
||||
marshalPoint(address, edit.oldEndPosition); address += SIZE_OF_POINT;
|
||||
marshalPoint(address, edit.newEndPosition); address += SIZE_OF_POINT;
|
||||
setValue(address, edit.startIndex, 'i32'); address += SIZE_OF_INT;
|
||||
setValue(address, edit.oldEndIndex, 'i32'); address += SIZE_OF_INT;
|
||||
setValue(address, edit.newEndIndex, 'i32'); address += SIZE_OF_INT;
|
||||
C.setValue(address, edit.startIndex, 'i32'); address += SIZE_OF_INT;
|
||||
C.setValue(address, edit.oldEndIndex, 'i32'); address += SIZE_OF_INT;
|
||||
C.setValue(address, edit.newEndIndex, 'i32'); address += SIZE_OF_INT;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@ import { TreeCursor } from './tree_cursor';
|
|||
import { marshalNode, marshalPoint, unmarshalNode, unmarshalPoint } from './marshal';
|
||||
import { TRANSFER_BUFFER } from './parser';
|
||||
|
||||
declare const AsciiToString: (ptr: number) => string;
|
||||
|
||||
export class Node {
|
||||
private [0]: number; // Internal handle for WASM
|
||||
private _children?: (Node | null)[];
|
||||
|
|
@ -145,14 +143,14 @@ export class Node {
|
|||
marshalNode(this);
|
||||
const address = C._ts_node_field_name_for_child_wasm(this.tree[0], index);
|
||||
if (!address) return null;
|
||||
return AsciiToString(address);
|
||||
return C.AsciiToString(address);
|
||||
}
|
||||
|
||||
fieldNameForNamedChild(index: number): string | null {
|
||||
marshalNode(this);
|
||||
const address = C._ts_node_field_name_for_named_child_wasm(this.tree[0], index);
|
||||
if (!address) return null;
|
||||
return AsciiToString(address);
|
||||
return C.AsciiToString(address);
|
||||
}
|
||||
|
||||
childrenForFieldName(fieldName: string): (Node | null)[] {
|
||||
|
|
@ -164,8 +162,8 @@ export class Node {
|
|||
childrenForFieldId(fieldId: number): (Node | null)[] {
|
||||
marshalNode(this);
|
||||
C._ts_node_children_by_field_id_wasm(this.tree[0], fieldId);
|
||||
const count = getValue(TRANSFER_BUFFER, 'i32');
|
||||
const buffer = getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const count = C.getValue(TRANSFER_BUFFER, 'i32');
|
||||
const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const result = new Array<Node | null>(count);
|
||||
|
||||
if (count > 0) {
|
||||
|
|
@ -182,7 +180,7 @@ export class Node {
|
|||
firstChildForIndex(index: number): Node | null {
|
||||
marshalNode(this);
|
||||
const address = TRANSFER_BUFFER + SIZE_OF_NODE;
|
||||
setValue(address, index, 'i32');
|
||||
C.setValue(address, index, 'i32');
|
||||
C._ts_node_first_child_for_byte_wasm(this.tree[0]);
|
||||
return unmarshalNode(this.tree);
|
||||
}
|
||||
|
|
@ -190,7 +188,7 @@ export class Node {
|
|||
firstNamedChildForIndex(index: number): Node | null {
|
||||
marshalNode(this);
|
||||
const address = TRANSFER_BUFFER + SIZE_OF_NODE;
|
||||
setValue(address, index, 'i32');
|
||||
C.setValue(address, index, 'i32');
|
||||
C._ts_node_first_named_child_for_byte_wasm(this.tree[0]);
|
||||
return unmarshalNode(this.tree);
|
||||
}
|
||||
|
|
@ -225,8 +223,8 @@ export class Node {
|
|||
if (!this._children) {
|
||||
marshalNode(this);
|
||||
C._ts_node_children_wasm(this.tree[0]);
|
||||
const count = getValue(TRANSFER_BUFFER, 'i32');
|
||||
const buffer = getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const count = C.getValue(TRANSFER_BUFFER, 'i32');
|
||||
const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
this._children = new Array<Node>(count);
|
||||
if (count > 0) {
|
||||
let address = buffer;
|
||||
|
|
@ -244,8 +242,8 @@ export class Node {
|
|||
if (!this._namedChildren) {
|
||||
marshalNode(this);
|
||||
C._ts_node_named_children_wasm(this.tree[0]);
|
||||
const count = getValue(TRANSFER_BUFFER, 'i32');
|
||||
const buffer = getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const count = C.getValue(TRANSFER_BUFFER, 'i32');
|
||||
const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
this._namedChildren = new Array<Node>(count);
|
||||
if (count > 0) {
|
||||
let address = buffer;
|
||||
|
|
@ -278,7 +276,7 @@ export class Node {
|
|||
// Copy the array of symbols to the WASM heap
|
||||
const symbolsAddress = C._malloc(SIZE_OF_INT * symbols.length);
|
||||
for (let i = 0, n = symbols.length; i < n; i++) {
|
||||
setValue(symbolsAddress + i * SIZE_OF_INT, symbols[i], 'i32');
|
||||
C.setValue(symbolsAddress + i * SIZE_OF_INT, symbols[i], 'i32');
|
||||
}
|
||||
|
||||
// Call the C API to compute the descendants
|
||||
|
|
@ -294,8 +292,8 @@ export class Node {
|
|||
);
|
||||
|
||||
// Instantiate the nodes based on the data returned
|
||||
const descendantCount = getValue(TRANSFER_BUFFER, 'i32');
|
||||
const descendantAddress = getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const descendantCount = C.getValue(TRANSFER_BUFFER, 'i32');
|
||||
const descendantAddress = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const result = new Array<Node | null>(descendantCount);
|
||||
if (descendantCount > 0) {
|
||||
let address = descendantAddress;
|
||||
|
|
@ -353,8 +351,8 @@ export class Node {
|
|||
|
||||
marshalNode(this);
|
||||
const address = TRANSFER_BUFFER + SIZE_OF_NODE;
|
||||
setValue(address, start, 'i32');
|
||||
setValue(address + SIZE_OF_INT, end, 'i32');
|
||||
C.setValue(address, start, 'i32');
|
||||
C.setValue(address + SIZE_OF_INT, end, 'i32');
|
||||
C._ts_node_descendant_for_index_wasm(this.tree[0]);
|
||||
return unmarshalNode(this.tree);
|
||||
}
|
||||
|
|
@ -366,8 +364,8 @@ export class Node {
|
|||
|
||||
marshalNode(this);
|
||||
const address = TRANSFER_BUFFER + SIZE_OF_NODE;
|
||||
setValue(address, start, 'i32');
|
||||
setValue(address + SIZE_OF_INT, end, 'i32');
|
||||
C.setValue(address, start, 'i32');
|
||||
C.setValue(address + SIZE_OF_INT, end, 'i32');
|
||||
C._ts_node_named_descendant_for_index_wasm(this.tree[0]);
|
||||
return unmarshalNode(this.tree);
|
||||
}
|
||||
|
|
@ -437,7 +435,7 @@ export class Node {
|
|||
toString() {
|
||||
marshalNode(this);
|
||||
const address = C._ts_node_to_string_wasm(this.tree[0]);
|
||||
const result = AsciiToString(address);
|
||||
const result = C.AsciiToString(address);
|
||||
C._free(address);
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { C, INTERNAL, Point, Range, SIZE_OF_INT, SIZE_OF_RANGE } from './constants';
|
||||
import { C, INTERNAL, Point, Range, SIZE_OF_INT, SIZE_OF_RANGE, setModule } from './constants';
|
||||
import { Language } from './language';
|
||||
import { marshalRange, unmarshalRange } from './marshal';
|
||||
import { checkModule, initializeBinding } from './bindings';
|
||||
import { Tree } from './tree';
|
||||
|
||||
interface ParseOptions {
|
||||
|
|
@ -17,29 +18,38 @@ export let TRANSFER_BUFFER: number;
|
|||
let VERSION: number;
|
||||
let MIN_COMPATIBLE_VERSION: number;
|
||||
|
||||
let currentParseCallback: ((index: number, position: Point) => string) | null = null;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
let currentLogCallback: LogCallback = null;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
let currentProgressCallback: ((percent: number) => void) | null = null;
|
||||
// declare let currentParseCallback: ((index: number, position: Point) => string) | null;
|
||||
// // eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
// declare let currentLogCallback: LogCallback;
|
||||
// // eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
// declare let currentProgressCallback: ((percent: number) => void) | null;
|
||||
|
||||
export class ParserImpl {
|
||||
export class Parser {
|
||||
protected [0] = 0;
|
||||
protected [1] = 0;
|
||||
protected language: Language | null = null;
|
||||
protected logCallback: LogCallback = null;
|
||||
static Language: typeof Language;
|
||||
|
||||
static init() {
|
||||
// This must always be called before creating a Parser.
|
||||
static async init(moduleOptions: EmscriptenModule) {
|
||||
setModule(await initializeBinding(moduleOptions));
|
||||
TRANSFER_BUFFER = C._ts_init();
|
||||
VERSION = getValue(TRANSFER_BUFFER, 'i32');
|
||||
MIN_COMPATIBLE_VERSION = getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
VERSION = C.getValue(TRANSFER_BUFFER, 'i32');
|
||||
MIN_COMPATIBLE_VERSION = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
initialize() {
|
||||
if (!checkModule()) {
|
||||
throw new Error("cannot construct a Parser before calling `init()`");
|
||||
}
|
||||
C._ts_parser_new_wasm();
|
||||
this[0] = getValue(TRANSFER_BUFFER, 'i32');
|
||||
this[1] = getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
this[0] = C.getValue(TRANSFER_BUFFER, 'i32');
|
||||
this[1] = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
}
|
||||
|
||||
delete() {
|
||||
|
|
@ -82,24 +92,24 @@ export class ParserImpl {
|
|||
options: ParseOptions = {}
|
||||
): Tree {
|
||||
if (typeof callback === 'string') {
|
||||
currentParseCallback = (index: number) => callback.slice(index);
|
||||
C.currentParseCallback = (index: number) => callback.slice(index);
|
||||
} else if (typeof callback === 'function') {
|
||||
currentParseCallback = callback;
|
||||
C.currentParseCallback = callback;
|
||||
} else {
|
||||
throw new Error('Argument must be a string or a function');
|
||||
}
|
||||
|
||||
if (options.progressCallback) {
|
||||
currentProgressCallback = options.progressCallback;
|
||||
C.currentProgressCallback = options.progressCallback;
|
||||
} else {
|
||||
currentProgressCallback = null;
|
||||
C.currentProgressCallback = null;
|
||||
}
|
||||
|
||||
if (this.logCallback) {
|
||||
currentLogCallback = this.logCallback;
|
||||
C.currentLogCallback = this.logCallback;
|
||||
C._ts_parser_enable_logger_wasm(this[0], 1);
|
||||
} else {
|
||||
currentLogCallback = null;
|
||||
C.currentLogCallback = null;
|
||||
C._ts_parser_enable_logger_wasm(this[0], 0);
|
||||
}
|
||||
|
||||
|
|
@ -124,9 +134,9 @@ export class ParserImpl {
|
|||
);
|
||||
|
||||
if (!treeAddress) {
|
||||
currentParseCallback = null;
|
||||
currentLogCallback = null;
|
||||
currentProgressCallback = null;
|
||||
C.currentParseCallback = null;
|
||||
C.currentLogCallback = null;
|
||||
C.currentProgressCallback = null;
|
||||
throw new Error('Parsing failed');
|
||||
}
|
||||
|
||||
|
|
@ -134,10 +144,10 @@ export class ParserImpl {
|
|||
throw new Error('Parser must have a language to parse');
|
||||
}
|
||||
|
||||
const result = new Tree(INTERNAL, treeAddress, this.language, currentParseCallback);
|
||||
currentParseCallback = null;
|
||||
currentLogCallback = null;
|
||||
currentProgressCallback = null;
|
||||
const result = new Tree(INTERNAL, treeAddress, this.language, C.currentParseCallback);
|
||||
C.currentParseCallback = null;
|
||||
C.currentLogCallback = null;
|
||||
C.currentProgressCallback = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -147,8 +157,8 @@ export class ParserImpl {
|
|||
|
||||
getIncludedRanges(): Range[] {
|
||||
C._ts_parser_included_ranges_wasm(this[0]);
|
||||
const count = getValue(TRANSFER_BUFFER, 'i32');
|
||||
const buffer = getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const count = C.getValue(TRANSFER_BUFFER, 'i32');
|
||||
const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const result = new Array<Range>(count);
|
||||
|
||||
if (count > 0) {
|
||||
|
|
@ -168,7 +178,7 @@ export class ParserImpl {
|
|||
}
|
||||
|
||||
setTimeoutMicros(timeout: number): void {
|
||||
C._ts_parser_set_timeout_micros(this[0], timeout);
|
||||
C._ts_parser_set_timeout_micros(this[0], 0, timeout);
|
||||
}
|
||||
|
||||
setLogger(callback: LogCallback): this {
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@ import { Node } from './node';
|
|||
import { marshalNode, unmarshalCaptures } from './marshal';
|
||||
import { TRANSFER_BUFFER } from './parser';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
let currentQueryProgressCallback: ((percent: number) => void) | null = null;
|
||||
// let currentQueryProgressCallback: ((percent: number) => void) | null = null;
|
||||
|
||||
interface QueryOptions {
|
||||
startPosition?: Point;
|
||||
|
|
@ -127,7 +126,7 @@ export class Query {
|
|||
}
|
||||
|
||||
if (progressCallback) {
|
||||
currentQueryProgressCallback = progressCallback;
|
||||
C.currentQueryProgressCallback = progressCallback;
|
||||
}
|
||||
|
||||
marshalNode(node);
|
||||
|
|
@ -146,18 +145,18 @@ export class Query {
|
|||
timeoutMicros,
|
||||
);
|
||||
|
||||
const rawCount = getValue(TRANSFER_BUFFER, 'i32');
|
||||
const startAddress = getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const didExceedMatchLimit = getValue(TRANSFER_BUFFER + 2 * SIZE_OF_INT, 'i32');
|
||||
const rawCount = C.getValue(TRANSFER_BUFFER, 'i32');
|
||||
const startAddress = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const didExceedMatchLimit = C.getValue(TRANSFER_BUFFER + 2 * SIZE_OF_INT, 'i32');
|
||||
const result = new Array<QueryMatch>(rawCount);
|
||||
this.exceededMatchLimit = Boolean(didExceedMatchLimit);
|
||||
|
||||
let filteredCount = 0;
|
||||
let address = startAddress;
|
||||
for (let i = 0; i < rawCount; i++) {
|
||||
const pattern = getValue(address, 'i32');
|
||||
const pattern = C.getValue(address, 'i32');
|
||||
address += SIZE_OF_INT;
|
||||
const captureCount = getValue(address, 'i32');
|
||||
const captureCount = C.getValue(address, 'i32');
|
||||
address += SIZE_OF_INT;
|
||||
|
||||
const captures = new Array<Capture>(captureCount);
|
||||
|
|
@ -177,7 +176,7 @@ export class Query {
|
|||
result.length = filteredCount;
|
||||
|
||||
C._free(startAddress);
|
||||
currentQueryProgressCallback = null;
|
||||
C.currentQueryProgressCallback = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -211,7 +210,7 @@ export class Query {
|
|||
}
|
||||
|
||||
if (progressCallback) {
|
||||
currentQueryProgressCallback = progressCallback;
|
||||
C.currentQueryProgressCallback = progressCallback;
|
||||
}
|
||||
|
||||
marshalNode(node);
|
||||
|
|
@ -230,20 +229,20 @@ export class Query {
|
|||
timeoutMicros,
|
||||
);
|
||||
|
||||
const count = getValue(TRANSFER_BUFFER, 'i32');
|
||||
const startAddress = getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const didExceedMatchLimit = getValue(TRANSFER_BUFFER + 2 * SIZE_OF_INT, 'i32');
|
||||
const count = C.getValue(TRANSFER_BUFFER, 'i32');
|
||||
const startAddress = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const didExceedMatchLimit = C.getValue(TRANSFER_BUFFER + 2 * SIZE_OF_INT, 'i32');
|
||||
const result: Capture[] = [];
|
||||
this.exceededMatchLimit = Boolean(didExceedMatchLimit);
|
||||
|
||||
const captures: Capture[] = [];
|
||||
let address = startAddress;
|
||||
for (let i = 0; i < count; i++) {
|
||||
const pattern = getValue(address, 'i32');
|
||||
const pattern = C.getValue(address, 'i32');
|
||||
address += SIZE_OF_INT;
|
||||
const captureCount = getValue(address, 'i32');
|
||||
const captureCount = C.getValue(address, 'i32');
|
||||
address += SIZE_OF_INT;
|
||||
const captureIndex = getValue(address, 'i32');
|
||||
const captureIndex = C.getValue(address, 'i32');
|
||||
address += SIZE_OF_INT;
|
||||
|
||||
captures.length = captureCount;
|
||||
|
|
@ -262,7 +261,7 @@ export class Query {
|
|||
}
|
||||
|
||||
C._free(startAddress);
|
||||
currentQueryProgressCallback = null;
|
||||
C.currentQueryProgressCallback = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -271,9 +270,9 @@ export class Query {
|
|||
}
|
||||
|
||||
disableCapture(captureName: string): void {
|
||||
const captureNameLength = lengthBytesUTF8(captureName);
|
||||
const captureNameLength = C.lengthBytesUTF8(captureName);
|
||||
const captureNameAddress = C._malloc(captureNameLength + 1);
|
||||
stringToUTF8(captureName, captureNameAddress, captureNameLength + 1);
|
||||
C.stringToUTF8(captureName, captureNameAddress, captureNameLength + 1);
|
||||
C._ts_query_disable_capture(this[0], captureNameAddress, captureNameLength);
|
||||
C._free(captureNameAddress);
|
||||
}
|
||||
|
|
@ -317,11 +316,7 @@ export class Query {
|
|||
return C._ts_query_is_pattern_rooted(this[0], patternIndex) === 1;
|
||||
}
|
||||
|
||||
isPatternGuaranteedAtStep(patternIndex: number, stepIndex: number): boolean {
|
||||
return C._ts_query_is_pattern_guaranteed_at_step(
|
||||
this[0],
|
||||
patternIndex,
|
||||
stepIndex
|
||||
) === 1;
|
||||
isPatternGuaranteedAtStep(byteIndex: number): boolean {
|
||||
return C._ts_query_is_pattern_guaranteed_at_step(this[0], byteIndex) === 1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ export class Tree {
|
|||
|
||||
rootNodeWithOffset(offsetBytes: number, offsetExtent: Point): Node {
|
||||
const address = TRANSFER_BUFFER + SIZE_OF_NODE;
|
||||
setValue(address, offsetBytes, 'i32');
|
||||
C.setValue(address, offsetBytes, 'i32');
|
||||
marshalPoint(address + SIZE_OF_INT, offsetExtent);
|
||||
C._ts_tree_root_node_with_offset_wasm(this[0]);
|
||||
return unmarshalNode(this)!;
|
||||
|
|
@ -81,8 +81,8 @@ export class Tree {
|
|||
}
|
||||
|
||||
C._ts_tree_get_changed_ranges_wasm(this[0], other[0]);
|
||||
const count = getValue(TRANSFER_BUFFER, 'i32');
|
||||
const buffer = getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const count = C.getValue(TRANSFER_BUFFER, 'i32');
|
||||
const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const result = new Array<Range>(count);
|
||||
|
||||
if (count > 0) {
|
||||
|
|
@ -98,8 +98,8 @@ export class Tree {
|
|||
|
||||
getIncludedRanges(): Range[] {
|
||||
C._ts_tree_included_ranges_wasm(this[0]);
|
||||
const count = getValue(TRANSFER_BUFFER, 'i32');
|
||||
const buffer = getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const count = C.getValue(TRANSFER_BUFFER, 'i32');
|
||||
const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const result = new Array<Range>(count);
|
||||
|
||||
if (count > 0) {
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ export class TreeCursor {
|
|||
|
||||
gotoFirstChildForIndex(goalIndex: number): boolean {
|
||||
marshalTreeCursor(this);
|
||||
setValue(TRANSFER_BUFFER + SIZE_OF_CURSOR, goalIndex, 'i32');
|
||||
C.setValue(TRANSFER_BUFFER + SIZE_OF_CURSOR, goalIndex, 'i32');
|
||||
const result = C._ts_tree_cursor_goto_first_child_for_index_wasm(this.tree[0]);
|
||||
unmarshalTreeCursor(this);
|
||||
return result === 1;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
import type { default as ParserType } from 'web-tree-sitter';
|
||||
import { type Parser as ParserType, type Language as LanguageType } from '../src';
|
||||
import path from 'path';
|
||||
|
||||
// @ts-expect-error We're intentionally importing ../tree-sitter.js
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
|
||||
const Parser: typeof ParserType = await import('..').then(m => m.default);
|
||||
import { Parser as ParserImpl, Language as LanguageImpl } from '..';
|
||||
|
||||
const Parser = ParserImpl as typeof ParserType;
|
||||
const Language = LanguageImpl as typeof LanguageType;
|
||||
|
||||
// https://github.com/tree-sitter/tree-sitter/blob/master/xtask/src/fetch.rs#L15
|
||||
export type LanguageName = 'bash' | 'c' | 'cpp' | 'embedded-template' | 'go' | 'html' | 'java' | 'javascript' | 'jsdoc' | 'json' | 'php' | 'python' | 'ruby' | 'rust' | 'typescript' | 'tsx';
|
||||
|
|
@ -15,12 +17,13 @@ function languageURL(name: LanguageName): string {
|
|||
|
||||
export default Parser.init().then(async () => ({
|
||||
Parser,
|
||||
Language,
|
||||
languageURL,
|
||||
C: await Parser.Language.load(languageURL('c')),
|
||||
EmbeddedTemplate: await Parser.Language.load(languageURL('embedded-template')),
|
||||
HTML: await Parser.Language.load(languageURL('html')),
|
||||
JavaScript: await Parser.Language.load(languageURL('javascript')),
|
||||
JSON: await Parser.Language.load(languageURL('json')),
|
||||
Python: await Parser.Language.load(languageURL('python')),
|
||||
Rust: await Parser.Language.load(languageURL('rust')),
|
||||
C: await Language.load(languageURL('c')),
|
||||
EmbeddedTemplate: await Language.load(languageURL('embedded-template')),
|
||||
HTML: await Language.load(languageURL('html')),
|
||||
JavaScript: await Language.load(languageURL('javascript')),
|
||||
JSON: await Language.load(languageURL('json')),
|
||||
Python: await Language.load(languageURL('python')),
|
||||
Rust: await Language.load(languageURL('rust')),
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
||||
import helper from './helper';
|
||||
import type { default as ParserType, LookaheadIterable, Language } from 'web-tree-sitter';
|
||||
import type { Parser as ParserType, LookaheadIterator, Language } from '../src';
|
||||
|
||||
let Parser: typeof ParserType;
|
||||
let JavaScript: Language;
|
||||
let Rust: Language;
|
||||
|
||||
|
|
@ -35,8 +36,8 @@ describe('Language', () => {
|
|||
|
||||
describe('.idForNodeType, .nodeTypeForId, .nodeTypeIsNamed', () => {
|
||||
it('converts between the string and integer representations of a node type', () => {
|
||||
const exportStatementId = JavaScript.idForNodeType('export_statement', true);
|
||||
const starId = JavaScript.idForNodeType('*', false);
|
||||
const exportStatementId = JavaScript.idForNodeType('export_statement', true)!;
|
||||
const starId = JavaScript.idForNodeType('*', false)!;
|
||||
|
||||
expect(exportStatementId).toBeLessThan(JavaScript.nodeTypeCount);
|
||||
expect(starId).toBeLessThan(JavaScript.nodeTypeCount);
|
||||
|
|
@ -131,12 +132,11 @@ describe('Language', () => {
|
|||
});
|
||||
|
||||
describe('Lookahead iterator', () => {
|
||||
let lookahead: LookaheadIterable;
|
||||
let lookahead: LookaheadIterator;
|
||||
let state: number;
|
||||
|
||||
beforeAll(async () => {
|
||||
let Parser: typeof ParserType;
|
||||
({ JavaScript, Parser } = await helper);
|
||||
({ Parser, JavaScript } = await helper);
|
||||
const parser = new Parser();
|
||||
parser.setLanguage(JavaScript);
|
||||
const tree = parser.parse('function fn() {}');
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, it, expect, beforeAll, beforeEach, afterEach } from 'vitest';
|
||||
import type { default as ParserType, Language, Tree, SyntaxNode } from 'web-tree-sitter';
|
||||
import type { Parser as ParserType, Language, Tree, Node } from '../src';
|
||||
import helper from './helper';
|
||||
|
||||
let Parser: typeof ParserType;
|
||||
|
|
@ -19,8 +19,8 @@ const JSON_EXAMPLE = `
|
|||
]
|
||||
`;
|
||||
|
||||
function getAllNodes(tree: Tree): SyntaxNode[] {
|
||||
const result: SyntaxNode[] = [];
|
||||
function getAllNodes(tree: Tree): Node[] {
|
||||
const result: Node[] = [];
|
||||
let visitedChildren = false;
|
||||
const cursor = tree.walk();
|
||||
|
||||
|
|
@ -55,15 +55,15 @@ describe('Node', () => {
|
|||
|
||||
afterEach(() => {
|
||||
parser.delete();
|
||||
tree!.delete();
|
||||
tree?.delete();
|
||||
});
|
||||
|
||||
describe('.children', () => {
|
||||
it('returns an array of child nodes', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
expect(tree.rootNode.children).toHaveLength(1);
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
expect(sumNode!.children.map(child => child.type)).toEqual([
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
expect(sumNode?.children.map(child => child?.type)).toEqual([
|
||||
'identifier',
|
||||
'+',
|
||||
'number'
|
||||
|
|
@ -74,9 +74,9 @@ describe('Node', () => {
|
|||
describe('.namedChildren', () => {
|
||||
it('returns an array of named child nodes', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
expect(tree.rootNode.namedChildren).toHaveLength(1);
|
||||
expect(sumNode!.namedChildren.map(child => child.type)).toEqual([
|
||||
expect(sumNode?.namedChildren.map(child => child?.type)).toEqual([
|
||||
'identifier',
|
||||
'number'
|
||||
]);
|
||||
|
|
@ -98,11 +98,11 @@ describe('Node', () => {
|
|||
|
||||
tree = parser.parse(source);
|
||||
const node = tree.rootNode.firstChild;
|
||||
expect(node!.type).toBe('if_statement');
|
||||
const alternatives = node!.childrenForFieldName('alternative');
|
||||
const alternativeTexts = alternatives.map(n => {
|
||||
const condition = n.childForFieldName('condition');
|
||||
return source.slice(condition!.startIndex, condition!.endIndex);
|
||||
expect(node?.type).toBe('if_statement');
|
||||
const alternatives = node?.childrenForFieldName('alternative');
|
||||
const alternativeTexts = alternatives?.map(n => {
|
||||
const condition = n?.childForFieldName('condition');
|
||||
return source.slice(condition?.startIndex, condition?.endIndex);
|
||||
});
|
||||
expect(alternativeTexts).toEqual(['two', 'three', 'four']);
|
||||
});
|
||||
|
|
@ -111,29 +111,29 @@ describe('Node', () => {
|
|||
describe('.startIndex and .endIndex', () => {
|
||||
it('returns the character index where the node starts/ends in the text', () => {
|
||||
tree = parser.parse('a👍👎1 / b👎c👎');
|
||||
const quotientNode = tree.rootNode.firstChild!.firstChild;
|
||||
const quotientNode = tree.rootNode.firstChild?.firstChild;
|
||||
|
||||
expect(quotientNode!.startIndex).toBe(0);
|
||||
expect(quotientNode!.endIndex).toBe(15);
|
||||
expect(quotientNode!.children.map(child => child.startIndex)).toEqual([0, 7, 9]);
|
||||
expect(quotientNode!.children.map(child => child.endIndex)).toEqual([6, 8, 15]);
|
||||
expect(quotientNode?.startIndex).toBe(0);
|
||||
expect(quotientNode?.endIndex).toBe(15);
|
||||
expect(quotientNode?.children.map(child => child?.startIndex)).toEqual([0, 7, 9]);
|
||||
expect(quotientNode?.children.map(child => child?.endIndex)).toEqual([6, 8, 15]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.startPosition and .endPosition', () => {
|
||||
it('returns the row and column where the node starts/ends in the text', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild!;
|
||||
expect(sumNode.type).toBe('binary_expression');
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
expect(sumNode?.type).toBe('binary_expression');
|
||||
|
||||
expect(sumNode.startPosition).toEqual({ row: 0, column: 0 });
|
||||
expect(sumNode.endPosition).toEqual({ row: 0, column: 10 });
|
||||
expect(sumNode.children.map((child) => child.startPosition)).toEqual([
|
||||
expect(sumNode?.startPosition).toEqual({ row: 0, column: 0 });
|
||||
expect(sumNode?.endPosition).toEqual({ row: 0, column: 10 });
|
||||
expect(sumNode?.children.map((child) => child?.startPosition)).toEqual([
|
||||
{ row: 0, column: 0 },
|
||||
{ row: 0, column: 4 },
|
||||
{ row: 0, column: 6 },
|
||||
]);
|
||||
expect(sumNode.children.map((child) => child.endPosition)).toEqual([
|
||||
expect(sumNode?.children.map((child) => child?.endPosition)).toEqual([
|
||||
{ row: 0, column: 3 },
|
||||
{ row: 0, column: 5 },
|
||||
{ row: 0, column: 10 },
|
||||
|
|
@ -142,8 +142,8 @@ describe('Node', () => {
|
|||
|
||||
it('handles characters that occupy two UTF16 code units', () => {
|
||||
tree = parser.parse('a👍👎1 /\n b👎c👎');
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
expect(sumNode!.children.map(child => [child.startPosition, child.endPosition])).toEqual([
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
expect(sumNode?.children.map(child => [child?.startPosition, child?.endPosition])).toEqual([
|
||||
[{ row: 0, column: 0 }, { row: 0, column: 6 }],
|
||||
[{ row: 0, column: 7 }, { row: 0, column: 8 }],
|
||||
[{ row: 1, column: 1 }, { row: 1, column: 7 }]
|
||||
|
|
@ -155,23 +155,23 @@ describe('Node', () => {
|
|||
it('returns the node\'s parent', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild;
|
||||
const variableNode = sumNode!.firstChild;
|
||||
expect(sumNode!.id).not.toBe(variableNode!.id);
|
||||
expect(sumNode!.id).toBe(variableNode!.parent!.id);
|
||||
expect(tree.rootNode.id).toBe(sumNode!.parent!.id);
|
||||
const variableNode = sumNode?.firstChild;
|
||||
expect(sumNode?.id).not.toBe(variableNode?.id);
|
||||
expect(sumNode?.id).toBe(variableNode?.parent?.id);
|
||||
expect(tree.rootNode.id).toBe(sumNode?.parent?.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.child(), .firstChild, .lastChild', () => {
|
||||
it('returns null when the node has no children', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
const variableNode = sumNode!.firstChild;
|
||||
expect(variableNode!.firstChild).toBeNull();
|
||||
expect(variableNode!.lastChild).toBeNull();
|
||||
expect(variableNode!.firstNamedChild).toBeNull();
|
||||
expect(variableNode!.lastNamedChild).toBeNull();
|
||||
expect(variableNode!.child(1)).toBeNull();
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
const variableNode = sumNode?.firstChild;
|
||||
expect(variableNode?.firstChild).toBeNull();
|
||||
expect(variableNode?.lastChild).toBeNull();
|
||||
expect(variableNode?.firstNamedChild).toBeNull();
|
||||
expect(variableNode?.lastNamedChild).toBeNull();
|
||||
expect(variableNode?.child(1)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -180,57 +180,57 @@ describe('Node', () => {
|
|||
tree = parser.parse('class A { b() {} }');
|
||||
|
||||
const classNode = tree.rootNode.firstChild;
|
||||
expect(classNode!.type).toBe('class_declaration');
|
||||
expect(classNode?.type).toBe('class_declaration');
|
||||
|
||||
const classNameNode = classNode!.childForFieldName('name');
|
||||
expect(classNameNode!.type).toBe('identifier');
|
||||
expect(classNameNode!.text).toBe('A');
|
||||
const classNameNode = classNode?.childForFieldName('name');
|
||||
expect(classNameNode?.type).toBe('identifier');
|
||||
expect(classNameNode?.text).toBe('A');
|
||||
|
||||
const bodyNode = classNode!.childForFieldName('body');
|
||||
expect(bodyNode!.type).toBe('class_body');
|
||||
expect(bodyNode!.text).toBe('{ b() {} }');
|
||||
const bodyNode = classNode?.childForFieldName('body');
|
||||
expect(bodyNode?.type).toBe('class_body');
|
||||
expect(bodyNode?.text).toBe('{ b() {} }');
|
||||
|
||||
const methodNode = bodyNode!.firstNamedChild;
|
||||
expect(methodNode!.type).toBe('method_definition');
|
||||
expect(methodNode!.text).toBe('b() {}');
|
||||
const methodNode = bodyNode?.firstNamedChild;
|
||||
expect(methodNode?.type).toBe('method_definition');
|
||||
expect(methodNode?.text).toBe('b() {}');
|
||||
});
|
||||
});
|
||||
|
||||
describe('.nextSibling and .previousSibling', () => {
|
||||
it('returns the node\'s next and previous sibling', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
expect(sumNode!.children[1].id).toBe(sumNode!.children[0].nextSibling!.id);
|
||||
expect(sumNode!.children[2].id).toBe(sumNode!.children[1].nextSibling!.id);
|
||||
expect(sumNode!.children[0].id).toBe(sumNode!.children[1].previousSibling!.id);
|
||||
expect(sumNode!.children[1].id).toBe(sumNode!.children[2].previousSibling!.id);
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
expect(sumNode?.children[1]?.id).toBe(sumNode?.children[0]?.nextSibling?.id);
|
||||
expect(sumNode?.children[2]?.id).toBe(sumNode?.children[1]?.nextSibling?.id);
|
||||
expect(sumNode?.children[0]?.id).toBe(sumNode?.children[1]?.previousSibling?.id);
|
||||
expect(sumNode?.children[1]?.id).toBe(sumNode?.children[2]?.previousSibling?.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.nextNamedSibling and .previousNamedSibling', () => {
|
||||
it('returns the node\'s next and previous named sibling', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
expect(sumNode!.namedChildren[1].id).toBe(sumNode!.namedChildren[0].nextNamedSibling!.id);
|
||||
expect(sumNode!.namedChildren[0].id).toBe(sumNode!.namedChildren[1].previousNamedSibling!.id);
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
expect(sumNode?.namedChildren[1]?.id).toBe(sumNode?.namedChildren[0]?.nextNamedSibling?.id);
|
||||
expect(sumNode?.namedChildren[0]?.id).toBe(sumNode?.namedChildren[1]?.previousNamedSibling?.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.descendantForIndex(min, max)', () => {
|
||||
it('returns the smallest node that spans the given range', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
expect(sumNode!.descendantForIndex(1, 2).type).toBe('identifier');
|
||||
expect(sumNode!.descendantForIndex(4, 4).type).toBe('+');
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
expect(sumNode?.descendantForIndex(1, 2)?.type).toBe('identifier');
|
||||
expect(sumNode?.descendantForIndex(4, 4)?.type).toBe('+');
|
||||
|
||||
expect(() => {
|
||||
// @ts-expect-error Testing invalid arguments
|
||||
sumNode!.descendantForIndex(1, {});
|
||||
sumNode.descendantForIndex(1, {});
|
||||
}).toThrow('Arguments must be numbers');
|
||||
|
||||
expect(() => {
|
||||
// @ts-expect-error Testing invalid arguments
|
||||
sumNode!.descendantForIndex(undefined);
|
||||
sumNode.descendantForIndex(undefined);
|
||||
}).toThrow('Arguments must be numbers');
|
||||
});
|
||||
});
|
||||
|
|
@ -238,36 +238,36 @@ describe('Node', () => {
|
|||
describe('.namedDescendantForIndex', () => {
|
||||
it('returns the smallest named node that spans the given range', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild;
|
||||
expect(sumNode!.descendantForIndex(1, 2).type).toBe('identifier');
|
||||
expect(sumNode!.descendantForIndex(4, 4).type).toBe('+');
|
||||
const sumNode = tree.rootNode.firstChild!;
|
||||
expect(sumNode.descendantForIndex(1, 2)?.type).toBe('identifier');
|
||||
expect(sumNode.descendantForIndex(4, 4)?.type).toBe('+');
|
||||
});
|
||||
});
|
||||
|
||||
describe('.descendantForPosition', () => {
|
||||
it('returns the smallest node that spans the given range', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild;
|
||||
const sumNode = tree.rootNode.firstChild!;
|
||||
|
||||
expect(
|
||||
sumNode!.descendantForPosition(
|
||||
sumNode.descendantForPosition(
|
||||
{ row: 0, column: 1 },
|
||||
{ row: 0, column: 2 }
|
||||
).type
|
||||
)?.type
|
||||
).toBe('identifier');
|
||||
|
||||
expect(
|
||||
sumNode!.descendantForPosition({ row: 0, column: 4 }).type
|
||||
sumNode.descendantForPosition({ row: 0, column: 4 })?.type
|
||||
).toBe('+');
|
||||
|
||||
expect(() => {
|
||||
// @ts-expect-error Testing invalid arguments
|
||||
sumNode!.descendantForPosition(1, {});
|
||||
sumNode.descendantForPosition(1, {});
|
||||
}).toThrow('Arguments must be {row, column} objects');
|
||||
|
||||
expect(() => {
|
||||
// @ts-expect-error Testing invalid arguments
|
||||
sumNode!.descendantForPosition(undefined);
|
||||
sumNode.descendantForPosition(undefined);
|
||||
}).toThrow('Arguments must be {row, column} objects');
|
||||
});
|
||||
});
|
||||
|
|
@ -281,11 +281,11 @@ describe('Node', () => {
|
|||
sumNode.namedDescendantForPosition(
|
||||
{ row: 0, column: 1 },
|
||||
{ row: 0, column: 2 },
|
||||
).type
|
||||
)?.type
|
||||
).toBe('identifier')
|
||||
|
||||
expect(
|
||||
sumNode.namedDescendantForPosition({ row: 0, column: 4 }).type
|
||||
sumNode.namedDescendantForPosition({ row: 0, column: 4 })?.type
|
||||
).toBe('binary_expression');
|
||||
});
|
||||
});
|
||||
|
|
@ -298,11 +298,11 @@ describe('Node', () => {
|
|||
'(program (expression_statement (binary_expression left: (number) right: (binary_expression left: (number) (ERROR) right: (number)))))'
|
||||
);
|
||||
|
||||
const sum = node.firstChild!.firstChild;
|
||||
expect(sum!.hasError).toBe(true);
|
||||
expect(sum!.children[0].hasError).toBe(false);
|
||||
expect(sum!.children[1].hasError).toBe(false);
|
||||
expect(sum!.children[2].hasError).toBe(true);
|
||||
const sum = node.firstChild?.firstChild;
|
||||
expect(sum?.hasError).toBe(true);
|
||||
expect(sum?.children[0]?.hasError).toBe(false);
|
||||
expect(sum?.children[1]?.hasError).toBe(false);
|
||||
expect(sum?.children[2]?.hasError).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -314,12 +314,12 @@ describe('Node', () => {
|
|||
'(program (expression_statement (binary_expression left: (number) (ERROR) right: (number))))'
|
||||
);
|
||||
|
||||
const multi = node.firstChild!.firstChild;
|
||||
expect(multi!.hasError).toBe(true);
|
||||
expect(multi!.children[0].isError).toBe(false);
|
||||
expect(multi!.children[1].isError).toBe(false);
|
||||
expect(multi!.children[2].isError).toBe(true);
|
||||
expect(multi!.children[3].isError).toBe(false);
|
||||
const multi = node.firstChild?.firstChild;
|
||||
expect(multi?.hasError).toBe(true);
|
||||
expect(multi?.children[0]?.isError).toBe(false);
|
||||
expect(multi?.children[1]?.isError).toBe(false);
|
||||
expect(multi?.children[2]?.isError).toBe(true);
|
||||
expect(multi?.children[3]?.isError).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -331,12 +331,12 @@ describe('Node', () => {
|
|||
'(program (expression_statement (parenthesized_expression (binary_expression left: (number) right: (MISSING identifier)))))'
|
||||
);
|
||||
|
||||
const sum = node.firstChild!.firstChild!.firstNamedChild;
|
||||
expect(sum!.type).toBe('binary_expression');
|
||||
expect(sum!.hasError).toBe(true);
|
||||
expect(sum!.children[0].isMissing).toBe(false);
|
||||
expect(sum!.children[1].isMissing).toBe(false);
|
||||
expect(sum!.children[2].isMissing).toBe(true);
|
||||
const sum = node.firstChild?.firstChild?.firstNamedChild;
|
||||
expect(sum?.type).toBe('binary_expression');
|
||||
expect(sum?.hasError).toBe(true);
|
||||
expect(sum?.children[0]?.isMissing).toBe(false);
|
||||
expect(sum?.children[1]?.isMissing).toBe(false);
|
||||
expect(sum?.children[2]?.isMissing).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -344,7 +344,7 @@ describe('Node', () => {
|
|||
it('returns true if the node is an extra node like comments', () => {
|
||||
tree = parser.parse('foo(/* hi */);');
|
||||
const node = tree.rootNode;
|
||||
const commentNode = node.descendantForIndex(7, 7);
|
||||
const commentNode = node.descendantForIndex(7, 7)!;
|
||||
|
||||
expect(node.type).toBe('program');
|
||||
expect(commentNode.type).toBe('comment');
|
||||
|
|
@ -363,14 +363,14 @@ describe('Node', () => {
|
|||
it(`returns the text of a node generated by ${method}`, () => {
|
||||
const [numeratorSrc, denominatorSrc] = text.split(/\s*\/\s+/);
|
||||
tree = parser.parse(_parse);
|
||||
const quotientNode = tree.rootNode.firstChild!.firstChild!;
|
||||
const [numerator, slash, denominator] = quotientNode.children;
|
||||
const quotientNode = tree.rootNode.firstChild?.firstChild;
|
||||
const [numerator, slash, denominator] = quotientNode!.children;
|
||||
|
||||
expect(tree.rootNode.text).toBe(text);
|
||||
expect(denominator.text).toBe(denominatorSrc);
|
||||
expect(quotientNode.text).toBe(text);
|
||||
expect(numerator.text).toBe(numeratorSrc);
|
||||
expect(slash.text).toBe('/');
|
||||
expect(denominator?.text).toBe(denominatorSrc);
|
||||
expect(quotientNode?.text).toBe(text);
|
||||
expect(numerator?.text).toBe(numeratorSrc);
|
||||
expect(slash?.text).toBe('/');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -427,12 +427,12 @@ describe('Node', () => {
|
|||
expect(node.startPosition).toEqual({ row: 2, column: 4 });
|
||||
expect(node.endPosition).toEqual({ row: 2, column: 12 });
|
||||
|
||||
let child = node.firstChild!.child(2);
|
||||
expect(child!.type).toBe('expression_statement');
|
||||
expect(child!.startIndex).toBe(15);
|
||||
expect(child!.endIndex).toBe(16);
|
||||
expect(child!.startPosition).toEqual({ row: 2, column: 11 });
|
||||
expect(child!.endPosition).toEqual({ row: 2, column: 12 });
|
||||
let child = node.firstChild?.child(2);
|
||||
expect(child?.type).toBe('expression_statement');
|
||||
expect(child?.startIndex).toBe(15);
|
||||
expect(child?.endIndex).toBe(16);
|
||||
expect(child?.startPosition).toEqual({ row: 2, column: 11 });
|
||||
expect(child?.endPosition).toEqual({ row: 2, column: 12 });
|
||||
|
||||
const cursor = node.walk();
|
||||
cursor.gotoFirstChild();
|
||||
|
|
@ -452,23 +452,23 @@ describe('Node', () => {
|
|||
|
||||
it('returns node parse state ids', () => {
|
||||
tree = parser.parse(text);
|
||||
const quotientNode = tree.rootNode.firstChild!.firstChild;
|
||||
const quotientNode = tree.rootNode.firstChild?.firstChild;
|
||||
const [numerator, slash, denominator] = quotientNode!.children;
|
||||
|
||||
expect(tree.rootNode.parseState).toBe(0);
|
||||
// parse states will change on any change to the grammar so test that it
|
||||
// returns something instead
|
||||
expect(numerator.parseState).toBeGreaterThan(0);
|
||||
expect(slash.parseState).toBeGreaterThan(0);
|
||||
expect(denominator.parseState).toBeGreaterThan(0);
|
||||
expect(numerator?.parseState).toBeGreaterThan(0);
|
||||
expect(slash?.parseState).toBeGreaterThan(0);
|
||||
expect(denominator?.parseState).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('returns next parse state equal to the language', () => {
|
||||
tree = parser.parse(text);
|
||||
const quotientNode = tree.rootNode.firstChild!.firstChild;
|
||||
quotientNode!.children.forEach((node) => {
|
||||
expect(node.nextParseState).toBe(
|
||||
JavaScript.nextState(node.parseState, node.grammarId)
|
||||
const quotientNode = tree.rootNode.firstChild?.firstChild;
|
||||
quotientNode?.children.forEach((node) => {
|
||||
expect(node?.nextParseState).toBe(
|
||||
JavaScript.nextState(node!.parseState, node!.grammarId)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -477,11 +477,11 @@ describe('Node', () => {
|
|||
describe('.descendantsOfType', () => {
|
||||
it('finds all descendants of a given type in the given range', () => {
|
||||
tree = parser.parse('a + 1 * b * 2 + c + 3');
|
||||
const outerSum = tree.rootNode.firstChild!.firstChild;
|
||||
const outerSum = tree.rootNode.firstChild?.firstChild;
|
||||
|
||||
const descendants = outerSum!.descendantsOfType('number', { row: 0, column: 2 }, { row: 0, column: 15 });
|
||||
expect(descendants.map(node => node.startIndex)).toEqual([4, 12]);
|
||||
expect(descendants.map(node => node.endPosition)).toEqual([
|
||||
const descendants = outerSum?.descendantsOfType('number', { row: 0, column: 2 }, { row: 0, column: 15 }) ?? [];
|
||||
expect(descendants.map(node => node?.startIndex)).toEqual([4, 12]);
|
||||
expect(descendants.map(node => node?.endPosition)).toEqual([
|
||||
{ row: 0, column: 5 },
|
||||
{ row: 0, column: 13 },
|
||||
]);
|
||||
|
|
@ -493,23 +493,23 @@ describe('Node', () => {
|
|||
describe('.firstChildForIndex(index)', () => {
|
||||
it('returns the first child that contains or starts after the given index', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
|
||||
expect(sumNode!.firstChildForIndex(0)!.type).toBe('identifier');
|
||||
expect(sumNode!.firstChildForIndex(1)!.type).toBe('identifier');
|
||||
expect(sumNode!.firstChildForIndex(3)!.type).toBe('+');
|
||||
expect(sumNode!.firstChildForIndex(5)!.type).toBe('number');
|
||||
expect(sumNode?.firstChildForIndex(0)?.type).toBe('identifier');
|
||||
expect(sumNode?.firstChildForIndex(1)?.type).toBe('identifier');
|
||||
expect(sumNode?.firstChildForIndex(3)?.type).toBe('+');
|
||||
expect(sumNode?.firstChildForIndex(5)?.type).toBe('number');
|
||||
});
|
||||
});
|
||||
|
||||
describe('.firstNamedChildForIndex(index)', () => {
|
||||
it('returns the first child that contains or starts after the given index', () => {
|
||||
tree = parser.parse('x10 + 1000');
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
|
||||
expect(sumNode!.firstNamedChildForIndex(0)!.type).toBe('identifier');
|
||||
expect(sumNode!.firstNamedChildForIndex(1)!.type).toBe('identifier');
|
||||
expect(sumNode!.firstNamedChildForIndex(3)!.type).toBe('number');
|
||||
expect(sumNode?.firstNamedChildForIndex(0)?.type).toBe('identifier');
|
||||
expect(sumNode?.firstNamedChildForIndex(1)?.type).toBe('identifier');
|
||||
expect(sumNode?.firstNamedChildForIndex(3)?.type).toBe('number');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -517,19 +517,19 @@ describe('Node', () => {
|
|||
it('returns true if the nodes are the same', () => {
|
||||
tree = parser.parse('1 + 2');
|
||||
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
const node1 = sumNode!.firstChild;
|
||||
const node2 = sumNode!.firstChild;
|
||||
expect(node1!.equals(node2!)).toBe(true);
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
const node1 = sumNode?.firstChild;
|
||||
const node2 = sumNode?.firstChild;
|
||||
expect(node1?.equals(node2!)).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false if the nodes are not the same', () => {
|
||||
tree = parser.parse('1 + 2');
|
||||
|
||||
const sumNode = tree.rootNode.firstChild!.firstChild;
|
||||
const node1 = sumNode!.firstChild;
|
||||
const node2 = node1!.nextSibling;
|
||||
expect(node1!.equals(node2!)).toBe(false);
|
||||
const sumNode = tree.rootNode.firstChild?.firstChild;
|
||||
const node1 = sumNode?.firstChild;
|
||||
const node2 = node1?.nextSibling;
|
||||
expect(node1?.equals(node2!)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -551,13 +551,13 @@ describe('Node', () => {
|
|||
// right: (identifier) 3
|
||||
// -------------------
|
||||
|
||||
expect(binaryExpressionNode!.fieldNameForChild(0)).toBe('left');
|
||||
expect(binaryExpressionNode!.fieldNameForChild(1)).toBe('operator');
|
||||
expect(binaryExpressionNode?.fieldNameForChild(0)).toBe('left');
|
||||
expect(binaryExpressionNode?.fieldNameForChild(1)).toBe('operator');
|
||||
// The comment should not have a field name, as it's just an extra
|
||||
expect(binaryExpressionNode!.fieldNameForChild(2)).toBeNull();
|
||||
expect(binaryExpressionNode!.fieldNameForChild(3)).toBe('right');
|
||||
expect(binaryExpressionNode?.fieldNameForChild(2)).toBeNull();
|
||||
expect(binaryExpressionNode?.fieldNameForChild(3)).toBe('right');
|
||||
// Negative test - Not a valid child index
|
||||
expect(binaryExpressionNode!.fieldNameForChild(4)).toBeNull();
|
||||
expect(binaryExpressionNode?.fieldNameForChild(4)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -579,13 +579,13 @@ describe('Node', () => {
|
|||
// right: (identifier) 2
|
||||
// -------------------
|
||||
|
||||
expect(binaryExpressionNode!.fieldNameForNamedChild(0)).toBe('left');
|
||||
expect(binaryExpressionNode?.fieldNameForNamedChild(0)).toBe('left');
|
||||
// The comment should not have a field name, as it's just an extra
|
||||
expect(binaryExpressionNode!.fieldNameForNamedChild(1)).toBeNull();
|
||||
expect(binaryExpressionNode?.fieldNameForNamedChild(1)).toBeNull();
|
||||
// The operator is not a named child, so the named child at index 2 is the right child
|
||||
expect(binaryExpressionNode!.fieldNameForNamedChild(2)).toBe('right');
|
||||
expect(binaryExpressionNode?.fieldNameForNamedChild(2)).toBe('right');
|
||||
// Negative test - Not a valid child index
|
||||
expect(binaryExpressionNode!.fieldNameForNamedChild(3)).toBeNull();
|
||||
expect(binaryExpressionNode?.fieldNameForNamedChild(3)).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
import { describe, it, expect, beforeAll, beforeEach, afterEach } from 'vitest';
|
||||
import helper, { type LanguageName } from './helper';
|
||||
import type { default as ParserType, Language } from 'web-tree-sitter';
|
||||
import type { ParseState, Tree, Parser as ParserType, Language as LanguageType } from '../src';
|
||||
|
||||
let Parser: typeof ParserType;
|
||||
let JavaScript: Language;
|
||||
let HTML: Language;
|
||||
let JSON: Language;
|
||||
let Language: typeof LanguageType;
|
||||
let JavaScript: LanguageType;
|
||||
let HTML: LanguageType;
|
||||
let JSON: LanguageType;
|
||||
let languageURL: (name: LanguageName) => string;
|
||||
|
||||
describe('Parser', () => {
|
||||
let parser: ParserType;
|
||||
|
||||
beforeAll(async () => {
|
||||
({ Parser, JavaScript, HTML, JSON, languageURL } = await helper);
|
||||
({ Parser, Language, JavaScript, HTML, JSON, languageURL } = await helper);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
@ -25,7 +26,7 @@ describe('Parser', () => {
|
|||
|
||||
describe('.setLanguage', () => {
|
||||
it('allows setting the language to null', () => {
|
||||
expect(parser.getLanguage()).toBeUndefined();
|
||||
expect(parser.getLanguage()).toBeNull();
|
||||
parser.setLanguage(JavaScript);
|
||||
expect(parser.getLanguage()).toBe(JavaScript);
|
||||
parser.setLanguage(null);
|
||||
|
|
@ -134,7 +135,7 @@ describe('Parser', () => {
|
|||
const templateStringNode = jsTree.rootNode.descendantForIndex(
|
||||
sourceCode.indexOf('`<'),
|
||||
sourceCode.indexOf('>`')
|
||||
);
|
||||
)!;
|
||||
expect(templateStringNode.type).toBe('template_string');
|
||||
|
||||
const openQuoteNode = templateStringNode.child(0)!;
|
||||
|
|
@ -222,7 +223,7 @@ describe('Parser', () => {
|
|||
});
|
||||
|
||||
describe('.parse', () => {
|
||||
let tree: ParserType.Tree | null;
|
||||
let tree: Tree | null;
|
||||
|
||||
beforeEach(() => {
|
||||
tree = null;
|
||||
|
|
@ -266,7 +267,7 @@ describe('Parser', () => {
|
|||
});
|
||||
|
||||
it('can use the bash parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Parser.Language.load(languageURL('bash')));
|
||||
parser.setLanguage(await Language.load(languageURL('bash')));
|
||||
tree = parser.parse('FOO=bar echo <<EOF 2> err.txt > hello.txt \nhello${FOO}\nEOF');
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(program ' +
|
||||
|
|
@ -283,7 +284,7 @@ describe('Parser', () => {
|
|||
});
|
||||
|
||||
it('can use the c++ parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Parser.Language.load(languageURL('cpp')));
|
||||
parser.setLanguage(await Language.load(languageURL('cpp')));
|
||||
tree = parser.parse('const char *s = R"EOF(HELLO WORLD)EOF";');
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(translation_unit (declaration ' +
|
||||
|
|
@ -296,7 +297,7 @@ describe('Parser', () => {
|
|||
});
|
||||
|
||||
it('can use the HTML parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Parser.Language.load(languageURL('html')));
|
||||
parser.setLanguage(await Language.load(languageURL('html')));
|
||||
tree = parser.parse('<div><span><custom></custom></span></div>');
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(document (element (start_tag (tag_name)) (element (start_tag (tag_name)) ' +
|
||||
|
|
@ -305,7 +306,7 @@ describe('Parser', () => {
|
|||
});
|
||||
|
||||
it('can use the python parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Parser.Language.load(languageURL('python')));
|
||||
parser.setLanguage(await Language.load(languageURL('python')));
|
||||
tree = parser.parse('class A:\n def b():\n c()');
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(module (class_definition ' +
|
||||
|
|
@ -321,7 +322,7 @@ describe('Parser', () => {
|
|||
});
|
||||
|
||||
it('can use the rust parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Parser.Language.load(languageURL('rust')));
|
||||
parser.setLanguage(await Language.load(languageURL('rust')));
|
||||
tree = parser.parse('const x: &\'static str = r###"hello"###;');
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(source_file (const_item ' +
|
||||
|
|
@ -332,7 +333,7 @@ describe('Parser', () => {
|
|||
});
|
||||
|
||||
it('can use the typescript parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Parser.Language.load(languageURL('typescript')));
|
||||
parser.setLanguage(await Language.load(languageURL('typescript')));
|
||||
tree = parser.parse('a()\nb()\n[c]');
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(program ' +
|
||||
|
|
@ -346,7 +347,7 @@ describe('Parser', () => {
|
|||
});
|
||||
|
||||
it('can use the tsx parser', { timeout: 5000 }, async () => {
|
||||
parser.setLanguage(await Parser.Language.load(languageURL('tsx')));
|
||||
parser.setLanguage(await Language.load(languageURL('tsx')));
|
||||
tree = parser.parse('a()\nb()\n[c]');
|
||||
expect(tree.rootNode.toString()).toBe(
|
||||
'(program ' +
|
||||
|
|
@ -397,7 +398,7 @@ describe('Parser', () => {
|
|||
|
||||
const startTime = performance.now();
|
||||
let currentByteOffset = 0;
|
||||
const progressCallback = (state: ParserType.State) => {
|
||||
const progressCallback = (state: ParseState) => {
|
||||
expect(state.currentOffset).toBeGreaterThanOrEqual(currentByteOffset);
|
||||
currentByteOffset = state.currentOffset;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, it, expect, beforeAll, beforeEach, afterEach } from 'vitest';
|
||||
import type { default as ParserType, Language, Tree, Query, QueryCapture, QueryMatch } from 'web-tree-sitter';
|
||||
import type { Parser as ParserType, Language, Tree, Query, QueryMatch, QueryCapture } from '../src';
|
||||
import helper from './helper';
|
||||
|
||||
let Parser: typeof ParserType;
|
||||
|
|
@ -576,12 +576,11 @@ function formatMatches(matches: QueryMatch[]): QueryMatch[] {
|
|||
}));
|
||||
}
|
||||
|
||||
function formatCaptures(captures: QueryCapture[]): QueryCapture[] {
|
||||
function formatCaptures(captures: QueryCapture[]): (QueryCapture & { text: string })[] {
|
||||
return captures.map((c) => {
|
||||
const node = c.node;
|
||||
// @ts-expect-error We're not interested in the node object for these tests
|
||||
delete c.node;
|
||||
c.text = node.text;
|
||||
return c;
|
||||
return { ...c, text: node.text };
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, it, expect, beforeAll, beforeEach, afterEach } from 'vitest';
|
||||
import type { default as ParserType, Language, Tree, TreeCursor, Edit, Point } from 'web-tree-sitter';
|
||||
import type { Parser as ParserType, Point, Language, Tree, Edit, TreeCursor } from '../src';
|
||||
import helper from './helper';
|
||||
|
||||
let Parser: typeof ParserType;
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
var TreeSitter = function() {
|
||||
var initPromise;
|
||||
var document = typeof window == 'object'
|
||||
? {currentScript: window.document.currentScript}
|
||||
: null;
|
||||
|
||||
class Parser {
|
||||
constructor() {
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
initialize() {
|
||||
throw new Error("cannot construct a Parser before calling `init()`");
|
||||
}
|
||||
|
||||
static init(moduleOptions) {
|
||||
if (initPromise) return initPromise;
|
||||
Module = Object.assign({}, Module, moduleOptions);
|
||||
return initPromise = new Promise((resolveInitPromise) => {
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
for (const name of Object.getOwnPropertyNames(ParserImpl.prototype)) {
|
||||
Object.defineProperty(Parser.prototype, name, {
|
||||
value: ParserImpl.prototype[name],
|
||||
enumerable: false,
|
||||
writable: false,
|
||||
})
|
||||
}
|
||||
|
||||
Parser.Language = Language;
|
||||
Module.onRuntimeInitialized = () => {
|
||||
ParserImpl.init();
|
||||
resolveInitPromise();
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return Parser;
|
||||
}();
|
||||
|
||||
if (typeof exports === 'object') {
|
||||
module.exports = TreeSitter;
|
||||
}
|
||||
|
|
@ -24,19 +24,18 @@ enum EmccSource {
|
|||
Podman,
|
||||
}
|
||||
|
||||
pub fn run_wasm(args: &BuildWasm) -> Result<()> {
|
||||
let npm = if cfg!(target_os = "windows") {
|
||||
"npm.cmd"
|
||||
} else {
|
||||
"npm"
|
||||
};
|
||||
let npm = Command::new(npm)
|
||||
.current_dir("lib/binding_web")
|
||||
.args(["run", "build:ts"])
|
||||
.output()
|
||||
.expect("Failed to run npm run build:ts");
|
||||
bail_on_err(&npm, "Failed to run npm run build:ts")?;
|
||||
const EXPORTED_RUNTIME_METHODS: [&str; 8] = [
|
||||
"AsciiToString",
|
||||
"stringToUTF8",
|
||||
"UTF8ToString",
|
||||
"lengthBytesUTF8",
|
||||
"stringToUTF16",
|
||||
"loadWebAssemblyModule",
|
||||
"getValue",
|
||||
"setValue",
|
||||
];
|
||||
|
||||
pub fn run_wasm(args: &BuildWasm) -> Result<()> {
|
||||
let mut emscripten_flags = vec!["-O3", "--minify", "0"];
|
||||
|
||||
if args.debug {
|
||||
|
|
@ -118,7 +117,7 @@ pub fn run_wasm(args: &BuildWasm) -> Result<()> {
|
|||
let exported_functions = format!(
|
||||
"{}{}",
|
||||
fs::read_to_string("lib/src/wasm/stdlib-symbols.txt")?,
|
||||
fs::read_to_string("lib/binding_web/wasm/exports.txt")?
|
||||
fs::read_to_string("lib/binding_web/lib/exports.txt")?
|
||||
)
|
||||
.replace('"', "")
|
||||
.lines()
|
||||
|
|
@ -130,7 +129,10 @@ pub fn run_wasm(args: &BuildWasm) -> Result<()> {
|
|||
.to_string();
|
||||
|
||||
let exported_functions = format!("EXPORTED_FUNCTIONS={exported_functions}");
|
||||
let exported_runtime_methods = "EXPORTED_RUNTIME_METHODS=stringToUTF16,AsciiToString";
|
||||
let exported_runtime_methods = format!(
|
||||
"EXPORTED_RUNTIME_METHODS={}",
|
||||
EXPORTED_RUNTIME_METHODS.join(",")
|
||||
);
|
||||
|
||||
std::env::set_var("EMCC_DEBUG_SAVE", "1");
|
||||
|
||||
|
|
@ -138,7 +140,11 @@ pub fn run_wasm(args: &BuildWasm) -> Result<()> {
|
|||
emscripten_flags.extend([
|
||||
"-gsource-map",
|
||||
"--source-map-base", ".",
|
||||
"-fno-exceptions",
|
||||
"-std=c11",
|
||||
"-s", "WASM=1",
|
||||
"-s", "EXPORT_ES6",
|
||||
"-s", "MODULARIZE=1",
|
||||
"-s", "INITIAL_MEMORY=33554432",
|
||||
"-s", "ALLOW_MEMORY_GROWTH=1",
|
||||
"-s", "SUPPORT_BIG_ENDIAN=1",
|
||||
|
|
@ -147,60 +153,40 @@ pub fn run_wasm(args: &BuildWasm) -> Result<()> {
|
|||
"-s", "NODEJS_CATCH_EXIT=0",
|
||||
"-s", "NODEJS_CATCH_REJECTION=0",
|
||||
"-s", &exported_functions,
|
||||
"-s", exported_runtime_methods,
|
||||
"-fno-exceptions",
|
||||
"-std=c11",
|
||||
"-s", &exported_runtime_methods,
|
||||
"-D", "fprintf(...)=",
|
||||
"-D", "NDEBUG=",
|
||||
"-D", "_POSIX_C_SOURCE=200112L",
|
||||
"-D", "_DEFAULT_SOURCE=",
|
||||
"-I", "lib/src",
|
||||
"-I", "lib/include",
|
||||
"--js-library", "lib/binding_web/wasm/imports.js",
|
||||
"--pre-js", "lib/binding_web/wasm/prefix.js",
|
||||
"--post-js", "lib/binding_web/dist/tree-sitter.js",
|
||||
"--post-js", "lib/binding_web/wasm/suffix.js",
|
||||
"-o", "target/scratch/tree-sitter.js",
|
||||
"--js-library", "lib/binding_web/lib/imports.js",
|
||||
"--pre-js", "lib/binding_web/lib/prefix.js",
|
||||
"-o", "lib/binding_web/lib/tree-sitter.js",
|
||||
"lib/src/lib.c",
|
||||
"lib/binding_web/lib/tree-sitter.c",
|
||||
]);
|
||||
if args.emit_tsd {
|
||||
emscripten_flags.extend(["--emit-tsd", "tree-sitter.d.ts"]);
|
||||
}
|
||||
|
||||
let command = command.args(&emscripten_flags);
|
||||
|
||||
if args.watch {
|
||||
watch_wasm!(|| build_wasm(command, args.debug));
|
||||
watch_wasm!(|| build_wasm(command));
|
||||
} else {
|
||||
build_wasm(command, args.debug)?;
|
||||
build_wasm(command)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build_wasm(cmd: &mut Command, debug: bool) -> Result<()> {
|
||||
fn build_wasm(cmd: &mut Command) -> Result<()> {
|
||||
bail_on_err(
|
||||
&cmd.spawn()?.wait_with_output()?,
|
||||
"Failed to compile the Tree-sitter WASM library",
|
||||
)?;
|
||||
|
||||
let dir = if debug {
|
||||
PathBuf::from("lib/binding_web/debug")
|
||||
} else {
|
||||
PathBuf::from("lib/binding_web")
|
||||
};
|
||||
|
||||
fs::create_dir_all(&dir)?;
|
||||
|
||||
fs::rename("target/scratch/tree-sitter.js", dir.join("tree-sitter.js"))?;
|
||||
|
||||
fs::rename(
|
||||
"target/scratch/tree-sitter.wasm",
|
||||
dir.join("tree-sitter.wasm"),
|
||||
)?;
|
||||
|
||||
fs::rename(
|
||||
"target/scratch/tree-sitter.wasm.map",
|
||||
dir.join("tree-sitter.wasm.map"),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ pub fn run(args: &CheckWasmExports) -> Result<()> {
|
|||
}
|
||||
|
||||
fn check_wasm_exports() -> Result<()> {
|
||||
let mut wasm_exports = std::fs::read_to_string("lib/binding_web/wasm/exports.txt")?
|
||||
let mut wasm_exports = std::fs::read_to_string("lib/binding_web/lib/exports.txt")?
|
||||
.lines()
|
||||
.map(|s| s.replace("_wasm", "").replace("byte", "index"))
|
||||
// remove leading and trailing quotes, trailing comma
|
||||
|
|
|
|||
|
|
@ -85,6 +85,10 @@ struct BuildWasm {
|
|||
/// Rebuild when relevant files are changed.
|
||||
#[arg(long, short)]
|
||||
watch: bool,
|
||||
/// Emit TypeScript type definitions for the generated bindings,
|
||||
/// requires `tsc` to be available.
|
||||
#[arg(long, short)]
|
||||
emit_tsd: bool,
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue