diff --git a/packages/shared/src/models/dataPipe/operators/filter.spec.ts b/packages/shared/src/models/dataPipe/operators/filter.spec.ts index 0beb5b54e9..d1ee031cfd 100644 --- a/packages/shared/src/models/dataPipe/operators/filter.spec.ts +++ b/packages/shared/src/models/dataPipe/operators/filter.spec.ts @@ -32,4 +32,11 @@ describe("Filter", () => { const outputIDs = output.column("first_name").values; expect(outputIDs).toEqual(["Ada"]); }); + it("Ignores context variables that do not appear in condition string", () => { + // Passing a function to evaluator would throw error if not ignored + const testDf = new DataFrame([{ first_name: "Ada", invalid: new Function() }]); + const output = new filter(testDf, ["first_name === 'Ada'"]).apply(); + const outputIDs = output.column("first_name").values; + expect(outputIDs).toEqual(["Ada"]); + }); }); diff --git a/packages/shared/src/models/dataPipe/operators/filter.ts b/packages/shared/src/models/dataPipe/operators/filter.ts index 21a360d624..7aa14e96a6 100644 --- a/packages/shared/src/models/dataPipe/operators/filter.ts +++ b/packages/shared/src/models/dataPipe/operators/filter.ts @@ -23,8 +23,8 @@ class FilterOperator extends BaseOperator { public satisfiesFilters(row: any) { const evaluator = new JSEvaluator(); - evaluator.setGlobalContext({ constants: row }); return this.filterConditions.every((condition) => { + evaluator.setGlobalContext({ constants: this.generateEvaluatorConstants(condition, row) }); try { /** * row fields can be accessed both from global and local context, e.g. @@ -39,6 +39,20 @@ class FilterOperator extends BaseOperator { } }); } + + /** + * Create a list of all key-value pairs of row data whose keys appear within condition string + * This reduces the complexity of later JS evaluation + **/ + private generateEvaluatorConstants(condition: string, row: Record) { + const constants: Record = {}; + for (const [key, value] of Object.entries(row)) { + if (condition.includes(key)) { + constants[key] = value; + } + } + return constants; + } } class FilterAnyOperator extends FilterOperator {