Skip to content
Merged
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
11 changes: 9 additions & 2 deletions packages/downgrader/src/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export interface Context {
readonly apart: Map<unknown, Context['seen']>
/** The targets of the `$ref`s being inlined, so a reference back into one stops there. */
readonly inlining: Set<unknown>
/** The outputs whose conversion is running, innermost last. */
readonly converting: object[]
}

export type Convert = (value: unknown, ctx: Context) => unknown
Expand Down Expand Up @@ -116,7 +118,7 @@ function copy(value: unknown, copies: Map<object, unknown>): unknown {
* Converts the object `value` key by key: a key listed in `fields` goes
* through its converter or is dropped, and any other key is copied. `finish`
* then edits the output in place. An object met again gives the same output,
* which `revisit` is told of.
* and `revisit` is told of one met again before its conversion is done.
*/
export function convertObject(
value: unknown,
Expand All @@ -135,11 +137,14 @@ export function convertObject(
}
const known = seen.get(value)
if (known !== undefined) {
revisit?.(known)
if (revisit !== undefined && ctx.converting.includes(known)) {
revisit(known)
}
return known
}
const out: Record<string, unknown> = {}
seen.set(value, out)
ctx.converting.push(out)
for (const key of Object.keys(value)) {
const item = value[key]
if (item === undefined) {
Expand All @@ -153,6 +158,7 @@ export function convertObject(
}
}
finish?.(out, value, ctx)
ctx.converting.pop()
return out
}

Expand Down Expand Up @@ -282,6 +288,7 @@ export function downgrade(root: unknown, convert: Convert): unknown {
const seen: Context['seen'] = new Map()
return convert(root, {
apart: new Map(),
converting: [],
inlining: new Set(),
root,
seen,
Expand Down
11 changes: 3 additions & 8 deletions packages/downgrader/src/v3.1-to-v3.0.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,6 @@ const IN_PLACE_APPLICATORS = [
// Converted schemas that lost a restriction, directly or in a subschema.
const LOOSE = new WeakSet<object>()

// Converted schemas whose conversion is done. One met again before that,
// around a cycle, counts as loose, since what it loses is not known yet.
const DONE = new WeakSet<object>()

// Converted schemas with an `anyOf` or `oneOf` of several branches, for
// `mergeEnums` and `mergeNullable`. They run once the whole input is converted,
// since a cycle can meet a branch before its conversion is done.
Expand Down Expand Up @@ -1496,13 +1492,12 @@ function finishSchema(
if (loose) {
LOOSE.add(out)
}
DONE.add(out)
}

// Met again before its conversion is done, around a cycle, a schema counts as
// loose, since what it loses is not known yet.
function revisitSchema(out: object): void {
if (!DONE.has(out)) {
LOOSE.add(out)
}
LOOSE.add(out)
}

// Spelled out, not through `hasOnly`, since it runs for every `$ref`.
Expand Down
Loading