Skip to content

Commit f674a14

Browse files
fix: recursion detection to allow same resolved $ref in different branches (#1241)
Co-authored-by: catosaurusrex2003 <mohdmehdi2003@gmail.com> Co-authored-by: Azeez Elegbede <40604284+AceTheCreator@users.noreply.github.com>
1 parent bf7f01b commit f674a14

1 file changed

Lines changed: 36 additions & 25 deletions

File tree

library/src/helpers/schema.ts

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -524,10 +524,14 @@ export class SchemaHelpers {
524524
return stringRange;
525525
}
526526

527-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
528-
private static jsonFieldToSchema(value: any, visited = new WeakSet()): any {
529-
// visited should never be passed as parameter.
530-
// it is meant for internal recursion limit tracking
527+
private static jsonFieldToSchema(
528+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
529+
value: any,
530+
visitedInPath = new Set<object>(),
531+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
532+
): any {
533+
// visitedInPath should never be passed as parameter.
534+
// it is meant for internal recursion limit tracking (add on entry, delete in finally)
531535
if (value === undefined || value === null) {
532536
return {
533537
type: 'string',
@@ -548,36 +552,43 @@ export class SchemaHelpers {
548552
};
549553
}
550554

551-
if (visited.has(value as object)) {
555+
const valueObject = value as object;
556+
557+
// Check if this object is already in the current path (circular reference)
558+
if (visitedInPath.has(valueObject)) {
552559
throw new Error(
553560
'too much recursion. Please check document for recursion.',
554561
);
555562
}
556-
visited.add(value as object);
557563

558-
if (this.isJSONSchema(value)) {
559-
return value;
560-
}
561-
if (Array.isArray(value)) {
564+
visitedInPath.add(valueObject);
565+
try {
566+
if (this.isJSONSchema(value)) {
567+
return value;
568+
}
569+
if (Array.isArray(value)) {
570+
return {
571+
type: 'array',
572+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
573+
items: value.map((v) => this.jsonFieldToSchema(v, visitedInPath)),
574+
[this.extRenderAdditionalInfo]: false,
575+
};
576+
}
562577
return {
563-
type: 'array',
564-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
565-
items: value.map((v) => this.jsonFieldToSchema(v, visited)),
578+
type: 'object',
579+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
580+
properties: Object.entries(value).reduce(
581+
(acc, [k, v]) => {
582+
acc[k] = this.jsonFieldToSchema(v, visitedInPath);
583+
return acc;
584+
},
585+
{} as Record<string, unknown>,
586+
),
566587
[this.extRenderAdditionalInfo]: false,
567588
};
589+
} finally {
590+
visitedInPath.delete(valueObject);
568591
}
569-
return {
570-
type: 'object',
571-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
572-
properties: Object.entries(value).reduce(
573-
(obj, [k, v]) => {
574-
obj[k] = this.jsonFieldToSchema(v, visited);
575-
return obj;
576-
},
577-
{} as Record<string, unknown>,
578-
),
579-
[this.extRenderAdditionalInfo]: false,
580-
};
581592
}
582593

583594
// eslint-disable-next-line @typescript-eslint/no-explicit-any

0 commit comments

Comments
 (0)