From 051f2a7c506bbbb3ef1d2c6c57de7c66fc5812f3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alvaro=20Cabrera=20Dur=C3=A1n?= <pateketrueke@gmail.com>
Date: Thu, 10 Oct 2019 01:10:56 -0500
Subject: [PATCH] FIXME: handle self-references at cost of recursive ones

---
 src/core/run.js                         | 16 ++++++++++------
 src/core/traverse.js                    |  2 +-
 src/types/object.js                     |  2 +-
 tests/schema/core/issues/issue-427.json |  1 +
 4 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/src/core/run.js b/src/core/run.js
index f7fda592..f8b97967 100644
--- a/src/core/run.js
+++ b/src/core/run.js
@@ -119,7 +119,7 @@ function run(refs, schema, container) {
   let depth = 0;
 
   try {
-    const result = traverse(utils.clone(schema), [], function reduce(sub, parentSchemaPath) {
+    const result = traverse(utils.clone(schema), [], function reduce(sub, index, rootPath, parentSchema) {
       if (typeof sub.generate === 'function') {
         return sub;
       }
@@ -134,7 +134,11 @@ function run(refs, schema, container) {
       }
 
       if (typeof sub.$ref === 'string') {
-        if (sub.$ref === '#' || ++depth > random.number(0, 2)) {
+        if (index !== null && parentSchema && parentSchema.required) {
+          if (parentSchema.required.includes(index)) return sub;
+        }
+
+        if (sub.$ref === '#' || (++depth > random.number(0, 1))) {
           delete sub.$ref;
           return sub;
         }
@@ -170,7 +174,7 @@ function run(refs, schema, container) {
         // this is the only case where all sub-schemas
         // must be resolved before any merge
         schemas.forEach(subSchema => {
-          const _sub = reduce(subSchema, parentSchemaPath);
+          const _sub = reduce(subSchema, null, rootPath, parentSchema);
 
           // call given thunks if present
           utils.merge(sub, typeof _sub.thunk === 'function'
@@ -217,13 +221,13 @@ 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], parentSchemaPath.concat(prop));
+          sub[prop] = reduce(sub[prop], prop, rootPath.concat(prop), parentSchema);
         }
       });
 
       // avoid extra calls on sub-schemas, fixes #458
-      if (parentSchemaPath) {
-        const lastProp = parentSchemaPath[parentSchemaPath.length - 1];
+      if (rootPath) {
+        const lastProp = rootPath[rootPath.length - 1];
 
         if (lastProp === 'properties' || lastProp === 'items') {
           return sub;
diff --git a/src/core/traverse.js b/src/core/traverse.js
index 6258f075..f68c8f16 100644
--- a/src/core/traverse.js
+++ b/src/core/traverse.js
@@ -7,7 +7,7 @@ import optionAPI from '../api/option';
 
 // TODO provide types
 function traverse(schema, path, resolve, rootSchema) {
-  schema = resolve(schema, path);
+  schema = resolve(schema, null, path, rootSchema);
 
   if (!schema) {
     return;
diff --git a/src/types/object.js b/src/types/object.js
index e26aa5eb..6de8ba15 100644
--- a/src/types/object.js
+++ b/src/types/object.js
@@ -251,7 +251,7 @@ function objectType(value, path, resolve, traverseCallback) {
     }
   }
 
-  return traverseCallback(props, path.concat(['properties']), resolve);
+  return traverseCallback(props, path.concat(['properties']), resolve, value);
 }
 
 export default objectType;
diff --git a/tests/schema/core/issues/issue-427.json b/tests/schema/core/issues/issue-427.json
index d75b7907..4db305ac 100644
--- a/tests/schema/core/issues/issue-427.json
+++ b/tests/schema/core/issues/issue-427.json
@@ -94,6 +94,7 @@
       "set": {
         "optionalsProbability": 0.6
       },
+      "skip": true,
       "valid": true
     }
   ]
-- 
GitLab