Skip to content

Commit 4686e90

Browse files
committed
Adds error coalescing
1 parent f33b29d commit 4686e90

File tree

4 files changed

+36
-7
lines changed

4 files changed

+36
-7
lines changed

compiler.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
import asyncIterators from './async_iterators.js'
1212
import { coerceArray } from './utilities/coerceArray.js'
1313
import { countArguments } from './utilities/countArguments.js'
14+
import { downgrade } from './utilities/downgrade.js'
1415

1516
/**
1617
* Provides a simple way to compile logic into a function that can be run.
@@ -307,12 +308,12 @@ function processBuiltString (method, str, buildState) {
307308
str = str.replace(`__%%%${x}%%%__`, item)
308309
})
309310

310-
const final = `(values, methods, notTraversed, asyncIterators, engine, above, coerceArray) => ${buildState.asyncDetected ? 'async' : ''} (context ${buildState.extraArguments ? ',' + buildState.extraArguments : ''}) => { let prev; const result = ${str}; return result }`
311+
const final = `(values, methods, notTraversed, asyncIterators, engine, above, coerceArray, downgrade) => ${buildState.asyncDetected ? 'async' : ''} (context ${buildState.extraArguments ? ',' + buildState.extraArguments : ''}) => { let prev; const result = ${str}; return result }`
311312
// console.log(str)
312-
// console.log(final)
313+
console.log(final)
313314
// eslint-disable-next-line no-eval
314315
return Object.assign(
315-
(typeof globalThis !== 'undefined' ? globalThis : global).eval(final)(values, methods, notTraversed, asyncIterators, engine, above, coerceArray), {
316+
(typeof globalThis !== 'undefined' ? globalThis : global).eval(final)(values, methods, notTraversed, asyncIterators, engine, above, coerceArray, downgrade), {
316317
[Sync]: !buildState.asyncDetected,
317318
aboveDetected: typeof str === 'string' && str.includes(', above')
318319
})

defaultMethods.js

+10-4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { build, buildString } from './compiler.js'
88
import chainingSupported from './utilities/chainingSupported.js'
99
import InvalidControlInput from './errors/InvalidControlInput.js'
1010
import legacyMethods from './legacy.js'
11+
import { downgrade } from './utilities/downgrade.js'
1112

1213
function isDeterministic (method, engine, buildState) {
1314
if (Array.isArray(method)) {
@@ -255,7 +256,7 @@ const defaultMethods = {
255256
let item
256257
for (let i = 0; i < arr.length; i++) {
257258
item = executeInLoop ? engine.run(arr[i], _1, { above: _2 }) : arr[i]
258-
if (item !== null && item !== undefined) return item
259+
if (downgrade(item) !== null && item !== undefined) return item
259260
}
260261

261262
if (item === undefined) return null
@@ -269,7 +270,7 @@ const defaultMethods = {
269270
let item
270271
for (let i = 0; i < arr.length; i++) {
271272
item = executeInLoop ? await engine.run(arr[i], _1, { above: _2 }) : arr[i]
272-
if (item !== null && item !== undefined) return item
273+
if (downgrade(item) !== null && item !== undefined) return item
273274
}
274275

275276
if (item === undefined) return null
@@ -278,8 +279,13 @@ const defaultMethods = {
278279
deterministic: (data, buildState) => isDeterministic(data, buildState.engine, buildState),
279280
compile: (data, buildState) => {
280281
if (!chainingSupported) return false
281-
if (Array.isArray(data) && data.length) return `(${data.map((i) => buildString(i, buildState)).join(' ?? ')})`
282-
return `(${buildString(data, buildState)}).reduce((a,b) => a ?? b, null)`
282+
if (Array.isArray(data) && data.length) {
283+
return `(${data.map((i, x) => {
284+
if (Array.isArray(i) || !i || typeof i !== 'object' || x === data.length - 1) return buildString(i, buildState)
285+
return 'downgrade(' + buildString(i, buildState) + ')'
286+
}).join(' ?? ')})`
287+
}
288+
return `(${buildString(data, buildState)}).reduce((a,b) => downgrade(a) ?? b, null)`
283289
},
284290
traverse: false
285291
},

suites/errors.json

+12
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,17 @@
1111
"rule": { "!!": { "error": "Some error" } },
1212
"result": true,
1313
"data": null
14+
},
15+
{
16+
"description": "Coalesce an error",
17+
"rule": { "??": [{ "error": "Some error" }, 1] },
18+
"result": 1,
19+
"data": null
20+
},
21+
{
22+
"description": "Coalesce an emitted error",
23+
"rule": { "??": [{ "+": [{ "val": "hello" }]}, 1] },
24+
"result": 1,
25+
"data": { "hello": "world" }
1426
}
1527
]

utilities/downgrade.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
/**
3+
* Used to make an "error" piece of data null, for the purposes of coalescing.
4+
* @param {any} item
5+
*/
6+
export function downgrade (item) {
7+
if (item && typeof item === 'object' && 'error' in item) return null
8+
if (Number.isNaN(item)) return null
9+
return item
10+
}

0 commit comments

Comments
 (0)