Skip to content

Commit 3424094

Browse files
committed
Create a branch that uses hard exceptions instead
1 parent 46e6e5f commit 3424094

File tree

12 files changed

+125
-101
lines changed

12 files changed

+125
-101
lines changed

defaultMethods.js

Lines changed: 60 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -59,27 +59,27 @@ const defaultMethods = {
5959
if (typeof data === 'string') return +data
6060
if (typeof data === 'number') return +data
6161
if (typeof data === 'boolean') return +data
62-
if (typeof data === 'object' && !Array.isArray(data)) return Number.NaN
62+
if (typeof data === 'object' && !Array.isArray(data)) throw new Error('NaN')
6363
let res = 0
6464
for (let i = 0; i < data.length; i++) {
65-
if (data[i] && typeof data[i] === 'object') return Number.NaN
65+
if (data[i] && typeof data[i] === 'object') throw new Error('NaN')
6666
res += +data[i]
6767
}
6868
return res
6969
},
7070
'*': (data) => {
7171
let res = 1
7272
for (let i = 0; i < data.length; i++) {
73-
if (data[i] && typeof data[i] === 'object') return Number.NaN
73+
if (data[i] && typeof data[i] === 'object') throw new Error('NaN')
7474
res *= +data[i]
7575
}
7676
return res
7777
},
7878
'/': (data) => {
79-
if (data[0] && typeof data[0] === 'object') return Number.NaN
79+
if (data[0] && typeof data[0] === 'object') throw new Error('NaN')
8080
let res = +data[0]
8181
for (let i = 1; i < data.length; i++) {
82-
if ((data[i] && typeof data[i] === 'object') || !data[i]) return Number.NaN
82+
if ((data[i] && typeof data[i] === 'object') || !data[i]) throw new Error('NaN')
8383
res /= +data[i]
8484
}
8585
return res
@@ -89,35 +89,27 @@ const defaultMethods = {
8989
if (typeof data === 'string') return -data
9090
if (typeof data === 'number') return -data
9191
if (typeof data === 'boolean') return -data
92-
if (typeof data === 'object' && !Array.isArray(data)) return Number.NaN
93-
if (data[0] && typeof data[0] === 'object') return Number.NaN
92+
if (typeof data === 'object' && !Array.isArray(data)) throw new Error('NaN')
93+
if (data[0] && typeof data[0] === 'object') throw new Error('NaN')
9494
if (data.length === 1) return -data[0]
9595
let res = data[0]
9696
for (let i = 1; i < data.length; i++) {
97-
if (data[i] && typeof data[i] === 'object') return Number.NaN
97+
if (data[i] && typeof data[i] === 'object') throw new Error('NaN')
9898
res -= +data[i]
9999
}
100100
return res
101101
},
102102
'%': (data) => {
103-
if (data[0] && typeof data[0] === 'object') return Number.NaN
103+
if (data[0] && typeof data[0] === 'object') throw new Error('NaN')
104104
let res = +data[0]
105105
for (let i = 1; i < data.length; i++) {
106-
if (data[i] && typeof data[i] === 'object') return Number.NaN
106+
if (data[i] && typeof data[i] === 'object') throw new Error('NaN')
107107
res %= +data[i]
108108
}
109109
return res
110110
},
111111
error: (type) => {
112-
if (Array.isArray(type)) type = type[0]
113-
if (type === 'NaN') return Number.NaN
114-
return { error: type }
115-
},
116-
panic: (item) => {
117-
if (Array.isArray(item)) item = item[0]
118-
if (Number.isNaN(item)) throw new Error('NaN was returned from expression')
119-
if (item && item.error) throw item.error
120-
return item
112+
throw new Error(type)
121113
},
122114
max: (data) => Math.max(...data),
123115
min: (data) => Math.min(...data),
@@ -290,7 +282,52 @@ const defaultMethods = {
290282
lazy: true
291283
},
292284
'??': defineCoalesce(),
293-
try: defineCoalesce(downgrade, true),
285+
try: {
286+
[Sync]: (data, buildState) => isSyncDeep(data, buildState.engine, buildState),
287+
method: (arr, _1, _2, engine) => {
288+
// See "executeInLoop" above
289+
const executeInLoop = Array.isArray(arr)
290+
if (!executeInLoop) arr = engine.run(arr, _1, { above: _2 })
291+
292+
let item
293+
let lastError
294+
for (let i = 0; i < arr.length; i++) {
295+
try {
296+
item = executeInLoop ? engine.run(arr[i], _1, { above: _2 }) : arr[i]
297+
return item
298+
} catch (e) {
299+
// Do nothing
300+
lastError = e
301+
}
302+
}
303+
304+
throw lastError
305+
},
306+
asyncMethod: async (arr, _1, _2, engine) => {
307+
// See "executeInLoop" above
308+
const executeInLoop = Array.isArray(arr)
309+
if (!executeInLoop) arr = await engine.run(arr, _1, { above: _2 })
310+
311+
let item
312+
let lastError
313+
for (let i = 0; i < arr.length; i++) {
314+
try {
315+
item = executeInLoop ? await engine.run(arr[i], _1, { above: _2 }) : arr[i]
316+
return item
317+
} catch (e) {
318+
// Do nothing
319+
lastError = e
320+
}
321+
}
322+
323+
throw lastError
324+
},
325+
deterministic: (data, buildState) => isDeterministic(data, buildState.engine, buildState),
326+
compile: (data, buildState) => {
327+
return false
328+
},
329+
lazy: true
330+
},
294331
and: {
295332
[Sync]: (data, buildState) => isSyncDeep(data, buildState.engine, buildState),
296333
method: (arr, _1, _2, engine) => {
@@ -933,11 +970,11 @@ defaultMethods['/'].compile = function (data, buildState) {
933970
if (Array.isArray(data)) {
934971
return `(${data.map((i, x) => {
935972
let res = numberCoercion(i, buildState)
936-
if (x) res = `(${res}||NaN)`
973+
if (x) res = `(${res}|| (() => { throw new Error() })() )`
937974
return res
938975
}).join(' / ')})`
939976
}
940-
return `(${buildString(data, buildState)}).reduce((a,b) => (+precoerceNumber(a))/(+precoerceNumber(b) || NaN))`
977+
return `(${buildString(data, buildState)}).reduce((a,b) => (+precoerceNumber(a))/(+precoerceNumber(b) || (() => { throw new Error() })() ))`
941978
}
942979
// @ts-ignore Allow custom attribute
943980
defaultMethods['*'].compile = function (data, buildState) {
@@ -964,7 +1001,7 @@ defaultMethods['!!'].compile = function (data, buildState) {
9641001
defaultMethods.none.deterministic = defaultMethods.some.deterministic
9651002

9661003
// @ts-ignore Allowing a optimizeUnary attribute that can be used for performance optimizations
967-
defaultMethods['+'].optimizeUnary = defaultMethods['-'].optimizeUnary = defaultMethods['!'].optimizeUnary = defaultMethods['!!'].optimizeUnary = defaultMethods.cat.optimizeUnary = defaultMethods.error.optimizeUnary = defaultMethods.panic.optimizeUnary = true
1004+
defaultMethods['+'].optimizeUnary = defaultMethods['-'].optimizeUnary = defaultMethods['!'].optimizeUnary = defaultMethods['!!'].optimizeUnary = defaultMethods.cat.optimizeUnary = defaultMethods.error.optimizeUnary = true
9681005

9691006
export default {
9701007
...defaultMethods,

general.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,14 +279,14 @@ describe('Various Test Cases', () => {
279279

280280
it('should throw on a soft error when panic is used', async () => {
281281
const rule = {
282-
panic: { '+': 'hi' }
282+
try: { '+': 'hi' }
283283
}
284284

285285
for (const engine of normalEngines) await testEngine(engine, rule, {}, Error)
286286
for (const engine of permissiveEngines) await testEngine(engine, rule, {}, Error)
287287

288288
const rule2 = {
289-
panic: { error: 'Yeet' }
289+
try: { error: 'Yeet' }
290290
}
291291

292292
for (const engine of normalEngines) await testEngine(engine, rule2, {}, Error)

suites/divide.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -150,37 +150,37 @@
150150
{
151151
"description": "Divide by Zero",
152152
"rule": { "/": [0, 0] },
153-
"result": { "error": "NaN" },
153+
"error": true,
154154
"data": null
155155
},
156156
{
157157
"description": "Divide by NaN",
158158
"rule": { "/": [1, { "error": "NaN" }] },
159-
"result": { "error": "NaN" },
159+
"error": true,
160160
"data": null
161161
},
162162
{
163163
"description": "Divide with String produces NaN",
164164
"rule": { "/": [1, "a"] },
165-
"result": { "error": "NaN" },
165+
"error": true,
166166
"data": null
167167
},
168168
{
169169
"description": "Divide with Array produces NaN",
170170
"rule": { "/": [1, [1]] },
171-
"result": { "error": "NaN" },
171+
"error": true,
172172
"data": null
173173
},
174174
{
175175
"description": "Any division by zero should return NaN",
176176
"rule": { "/": [1, 0] },
177-
"result": { "error": "NaN" },
177+
"error": true,
178178
"data": null
179179
},
180180
{
181181
"description": "Any division by zero should return NaN (2)",
182182
"rule": { "/": [8, 2, 0] },
183-
"result": { "error": "NaN" },
183+
"error": true,
184184
"data": null
185185
}
186186
]

suites/error.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[
2+
{
3+
"description": "Creates an error object",
4+
"rule": { "error": "hello" },
5+
"data": null,
6+
"error": true
7+
},
8+
{
9+
"description": "NaN creates an error object or measured equivalent (equivalence class test)",
10+
"rule": { "error": "NaN" },
11+
"data": null,
12+
"error": true
13+
}
14+
]

suites/minus.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,19 +118,19 @@
118118
{
119119
"description": "Subtraction with NaN",
120120
"rule": { "-": [{ "error": "NaN" }, 1] },
121-
"result": { "error": "NaN" },
121+
"error": true,
122122
"data": null
123123
},
124124
{
125125
"description": "Subtraction with string produces NaN",
126126
"rule": { "-": ["Hey", 1] },
127-
"result": { "error": "NaN" },
127+
"error": true,
128128
"data": null
129129
},
130130
{
131131
"description": "Subtraction with Array produces NaN",
132132
"rule": { "-": [[1], 1] },
133-
"result": { "error": "NaN" },
133+
"error": true,
134134
"data": null
135135
}
136136
]

suites/modulo.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,19 +161,19 @@
161161
{
162162
"description": "Modulo with NaN",
163163
"rule": { "%": [{ "error": "NaN" }, 1] },
164-
"result": { "error": "NaN" },
164+
"error": true,
165165
"data": null
166166
},
167167
{
168168
"description": "Modulo with string produces NaN",
169169
"rule": { "%": ["Hey", 1] },
170-
"result": { "error": "NaN" },
170+
"error": true,
171171
"data": null
172172
},
173173
{
174174
"description": "Modulo with array produces NaN",
175175
"rule": { "%": [[1], 1] },
176-
"result": { "error": "NaN" },
176+
"error": true,
177177
"data": null
178178
}
179179
]

suites/multiply.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,19 +148,19 @@
148148
{
149149
"description": "Multiply with NaN",
150150
"rule": { "*": [{ "error": "NaN" }, 1] },
151-
"result": { "error": "NaN" },
151+
"error": true,
152152
"data": null
153153
},
154154
{
155155
"description": "Multiply with string produces NaN",
156156
"rule": { "*": ["Hey", 1] },
157-
"result": { "error": "NaN" },
157+
"error": true,
158158
"data": null
159159
},
160160
{
161161
"description": "Multiply with Array produces NaN",
162162
"rule": { "*": [[1], 1] },
163-
"result": { "error": "NaN" },
163+
"error": true,
164164
"data": null
165165
}
166166
]

suites/panic.json

Lines changed: 0 additions & 32 deletions
This file was deleted.

0 commit comments

Comments
 (0)