Skip to content

Commit 1c77b90

Browse files
committed
Switch from ?? to try
1 parent 5618bf9 commit 1c77b90

File tree

2 files changed

+59
-46
lines changed

2 files changed

+59
-46
lines changed

defaultMethods.js

Lines changed: 56 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -247,49 +247,6 @@ const defaultMethods = {
247247
xor: ([a, b]) => a ^ b,
248248
// Why "executeInLoop"? Because if it needs to execute to get an array, I do not want to execute the arguments,
249249
// Both for performance and safety reasons.
250-
'??': {
251-
[Sync]: (data, buildState) => isSyncDeep(data, buildState.engine, buildState),
252-
method: (arr, _1, _2, engine) => {
253-
// See "executeInLoop" above
254-
const executeInLoop = Array.isArray(arr)
255-
if (!executeInLoop) arr = engine.run(arr, _1, { above: _2 })
256-
257-
let item
258-
for (let i = 0; i < arr.length; i++) {
259-
item = executeInLoop ? engine.run(arr[i], _1, { above: _2 }) : arr[i]
260-
if (downgrade(item) !== null && item !== undefined) return item
261-
}
262-
263-
if (item === undefined) return null
264-
return item
265-
},
266-
asyncMethod: async (arr, _1, _2, engine) => {
267-
// See "executeInLoop" above
268-
const executeInLoop = Array.isArray(arr)
269-
if (!executeInLoop) arr = await engine.run(arr, _1, { above: _2 })
270-
271-
let item
272-
for (let i = 0; i < arr.length; i++) {
273-
item = executeInLoop ? await engine.run(arr[i], _1, { above: _2 }) : arr[i]
274-
if (downgrade(item) !== null && item !== undefined) return item
275-
}
276-
277-
if (item === undefined) return null
278-
return item
279-
},
280-
deterministic: (data, buildState) => isDeterministic(data, buildState.engine, buildState),
281-
compile: (data, buildState) => {
282-
if (!chainingSupported) return false
283-
if (Array.isArray(data) && data.length) {
284-
return `(${data.map((i, x) => {
285-
if (Array.isArray(i) || !i || typeof i !== 'object' || x === data.length - 1) return buildString(i, buildState)
286-
return 'downgrade(' + buildString(i, buildState) + ')'
287-
}).join(' ?? ')})`
288-
}
289-
return `(${buildString(data, buildState)}).reduce((a,b) => downgrade(a) ?? b, null)`
290-
},
291-
traverse: false
292-
},
293250
or: {
294251
[Sync]: (data, buildState) => isSyncDeep(data, buildState.engine, buildState),
295252
method: (arr, _1, _2, engine) => {
@@ -326,6 +283,8 @@ const defaultMethods = {
326283
},
327284
traverse: false
328285
},
286+
'??': defineCoalesce(),
287+
try: defineCoalesce(downgrade),
329288
and: {
330289
[Sync]: (data, buildState) => isSyncDeep(data, buildState.engine, buildState),
331290
method: (arr, _1, _2, engine) => {
@@ -719,6 +678,60 @@ const defaultMethods = {
719678
}
720679
}
721680

681+
/**
682+
* Defines separate coalesce methods
683+
*/
684+
function defineCoalesce (func) {
685+
let downgrade
686+
if (func) downgrade = func
687+
else downgrade = (a) => a
688+
689+
return {
690+
[Sync]: (data, buildState) => isSyncDeep(data, buildState.engine, buildState),
691+
method: (arr, _1, _2, engine) => {
692+
// See "executeInLoop" above
693+
const executeInLoop = Array.isArray(arr)
694+
if (!executeInLoop) arr = engine.run(arr, _1, { above: _2 })
695+
696+
let item
697+
for (let i = 0; i < arr.length; i++) {
698+
item = executeInLoop ? engine.run(arr[i], _1, { above: _2 }) : arr[i]
699+
if (downgrade(item) !== null && item !== undefined) return item
700+
}
701+
702+
if (item === undefined) return null
703+
return item
704+
},
705+
asyncMethod: async (arr, _1, _2, engine) => {
706+
// See "executeInLoop" above
707+
const executeInLoop = Array.isArray(arr)
708+
if (!executeInLoop) arr = await engine.run(arr, _1, { above: _2 })
709+
710+
let item
711+
for (let i = 0; i < arr.length; i++) {
712+
item = executeInLoop ? await engine.run(arr[i], _1, { above: _2 }) : arr[i]
713+
if (downgrade(item) !== null && item !== undefined) return item
714+
}
715+
716+
if (item === undefined) return null
717+
return item
718+
},
719+
deterministic: (data, buildState) => isDeterministic(data, buildState.engine, buildState),
720+
compile: (data, buildState) => {
721+
if (!chainingSupported) return false
722+
const funcCall = func ? 'downgrade' : ''
723+
if (Array.isArray(data) && data.length) {
724+
return `(${data.map((i, x) => {
725+
if (Array.isArray(i) || !i || typeof i !== 'object' || x === data.length - 1) return buildString(i, buildState)
726+
return `${funcCall}(` + buildString(i, buildState) + ')'
727+
}).join(' ?? ')})`
728+
}
729+
return `(${buildString(data, buildState)}).reduce((a,b) => ${funcCall}(a) ?? b, null)`
730+
},
731+
traverse: false
732+
}
733+
}
734+
722735
function createArrayIterativeMethod (name, useTruthy = false) {
723736
return {
724737
deterministic: (data, buildState) => {

suites/errors.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,19 @@
1414
},
1515
{
1616
"description": "Coalesce an error",
17-
"rule": { "??": [{ "error": "Some error" }, 1] },
17+
"rule": { "try": [{ "error": "Some error" }, 1] },
1818
"result": 1,
1919
"data": null
2020
},
2121
{
2222
"description": "Coalesce an emitted error",
23-
"rule": { "??": [{ "+": [{ "val": "hello" }]}, 1] },
23+
"rule": { "try": [{ "+": [{ "val": "hello" }]}, 1] },
2424
"result": 1,
2525
"data": { "hello": "world" }
2626
},
2727
{
2828
"description": "Errors are just data",
29-
"rule": { "??": [{ "val": "x" }, 1]},
29+
"rule": { "try": [{ "val": "x" }, 1]},
3030
"data": { "x": { "error": "Some error" }},
3131
"result": 1
3232
}

0 commit comments

Comments
 (0)