@@ -44,34 +44,34 @@ function resolveExternal (parser, options) {
44
44
* @param {string } path - The full path of `obj`, possibly with a JSON Pointer in the hash
45
45
* @param {$Refs } $refs
46
46
* @param {$RefParserOptions } options
47
- * @param {Set } seen - Internal .
47
+ * @param {boolean } external - Whether `obj` was found in an external document .
48
48
*
49
49
* @returns {Promise[] }
50
50
* Returns an array of promises. There will be one promise for each JSON reference in `obj`.
51
51
* If `obj` does not contain any JSON references, then the array will be empty.
52
52
* If any of the JSON references point to files that contain additional JSON references,
53
53
* then the corresponding promise will internally reference an array of promises.
54
54
*/
55
- function crawl ( obj , path , $refs , options , seen ) {
55
+ function crawl ( obj , path , $refs , options , seen , external ) {
56
56
seen = seen || new Set ( ) ;
57
57
let promises = [ ] ;
58
58
59
- if ( obj && typeof obj === "object" && ! ArrayBuffer . isView ( obj ) && ! seen . has ( obj ) ) {
60
- seen . add ( obj ) ; // Track previously seen objects to avoid infinite recursion
59
+ if ( obj && typeof obj === "object" && ! ArrayBuffer . isView ( obj ) ) {
61
60
if ( $Ref . isExternal$Ref ( obj ) ) {
62
61
promises . push ( resolve$Ref ( obj , path , $refs , options ) ) ;
63
62
}
64
63
else {
64
+ if ( external && $Ref . is$Ref ( obj ) ) {
65
+ /* Correct the reference in the external document so we can resolve it */
66
+ const withoutHash = url . stripHash ( path ) ;
67
+ obj . $ref = withoutHash + obj . $ref ;
68
+ }
69
+
65
70
for ( let key of Object . keys ( obj ) ) {
66
71
let keyPath = Pointer . join ( path , key ) ;
67
72
let value = obj [ key ] ;
68
73
69
- if ( $Ref . isExternal$Ref ( value ) ) {
70
- promises . push ( resolve$Ref ( value , keyPath , $refs , options ) ) ;
71
- }
72
- else {
73
- promises = promises . concat ( crawl ( value , keyPath , $refs , options , seen ) ) ;
74
- }
74
+ promises = promises . concat ( crawl ( value , keyPath , $refs , options , seen , external ) ) ;
75
75
}
76
76
}
77
77
}
@@ -97,6 +97,12 @@ async function resolve$Ref ($ref, path, $refs, options) {
97
97
let resolvedPath = url . resolve ( path , $ref . $ref ) ;
98
98
let withoutHash = url . stripHash ( resolvedPath ) ;
99
99
100
+ /* Correct the $ref to use a path relative to the root, so that $Refs._resolve can resolve it,
101
+ otherwise transitive relative external references will be incorrect if the second external
102
+ relative ref doesn't work relative to the root document.
103
+ */
104
+ $ref . $ref = url . relative ( $refs . _root$Ref . path , resolvedPath ) ;
105
+
100
106
// Do we already have this $ref?
101
107
$ref = $refs . _$refs [ withoutHash ] ;
102
108
if ( $ref ) {
@@ -110,7 +116,7 @@ async function resolve$Ref ($ref, path, $refs, options) {
110
116
111
117
// Crawl the parsed value
112
118
// console.log('Resolving $ref pointers in %s', withoutHash);
113
- let promises = crawl ( result , withoutHash + "#" , $refs , options ) ;
119
+ let promises = crawl ( result , withoutHash + "#" , $refs , options , null , true ) ;
114
120
115
121
return Promise . all ( promises ) ;
116
122
}
0 commit comments