@@ -191,6 +191,7 @@ const compileSchema = (schema, root, opts, scope, basePathRoot = '') => {
191
191
const recursiveLog = [ ]
192
192
const getMeta = ( ) => rootMeta . get ( root )
193
193
const basePathStack = basePathRoot ? [ basePathRoot ] : [ ]
194
+ const recursiveDelta = root . $dynamicAnchor || root . $recursiveAnchor
194
195
const visit = ( errors , history , current , node , schemaPath , trace = { } , { constProp } = { } ) => {
195
196
// e.g. top-level data and property names, OR already checked by present() in history, OR in keys and not undefined
196
197
const isSub = history . length > 0 && history [ history . length - 1 ] . prop === current
@@ -254,7 +255,10 @@ const compileSchema = (schema, root, opts, scope, basePathRoot = '') => {
254
255
255
256
// evaluated tracing
256
257
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
+ }
258
262
259
263
if ( typeof node === 'boolean' ) {
260
264
if ( node === true ) {
@@ -375,24 +379,29 @@ const compileSchema = (schema, root, opts, scope, basePathRoot = '') => {
375
379
items : needUnevaluated ( 'unevaluatedItems' ) ? gensym ( 'evaluatedItems' ) : null ,
376
380
props : needUnevaluated ( 'unevaluatedProperties' ) ? gensym ( 'evaluatedProps' ) : null ,
377
381
} )
382
+ //RECHECK!
378
383
const dyn = Object . freeze ( {
379
384
item : local . item || trace . item ,
380
385
items : local . items || trace . items ,
381
386
props : local . props || trace . props ,
382
387
} )
388
+ //RECHECK!
383
389
const canSkipDynamic = ( ) =>
384
390
( ! 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 ) ) {
388
394
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 )
392
401
} else if ( dyn . props ) {
393
402
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 ] ) )
396
405
if ( properties . length > 0 ) fun . write ( '%s[0].push(...%j)' , dyn . props , properties )
397
406
if ( patterns . length > 0 ) fun . write ( '%s[1].push(...%j)' , dyn . props , patterns )
398
407
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 = '') => {
1351
1360
if ( refsNeedFullValidation . has ( funname ) ) throw new Error ( 'Unexpected: unvalidated cyclic ref' )
1352
1361
1353
1362
// 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
+ ) {
1355
1367
if ( ! local ) throw new Error ( 'Failed to trace dynamic properties' ) // Unreachable
1356
1368
fun . write ( 'validate.evaluatedDynamic = [%s, %s, %s]' , local . item , local . items , local . props )
1357
1369
}
0 commit comments