@@ -780,12 +780,17 @@ export class JSONSchemaService implements IJSONSchemaService {
780780
781781 const collectAnchors = ( root : JSONSchema ) : Map < string , JSONSchema > => {
782782 const result = new Map < string , JSONSchema > ( ) ;
783+ const seen = new Set < JSONSchema > ( ) ;
784+ // Use the schema's own $schema to determine draft, so that an external
785+ // schema referenced from a doesn't inherit the parent's anchor rules.
786+ const draft = root . $schema ? getSchemaDraftFromId ( root . $schema ) : schemaDraft ;
783787 // Traversal that stops at sub-schemas with their own $id
784788 // because those create a new URI scope for anchors
785789 const traverseForAnchors = ( node : JSONSchema , isRoot : boolean ) : void => {
786- if ( ! node || typeof node !== 'object' ) {
790+ if ( ! node || typeof node !== 'object' || seen . has ( node ) ) {
787791 return ;
788792 }
793+ seen . add ( node ) ;
789794 // If this node has its own $id, and it's not the root, it's a new URI scope
790795 const id = getSchemaId ( node ) ;
791796 if ( ! isRoot && isString ( id ) && id . charAt ( 0 ) !== '#' ) {
@@ -795,8 +800,8 @@ export class JSONSchemaService implements IJSONSchemaService {
795800 // Collect anchor from this node
796801 // In draft-04/06/07, anchors are defined via $id/#fragment (e.g., "$id": "#myanchor")
797802 // In 2019-09+, $id fragments are no longer anchors; $anchor is used instead
798- const fragmentAnchor = ( schemaDraft === undefined || schemaDraft < SchemaDraft . v2019_09 ) && isString ( id ) && id . charAt ( 0 ) === '#' ? id . substring ( 1 ) : undefined ;
799- const dollarAnchor = ( schemaDraft === undefined || schemaDraft >= SchemaDraft . v2019_09 ) ? node . $anchor : undefined ;
803+ const fragmentAnchor = ( draft === undefined || draft < SchemaDraft . v2019_09 ) && isString ( id ) && id . charAt ( 0 ) === '#' ? id . substring ( 1 ) : undefined ;
804+ const dollarAnchor = ( draft === undefined || draft >= SchemaDraft . v2019_09 ) ? node . $anchor : undefined ;
800805 const anchor = fragmentAnchor ?? dollarAnchor ;
801806 if ( anchor ) {
802807 if ( result . has ( anchor ) ) {
@@ -863,6 +868,11 @@ export class JSONSchemaService implements IJSONSchemaService {
863868 // Register embedded schemas before resolving refs
864869 registerEmbeddedSchemas ( schema , handle . uri ) ;
865870
871+ // Collect anchors eagerly before $ref resolution mutates the schema.
872+ // resolveRefs merges referenced nodes (including $anchor) into $ref targets,
873+ // so a lazy collectAnchors call could see duplicates from merged copies.
874+ handle . anchors = collectAnchors ( schema ) ;
875+
866876 // Resolve meta-schema to extract vocabularies if present
867877 const resolveMetaschemaVocabularies = ( ) : PromiseLike < void > => {
868878 if ( ! schema . $schema || typeof schema . $schema !== 'string' ) {
0 commit comments