mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-16 21:00:40 -07:00
fix(filters): charge json/inspect replacer by serialized node size
Replace the flat 1-unit charge for non-string JSON nodes with per-type estimates (primitives via JSON.stringify length, containers by structure). Co-authored-by: Cursor <[email protected]>
This commit is contained in:
+22
-4
@@ -2,6 +2,18 @@ import { isFalsy } from '../render/boolean'
|
||||
import { identify, isArray, isString, toValue } from '../util/underscore'
|
||||
import { FilterImpl } from '../template'
|
||||
|
||||
function chargeJsonReplacerValue (memoryLimit: { use(count: number): void }, val: unknown) {
|
||||
if (typeof val === 'string') {
|
||||
memoryLimit.use(val.length)
|
||||
} else if (val === null || typeof val === 'number' || typeof val === 'boolean') {
|
||||
memoryLimit.use(JSON.stringify(val).length)
|
||||
} else if (Array.isArray(val)) {
|
||||
memoryLimit.use(val.length + 1)
|
||||
} else if (typeof val === 'object') {
|
||||
memoryLimit.use(2)
|
||||
}
|
||||
}
|
||||
|
||||
function defaultFilter<T1 extends boolean, T2> (this: FilterImpl, value: T1, defaultValue: T2, ...args: Array<[string, any]>): T1 | T2 {
|
||||
value = toValue(value)
|
||||
if (isArray(value) || isString(value)) return value.length ? value : defaultValue
|
||||
@@ -12,7 +24,7 @@ function defaultFilter<T1 extends boolean, T2> (this: FilterImpl, value: T1, def
|
||||
function json (this: FilterImpl, value: any, space = 0) {
|
||||
const memoryLimit = this.context.memoryLimit
|
||||
return JSON.stringify(value, (_key, val) => {
|
||||
memoryLimit.use(typeof val === 'string' ? val.length : 1)
|
||||
chargeJsonReplacerValue(memoryLimit, val)
|
||||
return val
|
||||
}, space)
|
||||
}
|
||||
@@ -21,12 +33,18 @@ function inspect (this: FilterImpl, value: any, space = 0) {
|
||||
const memoryLimit = this.context.memoryLimit
|
||||
const ancestors: object[] = []
|
||||
return JSON.stringify(value, function (this: unknown, _key: unknown, value: any) {
|
||||
memoryLimit.use(typeof value === 'string' ? value.length : 1)
|
||||
if (typeof value !== 'object' || value === null) return value
|
||||
if (typeof value !== 'object' || value === null) {
|
||||
chargeJsonReplacerValue(memoryLimit, value)
|
||||
return value
|
||||
}
|
||||
// `this` is the object that value is contained in, i.e., its direct parent.
|
||||
while (ancestors.length > 0 && ancestors[ancestors.length - 1] !== this) ancestors.pop()
|
||||
if (ancestors.includes(value)) return '[Circular]'
|
||||
if (ancestors.includes(value)) {
|
||||
memoryLimit.use('[Circular]'.length)
|
||||
return '[Circular]'
|
||||
}
|
||||
ancestors.push(value)
|
||||
chargeJsonReplacerValue(memoryLimit, value)
|
||||
return value
|
||||
}, space)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user