@@ -918,9 +918,9 @@ const compileSchema = (schema, root, opts, scope, basePathRoot = '') => {
918918 enforce ( anyOf . length > 0 , 'anyOf cannot be empty' )
919919 if ( anyOf . length === 1 ) return performAllOf ( anyOf )
920920 if ( handleDiscriminator ) return handleDiscriminator ( anyOf , 'anyOf' )
921- uncertainBranchTypes ( 'anyOf' , anyOf )
922921 const suberr = suberror ( )
923922 if ( ! canSkipDynamic ( ) ) {
923+ uncertainBranchTypes ( 'anyOf' , anyOf ) // const sorting for removeAdditional is not supported in dynamic mode
924924 // In this case, all have to be checked to gather evaluated properties
925925 const entries = Object . entries ( anyOf ) . map ( ( [ key , sch ] ) =>
926926 subrule ( suberr , current , sch , subPath ( 'anyOf' , key ) , dyn )
@@ -931,9 +931,18 @@ const compileSchema = (schema, root, opts, scope, basePathRoot = '') => {
931931 for ( const { delta, sub } of entries ) fun . if ( sub , ( ) => evaluateDeltaDynamic ( delta ) )
932932 return null
933933 }
934+ // We sort the variants to perform const comparisons first, then primitives/array/object/unknown
935+ // This way, we can be sure that array/object + removeAdditional do not affect const evaluation
936+ // Note that this _might_ e.g. remove all elements of an array in a 2nd branch _and_ fail with `const: []` in the 1st, but that's expected behavior
937+ // This can be done because we can stop on the first match in anyOf if we don't need dynamic evaluation
938+ const constBlocks = anyOf . filter ( ( x ) => functions . hasOwn ( x , 'const' ) )
939+ const otherBlocks = anyOf . filter ( ( x ) => ! functions . hasOwn ( x , 'const' ) )
940+ uncertainBranchTypes ( 'anyOf' , otherBlocks )
941+ const blocks = [ ...constBlocks , ...otherBlocks ]
942+
934943 let delta
935944 let body = ( ) => error ( { path : [ 'anyOf' ] , suberr } )
936- for ( const [ key , sch ] of Object . entries ( anyOf ) . reverse ( ) ) {
945+ for ( const [ key , sch ] of Object . entries ( blocks ) . reverse ( ) ) {
937946 const oldBody = body
938947 body = ( ) => {
939948 const { sub, delta : deltaVar } = subrule ( suberr , current , sch , subPath ( 'anyOf' , key ) )
0 commit comments