diff --git a/lib/binding_web/binding.js b/lib/binding_web/binding.js index 3d3be350..016fa9ee 100644 --- a/lib/binding_web/binding.js +++ b/lib/binding_web/binding.js @@ -967,12 +967,13 @@ class Query { endPosition.column ); - const count = getValue(TRANSFER_BUFFER, 'i32'); + const rawCount = getValue(TRANSFER_BUFFER, 'i32'); const startAddress = getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32'); - const result = new Array(count); + const result = new Array(rawCount); + let filteredCount = 0; let address = startAddress; - for (let i = 0; i < count; i++) { + for (let i = 0; i < rawCount; i++) { const pattern = getValue(address, 'i32'); address += SIZE_OF_INT; const captureCount = getValue(address, 'i32'); @@ -981,7 +982,7 @@ class Query { const captures = new Array(captureCount); address = unmarshalCaptures(this, node.tree, address, captures); if (this.textPredicates[pattern].every(p => p(captures))) { - result[i] = {pattern, captures}; + result[filteredCount++] = {pattern, captures}; const setProperties = this.setProperties[pattern]; if (setProperties) result[i].setProperties = setProperties; const assertedProperties = this.assertedProperties[pattern]; @@ -990,6 +991,7 @@ class Query { if (refutedProperties) result[i].refutedProperties = refutedProperties; } } + result.length = filteredCount; C._free(startAddress); return result; diff --git a/lib/binding_web/test/query-test.js b/lib/binding_web/test/query-test.js index 23663e9a..77937a45 100644 --- a/lib/binding_web/test/query-test.js +++ b/lib/binding_web/test/query-test.js @@ -81,6 +81,32 @@ describe("Query", () => { { pattern: 0, captures: [{ name: "element", text: "g" }] }, ]); }); + + it("handles predicates that compare the text of capture to literal strings", () => { + tree = parser.parse(` + giraffe(1, 2, []); + helment([false]); + goat(false); + gross(3, []); + hiccup([]); + gaff(5); + `); + + // Find all calls to functions beginning with 'g', where one argument + // is an array literal. + query = JavaScript.query(` + (call_expression + function: (identifier) @name + arguments: (arguments (array)) + (#match? @name "^g")) + `); + + const matches = query.matches(tree.rootNode); + assert.deepEqual(formatMatches(matches), [ + { pattern: 0, captures: [{name: "name", text: "giraffe" }] }, + { pattern: 0, captures: [{name: "name", text: "gross" }] }, + ]); + }); }); describe(".captures", () => {