Skip to content

Commit a1d6c64

Browse files
committed
fix: dynamic recursion should always return dynamic deltas
1 parent e3224b1 commit a1d6c64

File tree

2 files changed

+23
-11
lines changed

2 files changed

+23
-11
lines changed

src/compile.js

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ const compileSchema = (schema, root, opts, scope, basePathRoot = '') => {
191191
const recursiveLog = []
192192
const getMeta = () => rootMeta.get(root)
193193
const basePathStack = basePathRoot ? [basePathRoot] : []
194+
const recursiveDelta = root.$dynamicAnchor || root.$recursiveAnchor
194195
const visit = (errors, history, current, node, schemaPath, trace = {}, { constProp } = {}) => {
195196
// e.g. top-level data and property names, OR already checked by present() in history, OR in keys and not undefined
196197
const isSub = history.length > 0 && history[history.length - 1].prop === current
@@ -254,7 +255,10 @@ const compileSchema = (schema, root, opts, scope, basePathRoot = '') => {
254255

255256
// evaluated tracing
256257
const stat = initTracing()
257-
const evaluateDelta = (delta) => applyDelta(stat, delta)
258+
const evaluateDelta = (delta) => {
259+
applyDelta(stat, delta)
260+
if (recursiveDelta && node === root) evaluateDeltaDynamic(delta, true)
261+
}
258262

259263
if (typeof node === 'boolean') {
260264
if (node === true) {
@@ -375,24 +379,29 @@ const compileSchema = (schema, root, opts, scope, basePathRoot = '') => {
375379
items: needUnevaluated('unevaluatedItems') ? gensym('evaluatedItems') : null,
376380
props: needUnevaluated('unevaluatedProperties') ? gensym('evaluatedProps') : null,
377381
})
382+
//RECHECK!
378383
const dyn = Object.freeze({
379384
item: local.item || trace.item,
380385
items: local.items || trace.items,
381386
props: local.props || trace.props,
382387
})
388+
//RECHECK!
383389
const canSkipDynamic = () =>
384390
(!dyn.items || stat.items === Infinity) && (!dyn.props || stat.properties.includes(true))
385-
const evaluateDeltaDynamic = (delta) => {
386-
// Skips applying those that have already been proved statically
387-
if (dyn.item && delta.item && stat.items !== Infinity)
391+
const evaluateDeltaDynamic = (delta, enforce = false) => {
392+
// Skips applying those that have already been proven statically (if not enforced for dynamic recursion)
393+
if (dyn.item && delta.item && (enforce || stat.items !== Infinity)) {
388394
fun.write('%s.push(%s)', dyn.item, delta.item)
389-
if (dyn.items && delta.items > stat.items) fun.write('%s.push(%d)', dyn.items, delta.items)
390-
if (dyn.props && (delta.properties || []).includes(true) && !stat.properties.includes(true)) {
391-
fun.write('%s[0].push(true)', dyn.props)
395+
}
396+
if (dyn.items && delta.items && (enforce || delta.items > stat.items)) {
397+
fun.write('%s.push(%d)', dyn.items, delta.items)
398+
}
399+
if (dyn.props && (delta.properties || []).includes(true)) {
400+
if (enforce || !stat.properties.includes(true)) fun.write('%s[0].push(true)', dyn.props)
392401
} else if (dyn.props) {
393402
const inStat = (properties, patterns) => inProperties(stat, { properties, patterns })
394-
const properties = (delta.properties || []).filter((x) => !inStat([x], []))
395-
const patterns = (delta.patterns || []).filter((x) => !inStat([], [x]))
403+
const properties = (delta.properties || []).filter((x) => enforce || !inStat([x], []))
404+
const patterns = (delta.patterns || []).filter((x) => enforce || !inStat([], [x]))
396405
if (properties.length > 0) fun.write('%s[0].push(...%j)', dyn.props, properties)
397406
if (patterns.length > 0) fun.write('%s[1].push(...%j)', dyn.props, patterns)
398407
for (const sym of delta.propertiesVars || []) fun.write('%s[0].push(%s)', dyn.props, sym)
@@ -1351,7 +1360,10 @@ const compileSchema = (schema, root, opts, scope, basePathRoot = '') => {
13511360
if (refsNeedFullValidation.has(funname)) throw new Error('Unexpected: unvalidated cyclic ref')
13521361

13531362
// evaluated: return dynamic for refs
1354-
if (opts[optDynamic] && (isDynamic(stat).items || isDynamic(stat).properties)) {
1363+
if (
1364+
(opts[optDynamic] && (isDynamic(stat).items || isDynamic(stat).properties)) ||
1365+
recursiveDelta
1366+
) {
13551367
if (!local) throw new Error('Failed to trace dynamic properties') // Unreachable
13561368
fun.write('validate.evaluatedDynamic = [%s, %s, %s]', local.item, local.items, local.props)
13571369
}

0 commit comments

Comments
 (0)