@@ -63,7 +63,8 @@ const REF_SIBLING_NONCONSTRAINT_KEYS = new Set([
6363 '$schema' ,
6464 '$id' ,
6565 'id' ,
66- '_baseUrl' ,
66+ '_baseUri' ,
67+ '_sourceUri' ,
6768 '_dialect' ,
6869 '$anchor' ,
6970 '$dynamicAnchor' ,
@@ -216,8 +217,13 @@ export class YAMLSchemaService extends JSONSchemaService {
216217 return new ResolvedSchema ( { } , resolveErrors ) ;
217218 }
218219
220+ const _setSourceUri = ( node : JSONSchema , sourceUri : string | undefined ) : void => {
221+ if ( ! node || typeof node !== 'object' || ! sourceUri ) return ;
222+ node . _sourceUri = sourceUri ;
223+ } ;
224+
219225 const _cloneSchema = (
220- value : unknown ,
226+ value : JSONSchema ,
221227 seen : Map < object , unknown > ,
222228 stopCondition ?: ( val : unknown , seenSize : number ) => unknown | undefined
223229 ) : unknown => {
@@ -243,11 +249,12 @@ export class YAMLSchemaService extends JSONSchemaService {
243249 }
244250
245251 // clone objects
246- const result = { } ;
252+ const result : JSONSchema = { } ;
247253 seen . set ( value , result ) ;
248254 for ( const prop in value ) {
249255 result [ prop ] = _cloneSchema ( value [ prop ] , seen , stopCondition ) ;
250256 }
257+ _setSourceUri ( result , value . _sourceUri ) ;
251258 return result ;
252259 } ;
253260
@@ -331,7 +338,7 @@ export class YAMLSchemaService extends JSONSchemaService {
331338 if ( ! entryItem . dynamic ) continue ;
332339
333340 const current = result ?. get ( name ) ?? [ ] ;
334- if ( current . some ( ( existing ) => existing . _baseUrl === resourceUri ) ) continue ;
341+ if ( current . some ( ( existing ) => existing . _baseUri === resourceUri ) ) continue ;
335342
336343 // clone map on first modification
337344 if ( result === scope ) result = scope ? new Map ( scope ) : new Map < string , JSONSchema [ ] > ( ) ;
@@ -347,28 +354,9 @@ export class YAMLSchemaService extends JSONSchemaService {
347354 return this . normalizeId ( ref ) ;
348355 } ;
349356
350- const _preferLocalBaseForRemoteId = async ( currentBase : string , id : string ) : Promise < string > => {
351- try {
352- const currentBaseUri = URI . parse ( currentBase ) ;
353- if ( currentBaseUri . scheme !== 'file' ) {
354- return _resolveAgainstBase ( currentBase , id ) ;
355- }
356- const idUri = URI . parse ( id ) ;
357- const localFileName = path . posix . basename ( idUri . path ) ;
358- const localDir = path . posix . dirname ( currentBaseUri . path ) ;
359- const localPath = path . posix . join ( localDir , localFileName ) ;
360- const localUriStr = currentBaseUri . with ( { path : localPath , query : idUri . query , fragment : idUri . fragment } ) . toString ( ) ;
361- if ( localUriStr === currentBase ) return localUriStr ;
362- const content = await this . requestService ( localUriStr ) ;
363- return content ? localUriStr : _resolveAgainstBase ( currentBase , id ) ;
364- } catch {
365- return _resolveAgainstBase ( currentBase , id ) ;
366- }
367- } ;
368-
369357 const _indexSchemaResources = async ( root : JSONSchema , initialBaseUri : string ) : Promise < void > => {
370- type WorkItem = { node : JSONSchema ; baseUri : string } ;
371- const preOrderStack : WorkItem [ ] = [ { node : root , baseUri : initialBaseUri } ] ;
358+ type WorkItem = { node : JSONSchema ; baseUri : string ; sourceUri : string } ;
359+ const preOrderStack : WorkItem [ ] = [ { node : root , baseUri : initialBaseUri , sourceUri : initialBaseUri } ] ;
372360 const postOrderStack : JSONSchema [ ] = [ ] ;
373361 const childListByNode = new WeakMap < JSONSchema , JSONSchema [ ] > ( ) ;
374362
@@ -382,19 +370,20 @@ export class YAMLSchemaService extends JSONSchemaService {
382370 seen . add ( node ) ;
383371
384372 let baseUri = current . baseUri ;
373+ _setSourceUri ( node , current . sourceUri ) ;
385374 const id = node . $id || node . id ;
386375 if ( id ) {
387- const preferredBaseUri = await _preferLocalBaseForRemoteId ( baseUri , id ) ;
388- node . _baseUrl = preferredBaseUri ;
389- const hashIndex = preferredBaseUri . indexOf ( '#' ) ;
390- if ( hashIndex !== - 1 && hashIndex < preferredBaseUri . length - 1 ) {
376+ const resolvedBaseUri = _resolveAgainstBase ( baseUri , id ) ;
377+ node . _baseUri = resolvedBaseUri ;
378+ const hashIndex = resolvedBaseUri . indexOf ( '#' ) ;
379+ if ( hashIndex !== - 1 && hashIndex < resolvedBaseUri . length - 1 ) {
391380 // Draft-07 and earlier: $id with fragment defines a plain-name anchor scoped to the resolved base
392- const frag = preferredBaseUri . slice ( hashIndex + 1 ) ;
381+ const frag = resolvedBaseUri . slice ( hashIndex + 1 ) ;
393382 _getResourceIndex ( baseUri ) . fragments . set ( frag , { node } ) ;
394383 } else {
395384 // $id without fragment creates a new embedded resource scope
396- baseUri = preferredBaseUri ;
397- const entry = _getResourceIndex ( preferredBaseUri ) ;
385+ baseUri = resolvedBaseUri ;
386+ const entry = _getResourceIndex ( resolvedBaseUri ) ;
398387 if ( ! entry . root ) {
399388 entry . root = node ;
400389 }
@@ -406,7 +395,7 @@ export class YAMLSchemaService extends JSONSchemaService {
406395 }
407396 // Draft 2020-12+: $dynamicAnchor keyword
408397 if ( node . $dynamicAnchor ) {
409- node . _baseUrl = baseUri ;
398+ node . _baseUri = baseUri ;
410399 _getResourceIndex ( baseUri ) . fragments . set ( node . $dynamicAnchor , { node, dynamic : true } ) ;
411400 }
412401
@@ -417,7 +406,7 @@ export class YAMLSchemaService extends JSONSchemaService {
417406 this . collectSchemaNodes (
418407 ( entry ) => {
419408 children . push ( entry ) ;
420- preOrderStack . push ( { node : entry , baseUri } ) ;
409+ preOrderStack . push ( { node : entry , baseUri, sourceUri : current . sourceUri } ) ;
421410 } ,
422411 node . not ,
423412 node . if ,
@@ -497,6 +486,7 @@ export class YAMLSchemaService extends JSONSchemaService {
497486 target [ key ] = source [ key ] ;
498487 }
499488 }
489+ _setSourceUri ( target , source . _sourceUri ) ;
500490 return ;
501491 } else {
502492 resolveErrors . push ( l10n . t ( "$ref '{0}' in '{1}' cannot be resolved." , refPath , sourceURI ) ) ;
@@ -537,7 +527,7 @@ export class YAMLSchemaService extends JSONSchemaService {
537527 uri : string ,
538528 linkPath : string ,
539529 parentSchemaURL : string ,
540- fallbackBaseURL : string ,
530+ parentSchemaSourceUri : string ,
541531 parentSchemaDependencies : SchemaDependencies ,
542532 resolutionStack : Set < string > ,
543533 recursiveAnchorBase : string ,
@@ -558,7 +548,7 @@ export class YAMLSchemaService extends JSONSchemaService {
558548 ) : Promise < any > => {
559549 parentSchemaDependencies [ schemaUri ] = true ;
560550 _merge ( node , schemaRoot , schemaUri , linkPath , ! ! inheritedDynamicScope || ! ! recursiveAnchorBase ) ;
561- if ( ! recursiveAnchorBase || ! node . _baseUrl ) node . _baseUrl = schemaUri ;
551+ if ( ! recursiveAnchorBase || ! node . _baseUri ) node . _baseUri = schemaUri ;
562552 node . url = schemaUri ;
563553
564554 const nextStack = new Set ( resolutionStack ) ;
@@ -623,8 +613,8 @@ export class YAMLSchemaService extends JSONSchemaService {
623613 } ;
624614
625615 const resolvedUri = _resolveRefUri ( parentSchemaURL , uri ) ;
626- const hasEmbeddedTarget = ! ! resourceIndexByUri . get ( resolvedUri ) ?. root ;
627- const localSiblingUri = hasEmbeddedTarget ? undefined : _resolveLocalSiblingFromRemoteUri ( fallbackBaseURL , resolvedUri ) ;
616+ const embeddedTarget = resourceIndexByUri . get ( resolvedUri ) ?. root ;
617+ const localSiblingUri = embeddedTarget ? undefined : _resolveLocalSiblingFromRemoteUri ( parentSchemaSourceUri , resolvedUri ) ;
628618 const targetUris = localSiblingUri && localSiblingUri !== resolvedUri ? [ localSiblingUri , resolvedUri ] : [ resolvedUri ] ;
629619 return _resolveByUri ( targetUris ) ;
630620 } ;
@@ -646,44 +636,45 @@ export class YAMLSchemaService extends JSONSchemaService {
646636 // track nodes with their base URL for $id resolution
647637 type WalkItem = {
648638 node : JSONSchema ;
649- baseURL ?: string ;
650- fallbackBaseURL ?: string ;
639+ baseUri ?: string ;
640+ sourceUri ?: string ;
651641 dialect ?: SchemaDialect ;
652642 recursiveAnchorBase ?: string ;
653643 inheritedDynamicScope ?: Map < string , JSONSchema [ ] > ;
654644 siblingRefCycleKeys ?: Set < string > ;
655645 } ;
656646 const toWalk : WalkItem [ ] = [
657- { node, baseURL : parentSchemaURL , fallbackBaseURL : parentSchemaURL , recursiveAnchorBase, inheritedDynamicScope } ,
647+ {
648+ node,
649+ baseUri : parentSchemaURL ,
650+ sourceUri : node . _sourceUri ?? parentSchemaURL ,
651+ recursiveAnchorBase,
652+ inheritedDynamicScope,
653+ } ,
658654 ] ;
659655 const seen = new WeakSet < JSONSchema > ( ) ; // prevents re-walking the same schema object graph
660656
661657 // eslint-disable-next-line @typescript-eslint/no-explicit-any
662658 const openPromises : Promise < any > [ ] = [ ] ;
663659
664- const _getChildFallbackBaseURL = ( entry : JSONSchema , currentFallbackBaseURL : string ) : string => {
665- const resourceUri = entry ?. _baseUrl ;
666- return resourceUri && resourceIndexByUri . get ( resourceUri ) ?. root === entry ? resourceUri : currentFallbackBaseURL ;
667- } ;
668-
669660 // handle $ref with siblings based on dialect
670661 const _handleRef = (
671662 next : JSONSchema ,
672- nodeBaseURL : string ,
673- fallbackBaseURL : string ,
663+ nodeBaseUri : string ,
664+ nodeSourceUri : string ,
674665 nodeDialect : SchemaDialect ,
675666 recursiveAnchorBase ?: string ,
676667 inheritedDynamicScope ?: Map < string , JSONSchema [ ] > ,
677668 siblingRefCycleKeys ?: Set < string >
678669 ) : void => {
679- const currentDynamicScope = _addResourceDynamicAnchors ( inheritedDynamicScope , nodeBaseURL ) ;
670+ const currentDynamicScope = _addResourceDynamicAnchors ( inheritedDynamicScope , nodeBaseUri ) ;
680671
681672 this . collectSchemaNodes (
682673 ( entry ) =>
683674 toWalk . push ( {
684675 node : entry ,
685- baseURL : nodeBaseURL ,
686- fallbackBaseURL : _getChildFallbackBaseURL ( entry , fallbackBaseURL ) ,
676+ baseUri : nodeBaseUri ,
677+ sourceUri : nodeSourceUri ,
687678 recursiveAnchorBase,
688679 inheritedDynamicScope : currentDynamicScope ,
689680 } ) ,
@@ -757,7 +748,7 @@ export class YAMLSchemaService extends JSONSchemaService {
757748 const segments = ref . split ( '#' , 2 ) ;
758749 const baseUri = segments [ 0 ] ;
759750 const frag = segments . length > 1 ? segments [ 1 ] : '' ;
760- const resolvedRefKey = `${ baseUri ? _resolveAgainstBase ( nodeBaseURL , baseUri ) : nodeBaseURL } #${ frag } ` ;
751+ const resolvedRefKey = `${ baseUri ? _resolveAgainstBase ( nodeBaseUri , baseUri ) : nodeBaseUri } #${ frag } ` ;
761752
762753 if ( _hasRefSiblings ( next ) ) {
763754 // Draft-07 and earlier: ignore siblings
@@ -779,8 +770,8 @@ export class YAMLSchemaService extends JSONSchemaService {
779770 }
780771 toWalk . push ( {
781772 node : entry as JSONSchema ,
782- baseURL : nodeBaseURL ,
783- fallbackBaseURL : _getChildFallbackBaseURL ( entry as JSONSchema , fallbackBaseURL ) ,
773+ baseUri : nodeBaseUri ,
774+ sourceUri : nodeSourceUri ,
784775 recursiveAnchorBase,
785776 inheritedDynamicScope : currentDynamicScope ,
786777 siblingRefCycleKeys : nextSiblingRefCycleKeys ,
@@ -798,11 +789,11 @@ export class YAMLSchemaService extends JSONSchemaService {
798789
799790 // Draft-2019+: $recursiveRef
800791 if ( isRecursiveRef && ( ref === '#' || ref === '' ) ) {
801- const targetRoot = resourceIndexByUri . get ( nodeBaseURL ) ?. root ;
802- const recursiveBase = targetRoot ?. $recursiveAnchor && recursiveAnchorBase ? recursiveAnchorBase : nodeBaseURL ;
792+ const targetRoot = resourceIndexByUri . get ( nodeBaseUri ) ?. root ;
793+ const recursiveBase = targetRoot ?. $recursiveAnchor && recursiveAnchorBase ? recursiveAnchorBase : nodeBaseUri ;
803794
804795 if ( recursiveBase . length > 0 ) {
805- if ( resolutionStack ?. has ( recursiveBase ) || recursiveBase === nodeBaseURL ) {
796+ if ( resolutionStack ?. has ( recursiveBase ) || recursiveBase === nodeBaseUri ) {
806797 const sourceRoot = resourceIndexByUri . get ( recursiveBase ) ?. root ?? parentSchema ;
807798 if ( ! seenRefs . has ( ref ) ) {
808799 _merge ( next , sourceRoot , recursiveBase , '' , false ) ;
@@ -815,8 +806,8 @@ export class YAMLSchemaService extends JSONSchemaService {
815806 next ,
816807 recursiveBase ,
817808 '' ,
818- nodeBaseURL ,
819- fallbackBaseURL ,
809+ nodeBaseUri ,
810+ nodeSourceUri ,
820811 parentSchemaDependencies ,
821812 resolutionStack ,
822813 recursiveAnchorBase ,
@@ -830,13 +821,13 @@ export class YAMLSchemaService extends JSONSchemaService {
830821
831822 // Draft-2020+: $dynamicRef
832823 else if ( isDynamicRef ) {
833- const targetResource = baseUri . length > 0 ? _resolveAgainstBase ( nodeBaseURL , baseUri ) : nodeBaseURL ;
824+ const targetResource = baseUri . length > 0 ? _resolveAgainstBase ( nodeBaseUri , baseUri ) : nodeBaseUri ;
834825 const targetFragments = resourceIndexByUri . get ( targetResource ) ?. fragments ;
835826 const targetHasDynamicAnchor = frag . length > 0 && targetFragments ?. get ( frag ) ?. dynamic ;
836827 const dynamicTarget = targetHasDynamicAnchor ? currentDynamicScope ?. get ( frag ) ?. [ 0 ] : undefined ;
837- const resolveResource = dynamicTarget ? dynamicTarget . _baseUrl : targetResource ;
828+ const resolveResource = dynamicTarget ? dynamicTarget . _baseUri : targetResource ;
838829
839- if ( dynamicTarget && ( resolveResource === nodeBaseURL || resolutionStack . has ( resolveResource ) ) ) {
830+ if ( dynamicTarget && ( resolveResource === nodeBaseUri || resolutionStack . has ( resolveResource ) ) ) {
840831 if ( ! seenRefs . has ( ref ) ) {
841832 _merge ( next , dynamicTarget , resolveResource , '' , false ) ;
842833 seenRefs . add ( ref ) ;
@@ -851,8 +842,8 @@ export class YAMLSchemaService extends JSONSchemaService {
851842 next ,
852843 resolveResource ,
853844 frag ,
854- nodeBaseURL ,
855- fallbackBaseURL ,
845+ nodeBaseUri ,
846+ nodeSourceUri ,
856847 parentSchemaDependencies ,
857848 resolutionStack ,
858849 recursiveAnchorBase ,
@@ -864,16 +855,16 @@ export class YAMLSchemaService extends JSONSchemaService {
864855 }
865856 // normal $ref with external baseUri
866857 else if ( baseUri . length > 0 ) {
867- const resolvedBaseUri = _resolveAgainstBase ( nodeBaseURL , baseUri ) ;
858+ const resolvedBaseUri = _resolveAgainstBase ( nodeBaseUri , baseUri ) ;
868859 if ( _mergeIfResourceAlreadyInResolutionStack ( ref , resolvedBaseUri , frag ) ) continue ;
869860 // resolve relative to this node's base URL
870861 openPromises . push (
871862 resolveExternalLink (
872863 next ,
873864 baseUri ,
874865 frag ,
875- nodeBaseURL ,
876- fallbackBaseURL ,
866+ nodeBaseUri ,
867+ nodeSourceUri ,
877868 parentSchemaDependencies ,
878869 resolutionStack ,
879870 recursiveAnchorBase ,
@@ -885,7 +876,7 @@ export class YAMLSchemaService extends JSONSchemaService {
885876
886877 // local $ref or $dynamicRef
887878 if ( ! seenRefs . has ( ref ) ) {
888- _merge ( next , parentSchema , nodeBaseURL , frag , isDynamicRef && ! ! currentDynamicScope ) ;
879+ _merge ( next , parentSchema , nodeBaseUri , frag , isDynamicRef && ! ! currentDynamicScope ) ;
889880 seenRefs . add ( ref ) ;
890881 }
891882 }
@@ -895,8 +886,8 @@ export class YAMLSchemaService extends JSONSchemaService {
895886 ( entry ) =>
896887 toWalk . push ( {
897888 node : entry ,
898- baseURL : next . _baseUrl || nodeBaseURL ,
899- fallbackBaseURL : _getChildFallbackBaseURL ( entry , fallbackBaseURL ) ,
889+ baseUri : next . _baseUri || nodeBaseUri ,
890+ sourceUri : next . _sourceUri || nodeSourceUri ,
900891 dialect : nodeDialect ,
901892 recursiveAnchorBase,
902893 inheritedDynamicScope : currentDynamicScope ,
@@ -932,7 +923,7 @@ export class YAMLSchemaService extends JSONSchemaService {
932923 segments [ 0 ] ,
933924 segments [ 1 ] ,
934925 parentSchemaURL ,
935- parentSchemaURL ,
926+ schema . _sourceUri ?? parentSchemaURL ,
936927 parentSchemaDependencies ,
937928 resolutionStack ,
938929 recursiveAnchorBase ,
@@ -953,16 +944,16 @@ export class YAMLSchemaService extends JSONSchemaService {
953944 while ( toWalk . length ) {
954945 const item = toWalk . pop ( ) ;
955946 const next = item . node ;
956- const nodeBaseURL = next . _baseUrl || item . baseURL ;
957- const fallbackBaseURL = item . fallbackBaseURL || item . baseURL ;
947+ const nodeBaseUri = next . _baseUri || item . baseUri ;
948+ const nodeSourceUri = next . _sourceUri || nodeBaseUri ;
958949 const nodeDialect = next . _dialect || item . dialect ;
959- const nodeRecursiveAnchorBase = item . recursiveAnchorBase ?? ( next . $recursiveAnchor ? nodeBaseURL : undefined ) ;
950+ const nodeRecursiveAnchorBase = item . recursiveAnchorBase ?? ( next . $recursiveAnchor ? nodeBaseUri : undefined ) ;
960951 if ( seen . has ( next ) ) continue ;
961952 seen . add ( next ) ;
962953 _handleRef (
963954 next ,
964- nodeBaseURL ,
965- fallbackBaseURL ,
955+ nodeBaseUri ,
956+ nodeSourceUri ,
966957 nodeDialect ,
967958 nodeRecursiveAnchorBase ,
968959 item . inheritedDynamicScope ,
@@ -973,7 +964,7 @@ export class YAMLSchemaService extends JSONSchemaService {
973964 } ;
974965
975966 const resolutionStack = new Set < string > ( ) ; // prevents $ref/$recursiveRef/$dynamicRef loops across schema URIs
976- const rootResource = schema . _baseUrl || schemaURL ;
967+ const rootResource = schema . _baseUri || schemaURL ;
977968 if ( rootResource ) resolutionStack . add ( rootResource ) ;
978969 await resolveRefs ( schema , schema , schemaURL , dependencies , resolutionStack ) ;
979970 return new ResolvedSchema ( schema , resolveErrors ) ;
0 commit comments