@@ -145,6 +145,11 @@ const OpenApi3_1DereferenceVisitor = stampit({
145
145
path : ( string | number ) [ ] ,
146
146
ancestors : [ Element | Element [ ] ] ,
147
147
) {
148
+ // skip current referencing element as it's already been access
149
+ if ( this . indirections . includes ( referencingElement ) ) {
150
+ return false ;
151
+ }
152
+
148
153
const [ ancestorsLineage , directAncestors ] = this . toAncestorLineage ( [ ...ancestors , parent ] ) ;
149
154
150
155
const retrievalURI = this . toBaseURI ( toValue ( referencingElement . $ref ) ) ;
@@ -241,10 +246,10 @@ const OpenApi3_1DereferenceVisitor = stampit({
241
246
* 3. We are dereferencing the fragment lazily/eagerly depending on circular mode
242
247
*/
243
248
if (
244
- ! ancestorsLineage . includesCycle ( referencedElement ) &&
245
249
( isExternalReference ||
246
250
isReferenceElement ( referencedElement ) ||
247
- [ 'error' , 'replace' ] . includes ( this . options . dereference . circular ) )
251
+ [ 'error' , 'replace' ] . includes ( this . options . dereference . circular ) ) &&
252
+ ! ancestorsLineage . includesCycle ( referencedElement )
248
253
) {
249
254
// append referencing reference to ancestors lineage
250
255
directAncestors . add ( referencingElement ) ;
@@ -329,6 +334,11 @@ const OpenApi3_1DereferenceVisitor = stampit({
329
334
return undefined ;
330
335
}
331
336
337
+ // skip current referencing element as it's already been access
338
+ if ( this . indirections . includes ( referencingElement ) ) {
339
+ return false ;
340
+ }
341
+
332
342
const [ ancestorsLineage , directAncestors ] = this . toAncestorLineage ( [ ...ancestors , parent ] ) ;
333
343
334
344
const retrievalURI = this . toBaseURI ( toValue ( referencingElement . $ref ) ) ;
@@ -419,10 +429,10 @@ const OpenApi3_1DereferenceVisitor = stampit({
419
429
* 3. We are dereferencing the fragment lazily/eagerly depending on circular mode
420
430
*/
421
431
if (
422
- ! ancestorsLineage . includesCycle ( referencedElement ) &&
423
432
( isExternalReference ||
424
433
( isPathItemElement ( referencedElement ) && isStringElement ( referencedElement . $ref ) ) ||
425
- [ 'error' , 'replace' ] . includes ( this . options . dereference . circular ) )
434
+ [ 'error' , 'replace' ] . includes ( this . options . dereference . circular ) ) &&
435
+ ! ancestorsLineage . includesCycle ( referencedElement )
426
436
) {
427
437
// append referencing reference to ancestors lineage
428
438
directAncestors . add ( referencingElement ) ;
@@ -667,18 +677,23 @@ const OpenApi3_1DereferenceVisitor = stampit({
667
677
return undefined ;
668
678
}
669
679
680
+ // skip current referencing element as it's already been access
681
+ if ( this . indirections . includes ( referencingElement ) ) {
682
+ return false ;
683
+ }
684
+
670
685
const [ ancestorsLineage , directAncestors ] = this . toAncestorLineage ( [ ...ancestors , parent ] ) ;
671
686
672
687
// compute baseURI using rules around $id and $ref keywords
673
688
let reference = await this . toReference ( url . unsanitize ( this . reference . uri ) ) ;
674
689
let { uri : retrievalURI } = reference ;
675
- const $refBaseURI = resolveSchema$refField ( retrievalURI , referencingElement ) as string ;
690
+ const $refBaseURI = resolveSchema$refField ( retrievalURI , referencingElement ) ! ;
676
691
const $refBaseURIStrippedHash = url . stripHash ( $refBaseURI ) ;
677
692
const file = File ( { uri : $refBaseURIStrippedHash } ) ;
678
693
const isUnknownURI = none ( ( r : IResolver ) => r . canRead ( file ) , this . options . resolve . resolvers ) ;
679
694
const isURL = ! isUnknownURI ;
680
- const isInternalReference = ( uri : string ) => url . stripHash ( this . reference . uri ) === uri ;
681
- const isExternalReference = ( uri : string ) => ! isInternalReference ( uri ) ;
695
+ let isInternalReference = url . stripHash ( this . reference . uri ) === $refBaseURI ;
696
+ let isExternalReference = ! isInternalReference ;
682
697
683
698
this . indirections . push ( referencingElement ) ;
684
699
@@ -689,29 +704,35 @@ const OpenApi3_1DereferenceVisitor = stampit({
689
704
if ( isUnknownURI || isURL ) {
690
705
// we're dealing with canonical URI or URL with possible fragment
691
706
retrievalURI = this . toBaseURI ( $refBaseURI ) ;
692
-
693
707
const selector = $refBaseURI ;
694
708
const referenceAsSchema = maybeRefractToSchemaElement ( reference . value . result ) ;
695
709
referencedElement = uriEvaluate ( selector , referenceAsSchema ) ;
696
710
referencedElement = maybeRefractToSchemaElement ( referencedElement ) ;
697
711
referencedElement . id = identityManager . identify ( referencedElement ) ;
698
712
699
713
// ignore resolving internal Schema Objects
700
- if ( ! this . options . resolve . internal ) {
714
+ if ( ! this . options . resolve . internal && isInternalReference ) {
715
+ // skip traversing this schema element but traverse all it's child elements
716
+ return undefined ;
717
+ }
718
+ // ignore resolving external Schema Objects
719
+ if ( ! this . options . resolve . external && isExternalReference ) {
701
720
// skip traversing this schema element but traverse all it's child elements
702
721
return undefined ;
703
722
}
704
723
} else {
705
724
// we're assuming here that we're dealing with JSON Pointer here
706
725
retrievalURI = this . toBaseURI ( $refBaseURI ) ;
726
+ isInternalReference = url . stripHash ( this . reference . uri ) === retrievalURI ;
727
+ isExternalReference = ! isInternalReference ;
707
728
708
729
// ignore resolving internal Schema Objects
709
- if ( ! this . options . resolve . internal && isInternalReference ( retrievalURI ) ) {
730
+ if ( ! this . options . resolve . internal && isInternalReference ) {
710
731
// skip traversing this schema element but traverse all it's child elements
711
732
return undefined ;
712
733
}
713
734
// ignore resolving external Schema Objects
714
- if ( ! this . options . resolve . external && isExternalReference ( retrievalURI ) ) {
735
+ if ( ! this . options . resolve . external && isExternalReference ) {
715
736
// skip traversing this schema element but traverse all it's child elements
716
737
return undefined ;
717
738
}
@@ -731,15 +752,16 @@ const OpenApi3_1DereferenceVisitor = stampit({
731
752
if ( isURL && error instanceof EvaluationJsonSchemaUriError ) {
732
753
if ( isAnchor ( uriToAnchor ( $refBaseURI ) ) ) {
733
754
// we're dealing with JSON Schema $anchor here
734
- retrievalURI = this . toBaseURI ( $refBaseURI ) ;
755
+ isInternalReference = url . stripHash ( this . reference . uri ) === retrievalURI ;
756
+ isExternalReference = ! isInternalReference ;
735
757
736
758
// ignore resolving internal Schema Objects
737
- if ( ! this . options . resolve . internal && isInternalReference ( retrievalURI ) ) {
759
+ if ( ! this . options . resolve . internal && isInternalReference ) {
738
760
// skip traversing this schema element but traverse all it's child elements
739
761
return undefined ;
740
762
}
741
763
// ignore resolving external Schema Objects
742
- if ( ! this . options . resolve . external && isExternalReference ( retrievalURI ) ) {
764
+ if ( ! this . options . resolve . external && isExternalReference ) {
743
765
// skip traversing this schema element but traverse all it's child elements
744
766
return undefined ;
745
767
}
@@ -753,14 +775,16 @@ const OpenApi3_1DereferenceVisitor = stampit({
753
775
} else {
754
776
// we're assuming here that we're dealing with JSON Pointer here
755
777
retrievalURI = this . toBaseURI ( $refBaseURI ) ;
778
+ isInternalReference = url . stripHash ( this . reference . uri ) === retrievalURI ;
779
+ isExternalReference = ! isInternalReference ;
756
780
757
781
// ignore resolving internal Schema Objects
758
- if ( ! this . options . resolve . internal && isInternalReference ( retrievalURI ) ) {
782
+ if ( ! this . options . resolve . internal && isInternalReference ) {
759
783
// skip traversing this schema element but traverse all it's child elements
760
784
return undefined ;
761
785
}
762
786
// ignore resolving external Schema Objects
763
- if ( ! this . options . resolve . external && isExternalReference ( retrievalURI ) ) {
787
+ if ( ! this . options . resolve . external && isExternalReference ) {
764
788
// skip traversing this schema element but traverse all it's child elements
765
789
return undefined ;
766
790
}
@@ -825,10 +849,10 @@ const OpenApi3_1DereferenceVisitor = stampit({
825
849
* 3. We are dereferencing the fragment lazily/eagerly depending on circular mode
826
850
*/
827
851
if (
828
- ! ancestorsLineage . includesCycle ( referencedElement ) &&
829
- ( isExternalReference ( retrievalURI ) ||
852
+ ( isExternalReference ||
830
853
( isSchemaElement ( referencedElement ) && isStringElement ( referencedElement . $ref ) ) ||
831
- [ 'error' , 'replace' ] . includes ( this . options . dereference . circular ) )
854
+ [ 'error' , 'replace' ] . includes ( this . options . dereference . circular ) ) &&
855
+ ! ancestorsLineage . includesCycle ( referencedElement )
832
856
) {
833
857
// append referencing reference to ancestors lineage
834
858
directAncestors . add ( referencingElement ) ;
0 commit comments