Skip to content

Commit

Permalink
Merge pull request #212 from haggholm/es6-collection-lookups
Browse files Browse the repository at this point in the history
fix(perf): Use ES6 collections for lookups in crawl().
  • Loading branch information
Phil Sturgeon authored Feb 4, 2021
2 parents f3ec536 + 7486084 commit 3980e6f
Showing 1 changed file with 17 additions and 18 deletions.
35 changes: 17 additions & 18 deletions lib/dereference.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module.exports = dereference;
*/
function dereference (parser, options) {
// console.log('Dereferencing $ref pointers in %s', parser.$refs._root$Ref.path);
let dereferenced = crawl(parser.schema, parser.$refs._root$Ref.path, "#", [], [], {}, parser.$refs, options);
let dereferenced = crawl(parser.schema, parser.$refs._root$Ref.path, "#", new Set(), new Set(), new Map(), parser.$refs, options);
parser.$refs.circular = dereferenced.circular;
parser.schema = dereferenced.value;
}
Expand All @@ -27,9 +27,9 @@ function dereference (parser, options) {
* @param {*} obj - The value to crawl. If it's not an object or array, it will be ignored.
* @param {string} path - The full path of `obj`, possibly with a JSON Pointer in the hash
* @param {string} pathFromRoot - The path of `obj` from the schema root
* @param {object[]} parents - An array of the parent objects that have already been dereferenced
* @param {object[]} processedObjects - An array of all the objects that have already been processed
* @param {object} dereferencedCache - An map of all the dereferenced objects
* @param {Set<object>} parents - An array of the parent objects that have already been dereferenced
* @param {Set<object>} processedObjects - An array of all the objects that have already been processed
* @param {Map<string,object>} dereferencedCache - An map of all the dereferenced objects
* @param {$Refs} $refs
* @param {$RefParserOptions} options
* @returns {{value: object, circular: boolean}}
Expand All @@ -41,18 +41,18 @@ function crawl (obj, path, pathFromRoot, parents, processedObjects, dereferenced
circular: false
};

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

if ($Ref.isAllowed$Ref(obj, options)) {
dereferenced = dereference$Ref(obj, path, pathFromRoot, parents, processedObjects, dereferencedCache, $refs, options);
result.circular = dereferenced.circular;
result.value = dereferenced.value;
}
else {
for (let key of Object.keys(obj)) {
for (const key of Object.keys(obj)) {
let keyPath = Pointer.join(path, key);
let keyPathFromRoot = Pointer.join(pathFromRoot, key);
let value = obj[key];
Expand All @@ -67,7 +67,7 @@ function crawl (obj, path, pathFromRoot, parents, processedObjects, dereferenced
}
}
else {
if (parents.indexOf(value) === -1) {
if (!parents.has(value)) {
dereferenced = crawl(value, keyPath, keyPathFromRoot, parents, processedObjects, dereferencedCache, $refs, options);
circular = dereferenced.circular;
// Avoid pointless mutations; breaks frozen objects to no profit
Expand All @@ -85,7 +85,7 @@ function crawl (obj, path, pathFromRoot, parents, processedObjects, dereferenced
}
}

parents.pop();
parents.delete(obj);
}
}

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

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

if (dereferencedCache[$refPath]) {
const cache = dereferencedCache[$refPath];

const cache = dereferencedCache.get($refPath);
if (cache) {
const refKeys = Object.keys($ref);
if (refKeys.length > 1) {
const extraKeys = {};
Expand Down Expand Up @@ -142,7 +141,7 @@ function dereference$Ref ($ref, path, pathFromRoot, parents, processedObjects, d

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

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

// only cache if no extra properties than $ref
if (Object.keys($ref).length === 1) {
dereferencedCache[$refPath] = dereferencedObject;
dereferencedCache.set($refPath, dereferencedObject);
}

return dereferencedObject;
Expand Down

0 comments on commit 3980e6f

Please sign in to comment.