@@ -204,9 +204,9 @@ const compileSchema = (schema, root, opts, scope, basePathRoot = '') => {
204
204
const visit = ( errors , history , current , node , schemaPath , trace = { } , { constProp } = { } ) => {
205
205
// e.g. top-level data and property names, OR already checked by present() in history, OR in keys and not undefined
206
206
const isSub = history . length > 0 && history [ history . length - 1 ] . prop === current
207
- const queryCurrent = ( ) => history . filter ( ( h ) => h . prop === current )
207
+ const statHistory = history . filter ( ( h ) => h . prop === current ) . map ( ( h ) => h . stat ) // nested stat objects only for the current node
208
208
const definitelyPresent =
209
- ! current . parent || current . checked || ( current . inKeys && isJSON ) || queryCurrent ( ) . length > 0
209
+ ! current . parent || current . checked || ( current . inKeys && isJSON ) || statHistory . length > 0
210
210
211
211
const name = buildName ( current )
212
212
const currPropImm = ( ...args ) => propimm ( current , ...args )
@@ -452,14 +452,15 @@ const compileSchema = (schema, root, opts, scope, basePathRoot = '') => {
452
452
453
453
/* Preparation and methods, post-$ref validation will begin at the end of the function */
454
454
455
+ // Trust already applied { type, required } restrictions from parent rules for the current node
456
+ // Can't apply items/properties as those affect child unevaluated*, and { fullstring } is just not needed in same-node subrules
457
+ for ( const { type, required } of statHistory ) evaluateDelta ( { type, required } )
458
+
455
459
// This is used for typechecks, null means * here
456
460
const allIn = ( arr , valid ) => arr && arr . every ( ( s ) => valid . includes ( s ) ) // all arr entries are in valid
457
461
const someIn = ( arr , possible ) => possible . some ( ( x ) => arr === null || arr . includes ( x ) ) // all possible are in arrs
458
-
459
- const parentCheckedType = ( ...valid ) => queryCurrent ( ) . some ( ( h ) => allIn ( h . stat . type , valid ) )
460
- const definitelyType = ( ...valid ) => allIn ( stat . type , valid ) || parentCheckedType ( ...valid )
461
- const typeApplicable = ( ...possible ) =>
462
- someIn ( stat . type , possible ) && queryCurrent ( ) . every ( ( h ) => someIn ( h . stat . type , possible ) )
462
+ const definitelyType = ( ...valid ) => allIn ( stat . type , valid )
463
+ const typeApplicable = ( ...possible ) => someIn ( stat . type , possible )
463
464
464
465
const enforceRegex = ( source , target = node ) => {
465
466
enforce ( typeof source === 'string' , 'Invalid pattern:' , source )
@@ -756,9 +757,7 @@ const compileSchema = (schema, root, opts, scope, basePathRoot = '') => {
756
757
}
757
758
758
759
// if allErrors is false, we can skip present check for required properties validated before
759
- const checked = ( p ) =>
760
- ! allErrors &&
761
- ( stat . required . includes ( p ) || queryCurrent ( ) . some ( ( h ) => h . stat . required . includes ( p ) ) )
760
+ const checked = ( p ) => ! allErrors && stat . required . includes ( p )
762
761
763
762
const checkObjects = ( ) => {
764
763
const propertiesCount = format ( 'Object.keys(%s).length' , name )
@@ -1284,10 +1283,7 @@ const compileSchema = (schema, root, opts, scope, basePathRoot = '') => {
1284
1283
evaluateDelta ( { type : [ current . type ] } )
1285
1284
return null
1286
1285
}
1287
- if ( parentCheckedType ( ...typearr ) ) {
1288
- evaluateDelta ( { type : typearr } )
1289
- return null
1290
- }
1286
+ if ( definitelyType ( ...typearr ) ) return null
1291
1287
const filteredTypes = typearr . filter ( ( t ) => typeApplicable ( t ) )
1292
1288
if ( filteredTypes . length === 0 ) fail ( 'No valid types possible' )
1293
1289
evaluateDelta ( { type : typearr } ) // can be safely done here, filteredTypes already prepared
0 commit comments