Skip to content
Open
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
18 changes: 16 additions & 2 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,17 @@ function derefSchema (schema, options, state) {
delete node.$ref
newValue = _.merge({}, newValue, node)
}
this.update(newValue)
// Only walk into a resolved value the first time it is substituted.
// The same object is reused at every site pointing at that ref, so
// re-walking it repeats work already done - and when refs nest, each
// level is re-walked once per path that reaches it, which is
// exponential in the number of definitions.
const alreadyResolved =
newValue !== null && typeof newValue === 'object' && state.resolved.has(newValue)
if (newValue !== null && typeof newValue === 'object') {
state.resolved.add(newValue)
}
this.update(newValue, alreadyResolved)
if (state.missing.indexOf(refVal) !== -1) {
state.missing.splice(state.missing.indexOf(refVal), 1)
}
Expand Down Expand Up @@ -293,7 +303,11 @@ function deref (schema, options) {
circularRefs: [],
cwd: cwd,
missing: [],
history: []
history: [],
// Values already dereferenced during this call. A resolved ref is shared -
// the same object is substituted at every site that points at it - so once
// one has been walked there is nothing left to do on later substitutions.
resolved: new WeakSet()
}

try {
Expand Down