Skip to content

code optimisation for circular ref issue #62

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

Closed
wants to merge 6 commits into from
Closed
Changes from 3 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
82 changes: 71 additions & 11 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,18 +42,34 @@ 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,
circular: false
circular: false,
};

if (obj && typeof obj === "object" && !ArrayBuffer.isView(obj)) {
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 All @@ -165,7 +225,7 @@ function dereference$Ref ($ref, path, pathFromRoot, parents, dereferencedCache,

const dereferencedObject = {
circular,
value: dereferencedValue
value: dereferencedValue,
};

// only cache if no extra properties than $ref
Expand Down
Loading