Skip to content

Commit d4b7bc5

Browse files
committed
Optimize "try" with an interesting technique... it's much more performant
1 parent 1d84786 commit d4b7bc5

File tree

1 file changed

+41
-2
lines changed

1 file changed

+41
-2
lines changed

defaultMethods.js

+41-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable no-ex-assign */
12
/* eslint-disable no-throw-literal */
23
// @ts-check
34
'use strict'
@@ -377,8 +378,41 @@ const defaultMethods = {
377378

378379
throw lastError
379380
},
380-
deterministic: (data, buildState) => isDeterministic(data, buildState.engine, buildState),
381-
lazy: true
381+
deterministic: (data, buildState) => {
382+
return isDeterministic(data[0], buildState.engine, { ...buildState, insideTry: true }) && isDeterministic(data, buildState.engine, { ...buildState, insideIterator: true, insideTry: true })
383+
},
384+
lazy: true,
385+
compile: (data, buildState) => {
386+
if (!Array.isArray(data) || !data.length) return false
387+
let res
388+
try {
389+
res = buildState.compile`((context, above) => { try { return ${data[0]} } catch(err) { above = [null, context, above]; context = { type: err.type || err.message || err.toString() }; `
390+
} catch (err) {
391+
if (Number.isNaN(err)) err = { type: 'NaN' }
392+
res = { [Compiled]: `((context, above) => { { above = [null, context, above]; context = ${JSON.stringify(err)}; ` }
393+
}
394+
395+
if (data.length > 1) {
396+
for (let i = 1; i < data.length; i++) {
397+
try {
398+
if (i === data.length - 1) res = buildState.compile`${res} try { return ${data[i]} } catch(err) { throw err; } `
399+
else res = buildState.compile`${res} try { return ${data[i]} } catch(err) { context = { type: err.type || err.message || err.toString() }; } `
400+
} catch (err) {
401+
if (Number.isNaN(err)) err = { type: 'NaN' }
402+
if (i === data.length - 1) res = buildState.compile`${res} throw ${{ [Compiled]: JSON.stringify(err) }} `
403+
else res = buildState.compile`${res} ${{ [Compiled]: `context = ${JSON.stringify(err)};` }}`
404+
}
405+
}
406+
} else {
407+
if (res[Compiled].includes('err')) res = buildState.compile`${res} throw err;`
408+
else res = buildState.compile`${res} throw context;`
409+
}
410+
411+
res = buildState.compile`${res} } })(context, above)`
412+
if (res[Compiled].includes('await')) res[Compiled] = res[Compiled].replace('((context', '(async (context')
413+
414+
return res
415+
}
382416
},
383417
and: {
384418
[Sync]: (data, buildState) => isSyncDeep(data, buildState.engine, buildState),
@@ -1004,6 +1038,11 @@ defaultMethods['!!'].compile = function (data, buildState) {
10041038
}
10051039
defaultMethods.none.deterministic = defaultMethods.some.deterministic
10061040

1041+
// @ts-ignore
1042+
defaultMethods.throw.deterministic = (data, buildState) => {
1043+
return buildState.insideTry && isDeterministic(data, buildState.engine, buildState)
1044+
}
1045+
10071046
// @ts-ignore Allowing a optimizeUnary attribute that can be used for performance optimizations
10081047
defaultMethods['+'].optimizeUnary = defaultMethods['-'].optimizeUnary = defaultMethods['!'].optimizeUnary = defaultMethods['!!'].optimizeUnary = defaultMethods.cat.optimizeUnary = defaultMethods.throw.optimizeUnary = true
10091048

0 commit comments

Comments
 (0)