diff --git a/src/json-expression/__tests__/codegen.spec.ts b/src/json-expression/__tests__/codegen.spec.ts index 41450e015c..24f0cc5fa1 100644 --- a/src/json-expression/__tests__/codegen.spec.ts +++ b/src/json-expression/__tests__/codegen.spec.ts @@ -65,3 +65,22 @@ describe('ne', () => { check(['ne', 3, ['=', '/foo']], false, {foo: 3}); }); }); + +describe('not', () => { + test('on two literals', () => { + check(['!', ['==', 1, 2]], true); + check(['!', ['==', {foo: 'bar'}, {foo: 'bar'}]], false); + check(['not', ['==', {foo: 'bar'}, {foo: 'baz'}]], true); + check(['not', ['==', [[]], [[]]]], false); + }); + + test('literal and expression', () => { + check(['!', ['eq', 3, ['=', '/foo']]], true); + check(['not', ['eq', 'bar', ['eq', 1, 1]]], true); + check(['not', ['eq', true, ['eq', 1, 1]]], false); + }); + + test('together with get', () => { + check(['!', ['eq', 3, ['=', '/foo']]], false, {foo: 3}); + }); +}); diff --git a/src/json-expression/codegen.ts b/src/json-expression/codegen.ts index 5046a7ce66..4abf66cb85 100644 --- a/src/json-expression/codegen.ts +++ b/src/json-expression/codegen.ts @@ -1,4 +1,4 @@ -import type {Expr, ExprEquals, ExprGet, ExprNotEquals, JsonExpressionCodegenContext, JsonExpressionExecutionContext} from './types'; +import type {Expr, ExprEquals, ExprGet, ExprNot, ExprNotEquals, JsonExpressionCodegenContext, JsonExpressionExecutionContext} from './types'; import {Codegen} from '../util/codegen/Codegen'; import {deepEqual} from '../json-equal/deepEqual'; import {toPath, get as get_} from '../json-pointer'; @@ -112,6 +112,12 @@ export class JsonExpressionCodegen { return new Expression(`!(${res})`); } + protected onNot([, a]: ExprNot): ExpressionResult { + const res = this.onExpression(a); + if (res instanceof Literal) return new Literal(!res.val); + return new Expression(`!(${res})`); + } + protected onExpression(expr: Expr | unknown): ExpressionResult { if (!isExpression(expr)) { if (expr instanceof Array) { @@ -128,6 +134,8 @@ export class JsonExpressionCodegen { case 'eq': return this.onEquals(expr as ExprEquals); case '!=': case 'ne': return this.onNotEquals(expr as ExprNotEquals); + case '!': + case 'not': return this.onNot(expr as ExprNot); } return new Literal(false);; }