Skip to content

Commit 3980e6f

Browse files
author
Phil Sturgeon
authoredFeb 4, 2021
Merge pull request #212 from haggholm/es6-collection-lookups
fix(perf): Use ES6 collections for lookups in crawl().
2 parents f3ec536 + 7486084 commit 3980e6f

File tree

1 file changed

+17
-18
lines changed

1 file changed

+17
-18
lines changed
 

‎lib/dereference.js

+17-18
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ module.exports = dereference;
1616
*/
1717
function dereference (parser, options) {
1818
// console.log('Dereferencing $ref pointers in %s', parser.$refs._root$Ref.path);
19-
let dereferenced = crawl(parser.schema, parser.$refs._root$Ref.path, "#", [], [], {}, parser.$refs, options);
19+
let dereferenced = crawl(parser.schema, parser.$refs._root$Ref.path, "#", new Set(), new Set(), new Map(), parser.$refs, options);
2020
parser.$refs.circular = dereferenced.circular;
2121
parser.schema = dereferenced.value;
2222
}
@@ -27,9 +27,9 @@ function dereference (parser, options) {
2727
* @param {*} obj - The value to crawl. If it's not an object or array, it will be ignored.
2828
* @param {string} path - The full path of `obj`, possibly with a JSON Pointer in the hash
2929
* @param {string} pathFromRoot - The path of `obj` from the schema root
30-
* @param {object[]} parents - An array of the parent objects that have already been dereferenced
31-
* @param {object[]} processedObjects - An array of all the objects that have already been processed
32-
* @param {object} dereferencedCache - An map of all the dereferenced objects
30+
* @param {Set<object>} parents - An array of the parent objects that have already been dereferenced
31+
* @param {Set<object>} processedObjects - An array of all the objects that have already been processed
32+
* @param {Map<string,object>} dereferencedCache - An map of all the dereferenced objects
3333
* @param {$Refs} $refs
3434
* @param {$RefParserOptions} options
3535
* @returns {{value: object, circular: boolean}}
@@ -41,18 +41,18 @@ function crawl (obj, path, pathFromRoot, parents, processedObjects, dereferenced
4141
circular: false
4242
};
4343

44-
if (options.dereference.circular === "ignore" || processedObjects.indexOf(obj) === -1) {
44+
if (options.dereference.circular === "ignore" || !processedObjects.has(obj)) {
4545
if (obj && typeof obj === "object" && !ArrayBuffer.isView(obj)) {
46-
parents.push(obj);
47-
processedObjects.push(obj);
46+
parents.add(obj);
47+
processedObjects.add(obj);
4848

4949
if ($Ref.isAllowed$Ref(obj, options)) {
5050
dereferenced = dereference$Ref(obj, path, pathFromRoot, parents, processedObjects, dereferencedCache, $refs, options);
5151
result.circular = dereferenced.circular;
5252
result.value = dereferenced.value;
5353
}
5454
else {
55-
for (let key of Object.keys(obj)) {
55+
for (const key of Object.keys(obj)) {
5656
let keyPath = Pointer.join(path, key);
5757
let keyPathFromRoot = Pointer.join(pathFromRoot, key);
5858
let value = obj[key];
@@ -67,7 +67,7 @@ function crawl (obj, path, pathFromRoot, parents, processedObjects, dereferenced
6767
}
6868
}
6969
else {
70-
if (parents.indexOf(value) === -1) {
70+
if (!parents.has(value)) {
7171
dereferenced = crawl(value, keyPath, keyPathFromRoot, parents, processedObjects, dereferencedCache, $refs, options);
7272
circular = dereferenced.circular;
7373
// Avoid pointless mutations; breaks frozen objects to no profit
@@ -85,7 +85,7 @@ function crawl (obj, path, pathFromRoot, parents, processedObjects, dereferenced
8585
}
8686
}
8787

88-
parents.pop();
88+
parents.delete(obj);
8989
}
9090
}
9191

@@ -98,9 +98,9 @@ function crawl (obj, path, pathFromRoot, parents, processedObjects, dereferenced
9898
* @param {{$ref: string}} $ref - The JSON Reference to resolve
9999
* @param {string} path - The full path of `$ref`, possibly with a JSON Pointer in the hash
100100
* @param {string} pathFromRoot - The path of `$ref` from the schema root
101-
* @param {object[]} parents - An array of the parent objects that have already been dereferenced
102-
* @param {object[]} processedObjects - An array of all the objects that have already been dereferenced
103-
* @param {object} dereferencedCache - An map of all the dereferenced objects
101+
* @param {Set<object>} parents - An array of the parent objects that have already been dereferenced
102+
* @param {Set<object>} processedObjects - An array of all the objects that have already been dereferenced
103+
* @param {Map<string,object>} dereferencedCache - An map of all the dereferenced objects
104104
* @param {$Refs} $refs
105105
* @param {$RefParserOptions} options
106106
* @returns {{value: object, circular: boolean}}
@@ -110,9 +110,8 @@ function dereference$Ref ($ref, path, pathFromRoot, parents, processedObjects, d
110110

111111
let $refPath = url.resolve(path, $ref.$ref);
112112

113-
if (dereferencedCache[$refPath]) {
114-
const cache = dereferencedCache[$refPath];
115-
113+
const cache = dereferencedCache.get($refPath);
114+
if (cache) {
116115
const refKeys = Object.keys($ref);
117116
if (refKeys.length > 1) {
118117
const extraKeys = {};
@@ -142,7 +141,7 @@ function dereference$Ref ($ref, path, pathFromRoot, parents, processedObjects, d
142141

143142
// Check for circular references
144143
let directCircular = pointer.circular;
145-
let circular = directCircular || parents.indexOf(pointer.value) !== -1;
144+
let circular = directCircular || parents.has(pointer.value);
146145
circular && foundCircularReference(path, $refs, options);
147146

148147
// Dereference the JSON reference
@@ -175,7 +174,7 @@ function dereference$Ref ($ref, path, pathFromRoot, parents, processedObjects, d
175174

176175
// only cache if no extra properties than $ref
177176
if (Object.keys($ref).length === 1) {
178-
dereferencedCache[$refPath] = dereferencedObject;
177+
dereferencedCache.set($refPath, dereferencedObject);
179178
}
180179

181180
return dereferencedObject;

0 commit comments

Comments
 (0)
Please sign in to comment.