Skip to content

Commit 2217e6d

Browse files
committed
Switch to variadic comparison operators a bit early. This is a change I'd strongly like to implement.
1 parent 359e5a8 commit 2217e6d

File tree

3 files changed

+158
-27
lines changed

3 files changed

+158
-27
lines changed

defaultMethods.js

+88-26
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,6 @@ const defaultMethods = {
8484
max: (data) => Math.max(...data),
8585
min: (data) => Math.min(...data),
8686
in: ([item, array]) => (array || []).includes(item),
87-
'>': ([a, b]) => a > b,
88-
'<': ([a, b, c]) => (c === undefined ? a < b : a < b && b < c),
8987
preserve: {
9088
traverse: false,
9189
method: declareSync((i) => i, true),
@@ -150,14 +148,66 @@ const defaultMethods = {
150148
},
151149
traverse: false
152150
},
153-
'<=': ([a, b, c]) => (c === undefined ? a <= b : a <= b && b <= c),
154-
'>=': ([a, b]) => a >= b,
155-
// eslint-disable-next-line eqeqeq
156-
'==': ([a, b]) => a == b,
157-
'===': ([a, b]) => a === b,
158-
// eslint-disable-next-line eqeqeq
159-
'!=': ([a, b]) => a != b,
160-
'!==': ([a, b]) => a !== b,
151+
'<': (args) => {
152+
if (args.length === 2) return args[0] < args[1]
153+
for (let i = 1; i < args.length; i++) {
154+
if (args[i - 1] >= args[i]) return false
155+
}
156+
return true
157+
},
158+
'<=': (args) => {
159+
if (args.length === 2) return args[0] <= args[1]
160+
for (let i = 1; i < args.length; i++) {
161+
if (args[i - 1] > args[i]) return false
162+
}
163+
return true
164+
},
165+
'>': (args) => {
166+
if (args.length === 2) return args[0] > args[1]
167+
for (let i = 1; i < args.length; i++) {
168+
if (args[i - 1] <= args[i]) return false
169+
}
170+
return true
171+
},
172+
'>=': (args) => {
173+
if (args.length === 2) return args[0] >= args[1]
174+
for (let i = 1; i < args.length; i++) {
175+
if (args[i - 1] < args[i]) return false
176+
}
177+
return true
178+
},
179+
'==': (args) => {
180+
// eslint-disable-next-line eqeqeq
181+
if (args.length === 2) return args[0] == args[1]
182+
for (let i = 1; i < args.length; i++) {
183+
// eslint-disable-next-line eqeqeq
184+
if (args[i - 1] != args[i]) return false
185+
}
186+
return true
187+
},
188+
'===': (args) => {
189+
if (args.length === 2) return args[0] === args[1]
190+
for (let i = 1; i < args.length; i++) {
191+
if (args[i - 1] !== args[i]) return false
192+
}
193+
return true
194+
},
195+
'!=': (args) => {
196+
// eslint-disable-next-line eqeqeq
197+
if (args.length === 2) return args[0] != args[1]
198+
for (let i = 1; i < args.length; i++) {
199+
// eslint-disable-next-line eqeqeq
200+
if (args[i - 1] == args[i]) return false
201+
}
202+
return true
203+
},
204+
'!==': (args) => {
205+
if (args.length === 2) return args[0] !== args[1]
206+
for (let i = 1; i < args.length; i++) {
207+
if (args[i - 1] === args[i]) return false
208+
}
209+
return true
210+
},
161211
xor: ([a, b]) => a ^ b,
162212
// Why "executeInLoop"? Because if it needs to execute to get an array, I do not want to execute the arguments,
163213
// Both for performance and safety reasons.
@@ -641,16 +691,18 @@ Object.assign(defaultMethods.missing_some, {
641691
// @ts-ignore Allow custom attribute
642692
defaultMethods['<'].compile = function (data, buildState) {
643693
if (!Array.isArray(data)) return false
644-
if (data.length === 2) return buildState.compile`(${data[0]} < ${data[1]})`
645-
if (data.length === 3) return buildState.compile`(${data[0]} < ${data[1]} && ${data[1]} < ${data[2]})`
646-
return false
694+
if (data.length < 2) return false
695+
let res = buildState.compile`(${data[0]} < ${data[1]})`
696+
for (let i = 2; i < data.length; i++) res = buildState.compile`(${res} && ${data[i - 1]} < ${data[i]})`
697+
return res
647698
}
648699
// @ts-ignore Allow custom attribute
649700
defaultMethods['<='].compile = function (data, buildState) {
650701
if (!Array.isArray(data)) return false
651-
if (data.length === 2) return buildState.compile`(${data[0]} <= ${data[1]})`
652-
if (data.length === 3) return buildState.compile`(${data[0]} <= ${data[1]} && ${data[1]} <= ${data[2]})`
653-
return false
702+
if (data.length < 2) return false
703+
let res = buildState.compile`(${data[0]} <= ${data[1]})`
704+
for (let i = 2; i < data.length; i++) res = buildState.compile`(${res} && ${data[i - 1]} <= ${data[i]})`
705+
return res
654706
}
655707
// @ts-ignore Allow custom attribute
656708
defaultMethods.min.compile = function (data, buildState) {
@@ -669,26 +721,34 @@ defaultMethods.max.compile = function (data, buildState) {
669721
// @ts-ignore Allow custom attribute
670722
defaultMethods['>'].compile = function (data, buildState) {
671723
if (!Array.isArray(data)) return false
672-
if (data.length !== 2) return false
673-
return buildState.compile`(${data[0]} > ${data[1]})`
724+
if (data.length < 2) return false
725+
let res = buildState.compile`(${data[0]} > ${data[1]})`
726+
for (let i = 2; i < data.length; i++) res = buildState.compile`(${res} && ${data[i - 1]} > ${data[i]})`
727+
return res
674728
}
675729
// @ts-ignore Allow custom attribute
676730
defaultMethods['>='].compile = function (data, buildState) {
677731
if (!Array.isArray(data)) return false
678-
if (data.length !== 2) return false
679-
return buildState.compile`(${data[0]} >= ${data[1]})`
732+
if (data.length < 2) return false
733+
let res = buildState.compile`(${data[0]} >= ${data[1]})`
734+
for (let i = 2; i < data.length; i++) res = buildState.compile`(${res} && ${data[i - 1]} >= ${data[i]})`
735+
return res
680736
}
681737
// @ts-ignore Allow custom attribute
682738
defaultMethods['=='].compile = function (data, buildState) {
683739
if (!Array.isArray(data)) return false
684-
if (data.length !== 2) return false
685-
return buildState.compile`(${data[0]} == ${data[1]})`
740+
if (data.length < 2) return false
741+
let res = buildState.compile`(${data[0]} == ${data[1]})`
742+
for (let i = 2; i < data.length; i++) res = buildState.compile`(${res} && ${data[i - 1]} == ${data[i]})`
743+
return res
686744
}
687745
// @ts-ignore Allow custom attribute
688746
defaultMethods['!='].compile = function (data, buildState) {
689747
if (!Array.isArray(data)) return false
690-
if (data.length !== 2) return false
691-
return buildState.compile`(${data[0]} != ${data[1]})`
748+
if (data.length < 2) return false
749+
let res = buildState.compile`(${data[0]} != ${data[1]})`
750+
for (let i = 2; i < data.length; i++) res = buildState.compile`(${res} && ${data[i - 1]} != ${data[i]})`
751+
return res
692752
}
693753
// @ts-ignore Allow custom attribute
694754
defaultMethods.if.compile = function (data, buildState) {
@@ -711,8 +771,10 @@ defaultMethods.if.compile = function (data, buildState) {
711771
// @ts-ignore Allow custom attribute
712772
defaultMethods['==='].compile = function (data, buildState) {
713773
if (!Array.isArray(data)) return false
714-
if (data.length !== 2) return false
715-
return buildState.compile`(${data[0]} === ${data[1]})`
774+
if (data.length < 2) return false
775+
let res = buildState.compile`(${data[0]} === ${data[1]})`
776+
for (let i = 2; i < data.length; i++) res = buildState.compile`(${res} && ${data[i - 1]} === ${data[i]})`
777+
return res
716778
}
717779
// @ts-ignore Allow custom attribute
718780
defaultMethods['+'].compile = function (data, buildState) {

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "json-logic-engine",
3-
"version": "4.0.3",
3+
"version": "4.0.4",
44
"description": "Construct complex rules with JSON & process them.",
55
"main": "./dist/cjs/index.js",
66
"module": "./dist/esm/index.js",

suites/comparison.json

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
[
2+
"This is a set of comparisons with variadic amounts",
3+
{
4+
"description": "< with 3 arguments",
5+
"rule": { "<": [1, 2, 3] },
6+
"data": {},
7+
"result": true
8+
},
9+
{
10+
"description": "> with 3 arguments",
11+
"rule": { ">": [3, 2, 1] },
12+
"data": {},
13+
"result": true
14+
},
15+
{
16+
"description": "> with 3 arguments failing",
17+
"rule": { ">": [3, 2, 3] },
18+
"data": {},
19+
"result": false
20+
},
21+
{
22+
"description": ">= with 3 arguments",
23+
"rule": { ">=": [3, 3, 1] },
24+
"data": {},
25+
"result": true
26+
},
27+
{
28+
"description": ">= with 3 arguments failing",
29+
"rule": { ">=": [3, 3, 4] },
30+
"data": {},
31+
"result": false
32+
},
33+
{
34+
"description": "== with 3 arguments",
35+
"rule": { "==": [3, 3, 3] },
36+
"data": {},
37+
"result": true
38+
},
39+
{
40+
"description": "== with 3 arguments failing",
41+
"rule": { "==": [3, 2, 3] },
42+
"data": {},
43+
"result": false
44+
},
45+
{
46+
"description": "!= with 3 arguments",
47+
"rule": { "!=": [3, 2, 3] },
48+
"data": {},
49+
"result": true
50+
},
51+
{
52+
"description": "!== with 3 arguments failing",
53+
"rule": { "!==": [3, 3, 3] },
54+
"data": {},
55+
"result": false
56+
},
57+
{
58+
"description": "=== with 3 arguments",
59+
"rule": { "===": [3, 3, 3] },
60+
"data": {},
61+
"result": true
62+
},
63+
{
64+
"description": "=== with 3 arguments failing",
65+
"rule": { "===": [3, 3, 2] },
66+
"data": {},
67+
"result": false
68+
}
69+
]

0 commit comments

Comments
 (0)