From 55194b9d81dc23f65c3907ae289491086e429b63 Mon Sep 17 00:00:00 2001 From: Jolse Maginnis Date: Tue, 17 Mar 2026 22:59:12 +1100 Subject: [PATCH] Fix ?? operator returning wrong result when LHS has array predicate The ?? infix handler reused the same `left` AST node reference for both the $exists() condition and the `then` branch. During AST post-processing, filter stages were pushed onto the shared node twice, turning e.g. `array[1]` into `array[1][1]`. Deep-clone `left` for the condition argument so the two branches have independent AST nodes. Fixes #773 --- src/parser.js | 2 +- test/test-suite/groups/coalescing-operator/case013.json | 7 +++++++ test/test-suite/groups/coalescing-operator/case014.json | 7 +++++++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 test/test-suite/groups/coalescing-operator/case013.json create mode 100644 test/test-suite/groups/coalescing-operator/case014.json diff --git a/src/parser.js b/src/parser.js index a6d4223e..34906054 100644 --- a/src/parser.js +++ b/src/parser.js @@ -585,7 +585,7 @@ const parser = (() => { type: 'function', value: '(', procedure: { type: 'variable', value: 'exists' }, - arguments: [left] + arguments: [JSON.parse(JSON.stringify(left))] }; this.then = left; this.else = expression(0); diff --git a/test/test-suite/groups/coalescing-operator/case013.json b/test/test-suite/groups/coalescing-operator/case013.json new file mode 100644 index 00000000..0f32ae7f --- /dev/null +++ b/test/test-suite/groups/coalescing-operator/case013.json @@ -0,0 +1,7 @@ +{ + "description": "array predicate on lhs exists, should return lhs value", + "expr": "foo.blah[0] ?? 42", + "dataset": "dataset0", + "bindings": {}, + "result": {"baz": {"fud": "hello"}} +} diff --git a/test/test-suite/groups/coalescing-operator/case014.json b/test/test-suite/groups/coalescing-operator/case014.json new file mode 100644 index 00000000..c9b1f463 --- /dev/null +++ b/test/test-suite/groups/coalescing-operator/case014.json @@ -0,0 +1,7 @@ +{ + "description": "array predicate on lhs does not exist, should return rhs value", + "expr": "foo.blah[5] ?? 42", + "dataset": "dataset0", + "bindings": {}, + "result": 42 +}