From 426ef2a5b6c51eaed9eaaddef1cbfbe8dcb42569 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alvaro=20Cabrera=20Dur=C3=A1n?= <pateketrueke@gmail.com>
Date: Tue, 22 Oct 2019 21:05:31 -0500
Subject: [PATCH] Handle circular-refs and such; fixes #258 #427

---
 src/core/run.js                         | 14 +++++++-------
 src/types/object.js                     |  4 ++--
 tests/schema/core/issues/issue-427.json |  1 -
 3 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/src/core/run.js b/src/core/run.js
index 7780d5ad..2194479b 100644
--- a/src/core/run.js
+++ b/src/core/run.js
@@ -117,9 +117,10 @@ function resolve(obj, data, values, property) {
 // TODO provide types
 function run(refs, schema, container) {
   let depth = 0;
+  let lastRef;
 
   try {
-    const result = traverse(utils.clone(schema), [], function reduce(sub, index, rootPath, parentSchema) {
+    const result = traverse(utils.clone(schema), [], function reduce(sub, index, rootPath) {
       if (typeof sub.generate === 'function') {
         return sub;
       }
@@ -134,15 +135,14 @@ function run(refs, schema, container) {
       }
 
       if (typeof sub.$ref === 'string') {
-        if (index !== null && parentSchema && parentSchema.required) {
-          if (parentSchema.required.includes(index)) return sub;
-        }
-
-        if (sub.$ref === '#' || (++depth > random.number(1, 2))) {
+        // increasing depth only for repeated refs seems to be fixing #258
+        if (sub.$ref === '#' || (lastRef === sub.$ref && ++depth > random.number(0, 3))) {
           delete sub.$ref;
           return sub;
         }
 
+        lastRef = sub.$ref;
+
         let ref;
 
         if (sub.$ref.indexOf('#/') === -1) {
@@ -221,7 +221,7 @@ function run(refs, schema, container) {
 
       Object.keys(sub).forEach(prop => {
         if ((Array.isArray(sub[prop]) || typeof sub[prop] === 'object') && !utils.isKey(prop)) {
-          sub[prop] = reduce(sub[prop], prop, rootPath.concat(prop), parentSchema);
+          sub[prop] = reduce(sub[prop], prop, rootPath.concat(prop));
         }
       });
 
diff --git a/src/types/object.js b/src/types/object.js
index 6de8ba15..69733473 100644
--- a/src/types/object.js
+++ b/src/types/object.js
@@ -43,7 +43,7 @@ function objectType(value, path, resolve, traverseCallback) {
       }
     });
 
-    return traverseCallback(props, path.concat(['properties']), resolve);
+    return traverseCallback(props, path.concat(['properties']), resolve, value);
   }
 
   const optionalsProbability = optionAPI('alwaysFakeOptionals') === true ? 1.0 : optionAPI('optionalsProbability');
@@ -100,7 +100,7 @@ function objectType(value, path, resolve, traverseCallback) {
 
       return traverseCallback({
         allOf: _defns.concat(value),
-      }, path.concat(['properties']), resolve);
+      }, path.concat(['properties']), resolve, value);
     }
   }
 
diff --git a/tests/schema/core/issues/issue-427.json b/tests/schema/core/issues/issue-427.json
index 4db305ac..d75b7907 100644
--- a/tests/schema/core/issues/issue-427.json
+++ b/tests/schema/core/issues/issue-427.json
@@ -94,7 +94,6 @@
       "set": {
         "optionalsProbability": 0.6
       },
-      "skip": true,
       "valid": true
     }
   ]
-- 
GitLab