Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

code optimisation for circular ref issue #62

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 69 additions & 9 deletions lib/dereference.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,18 @@ module.exports = dereference;
* @param {$RefParser} parser
* @param {$RefParserOptions} options
*/
function dereference (parser, options) {
async function dereference (parser, options) {
parser.$refs.propertyMap = {}; // we assign a new object prior to another dereference process
// 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 = await crawl(
parser.schema,
parser.$refs._root$Ref.path,
"#",
[],
{},
parser.$refs,
options
);
parser.$refs.circular = dereferenced.circular;
parser.schema = dereferenced.value;
}
Expand All @@ -34,7 +42,15 @@ function dereference (parser, options) {
* @param {$RefParserOptions} options
* @returns {{value: object, circular: boolean}}
*/
function crawl (obj, path, pathFromRoot, parents, dereferencedCache, $refs, options) {
async function crawl (
obj,
path,
pathFromRoot,
parents,
dereferencedCache,
$refs,
options
) {
let dereferenced;
let result = {
value: obj,
Expand All @@ -45,7 +61,15 @@ function crawl (obj, path, pathFromRoot, parents, dereferencedCache, $refs, opti
parents.push(obj);

if ($Ref.isAllowed$Ref(obj, options)) {
dereferenced = dereference$Ref(obj, path, pathFromRoot, parents, dereferencedCache, $refs, options);
dereferenced = await dereference$Ref(
obj,
path,
pathFromRoot,
parents,
dereferencedCache,
$refs,
options
);
result.circular = dereferenced.circular;
result.value = dereferenced.value;
}
Expand All @@ -57,7 +81,15 @@ function crawl (obj, path, pathFromRoot, parents, dereferencedCache, $refs, opti
let circular = false;

if ($Ref.isAllowed$Ref(value, options)) {
dereferenced = dereference$Ref(value, keyPath, keyPathFromRoot, parents, dereferencedCache, $refs, options);
dereferenced = await dereference$Ref(
value,
keyPath,
keyPathFromRoot,
parents,
dereferencedCache,
$refs,
options
);
circular = dereferenced.circular;
// Avoid pointless mutations; breaks frozen objects to no profit
if (obj[key] !== dereferenced.value) {
Expand All @@ -66,7 +98,15 @@ function crawl (obj, path, pathFromRoot, parents, dereferencedCache, $refs, opti
}
else {
if (parents.indexOf(value) === -1) {
dereferenced = crawl(value, keyPath, keyPathFromRoot, parents, dereferencedCache, $refs, options);
dereferenced = await crawl(
value,
keyPath,
keyPathFromRoot,
parents,
dereferencedCache,
$refs,
options
);
circular = dereferenced.circular;
// Avoid pointless mutations; breaks frozen objects to no profit
if (obj[key] !== dereferenced.value) {
Expand Down Expand Up @@ -101,7 +141,15 @@ function crawl (obj, path, pathFromRoot, parents, dereferencedCache, $refs, opti
* @param {$RefParserOptions} options
* @returns {{value: object, circular: boolean}}
*/
function dereference$Ref ($ref, path, pathFromRoot, parents, dereferencedCache, $refs, options) {
async function dereference$Ref (
$ref,
path,
pathFromRoot,
parents,
dereferencedCache,
$refs,
options
) {
// console.log('Dereferencing $ref pointer "%s" at %s', $ref.$ref, path);

let $refPath = url.resolve(path, $ref.$ref);
Expand Down Expand Up @@ -147,12 +195,24 @@ function dereference$Ref ($ref, path, pathFromRoot, parents, dereferencedCache,
// Crawl the dereferenced value (unless it's circular)
if (!circular) {
// Determine if the dereferenced value is circular
let dereferenced = crawl(dereferencedValue, pointer.path, pathFromRoot, parents, dereferencedCache, $refs, options);
let dereferenced = await crawl(
dereferencedValue,
pointer.path,
pathFromRoot,
parents,
dereferencedCache,
$refs,
options
);
circular = dereferenced.circular;
dereferencedValue = dereferenced.value;
}

if (circular && !directCircular && options.dereference.circular === "ignore") {
if (
circular &&
!directCircular &&
options.dereference.circular === "ignore"
) {
// The user has chosen to "ignore" circular references, so don't change the value
dereferencedValue = $ref;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ $RefParser.prototype.dereference = async function dereference (path, schema, opt

try {
await this.resolve(args.path, args.schema, args.options);
_dereference(me, args.options);
await _dereference(me, args.options);
finalize(me);
return maybe(args.callback, Promise.resolve(me.schema));
}
Expand Down
Loading