From 5c2f80ebb069bd8ec119d7ba418ba85bc33d54ee Mon Sep 17 00:00:00 2001 From: Amaan Qureshi Date: Mon, 11 Mar 2024 23:12:06 -0400 Subject: [PATCH] fix(bindings/wasm): fix `Parser.getIncludedRanges()` --- lib/binding_web/binding.c | 12 +++++++++ lib/binding_web/binding.js | 26 ++++++++++++------- lib/binding_web/exports.txt | 2 ++ lib/binding_web/package.json | 1 + lib/binding_web/test/parser-test.js | 38 ++++++++++++++++++++++++++++ lib/binding_web/tree-sitter-web.d.ts | 2 +- 6 files changed, 71 insertions(+), 10 deletions(-) diff --git a/lib/binding_web/binding.c b/lib/binding_web/binding.c index 9db2bc5f..845314b2 100644 --- a/lib/binding_web/binding.c +++ b/lib/binding_web/binding.c @@ -184,6 +184,18 @@ TSTree *ts_parser_parse_wasm( return ts_parser_parse(self, old_tree, input); } +void ts_parser_included_ranges_wasm(TSParser *self) { + uint32_t range_count = 0; + const TSRange *ranges = ts_parser_included_ranges(self, &range_count); + TSRange *copied_ranges = malloc(sizeof(TSRange) * range_count); + memcpy(copied_ranges, ranges, sizeof(TSRange) * range_count); + for (unsigned i = 0; i < range_count; i++) { + marshal_range(&copied_ranges[i]); + } + TRANSFER_BUFFER[0] = range_count ? (const void *)range_count : NULL; + TRANSFER_BUFFER[1] = copied_ranges; +} + /**********************/ /* Section - Language */ /**********************/ diff --git a/lib/binding_web/binding.js b/lib/binding_web/binding.js index c870f33d..fafc885c 100644 --- a/lib/binding_web/binding.js +++ b/lib/binding_web/binding.js @@ -1,3 +1,8 @@ +/* eslint-disable-next-line spaced-comment */ +/// +/* eslint-disable-next-line spaced-comment */ +/// + const C = Module; const INTERNAL = {}; const SIZE_OF_INT = 4; @@ -121,17 +126,19 @@ class ParserImpl { } getIncludedRanges() { - const count = C._malloc(SIZE_OF_INT); - const rangeAddress = C._ts_parser_included_ranges(this[0], count); - count = getValue(count, 'i32'); + C._ts_parser_included_ranges_wasm(this[0]); + const count = getValue(TRANSFER_BUFFER, 'i32'); + const buffer = getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32'); const result = new Array(count); if (count > 0) { - let address = rangeAddress; + let address = buffer; for (let i = 0; i < count; i++) { result[i] = unmarshalRange(address); address += SIZE_OF_RANGE; } + C._free(buffer); } + return result; } getTimeoutMicros() { @@ -1500,10 +1507,11 @@ function marshalPoint(address, point) { } function unmarshalPoint(address) { - return { - row: getValue(address, 'i32'), - column: getValue(address + SIZE_OF_INT, 'i32'), + const result = { + row: getValue(address, 'i32') >>> 0, + column: getValue(address + SIZE_OF_INT, 'i32') >>> 0, }; + return result; } function marshalRange(address, range) { @@ -1517,8 +1525,8 @@ function unmarshalRange(address) { const result = {}; result.startPosition = unmarshalPoint(address); address += SIZE_OF_POINT; result.endPosition = unmarshalPoint(address); address += SIZE_OF_POINT; - result.startIndex = getValue(address, 'i32'); address += SIZE_OF_INT; - result.endIndex = getValue(address, 'i32'); + result.startIndex = getValue(address, 'i32') >>> 0; address += SIZE_OF_INT; + result.endIndex = getValue(address, 'i32') >>> 0; return result; } diff --git a/lib/binding_web/exports.txt b/lib/binding_web/exports.txt index 68bbd47e..7507c51f 100644 --- a/lib/binding_web/exports.txt +++ b/lib/binding_web/exports.txt @@ -53,6 +53,8 @@ "ts_parser_parse_wasm", "ts_parser_reset", "ts_parser_set_language", +"ts_parser_set_included_ranges", +"ts_parser_included_ranges_wasm", "ts_parser_set_timeout_micros", "ts_parser_timeout_micros", "ts_query_capture_count", diff --git a/lib/binding_web/package.json b/lib/binding_web/package.json index 62a1022c..0b2dfbc4 100644 --- a/lib/binding_web/package.json +++ b/lib/binding_web/package.json @@ -27,6 +27,7 @@ }, "homepage": "https://github.com/tree-sitter/tree-sitter/tree/master/lib/binding_web", "devDependencies": { + "@types/emscripten": "^1.39.10", "chai": "^4.3.7", "eslint": ">=8.56.0", "eslint-config-google": "^0.14.0", diff --git a/lib/binding_web/test/parser-test.js b/lib/binding_web/test/parser-test.js index 3af59e11..cf087599 100644 --- a/lib/binding_web/test/parser-test.js +++ b/lib/binding_web/test/parser-test.js @@ -83,6 +83,44 @@ describe('Parser', () => { }); }); + describe('one included range', () => { + it('parses the text within a range', () => { + parser.setLanguage(HTML); + const sourceCode = 'hi'; + const htmlTree = parser.parse(sourceCode); + const scriptContentNode = htmlTree.rootNode.child(1).child(1); + assert.equal(scriptContentNode.type, 'raw_text'); + + parser.setLanguage(JavaScript); + assert.deepEqual(parser.getIncludedRanges(), [{ + startIndex: 0, + endIndex: 2147483647, + startPosition: {row: 0, column: 0}, + endPosition: {row: 4294967295, column: 2147483647}, + }]); + const ranges = [{ + startIndex: scriptContentNode.startIndex, + endIndex: scriptContentNode.endIndex, + startPosition: scriptContentNode.startPosition, + endPosition: scriptContentNode.endPosition, + }]; + const jsTree = parser.parse( + sourceCode, + null, + {includedRanges: ranges}, + ); + assert.deepEqual(parser.getIncludedRanges(), ranges); + + assert.equal( + jsTree.rootNode.toString(), + '(program (expression_statement (call_expression ' + + 'function: (member_expression object: (identifier) property: (property_identifier)) ' + + 'arguments: (arguments (string (string_fragment))))))', + ); + assert.deepEqual(jsTree.rootNode.startPosition, {row: 0, column: sourceCode.indexOf('console')}); + }); + }); + describe('multiple included ranges', () => { it('parses the text within multiple ranges', () => { parser.setLanguage(JavaScript); diff --git a/lib/binding_web/tree-sitter-web.d.ts b/lib/binding_web/tree-sitter-web.d.ts index 6bf1af20..dc984bf1 100644 --- a/lib/binding_web/tree-sitter-web.d.ts +++ b/lib/binding_web/tree-sitter-web.d.ts @@ -150,7 +150,7 @@ declare module 'web-tree-sitter' { rootNodeWithOffset(offsetBytes: number, offsetExtent: Point): SyntaxNode; copy(): Tree; delete(): void; - edit(delta: Edit): Tree; + edit(edit: Edit): Tree; walk(): TreeCursor; getChangedRanges(other: Tree): Range[]; getIncludedRanges(): Range[];