Skip to content

Commit 21390af

Browse files
ribru17WillLillis
authored andcommitted
fix(web): correct childWithDescendant() functionality
This fix allows for more granular address control when marshalling nodes across WASM. This is necessary for node methods which accept another node as a parameter (i.e., `childWithDescendant()`)
1 parent 45a281c commit 21390af

File tree

4 files changed

+30
-10
lines changed

4 files changed

+30
-10
lines changed

lib/binding_web/lib/tree-sitter.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,22 @@ static inline void marshal_node(const void **buffer, TSNode node) {
4444
buffer[4] = (const void *)node.context[3];
4545
}
4646

47-
static inline TSNode unmarshal_node(const TSTree *tree) {
47+
static inline TSNode unmarshal_node_at(const TSTree *tree, uint32_t index) {
4848
TSNode node;
49-
node.id = TRANSFER_BUFFER[0];
50-
node.context[0] = code_unit_to_byte((uint32_t)TRANSFER_BUFFER[1]);
51-
node.context[1] = (uint32_t)TRANSFER_BUFFER[2];
52-
node.context[2] = code_unit_to_byte((uint32_t)TRANSFER_BUFFER[3]);
53-
node.context[3] = (uint32_t)TRANSFER_BUFFER[4];
49+
const void **buffer = TRANSFER_BUFFER + index * SIZE_OF_NODE;
50+
node.id = buffer[0];
51+
node.context[0] = code_unit_to_byte((uint32_t)buffer[1]);
52+
node.context[1] = (uint32_t)buffer[2];
53+
node.context[2] = code_unit_to_byte((uint32_t)buffer[3]);
54+
node.context[3] = (uint32_t)buffer[4];
5455
node.tree = tree;
5556
return node;
5657
}
5758

59+
static inline TSNode unmarshal_node(const TSTree *tree) {
60+
return unmarshal_node_at(tree, 0);
61+
}
62+
5863
static inline void marshal_cursor(const TSTreeCursor *cursor) {
5964
TRANSFER_BUFFER[0] = cursor->id;
6065
TRANSFER_BUFFER[1] = (const void *)cursor->context[0];
@@ -616,7 +621,7 @@ void ts_node_parent_wasm(const TSTree *tree) {
616621

617622
void ts_node_child_with_descendant_wasm(const TSTree *tree) {
618623
TSNode node = unmarshal_node(tree);
619-
TSNode descendant = unmarshal_node(tree);
624+
TSNode descendant = unmarshal_node_at(tree, 1);
620625
marshal_node(TRANSFER_BUFFER, ts_node_child_with_descendant(node, descendant));
621626
}
622627

lib/binding_web/src/marshal.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ export function unmarshalCaptures(
3434
*
3535
* Marshals a {@link Node} to the transfer buffer.
3636
*/
37-
export function marshalNode(node: Node) {
38-
let address = TRANSFER_BUFFER;
37+
export function marshalNode(node: Node, index = 0) {
38+
let address = TRANSFER_BUFFER + index * SIZE_OF_NODE;
3939
C.setValue(address, node.id, 'i32');
4040
address += SIZE_OF_INT;
4141
C.setValue(address, node.startIndex, 'i32');

lib/binding_web/src/node.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ export class Node {
522522
*/
523523
childWithDescendant(descendant: Node): Node | null {
524524
marshalNode(this);
525-
marshalNode(descendant);
525+
marshalNode(descendant, 1);
526526
C._ts_node_child_with_descendant_wasm(this.tree[0]);
527527
return unmarshalNode(this.tree);
528528
}

lib/binding_web/test/node.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,21 @@ describe('Node', () => {
189189
});
190190
});
191191

192+
describe('.childWithDescendant()', () => {
193+
it('correctly retrieves immediate children', () => {
194+
const sourceCode = 'let x = 1; console.log(x);';
195+
tree = parser.parse(sourceCode)!;
196+
const root = tree.rootNode
197+
const child = root.children[0].children[0]
198+
const a = root.childWithDescendant(child)
199+
expect(a!.startIndex).toBe(0)
200+
const b = a!.childWithDescendant(child)
201+
expect(b).toEqual(child)
202+
const c = b!.childWithDescendant(child)
203+
expect(c).toBeNull()
204+
});
205+
});
206+
192207
describe('.nextSibling and .previousSibling', () => {
193208
it('returns the node\'s next and previous sibling', () => {
194209
tree = parser.parse('x10 + 1000')!;

0 commit comments

Comments
 (0)