Skip to content

Commit ddd886e

Browse files
committed
Some of the rewrites made things mildly slower, so I looked for an optimization to speed things back up. I've added a micro-optimization for val/var, making things generally more performant.
1 parent 3609975 commit ddd886e

File tree

5 files changed

+29
-9
lines changed

5 files changed

+29
-9
lines changed

asyncLogic.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import defaultMethods from './defaultMethods.js'
55
import LogicEngine from './logic.js'
6-
import { isSync } from './constants.js'
6+
import { isSync, OriginalImpl } from './constants.js'
77
import declareSync from './utilities/declareSync.js'
88
import { buildAsync } from './compiler.js'
99
import omitUndefined from './utilities/omitUndefined.js'
@@ -75,6 +75,13 @@ class AsyncLogicEngine {
7575
if (this.isData(logic, func)) return logic
7676
if (!this.methods[func]) throw new Error(`Method '${func}' was not found in the Logic Engine.`)
7777

78+
// A small but useful micro-optimization for some of the most common functions.
79+
// Later on, I could define something to shut this off if var / val are redefined.
80+
if ((func === 'var' || func === 'val') && this.methods[func][OriginalImpl]) {
81+
const input = (!data || typeof data !== 'object') ? data : this.fallback.run(data, context, { above })
82+
return this.methods[func].method(input, context, above, this)
83+
}
84+
7885
if (typeof this.methods[func] === 'function') {
7986
const input = (!data || typeof data !== 'object') ? [data] : await this.run(data, context, { above })
8087
const result = await this.methods[func](coerceArray(input), context, above, this)
@@ -210,5 +217,5 @@ class AsyncLogicEngine {
210217
return logic
211218
}
212219
}
213-
Object.assign(AsyncLogicEngine.prototype.truthy, { IDENTITY: true })
220+
Object.assign(AsyncLogicEngine.prototype.truthy, { [OriginalImpl]: true })
214221
export default AsyncLogicEngine

constants.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
export const Sync = Symbol.for('json_logic_sync')
55
export const Compiled = Symbol.for('json_logic_compiled')
6-
export const EfficientTop = Symbol.for('json_logic_efficientTop')
6+
export const OriginalImpl = Symbol.for('json_logic_original')
77
export const Unfound = Symbol.for('json_logic_unfound')
88

99
/**
@@ -23,6 +23,6 @@ export function isSync (item) {
2323

2424
export default {
2525
Sync,
26-
EfficientTop,
26+
OriginalImpl,
2727
isSync
2828
}

defaultMethods.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
'use strict'
33

44
import asyncIterators from './async_iterators.js'
5-
import { Sync, isSync, Unfound } from './constants.js'
5+
import { Sync, isSync, Unfound, OriginalImpl } from './constants.js'
66
import declareSync from './utilities/declareSync.js'
77
import { build, buildString } from './compiler.js'
88
import chainingSupported from './utilities/chainingSupported.js'
@@ -277,7 +277,7 @@ const defaultMethods = {
277277
},
278278
deterministic: (data, buildState) => isDeterministic(data, buildState.engine, buildState),
279279
compile: (data, buildState) => {
280-
if (!buildState.engine.truthy.IDENTITY) return false
280+
if (!buildState.engine.truthy[OriginalImpl]) return false
281281
if (Array.isArray(data) && data.length) return `(${data.map((i) => buildString(i, buildState)).join(' || ')})`
282282
return `(${buildString(data, buildState)}).reduce((a,b) => a||b, false)`
283283
},
@@ -311,7 +311,7 @@ const defaultMethods = {
311311
traverse: false,
312312
deterministic: (data, buildState) => isDeterministic(data, buildState.engine, buildState),
313313
compile: (data, buildState) => {
314-
if (!buildState.engine.truthy.IDENTITY) return false
314+
if (!buildState.engine.truthy[OriginalImpl]) return false
315315
if (Array.isArray(data) && data.length) return `(${data.map((i) => buildString(i, buildState)).join(' && ')})`
316316
return `(${buildString(data, buildState)}).reduce((a,b) => a&&b, true)`
317317
}
@@ -337,6 +337,7 @@ const defaultMethods = {
337337
deterministic: false
338338
},
339339
val: {
340+
[OriginalImpl]: true,
340341
method: (args, context, above, engine, /** @type {null | Symbol} */ unFound = null) => {
341342
if (Array.isArray(args) && args.length === 1) args = args[0]
342343
// A unary optimization

legacy.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
'use strict'
12
import { buildString } from './compiler.js'
23
import { splitPathMemoized } from './utilities/splitPath.js'
34
import chainingSupported from './utilities/chainingSupported.js'
4-
import { Sync } from './constants.js'
5+
import { Sync, OriginalImpl } from './constants.js'
56

67
const legacyMethods = {
78
get: {
@@ -49,6 +50,7 @@ const legacyMethods = {
4950
}
5051
},
5152
var: {
53+
[OriginalImpl]: true,
5254
[Sync]: true,
5355
method: (key, context, above, engine) => {
5456
let b
@@ -132,6 +134,7 @@ const legacyMethods = {
132134
},
133135
missing: {
134136
[Sync]: true,
137+
optimizeUnary: false,
135138
method: (checked, context, above, engine) => {
136139
return (Array.isArray(checked) ? checked : [checked]).filter((key) => {
137140
return legacyMethods.var.method(key, context, above, engine) === null
@@ -141,6 +144,7 @@ const legacyMethods = {
141144
},
142145
missing_some: {
143146
[Sync]: true,
147+
optimizeUnary: false,
144148
method: ([needCount, options], context, above, engine) => {
145149
const missing = legacyMethods.missing.method(options, context, above, engine)
146150
if (options.length - missing.length >= needCount) {

logic.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import omitUndefined from './utilities/omitUndefined.js'
99
import { optimize } from './optimizer.js'
1010
import { applyPatches } from './compatibility.js'
1111
import { coerceArray } from './utilities/coerceArray.js'
12+
import { OriginalImpl } from './constants.js'
1213

1314
/**
1415
* An engine capable of running synchronous JSON Logic.
@@ -71,6 +72,13 @@ class LogicEngine {
7172

7273
if (!this.methods[func]) throw new Error(`Method '${func}' was not found in the Logic Engine.`)
7374

75+
// A small but useful micro-optimization for some of the most common functions.
76+
// Later on, I could define something to shut this off if var / val are redefined.
77+
if ((func === 'var' || func === 'val') && this.methods[func][OriginalImpl]) {
78+
const input = (!data || typeof data !== 'object') ? data : this.run(data, context, { above })
79+
return this.methods[func].method(input, context, above, this)
80+
}
81+
7482
if (typeof this.methods[func] === 'function') {
7583
const input = (!data || typeof data !== 'object') ? [data] : coerceArray(this.run(data, context, { above }))
7684
return this.methods[func](input, context, above, this)
@@ -174,5 +182,5 @@ class LogicEngine {
174182
return logic
175183
}
176184
}
177-
Object.assign(LogicEngine.prototype.truthy, { IDENTITY: true })
185+
Object.assign(LogicEngine.prototype.truthy, { [OriginalImpl]: true })
178186
export default LogicEngine

0 commit comments

Comments
 (0)