Skip to content

Commit c1af82b

Browse files
committed
code optimisation for circular ref issue
1 parent 2299bcc commit c1af82b

File tree

1 file changed

+75
-18
lines changed

1 file changed

+75
-18
lines changed

lib/dereference.js

Lines changed: 75 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,18 @@ module.exports = dereference;
1414
* @param {$RefParser} parser
1515
* @param {$RefParserOptions} options
1616
*/
17-
function dereference (parser, options) {
17+
async function dereference(parser, options) {
1818
parser.$refs.propertyMap = {}; // we assign a new object prior to another dereference process
1919
// console.log('Dereferencing $ref pointers in %s', parser.$refs._root$Ref.path);
20-
let dereferenced = crawl(parser.schema, parser.$refs._root$Ref.path, "#", [], {}, parser.$refs, options);
20+
let dereferenced = await crawl(
21+
parser.schema,
22+
parser.$refs._root$Ref.path,
23+
"#",
24+
[],
25+
{},
26+
parser.$refs,
27+
options
28+
);
2129
parser.$refs.circular = dereferenced.circular;
2230
parser.schema = dereferenced.value;
2331
}
@@ -34,46 +42,75 @@ function dereference (parser, options) {
3442
* @param {$RefParserOptions} options
3543
* @returns {{value: object, circular: boolean}}
3644
*/
37-
function crawl (obj, path, pathFromRoot, parents, dereferencedCache, $refs, options) {
45+
async function crawl(
46+
obj,
47+
path,
48+
pathFromRoot,
49+
parents,
50+
dereferencedCache,
51+
$refs,
52+
options
53+
) {
3854
let dereferenced;
3955
let result = {
4056
value: obj,
41-
circular: false
57+
circular: false,
4258
};
4359

4460
if (obj && typeof obj === "object" && !ArrayBuffer.isView(obj)) {
4561
parents.push(obj);
4662

4763
if ($Ref.isAllowed$Ref(obj, options)) {
48-
dereferenced = dereference$Ref(obj, path, pathFromRoot, parents, dereferencedCache, $refs, options);
64+
dereferenced = await dereference$Ref(
65+
obj,
66+
path,
67+
pathFromRoot,
68+
parents,
69+
dereferencedCache,
70+
$refs,
71+
options
72+
);
4973
result.circular = dereferenced.circular;
5074
result.value = dereferenced.value;
51-
}
52-
else {
75+
} else {
5376
for (let key of Object.keys(obj)) {
5477
let keyPath = Pointer.join(path, key);
5578
let keyPathFromRoot = Pointer.join(pathFromRoot, key);
5679
let value = obj[key];
5780
let circular = false;
5881

5982
if ($Ref.isAllowed$Ref(value, options)) {
60-
dereferenced = dereference$Ref(value, keyPath, keyPathFromRoot, parents, dereferencedCache, $refs, options);
83+
dereferenced = await dereference$Ref(
84+
value,
85+
keyPath,
86+
keyPathFromRoot,
87+
parents,
88+
dereferencedCache,
89+
$refs,
90+
options
91+
);
6192
circular = dereferenced.circular;
6293
// Avoid pointless mutations; breaks frozen objects to no profit
6394
if (obj[key] !== dereferenced.value) {
6495
obj[key] = dereferenced.value;
6596
}
66-
}
67-
else {
97+
} else {
6898
if (parents.indexOf(value) === -1) {
69-
dereferenced = crawl(value, keyPath, keyPathFromRoot, parents, dereferencedCache, $refs, options);
99+
dereferenced = await crawl(
100+
value,
101+
keyPath,
102+
keyPathFromRoot,
103+
parents,
104+
dereferencedCache,
105+
$refs,
106+
options
107+
);
70108
circular = dereferenced.circular;
71109
// Avoid pointless mutations; breaks frozen objects to no profit
72110
if (obj[key] !== dereferenced.value) {
73111
obj[key] = dereferenced.value;
74112
}
75-
}
76-
else {
113+
} else {
77114
circular = foundCircularReference(keyPath, $refs, options);
78115
}
79116
}
@@ -101,7 +138,15 @@ function crawl (obj, path, pathFromRoot, parents, dereferencedCache, $refs, opti
101138
* @param {$RefParserOptions} options
102139
* @returns {{value: object, circular: boolean}}
103140
*/
104-
function dereference$Ref ($ref, path, pathFromRoot, parents, dereferencedCache, $refs, options) {
141+
async function dereference$Ref(
142+
$ref,
143+
path,
144+
pathFromRoot,
145+
parents,
146+
dereferencedCache,
147+
$refs,
148+
options
149+
) {
105150
// console.log('Dereferencing $ref pointer "%s" at %s', $ref.$ref, path);
106151

107152
let $refPath = url.resolve(path, $ref.$ref);
@@ -147,12 +192,24 @@ function dereference$Ref ($ref, path, pathFromRoot, parents, dereferencedCache,
147192
// Crawl the dereferenced value (unless it's circular)
148193
if (!circular) {
149194
// Determine if the dereferenced value is circular
150-
let dereferenced = crawl(dereferencedValue, pointer.path, pathFromRoot, parents, dereferencedCache, $refs, options);
195+
let dereferenced = await crawl(
196+
dereferencedValue,
197+
pointer.path,
198+
pathFromRoot,
199+
parents,
200+
dereferencedCache,
201+
$refs,
202+
options
203+
);
151204
circular = dereferenced.circular;
152205
dereferencedValue = dereferenced.value;
153206
}
154207

155-
if (circular && !directCircular && options.dereference.circular === "ignore") {
208+
if (
209+
circular &&
210+
!directCircular &&
211+
options.dereference.circular === "ignore"
212+
) {
156213
// The user has chosen to "ignore" circular references, so don't change the value
157214
dereferencedValue = $ref;
158215
}
@@ -165,7 +222,7 @@ function dereference$Ref ($ref, path, pathFromRoot, parents, dereferencedCache,
165222

166223
const dereferencedObject = {
167224
circular,
168-
value: dereferencedValue
225+
value: dereferencedValue,
169226
};
170227

171228
// only cache if no extra properties than $ref
@@ -185,7 +242,7 @@ function dereference$Ref ($ref, path, pathFromRoot, parents, dereferencedCache,
185242
* @param {$RefParserOptions} options
186243
* @returns {boolean} - always returns true, to indicate that a circular reference was found
187244
*/
188-
function foundCircularReference (keyPath, $refs, options) {
245+
function foundCircularReference(keyPath, $refs, options) {
189246
$refs.circular = true;
190247
if (!options.dereference.circular) {
191248
throw ono.reference(`Circular $ref pointer found at ${keyPath}`);

0 commit comments

Comments
 (0)