diff --git a/src/parser.js b/src/parser.js index 97d186e7..352a1d45 100644 --- a/src/parser.js +++ b/src/parser.js @@ -878,7 +878,12 @@ const parser = (() => { // elvis/default operator infix("?:", operators['?:'], function (left) { this.type = 'condition'; - this.condition = left; + // Deep-clone `left` so the condition and then branches have + // independent AST nodes. Sharing the same reference causes + // post-parse processing (e.g. predicate stages, unary minus + // folding on number literals) to mutate the same node twice, + // producing wrong results (see #773 for the equivalent ?? fix). + this.condition = JSON.parse(JSON.stringify(left)); this.then = left; this.else = expression(0); return this; diff --git a/test/test-suite/groups/default-operator/case014.json b/test/test-suite/groups/default-operator/case014.json new file mode 100644 index 00000000..0719d339 --- /dev/null +++ b/test/test-suite/groups/default-operator/case014.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/default-operator/case015.json b/test/test-suite/groups/default-operator/case015.json new file mode 100644 index 00000000..7009e5c0 --- /dev/null +++ b/test/test-suite/groups/default-operator/case015.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 +} diff --git a/test/test-suite/groups/default-operator/case016.json b/test/test-suite/groups/default-operator/case016.json new file mode 100644 index 00000000..c8676686 --- /dev/null +++ b/test/test-suite/groups/default-operator/case016.json @@ -0,0 +1,7 @@ +{ + "description": "negative array index on lhs returns last element", + "expr": "[1,2,3][-1] ?: 42", + "dataset": null, + "bindings": {}, + "result": 3 +} diff --git a/test/test-suite/groups/default-operator/case017.json b/test/test-suite/groups/default-operator/case017.json new file mode 100644 index 00000000..98332d3f --- /dev/null +++ b/test/test-suite/groups/default-operator/case017.json @@ -0,0 +1,7 @@ +{ + "description": "negative array index on single-element array returns the element", + "expr": "[true][-1] ?: \"no\"", + "dataset": null, + "bindings": {}, + "result": true +} diff --git a/test/test-suite/groups/default-operator/case018.json b/test/test-suite/groups/default-operator/case018.json new file mode 100644 index 00000000..f3a81072 --- /dev/null +++ b/test/test-suite/groups/default-operator/case018.json @@ -0,0 +1,7 @@ +{ + "description": "unary minus on number literal LHS is not double-negated", + "expr": "-5 ?: 99", + "dataset": null, + "bindings": {}, + "result": -5 +}