Repository: reduxjs/react-redux
Pull request #1122 (2018-12-12 15:54:55)

Fix issue with isValidElementType invariant check crashing on valid t…
…ype with circular structure

Repro - https://codesandbox.io/s/jnmoxr5mk3

Emotion is attaching created component to the returned styled component (creating a circular structure) to easily "flatten" subsequent calls wrapping that component, as in:
```js
const Div = styled.div`color: white;`
const Div2 = styled(Div)`background-color: pink;`
```

netlify[bot]: Deploy preview for *react-redux-docs* ready!

Built with commit 1fe203aac489ec150e51313e914f58cc82fc4f89

https://deploy-preview-1122--react-redux-docs.netlify.com
timdorr: Can you run this through Prettier? And can you add a test?
Andarist: > Can you run this through Prettier? And can you add a test?

Done & done.
timdorr: Thanks for this and the other updates!

Patch:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 142934c..a2388e2 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -42,12 +42,12 @@ npm run test
 
 To run in explicit React versions (the number is the version, so `test:16.3` will run in React version `16.3`):
 ```
-REACT=16.4 npm run test:ci
+REACT=16.4 npm run test
 ```
 
 To run tests in all supported React versions, `16.4`, 16.5`,
 ```
-REACT=all npm run test:ci
+REACT=all npm run test
 ```
 
 To continuously watch and run tests, run the following:
diff --git a/package-lock.json b/package-lock.json
index 558c110..ac54136 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1925,7 +1925,7 @@
     },
     "babel-plugin-istanbul": {
       "version": "4.1.6",
-      "resolved": "http://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz",
+      "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz",
       "integrity": "sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==",
       "dev": true,
       "requires": {
@@ -1954,7 +1954,7 @@
     },
     "babel-plugin-syntax-object-rest-spread": {
       "version": "6.13.0",
-      "resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
+      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
       "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=",
       "dev": true
     },
@@ -2322,7 +2322,7 @@
     },
     "callsites": {
       "version": "0.2.0",
-      "resolved": "http://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
+      "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
       "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
       "dev": true
     },
@@ -3647,7 +3647,7 @@
     },
     "fast-deep-equal": {
       "version": "1.1.0",
-      "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
       "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
       "dev": true
     },
@@ -4412,7 +4412,7 @@
     },
     "get-stream": {
       "version": "3.0.0",
-      "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
       "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
       "dev": true
     },
@@ -4853,7 +4853,7 @@
     },
     "is-builtin-module": {
       "version": "1.0.0",
-      "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+      "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
       "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
       "dev": true,
       "requires": {
@@ -5685,7 +5685,7 @@
     },
     "jest-get-type": {
       "version": "22.4.3",
-      "resolved": "http://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz",
+      "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz",
       "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==",
       "dev": true
     },
@@ -6518,7 +6518,7 @@
     },
     "json5": {
       "version": "0.5.1",
-      "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
       "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
       "dev": true
     },
@@ -6635,7 +6635,7 @@
     },
     "load-json-file": {
       "version": "2.0.0",
-      "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
+      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
       "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
       "dev": true,
       "requires": {
@@ -6816,7 +6816,7 @@
     },
     "minimist": {
       "version": "0.0.8",
-      "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
       "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
       "dev": true
     },
@@ -6843,7 +6843,7 @@
     },
     "mkdirp": {
       "version": "0.5.1",
-      "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
       "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
       "dev": true,
       "requires": {
@@ -7001,7 +7001,7 @@
       "dependencies": {
         "minimist": {
           "version": "1.2.0",
-          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
           "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
           "dev": true
         }
@@ -7336,7 +7336,7 @@
     },
     "pify": {
       "version": "2.3.0",
-      "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
       "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
       "dev": true
     },
@@ -8145,7 +8145,7 @@
     },
     "require-uncached": {
       "version": "1.0.3",
-      "resolved": "http://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
+      "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
       "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
       "dev": true,
       "requires": {
@@ -8422,7 +8422,7 @@
     },
     "safe-regex": {
       "version": "1.1.0",
-      "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+      "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
       "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
       "dev": true,
       "requires": {
@@ -8728,7 +8728,7 @@
         },
         "minimist": {
           "version": "1.2.0",
-          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
           "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
           "dev": true
         }
@@ -9285,7 +9285,7 @@
       "dependencies": {
         "load-json-file": {
           "version": "1.1.0",
-          "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+          "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
           "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
           "dev": true,
           "requires": {
@@ -9353,7 +9353,7 @@
     },
     "through": {
       "version": "2.3.8",
-      "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
+      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
       "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
       "dev": true
     },
@@ -9753,7 +9753,7 @@
       "dependencies": {
         "minimist": {
           "version": "1.2.0",
-          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
           "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
           "dev": true
         }
@@ -9831,7 +9831,7 @@
     },
     "wrap-ansi": {
       "version": "2.1.0",
-      "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
       "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
       "dev": true,
       "requires": {
@@ -9916,7 +9916,7 @@
     },
     "yargs": {
       "version": "11.1.0",
-      "resolved": "http://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz",
       "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==",
       "dev": true,
       "requires": {
diff --git a/src/components/connectAdvanced.js b/src/components/connectAdvanced.js
index 066776e..081899d 100644
--- a/src/components/connectAdvanced.js
+++ b/src/components/connectAdvanced.js
@@ -5,6 +5,14 @@ import { isValidElementType } from 'react-is'
 
 import { ReactReduxContext } from './Context'
 
+const stringifyComponent = Comp => {
+  try {
+    return JSON.stringify(Comp)
+  } catch (err) {
+    return String(Comp)
+  }
+}
+
 export default function connectAdvanced(
   /*
     selectorFactory is a func that is responsible for returning the selector function used to
@@ -86,7 +94,9 @@ export default function connectAdvanced(
       invariant(
         isValidElementType(WrappedComponent),
         `You must pass a component to the function returned by ` +
-          `${methodName}. Instead received ${JSON.stringify(WrappedComponent)}`
+          `${methodName}. Instead received ${stringifyComponent(
+            WrappedComponent
+          )}`
       )
     }
 


Test patch:
diff --git a/test/components/connect.spec.js b/test/components/connect.spec.js
index 500ad7b..7a8629e 100644
--- a/test/components/connect.spec.js
+++ b/test/components/connect.spec.js
@@ -2604,5 +2604,19 @@ describe('React', () => {
         )(Comp)
       }).toThrow(/renderCountProp is removed/)
     })
+
+    it('should not error on valid component with circular structure', () => {
+      const createComp = Tag => {
+        const Comp = React.forwardRef(function Comp(props) {
+          return <Tag>{props.count}</Tag>
+        })
+        Comp.__real = Comp
+        return Comp
+      }
+
+      expect(() => {
+        connect()(createComp('div'))
+      }).not.toThrow()
+    })
   })
 })
diff --git a/test/run-tests.js b/test/run-tests.js
index d4057a4..640a79d 100644
--- a/test/run-tests.js
+++ b/test/run-tests.js
@@ -27,4 +27,7 @@ if (version.toLowerCase() === 'all') {
   }
 }
 
-npmRun.execSync(`jest -c '${JSON.stringify(jestConfig)}'`, { stdio: 'inherit' })
+npmRun.execSync(
+  `jest -c '${JSON.stringify(jestConfig)}' ${process.argv.slice(2).join(' ')}`,
+  { stdio: 'inherit' }
+)