Merge pull request #173 from bvaughn/legacy

Support legacy React versions
This commit is contained in:
Brian Vaughn
2019-06-09 16:24:00 -07:00
committed by GitHub
36 changed files with 3251 additions and 27 deletions
-1
View File
@@ -1,6 +1,5 @@
node_modules
flow-typed
shells/browser/chrome/build
shells/browser/firefox/build
shells/browser/shared/build
+1 -3
View File
@@ -12,6 +12,4 @@ yarn-error.log
yarn-error.log
.vscode
.idea
.watchmanconfig
key.pem
.watchmanconfig
+38
View File
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 14.9</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@0.14.9/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@0.14.9/dist/react-dom.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/fixtures/regression/14.9.html">http://localhost:3000/fixtures/regression/14.9.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>
+38
View File
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 15.0</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@15.0/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15.0/dist/react-dom.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/fixtures/regression/15.0.html">http://localhost:3000/fixtures/regression/15.0.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>
+38
View File
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 15.1</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@15.1/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15.1/dist/react-dom.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/fixtures/regression/15.1.html">http://localhost:3000/fixtures/regression/15.1.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>
+38
View File
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 15.2</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@15.2/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15.2/dist/react-dom.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/fixtures/regression/15.2.html">http://localhost:3000/fixtures/regression/15.2.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>
+38
View File
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 15.3</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@15.3/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15.3/dist/react-dom.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/fixtures/regression/15.3.html">http://localhost:3000/fixtures/regression/15.3.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>
+38
View File
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 15.4</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@15.4/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15.4/dist/react-dom.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/fixtures/regression/15.4.html">http://localhost:3000/fixtures/regression/15.4.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>
+38
View File
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 15.5</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@15.5/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15.5/dist/react-dom.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/fixtures/regression/15.5.html">http://localhost:3000/fixtures/regression/15.5.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>
+38
View File
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 15.6</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@15.6/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15.6/dist/react-dom.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/fixtures/regression/15.6.html">http://localhost:3000/fixtures/regression/15.6.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>
+38
View File
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 16.0</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@16.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.0/umd/react-dom.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/fixtures/regression/16.0.html">http://localhost:3000/fixtures/regression/16.0.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>
+38
View File
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 16.1</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@16.1/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.1/umd/react-dom.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/fixtures/regression/16.1.html">http://localhost:3000/fixtures/regression/16.1.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>
+38
View File
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 16.2</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@16.2/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.2/umd/react-dom.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/fixtures/regression/16.2.html">http://localhost:3000/fixtures/regression/16.2.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>
+38
View File
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 16.3</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@16.3/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.3/umd/react-dom.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/fixtures/regression/16.3.html">http://localhost:3000/fixtures/regression/16.3.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>
+38
View File
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 16.4</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/react@16.4/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.4/umd/react-dom.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/fixtures/regression/16.4.html">http://localhost:3000/fixtures/regression/16.4.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>
+40
View File
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 16.5</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/schedule@0.5.0/umd/schedule.development.js"></script>
<script src="https://unpkg.com/schedule@0.5.0/umd/schedule-tracing.development.js"></script>
<script src="https://unpkg.com/react@16.5/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.5/umd/react-dom.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/fixtures/regression/16.5.html">http://localhost:3000/fixtures/regression/16.5.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>
+41
View File
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 16.6</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/scheduler@0.10.0/umd/scheduler.development.js"></script>
<script src="https://unpkg.com/scheduler@0.10.0/umd/scheduler-tracing.development.js"></script>
<script src="https://unpkg.com/react@16.6/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.6/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/react-cache@2.0.0-alpha.1/umd/react-cache.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/fixtures/regression/16.6.html">http://localhost:3000/fixtures/regression/16.6.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>
+41
View File
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React 16.7</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/scheduler@0.12.0/umd/scheduler.development.js"></script>
<script src="https://unpkg.com/scheduler@0.12.0/umd/scheduler-tracing.development.js"></script>
<script src="https://unpkg.com/react@16.7/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/react-cache@2.0.0-alpha.1/umd/react-cache.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/fixtures/regression/16.7.html">http://localhost:3000/fixtures/regression/16.7.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>
+41
View File
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React canary</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/scheduler@canary/umd/scheduler.development.js"></script>
<script src="https://unpkg.com/scheduler@canary/umd/scheduler-tracing.development.js"></script>
<script src="https://unpkg.com/react@canary/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@canary/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/react-cache@next/umd/react-cache.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/fixtures/regression/canary.html">http://localhost:3000/fixtures/regression/canary.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>
+28
View File
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React DevTools regression test</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<iframe src="canary.html"></iframe>
<iframe src="next.html"></iframe>
<iframe src="16.7.html"></iframe>
<iframe src="16.6.html"></iframe>
<iframe src="16.5.html"></iframe>
<iframe src="16.4.html"></iframe>
<iframe src="16.3.html"></iframe>
<iframe src="16.2.html"></iframe>
<iframe src="16.1.html"></iframe>
<iframe src="16.0.html"></iframe>
<iframe src="15.6.html"></iframe>
<iframe src="15.5.html"></iframe>
<iframe src="15.4.html"></iframe>
<iframe src="15.3.html"></iframe>
<iframe src="15.2.html"></iframe>
<iframe src="15.1.html"></iframe>
<iframe src="15.0.html"></iframe>
<iframe src="14.9.html"></iframe>
</body>
</html>
+41
View File
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React next</title>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
// Enable DevTools to inspect React inside of an <iframe>
// This must run before React is loaded
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/scheduler@next/umd/scheduler.development.js"></script>
<script src="https://unpkg.com/scheduler@next/umd/scheduler-tracing.development.js"></script>
<script src="https://unpkg.com/react@next/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@next/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/react-cache@next/umd/react-cache.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root">
If you are seeing this message, you are likely viewing this file using the <code>file</code> protocol which does not support cross origin requests.
<br/><br/>
Use the <code>server</code> script instead:
<br/><br/>
<code>node ./fixtures/regression/server.js</code><br/>
<code>open <a href="http://localhost:3000/fixtures/regression/next.html">http://localhost:3000/fixtures/regression/next.html</a></code>
</div>
<script src="shared.js" type="text/babel"></script>
<!--
This is a great way to try React but it's not suitable for production.
It slowly compiles JSX with Babel in the browser and uses a large development build of React.
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>
+16
View File
@@ -0,0 +1,16 @@
#!/usr/bin/env node
const finalhandler = require('finalhandler');
const http = require('http');
const serveStatic = require('serve-static');
// Serve fixtures folder
const serve = serveStatic(__dirname, { index: 'index.html' });
// Create server
const server = http.createServer(function onRequest(req, res) {
serve(req, res, finalhandler(req, res));
});
// Listen
server.listen(3000);
+330
View File
@@ -0,0 +1,330 @@
/* eslint-disable no-fallthrough, react/react-in-jsx-scope, react/jsx-no-undef */
/* global React ReactCache ReactDOM SchedulerTracing ScheduleTracing */
const apps = [];
const pieces = React.version.split('.');
const major =
pieces[0] === '0' ? parseInt(pieces[1], 10) : parseInt(pieces[0], 10);
const minor =
pieces[0] === '0' ? parseInt(pieces[2], 10) : parseInt(pieces[1], 10);
// Convenience wrapper to organize API features in DevTools.
function Feature({ children, label, version }) {
return (
<div className="Feature">
<div className="FeatureHeader">
<code className="FeatureCode">{label}</code>
<small>{version}</small>
</div>
{children}
</div>
);
}
// Simplify interaction tracing for tests below.
let trace = null;
if (typeof SchedulerTracing !== 'undefined') {
trace = SchedulerTracing.unstable_trace;
} else if (typeof ScheduleTracing !== 'undefined') {
trace = ScheduleTracing.unstable_trace;
} else {
trace = (_, __, callback) => callback();
}
// https://github.com/facebook/react/blob/master/CHANGELOG.md
switch (major) {
case 16:
switch (minor) {
case 7:
if (typeof React.useState === 'function') {
// Hooks
function Hooks() {
const [count, setCount] = React.useState(0);
const incrementCount = React.useCallback(
() => setCount(count + 1),
[count]
);
return (
<div>
count: {count}{' '}
<button onClick={incrementCount}>increment</button>
</div>
);
}
apps.push(
<Feature key="Hooks" label="Hooks" version="16.7+">
<Hooks />
</Feature>
);
}
case 6:
// memo
function LabelComponent({ label }) {
return <label>{label}</label>;
}
const AnonymousMemoized = React.memo(({ label }) => (
<label>{label}</label>
));
const Memoized = React.memo(LabelComponent);
const CustomMemoized = React.memo(LabelComponent);
CustomMemoized.displayName = 'MemoizedLabelFunction';
apps.push(
<Feature key="memo" label="memo" version="16.6+">
<AnonymousMemoized label="AnonymousMemoized" />
<Memoized label="Memoized" />
<CustomMemoized label="CustomMemoized" />
</Feature>
);
// Suspense
const loadResource = ([text, ms]) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(text);
}, ms);
});
};
const getResourceKey = ([text, ms]) => text;
const Resource = ReactCache.unstable_createResource(
loadResource,
getResourceKey
);
class Suspending extends React.Component {
state = { useSuspense: false };
useSuspense = () => this.setState({ useSuspense: true });
render() {
if (this.state.useSuspense) {
const text = Resource.read(['loaded', 2000]);
return text;
} else {
return <button onClick={this.useSuspense}>load data</button>;
}
}
}
apps.push(
<Feature key="Suspense" label="Suspense" version="16.6+">
<React.Suspense fallback={<div>loading...</div>}>
<Suspending />
</React.Suspense>
</Feature>
);
// lazy
const LazyWithDefaultProps = React.lazy(
() =>
new Promise(resolve => {
function FooWithDefaultProps(props) {
return (
<h1>
{props.greeting}, {props.name}
</h1>
);
}
FooWithDefaultProps.defaultProps = {
name: 'World',
greeting: 'Bonjour',
};
resolve({
default: FooWithDefaultProps,
});
})
);
apps.push(
<Feature key="lazy" label="lazy" version="16.6+">
<React.Suspense fallback={<div>loading...</div>}>
<LazyWithDefaultProps greeting="Hello" />
</React.Suspense>
</Feature>
);
case 5:
case 4:
// unstable_Profiler
class ProfilerChild extends React.Component {
state = { count: 0 };
incrementCount = () =>
this.setState(prevState => ({ count: prevState.count + 1 }));
render() {
return (
<div>
count: {this.state.count}{' '}
<button onClick={this.incrementCount}>increment</button>
</div>
);
}
}
const onRender = (...args) => {};
const Profiler = React.unstable_Profiler || React.Profiler;
apps.push(
<Feature
key="unstable_Profiler"
label="unstable_Profiler"
version="16.4+"
>
<Profiler id="count" onRender={onRender}>
<div>
<ProfilerChild />
</div>
</Profiler>
</Feature>
);
case 3:
// createContext()
const LocaleContext = React.createContext();
LocaleContext.displayName = 'LocaleContext';
const ThemeContext = React.createContext();
apps.push(
<Feature key="createContext" label="createContext" version="16.3+">
<ThemeContext.Provider value="blue">
<ThemeContext.Consumer>
{theme => <div>theme: {theme}</div>}
</ThemeContext.Consumer>
</ThemeContext.Provider>
<LocaleContext.Provider value="en-US">
<LocaleContext.Consumer>
{locale => <div>locale: {locale}</div>}
</LocaleContext.Consumer>
</LocaleContext.Provider>
</Feature>
);
// forwardRef()
const AnonymousFunction = React.forwardRef((props, ref) => (
<div ref={ref}>{props.children}</div>
));
const NamedFunction = React.forwardRef(function named(props, ref) {
return <div ref={ref}>{props.children}</div>;
});
const CustomName = React.forwardRef((props, ref) => (
<div ref={ref}>{props.children}</div>
));
CustomName.displayName = 'CustomNameForwardRef';
apps.push(
<Feature key="forwardRef" label="forwardRef" version="16.3+">
<AnonymousFunction>AnonymousFunction</AnonymousFunction>
<NamedFunction>NamedFunction</NamedFunction>
<CustomName>CustomName</CustomName>
</Feature>
);
// StrictMode
class StrictModeChild extends React.Component {
render() {
return 'StrictModeChild';
}
}
apps.push(
<Feature key="StrictMode" label="StrictMode" version="16.3+">
<React.StrictMode>
<StrictModeChild />
</React.StrictMode>
</Feature>
);
// unstable_AsyncMode (later renamed to unstable_ConcurrentMode, then ConcurrentMode)
const ConcurrentMode =
React.ConcurrentMode ||
React.unstable_ConcurrentMode ||
React.unstable_AsyncMode;
apps.push(
<Feature
key="AsyncMode/ConcurrentMode"
label="AsyncMode/ConcurrentMode"
version="16.3+"
>
<ConcurrentMode>
<div>
unstable_AsyncMode was added in 16.3, renamed to
unstable_ConcurrentMode in 16.5, and then renamed to
ConcurrentMode in 16.7
</div>
</ConcurrentMode>
</Feature>
);
case 2:
// Fragment
apps.push(
<Feature key="Fragment" label="Fragment" version="16.4+">
<React.Fragment>
<div>one</div>
<div>two</div>
</React.Fragment>
</Feature>
);
case 1:
case 0:
default:
break;
}
break;
case 15:
break;
case 14:
break;
default:
break;
}
function Even() {
return <small>(even)</small>;
}
// Simple stateful app shared by all React versions
class SimpleApp extends React.Component {
state = { count: 0 };
incrementCount = () => {
const updaterFn = prevState => ({ count: prevState.count + 1 });
trace('Updating count', performance.now(), () => this.setState(updaterFn));
};
render() {
const { count } = this.state;
return (
<div>
{count % 2 === 0 ? (
<span>
count: {count} <Even />
</span>
) : (
<span>count: {count}</span>
)}{' '}
<button onClick={this.incrementCount}>increment</button>
</div>
);
}
}
apps.push(
<Feature key="Simple stateful app" label="Simple stateful app" version="any">
<SimpleApp />
</Feature>
);
// This component, with the version prop, helps organize DevTools at a glance.
function TopLevelWrapperForDevTools({ version }) {
let header = <h1>React {version}</h1>;
if (version.includes('canary')) {
const commitSha = version.match(/.+canary-(.+)/)[1];
header = (
<h1>
React canary{' '}
<a href={`https://github.com/facebook/react/commit/${commitSha}`}>
{commitSha}
</a>
</h1>
);
} else if (version.includes('alpha')) {
header = <h1>React next</h1>;
}
return (
<div>
{header}
{apps}
</div>
);
}
TopLevelWrapperForDevTools.displayName = 'React';
ReactDOM.render(
<TopLevelWrapperForDevTools version={React.version} />,
document.getElementById('root')
);
+37
View File
@@ -0,0 +1,37 @@
body {
font-family: sans-serif;
font-size: 12px;
}
h1 {
margin: 0;
font-size: 20px;
}
h2 {
margin: 1rem 0 0;
}
iframe {
border: 1px solid #ddd;
border-radius: 0.5rem;
}
code {
white-space: nowrap;
}
.Feature {
margin: 1rem 0;
border-bottom: 1px solid #eee;
padding-bottom: 1rem;
}
.FeatureHeader {
font-size: 16px;
margin-bottom: 0.5rem;
}
.FeatureCode {
background-color: #eee;
padding: 0.25rem;
border-radius: 0.25rem;
}
+5
View File
@@ -133,11 +133,13 @@ type JestPromiseType = {
* Use rejects to unwrap the reason of a rejected promise so any other
* matcher can be chained. If the promise is fulfilled the assertion fails.
*/
// eslint-disable-next-line no-use-before-define
rejects: JestExpectType,
/**
* Use resolves to unwrap the value of a fulfilled promise so any other
* matcher can be chained. If the promise is rejected the assertion fails.
*/
// eslint-disable-next-line no-use-before-define
resolves: JestExpectType,
};
@@ -1085,8 +1087,10 @@ type JestPrettyFormatColors = {
};
type JestPrettyFormatIndent = string => string;
// eslint-disable-next-line no-unused-vars
type JestPrettyFormatRefs = Array<any>;
type JestPrettyFormatPrint = any => string;
// eslint-disable-next-line no-unused-vars
type JestPrettyFormatStringOrNull = string | null;
type JestPrettyFormatOptions = {|
@@ -1097,6 +1101,7 @@ type JestPrettyFormatOptions = {|
indent: number,
maxDepth: number,
min: boolean,
// eslint-disable-next-line no-use-before-define
plugins: JestPrettyFormatPlugins,
printFunctionName: boolean,
spacing: string,
+4 -1
View File
@@ -28,7 +28,7 @@
"<rootDir>/src/__tests__/storeSerializer"
],
"testMatch": [
"**/__tests__/*-test.js"
"**/__tests__/**/*-test.js"
]
},
"scripts": {
@@ -132,8 +132,10 @@
"prettier": "^1.16.4",
"prop-types": "^15.6.2",
"react": "^0.0.0-50b50c26f",
"react-15": "npm:react@^15",
"react-color": "^2.11.7",
"react-dom": "^0.0.0-50b50c26f",
"react-dom-15": "npm:react-dom@^15",
"react-is": "^0.0.0-50b50c26f",
"react-test-renderer": "^0.0.0-50b50c26f",
"react-virtualized-auto-sizer": "^1.0.2",
@@ -142,6 +144,7 @@
"rimraf": "^2.6.3",
"scheduler": "^0.0.0-50b50c26f",
"semver": "^5.5.1",
"serve-static": "^1.14.1",
"style-loader": "^0.23.1",
"web-ext": "^3.0.0",
"webpack": "^4.26.0",
@@ -0,0 +1,498 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Store (legacy) collapseNodesByDefault:false should not filter DOM nodes from the store tree: 1: mount 1`] = `
[root]
▾ <Grandparent>
▾ <div>
▾ <div>
▾ <Parent>
▾ <div>
▾ <Child>
<div>
▾ <Parent>
▾ <div>
▾ <Child>
<div>
<Nothing>
`;
exports[`Store (legacy) collapseNodesByDefault:false should not filter DOM nodes from the store tree: 2: update 1`] = `
[root]
▾ <Grandparent>
▾ <div>
▾ <div>
▾ <Parent>
▾ <div>
▾ <Child>
<div>
▾ <Parent>
▾ <div>
▾ <Child>
<div>
<Nothing>
`;
exports[`Store (legacy) collapseNodesByDefault:false should not filter DOM nodes from the store tree: 5: unmount 1`] = ``;
exports[`Store (legacy) collapseNodesByDefault:false should support adding and removing children: 1: mount 1`] = `
[root]
▾ <Root>
▾ <div>
▾ <Component key="a">
<div>
`;
exports[`Store (legacy) collapseNodesByDefault:false should support adding and removing children: 2: add child 1`] = `
[root]
▾ <Root>
▾ <div>
▾ <Component key="a">
<div>
▾ <Component key="b">
<div>
`;
exports[`Store (legacy) collapseNodesByDefault:false should support adding and removing children: 3: remove child 1`] = `
[root]
▾ <Root>
▾ <div>
▾ <Component key="b">
<div>
`;
exports[`Store (legacy) collapseNodesByDefault:false should support collapsing parts of the tree: 1: mount 1`] = `
[root]
▾ <Grandparent>
▾ <div>
▾ <Parent>
▾ <div>
▾ <Child key="0">
<div>
▾ <Child key="1">
<div>
▾ <Parent>
▾ <div>
▾ <Child key="0">
<div>
▾ <Child key="1">
<div>
`;
exports[`Store (legacy) collapseNodesByDefault:false should support collapsing parts of the tree: 2: collapse first Parent 1`] = `
[root]
▾ <Grandparent>
▾ <div>
▸ <Parent>
▾ <Parent>
▾ <div>
▾ <Child key="0">
<div>
▾ <Child key="1">
<div>
`;
exports[`Store (legacy) collapseNodesByDefault:false should support collapsing parts of the tree: 3: collapse second Parent 1`] = `
[root]
▾ <Grandparent>
▾ <div>
▸ <Parent>
▸ <Parent>
`;
exports[`Store (legacy) collapseNodesByDefault:false should support collapsing parts of the tree: 4: expand first Parent 1`] = `
[root]
▾ <Grandparent>
▾ <div>
▾ <Parent>
▾ <div>
▾ <Child key="0">
<div>
▾ <Child key="1">
<div>
▸ <Parent>
`;
exports[`Store (legacy) collapseNodesByDefault:false should support collapsing parts of the tree: 5: collapse Grandparent 1`] = `
[root]
▸ <Grandparent>
`;
exports[`Store (legacy) collapseNodesByDefault:false should support collapsing parts of the tree: 6: expand Grandparent 1`] = `
[root]
▾ <Grandparent>
▾ <div>
▾ <Parent>
▾ <div>
▾ <Child key="0">
<div>
▾ <Child key="1">
<div>
▸ <Parent>
`;
exports[`Store (legacy) collapseNodesByDefault:false should support mount and update operations for multiple roots: 1: mount 1`] = `
[root]
▾ <Parent key="A">
▾ <div>
▾ <Child key="0">
<div>
▾ <Child key="1">
<div>
▾ <Child key="2">
<div>
[root]
▾ <Parent key="B">
▾ <div>
▾ <Child key="0">
<div>
▾ <Child key="1">
<div>
`;
exports[`Store (legacy) collapseNodesByDefault:false should support mount and update operations for multiple roots: 2: update 1`] = `
[root]
▾ <Parent key="A">
▾ <div>
▾ <Child key="0">
<div>
▾ <Child key="1">
<div>
▾ <Child key="2">
<div>
▾ <Child key="3">
<div>
[root]
▾ <Parent key="B">
▾ <div>
▾ <Child key="0">
<div>
`;
exports[`Store (legacy) collapseNodesByDefault:false should support mount and update operations for multiple roots: 3: unmount B 1`] = `
[root]
▾ <Parent key="A">
▾ <div>
▾ <Child key="0">
<div>
▾ <Child key="1">
<div>
▾ <Child key="2">
<div>
▾ <Child key="3">
<div>
`;
exports[`Store (legacy) collapseNodesByDefault:false should support mount and update operations for multiple roots: 4: unmount A 1`] = ``;
exports[`Store (legacy) collapseNodesByDefault:false should support mount and update operations: 1: mount 1`] = `
[root]
▾ <Grandparent>
▾ <div>
▾ <Parent>
▾ <div>
▾ <Child key="0">
<div>
▾ <Child key="1">
<div>
▾ <Child key="2">
<div>
▾ <Child key="3">
<div>
▾ <Parent>
▾ <div>
▾ <Child key="0">
<div>
▾ <Child key="1">
<div>
▾ <Child key="2">
<div>
▾ <Child key="3">
<div>
`;
exports[`Store (legacy) collapseNodesByDefault:false should support mount and update operations: 2: update 1`] = `
[root]
▾ <Grandparent>
▾ <div>
▾ <Parent>
▾ <div>
▾ <Child key="0">
<div>
▾ <Child key="1">
<div>
▾ <Parent>
▾ <div>
▾ <Child key="0">
<div>
▾ <Child key="1">
<div>
`;
exports[`Store (legacy) collapseNodesByDefault:false should support mount and update operations: 3: unmount 1`] = ``;
exports[`Store (legacy) collapseNodesByDefault:false should support reordering of children: 1: mount 1`] = `
[root]
▾ <Root>
▾ <div>
▾ <Foo key="foo">
▾ <div>
▾ <Component key="0">
<div>
▾ <Bar key="bar">
▾ <div>
▾ <Component key="0">
<div>
▾ <Component key="1">
<div>
`;
exports[`Store (legacy) collapseNodesByDefault:false should support reordering of children: 2: reorder children 1`] = `
[root]
▾ <Root>
▾ <div>
▾ <Bar key="bar">
▾ <div>
▾ <Component key="0">
<div>
▾ <Component key="1">
<div>
▾ <Foo key="foo">
▾ <div>
▾ <Component key="0">
<div>
`;
exports[`Store (legacy) collapseNodesByDefault:false should support reordering of children: 3: collapse root 1`] = `
[root]
▸ <Root>
`;
exports[`Store (legacy) collapseNodesByDefault:false should support reordering of children: 4: expand root 1`] = `
[root]
▾ <Root>
▾ <div>
▾ <Bar key="bar">
▾ <div>
▾ <Component key="0">
<div>
▾ <Component key="1">
<div>
▾ <Foo key="foo">
▾ <div>
▾ <Component key="0">
<div>
`;
exports[`Store (legacy) collapseNodesByDefault:true should not filter DOM nodes from the store tree: 1: mount 1`] = `
[root]
▸ <Grandparent>
`;
exports[`Store (legacy) collapseNodesByDefault:true should not filter DOM nodes from the store tree: 2: expand Grandparent 1`] = `
[root]
▾ <Grandparent>
▸ <div>
`;
exports[`Store (legacy) collapseNodesByDefault:true should not filter DOM nodes from the store tree: 3: expand div 1`] = `
[root]
▾ <Grandparent>
▾ <div>
▸ <div>
▸ <Parent>
<Nothing>
`;
exports[`Store (legacy) collapseNodesByDefault:true should not filter DOM nodes from the store tree: 4: final update 1`] = `
[root]
▾ <Grandparent>
▾ <div>
▸ <div>
▸ <Parent>
<Nothing>
`;
exports[`Store (legacy) collapseNodesByDefault:true should not filter DOM nodes from the store tree: 5: unmount 1`] = ``;
exports[`Store (legacy) collapseNodesByDefault:true should support expanding deep parts of the tree: 1: mount 1`] = `
[root]
▸ <Wrapper>
`;
exports[`Store (legacy) collapseNodesByDefault:true should support expanding deep parts of the tree: 2: expand deepest node 1`] = `
[root]
▾ <Wrapper>
▾ <Nested>
▾ <Nested>
▾ <Nested>
▾ <Nested>
<div>
`;
exports[`Store (legacy) collapseNodesByDefault:true should support expanding deep parts of the tree: 3: collapse root 1`] = `
[root]
▸ <Wrapper>
`;
exports[`Store (legacy) collapseNodesByDefault:true should support expanding deep parts of the tree: 4: expand root 1`] = `
[root]
▾ <Wrapper>
▾ <Nested>
▾ <Nested>
▾ <Nested>
▾ <Nested>
<div>
`;
exports[`Store (legacy) collapseNodesByDefault:true should support expanding deep parts of the tree: 5: collapse middle node 1`] = `
[root]
▾ <Wrapper>
▸ <Nested>
`;
exports[`Store (legacy) collapseNodesByDefault:true should support expanding deep parts of the tree: 6: expand middle node 1`] = `
[root]
▾ <Wrapper>
▾ <Nested>
▾ <Nested>
▾ <Nested>
▾ <Nested>
<div>
`;
exports[`Store (legacy) collapseNodesByDefault:true should support expanding parts of the tree: 1: mount 1`] = `
[root]
▸ <Grandparent>
`;
exports[`Store (legacy) collapseNodesByDefault:true should support expanding parts of the tree: 2: expand Grandparent 1`] = `
[root]
▾ <Grandparent>
▸ <div>
`;
exports[`Store (legacy) collapseNodesByDefault:true should support expanding parts of the tree: 3: expand parent div 1`] = `
[root]
▾ <Grandparent>
▾ <div>
▸ <Parent>
▸ <Parent>
`;
exports[`Store (legacy) collapseNodesByDefault:true should support expanding parts of the tree: 4: expand first Parent 1`] = `
[root]
▾ <Grandparent>
▾ <div>
▾ <Parent>
▸ <div>
▸ <Parent>
`;
exports[`Store (legacy) collapseNodesByDefault:true should support expanding parts of the tree: 5: expand second Parent 1`] = `
[root]
▾ <Grandparent>
▾ <div>
▾ <Parent>
▸ <div>
▾ <Parent>
▸ <div>
`;
exports[`Store (legacy) collapseNodesByDefault:true should support expanding parts of the tree: 6: collapse first Parent 1`] = `
[root]
▾ <Grandparent>
▾ <div>
▸ <Parent>
▾ <Parent>
▸ <div>
`;
exports[`Store (legacy) collapseNodesByDefault:true should support expanding parts of the tree: 7: collapse second Parent 1`] = `
[root]
▾ <Grandparent>
▾ <div>
▸ <Parent>
▸ <Parent>
`;
exports[`Store (legacy) collapseNodesByDefault:true should support expanding parts of the tree: 8: collapse Grandparent 1`] = `
[root]
▸ <Grandparent>
`;
exports[`Store (legacy) collapseNodesByDefault:true should support mount and update operations for multiple roots: 1: mount 1`] = `
[root]
▸ <Parent key="A">
[root]
▸ <Parent key="B">
`;
exports[`Store (legacy) collapseNodesByDefault:true should support mount and update operations for multiple roots: 2: update 1`] = `
[root]
▸ <Parent key="A">
[root]
▸ <Parent key="B">
`;
exports[`Store (legacy) collapseNodesByDefault:true should support mount and update operations for multiple roots: 3: unmount B 1`] = `
[root]
▸ <Parent key="A">
`;
exports[`Store (legacy) collapseNodesByDefault:true should support mount and update operations for multiple roots: 4: unmount A 1`] = ``;
exports[`Store (legacy) collapseNodesByDefault:true should support mount and update operations: 1: mount 1`] = `
[root]
▸ <div>
`;
exports[`Store (legacy) collapseNodesByDefault:true should support mount and update operations: 2: update 1`] = `
[root]
▸ <div>
`;
exports[`Store (legacy) collapseNodesByDefault:true should support mount and update operations: 3: unmount 1`] = ``;
exports[`Store (legacy) collapseNodesByDefault:true should support reordering of children: 1: mount 1`] = `
[root]
▸ <Root>
`;
exports[`Store (legacy) collapseNodesByDefault:true should support reordering of children: 2: reorder children 1`] = `
[root]
▸ <Root>
`;
exports[`Store (legacy) collapseNodesByDefault:true should support reordering of children: 3: expand root 1`] = `
[root]
▾ <Root>
▸ <div>
`;
exports[`Store (legacy) collapseNodesByDefault:true should support reordering of children: 4: expand div 1`] = `
[root]
▾ <Root>
▾ <div>
▸ <Bar key="bar">
▸ <Foo key="foo">
`;
exports[`Store (legacy) collapseNodesByDefault:true should support reordering of children: 4: expand leaves 1`] = `
[root]
▾ <Root>
▾ <div>
▾ <Bar key="bar">
▸ <div>
▾ <Foo key="foo">
▸ <div>
`;
exports[`Store (legacy) collapseNodesByDefault:true should support reordering of children: 5: collapse root 1`] = `
[root]
▸ <Root>
`;
exports[`Store (legacy) should not allow a root node to be collapsed: 1: mount 1`] = `
[root]
▸ <Component>
`;
@@ -0,0 +1,505 @@
// @flow
describe('Store (legacy)', () => {
let React;
let ReactDOM;
let store;
const act = (callback: Function) => {
callback();
jest.runAllTimers(); // Flush Bridge operations
};
beforeEach(() => {
store = global.store;
// Redirect all React/ReactDOM requires to the v15 UMD.
// We use the UMD because Jest doesn't enable us to mock deep imports (e.g. "react/lib/Something").
jest.mock('react', () => jest.requireActual('react-15/dist/react.js'));
jest.mock('react-dom', () =>
jest.requireActual('react-dom-15/dist/react-dom.js')
);
React = require('react');
ReactDOM = require('react-dom');
});
it('should not allow a root node to be collapsed', () => {
const Component = () => <div>Hi</div>;
act(() =>
ReactDOM.render(<Component count={4} />, document.createElement('div'))
);
expect(store).toMatchSnapshot('1: mount');
expect(store.roots).toHaveLength(1);
const rootID = store.roots[0];
expect(() => store.toggleIsCollapsed(rootID, true)).toThrow(
'Root nodes cannot be collapsed'
);
});
describe('collapseNodesByDefault:false', () => {
beforeEach(() => {
store.collapseNodesByDefault = false;
});
it('should support mount and update operations', () => {
const Grandparent = ({ count }) => (
<div>
<Parent count={count} />
<Parent count={count} />
</div>
);
const Parent = ({ count }) => (
<div>
{new Array(count).fill(true).map((_, index) => (
<Child key={index} />
))}
</div>
);
const Child = () => <div>Hi!</div>;
const container = document.createElement('div');
act(() => ReactDOM.render(<Grandparent count={4} />, container));
expect(store).toMatchSnapshot('1: mount');
act(() => ReactDOM.render(<Grandparent count={2} />, container));
expect(store).toMatchSnapshot('2: update');
act(() => ReactDOM.unmountComponentAtNode(container));
expect(store).toMatchSnapshot('3: unmount');
});
it('should support mount and update operations for multiple roots', () => {
const Parent = ({ count }) => (
<div>
{new Array(count).fill(true).map((_, index) => (
<Child key={index} />
))}
</div>
);
const Child = () => <div>Hi!</div>;
const containerA = document.createElement('div');
const containerB = document.createElement('div');
act(() => {
ReactDOM.render(<Parent key="A" count={3} />, containerA);
ReactDOM.render(<Parent key="B" count={2} />, containerB);
});
expect(store).toMatchSnapshot('1: mount');
act(() => {
ReactDOM.render(<Parent key="A" count={4} />, containerA);
ReactDOM.render(<Parent key="B" count={1} />, containerB);
});
expect(store).toMatchSnapshot('2: update');
act(() => ReactDOM.unmountComponentAtNode(containerB));
expect(store).toMatchSnapshot('3: unmount B');
act(() => ReactDOM.unmountComponentAtNode(containerA));
expect(store).toMatchSnapshot('4: unmount A');
});
it('should not filter DOM nodes from the store tree', () => {
const Grandparent = ({ flip }) => (
<div>
<div>
<Parent flip={flip} />
</div>
<Parent flip={flip} />
<Nothing />
</div>
);
const Parent = ({ flip }) => (
<div>
{flip ? 'foo' : null}
<Child />
{flip && [null, 'hello', 42]}
{flip ? 'bar' : 'baz'}
</div>
);
const Child = () => <div>Hi!</div>;
const Nothing = () => null;
const container = document.createElement('div');
act(() =>
ReactDOM.render(<Grandparent count={4} flip={false} />, container)
);
expect(store).toMatchSnapshot('1: mount');
act(() =>
ReactDOM.render(<Grandparent count={4} flip={true} />, container)
);
expect(store).toMatchSnapshot('2: update');
act(() => ReactDOM.unmountComponentAtNode(container));
expect(store).toMatchSnapshot('5: unmount');
});
it('should support collapsing parts of the tree', () => {
const Grandparent = ({ count }) => (
<div>
<Parent count={count} />
<Parent count={count} />
</div>
);
const Parent = ({ count }) => (
<div>
{new Array(count).fill(true).map((_, index) => (
<Child key={index} />
))}
</div>
);
const Child = () => <div>Hi!</div>;
act(() =>
ReactDOM.render(
<Grandparent count={2} />,
document.createElement('div')
)
);
expect(store).toMatchSnapshot('1: mount');
const grandparentID = store.getElementIDAtIndex(0);
const parentOneID = store.getElementIDAtIndex(2);
const parentTwoID = store.getElementIDAtIndex(8);
act(() => store.toggleIsCollapsed(parentOneID, true));
expect(store).toMatchSnapshot('2: collapse first Parent');
act(() => store.toggleIsCollapsed(parentTwoID, true));
expect(store).toMatchSnapshot('3: collapse second Parent');
act(() => store.toggleIsCollapsed(parentOneID, false));
expect(store).toMatchSnapshot('4: expand first Parent');
act(() => store.toggleIsCollapsed(grandparentID, true));
expect(store).toMatchSnapshot('5: collapse Grandparent');
act(() => store.toggleIsCollapsed(grandparentID, false));
expect(store).toMatchSnapshot('6: expand Grandparent');
});
it('should support adding and removing children', () => {
const Root = ({ children }) => <div>{children}</div>;
const Component = () => <div />;
const container = document.createElement('div');
act(() =>
ReactDOM.render(
<Root>
<Component key="a" />
</Root>,
container
)
);
expect(store).toMatchSnapshot('1: mount');
act(() =>
ReactDOM.render(
<Root>
<Component key="a" />
<Component key="b" />
</Root>,
container
)
);
expect(store).toMatchSnapshot('2: add child');
act(() =>
ReactDOM.render(
<Root>
<Component key="b" />
</Root>,
container
)
);
expect(store).toMatchSnapshot('3: remove child');
});
it('should support reordering of children', () => {
const Root = ({ children }) => <div>{children}</div>;
const Component = () => <div />;
const Foo = () => <div>{[<Component key="0" />]}</div>;
const Bar = () => (
<div>{[<Component key="0" />, <Component key="1" />]}</div>
);
const foo = <Foo key="foo" />;
const bar = <Bar key="bar" />;
const container = document.createElement('div');
act(() => ReactDOM.render(<Root>{[foo, bar]}</Root>, container));
expect(store).toMatchSnapshot('1: mount');
act(() => ReactDOM.render(<Root>{[bar, foo]}</Root>, container));
expect(store).toMatchSnapshot('2: reorder children');
act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(0), true));
expect(store).toMatchSnapshot('3: collapse root');
act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(0), false));
expect(store).toMatchSnapshot('4: expand root');
});
});
describe('collapseNodesByDefault:true', () => {
beforeEach(() => {
store.collapseNodesByDefault = true;
});
it('should support mount and update operations', () => {
const Parent = ({ count }) => (
<div>
{new Array(count).fill(true).map((_, index) => (
<Child key={index} />
))}
</div>
);
const Child = () => <div>Hi!</div>;
const container = document.createElement('div');
act(() =>
ReactDOM.render(
<div>
<Parent count={1} />
<Parent count={3} />
</div>,
container
)
);
expect(store).toMatchSnapshot('1: mount');
act(() =>
ReactDOM.render(
<div>
<Parent count={2} />
<Parent count={1} />
</div>,
container
)
);
expect(store).toMatchSnapshot('2: update');
act(() => ReactDOM.unmountComponentAtNode(container));
expect(store).toMatchSnapshot('3: unmount');
});
it('should support mount and update operations for multiple roots', () => {
const Parent = ({ count }) => (
<div>
{new Array(count).fill(true).map((_, index) => (
<Child key={index} />
))}
</div>
);
const Child = () => <div>Hi!</div>;
const containerA = document.createElement('div');
const containerB = document.createElement('div');
act(() => {
ReactDOM.render(<Parent key="A" count={3} />, containerA);
ReactDOM.render(<Parent key="B" count={2} />, containerB);
});
expect(store).toMatchSnapshot('1: mount');
act(() => {
ReactDOM.render(<Parent key="A" count={4} />, containerA);
ReactDOM.render(<Parent key="B" count={1} />, containerB);
});
expect(store).toMatchSnapshot('2: update');
act(() => ReactDOM.unmountComponentAtNode(containerB));
expect(store).toMatchSnapshot('3: unmount B');
act(() => ReactDOM.unmountComponentAtNode(containerA));
expect(store).toMatchSnapshot('4: unmount A');
});
it('should not filter DOM nodes from the store tree', () => {
const Grandparent = ({ flip }) => (
<div>
<div>
<Parent flip={flip} />
</div>
<Parent flip={flip} />
<Nothing />
</div>
);
const Parent = ({ flip }) => (
<div>
{flip ? 'foo' : null}
<Child />
{flip && [null, 'hello', 42]}
{flip ? 'bar' : 'baz'}
</div>
);
const Child = () => <div>Hi!</div>;
const Nothing = () => null;
const container = document.createElement('div');
act(() =>
ReactDOM.render(<Grandparent count={4} flip={false} />, container)
);
expect(store).toMatchSnapshot('1: mount');
act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(0), false));
expect(store).toMatchSnapshot('2: expand Grandparent');
act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(1), false));
expect(store).toMatchSnapshot('3: expand div');
act(() =>
ReactDOM.render(<Grandparent count={4} flip={true} />, container)
);
expect(store).toMatchSnapshot('4: final update');
act(() => ReactDOM.unmountComponentAtNode(container));
expect(store).toMatchSnapshot('5: unmount');
});
it('should support expanding parts of the tree', () => {
const Grandparent = ({ count }) => (
<div>
<Parent count={count} />
<Parent count={count} />
</div>
);
const Parent = ({ count }) => (
<div>
{new Array(count).fill(true).map((_, index) => (
<Child key={index} />
))}
</div>
);
const Child = () => <div>Hi!</div>;
act(() =>
ReactDOM.render(
<Grandparent count={2} />,
document.createElement('div')
)
);
expect(store).toMatchSnapshot('1: mount');
const grandparentID = store.getElementIDAtIndex(0);
act(() => store.toggleIsCollapsed(grandparentID, false));
expect(store).toMatchSnapshot('2: expand Grandparent');
const parentDivID = store.getElementIDAtIndex(1);
act(() => store.toggleIsCollapsed(parentDivID, false));
expect(store).toMatchSnapshot('3: expand parent div');
const parentOneID = store.getElementIDAtIndex(2);
const parentTwoID = store.getElementIDAtIndex(3);
act(() => store.toggleIsCollapsed(parentOneID, false));
expect(store).toMatchSnapshot('4: expand first Parent');
act(() => store.toggleIsCollapsed(parentTwoID, false));
expect(store).toMatchSnapshot('5: expand second Parent');
act(() => store.toggleIsCollapsed(parentOneID, true));
expect(store).toMatchSnapshot('6: collapse first Parent');
act(() => store.toggleIsCollapsed(parentTwoID, true));
expect(store).toMatchSnapshot('7: collapse second Parent');
act(() => store.toggleIsCollapsed(grandparentID, true));
expect(store).toMatchSnapshot('8: collapse Grandparent');
});
it('should support expanding deep parts of the tree', () => {
const Wrapper = ({ forwardedRef }) => (
<Nested depth={3} forwardedRef={forwardedRef} />
);
const Nested = ({ depth, forwardedRef }) =>
depth > 0 ? (
<Nested depth={depth - 1} forwardedRef={forwardedRef} />
) : (
<div ref={forwardedRef} />
);
let ref = null;
const refSetter = value => {
ref = value;
};
act(() =>
ReactDOM.render(
<Wrapper forwardedRef={refSetter} />,
document.createElement('div')
)
);
expect(store).toMatchSnapshot('1: mount');
const deepestedNodeID = global.agent.getIDForNode(ref);
act(() => store.toggleIsCollapsed(deepestedNodeID, false));
expect(store).toMatchSnapshot('2: expand deepest node');
const rootID = store.getElementIDAtIndex(0);
act(() => store.toggleIsCollapsed(rootID, true));
expect(store).toMatchSnapshot('3: collapse root');
act(() => store.toggleIsCollapsed(rootID, false));
expect(store).toMatchSnapshot('4: expand root');
const id = store.getElementIDAtIndex(1);
act(() => store.toggleIsCollapsed(id, true));
expect(store).toMatchSnapshot('5: collapse middle node');
act(() => store.toggleIsCollapsed(id, false));
expect(store).toMatchSnapshot('6: expand middle node');
});
it('should support reordering of children', () => {
const Root = ({ children }) => <div>{children}</div>;
const Component = () => <div />;
const Foo = () => <div>{[<Component key="0" />]}</div>;
const Bar = () => (
<div>{[<Component key="0" />, <Component key="1" />]}</div>
);
const foo = <Foo key="foo" />;
const bar = <Bar key="bar" />;
const container = document.createElement('div');
act(() => ReactDOM.render(<Root>{[foo, bar]}</Root>, container));
expect(store).toMatchSnapshot('1: mount');
act(() => ReactDOM.render(<Root>{[bar, foo]}</Root>, container));
expect(store).toMatchSnapshot('2: reorder children');
act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(0), false));
expect(store).toMatchSnapshot('3: expand root');
act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(1), false));
expect(store).toMatchSnapshot('4: expand div');
act(() => {
store.toggleIsCollapsed(store.getElementIDAtIndex(3), false);
store.toggleIsCollapsed(store.getElementIDAtIndex(2), false);
});
expect(store).toMatchSnapshot('4: expand leaves');
act(() => store.toggleIsCollapsed(store.getElementIDAtIndex(0), true));
expect(store).toMatchSnapshot('5: collapse root');
});
});
});
+6 -8
View File
@@ -47,17 +47,15 @@ export async function actAsync(
export function beforeEachProfiling(): void {
// Mock React's timing information so that test runs are predictable.
jest.mock('scheduler', () =>
// $FlowFixMe Flow does not konw about requireActual
require.requireActual('scheduler/unstable_mock')
);
jest.mock('scheduler', () => jest.requireActual('scheduler/unstable_mock'));
// DevTools itself uses performance.now() to offset commit times
// so they appear relative to when profiling was started in the UI.
jest.spyOn(performance, 'now').mockImplementation(
// $FlowFixMe Flow does not konw about requireActual
require.requireActual('scheduler/unstable_mock').unstable_now
);
jest
.spyOn(performance, 'now')
.mockImplementation(
jest.requireActual('scheduler/unstable_mock').unstable_now
);
}
export function createDisplayNameFilter(
+6 -1
View File
@@ -4,6 +4,7 @@ import type { DevToolsHook, ReactRenderer, RendererInterface } from './types';
import Agent from './agent';
import { attach } from './renderer';
import { attach as attachLegacy } from './legacy/renderer';
export function initBackend(
hook: DevToolsHook,
@@ -40,7 +41,11 @@ export function initBackend(
// Inject any not-yet-injected renderers (if we didn't reload-and-profile)
if (!rendererInterface) {
rendererInterface = attach(hook, id, renderer, global);
if (typeof renderer.findFiberByHostInstance === 'function') {
rendererInterface = attach(hook, id, renderer, global);
} else {
rendererInterface = attachLegacy(hook, id, renderer, global);
}
hook.rendererInterfaces.set(id, rendererInterface);
}
+40
View File
@@ -0,0 +1,40 @@
// @flow
import {
ElementTypeClass,
ElementTypeHostComponent,
ElementTypeOtherOrUnknown,
} from 'src/types';
import { getDisplayName } from 'src/utils';
import type { InternalInstance } from './renderer';
import type { FiberData } from '../types';
export default function getData(internalInstance: InternalInstance): FiberData {
let displayName = null;
let key = null;
let type = ElementTypeOtherOrUnknown;
// != used deliberately here to catch undefined and null
if (internalInstance._currentElement != null) {
if (internalInstance._currentElement.key) {
key = String(internalInstance._currentElement.key);
}
const elementType = internalInstance._currentElement.type;
if (typeof elementType === 'string') {
type = ElementTypeHostComponent;
displayName = elementType;
} else if (typeof elementType === 'function') {
// TODO: detect function components.
type = ElementTypeClass;
displayName = getDisplayName(elementType);
}
}
return {
displayName,
key,
type,
};
}
+791
View File
@@ -0,0 +1,791 @@
// @flow
import {
ElementTypeClass,
ElementTypeFunction,
ElementTypeRoot,
ElementTypeHostComponent,
ElementTypeOtherOrUnknown,
} from 'src/types';
import { getUID, utfEncodeString, printOperationsArray } from '../../utils';
import { cleanForBridge, copyWithSet } from '../utils';
import {
__DEBUG__,
TREE_OPERATION_ADD,
TREE_OPERATION_REMOVE,
TREE_OPERATION_REORDER_CHILDREN,
} from '../../constants';
import getData from './getData';
import { decorateMany, forceUpdate, restoreMany } from './utils';
import type {
DevToolsHook,
GetFiberIDForNative,
NativeType,
PathFrame,
PathMatch,
RendererInterface,
} from '../types';
import type { ComponentFilter, ElementType } from 'src/types';
import type { Owner, InspectedElement } from '../types';
export type InternalInstance = Object;
type LegacyRenderer = Object;
function getElementType(internalInstance: InternalInstance): ElementType {
// != used deliberately here to catch undefined and null
if (internalInstance._currentElement != null) {
const elementType = internalInstance._currentElement.type;
if (typeof elementType === 'function') {
return ElementTypeClass;
} else if (typeof elementType === 'string') {
return ElementTypeHostComponent;
}
}
return ElementTypeOtherOrUnknown;
}
function getChildren(internalInstance: Object): Array<any> {
let children = [];
// If the parent is a native node without rendered children, but with
// multiple string children, then the `element` that gets passed in here is
// a plain value -- a string or number.
if (typeof internalInstance !== 'object') {
// No children
} else if (
internalInstance._currentElement === null ||
internalInstance._currentElement === false
) {
// No children
} else if (internalInstance._renderedComponent) {
const child = internalInstance._renderedComponent;
if (getElementType(child) !== ElementTypeOtherOrUnknown) {
children.push(child);
}
} else if (internalInstance._renderedChildren) {
const renderedChildren = internalInstance._renderedChildren;
for (let name in renderedChildren) {
const child = renderedChildren[name];
if (getElementType(child) !== ElementTypeOtherOrUnknown) {
children.push(child);
}
}
}
// Note: we skip the case where children are just strings or numbers
// because the new DevTools skips over host text nodes anyway.
return children;
}
export function attach(
hook: DevToolsHook,
rendererID: number,
renderer: LegacyRenderer,
global: Object
): RendererInterface {
const idToInternalInstanceMap: Map<number, InternalInstance> = new Map();
const internalInstanceToIDMap: WeakMap<
InternalInstance,
number
> = new WeakMap();
const internalInstanceToRootIDMap: WeakMap<
InternalInstance,
number
> = new WeakMap();
let getInternalIDForNative: GetFiberIDForNative = ((null: any): GetFiberIDForNative);
let findNativeNodeForInternalID: (id: number) => ?NativeType;
if (renderer.ComponentTree) {
getInternalIDForNative = (node, findNearestUnfilteredAncestor) => {
const internalInstance = renderer.ComponentTree.getClosestInstanceFromNode(
node
);
return internalInstanceToIDMap.get(internalInstance) || null;
};
findNativeNodeForInternalID = (id: number) => {
const internalInstance = idToInternalInstanceMap.get(id);
return renderer.ComponentTree.getNodeFromInstance(internalInstance);
};
} else if (renderer.Mount.getID && renderer.Mount.getNode) {
getInternalIDForNative = (node, findNearestUnfilteredAncestor) => {
// Not implemented.
return null;
};
findNativeNodeForInternalID = (id: number) => {
// Not implemented.
return null;
};
}
function getID(internalInstance: InternalInstance): number {
if (typeof internalInstance !== 'object') {
throw new Error('Invalid internal instance: ' + internalInstance);
}
if (!internalInstanceToIDMap.has(internalInstance)) {
const id = getUID();
internalInstanceToIDMap.set(internalInstance, id);
idToInternalInstanceMap.set(id, internalInstance);
}
return ((internalInstanceToIDMap.get(internalInstance): any): number);
}
function areEqualArrays(a, b) {
if (a.length !== b.length) {
return false;
}
for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
}
// This is shared mutable state that lets us keep track of where we are.
let parentIDStack = [];
let oldReconcilerMethods = null;
if (renderer.Reconciler) {
// React 15
oldReconcilerMethods = decorateMany(renderer.Reconciler, {
mountComponent(fn, args) {
const [internalInstance, , , hostContainerInfo] = args;
if (getElementType(internalInstance) === ElementTypeOtherOrUnknown) {
return fn.apply(this, args);
}
const id = getID(internalInstance);
// Push the operation.
const parentID =
parentIDStack.length > 0
? parentIDStack[parentIDStack.length - 1]
: 0;
recordMount(internalInstance, id, parentID);
parentIDStack.push(id);
// Remember the root.
internalInstanceToRootIDMap.set(
internalInstance,
getID(hostContainerInfo._topLevelWrapper)
);
try {
const result = fn.apply(this, args);
parentIDStack.pop();
return result;
} catch (err) {
parentIDStack = [];
throw err;
} finally {
if (parentIDStack.length === 0) {
const rootID = internalInstanceToRootIDMap.get(internalInstance);
if (rootID === undefined) {
throw new Error('Expected to find root ID.');
}
flushPendingEvents(rootID);
}
}
},
performUpdateIfNecessary(fn, args) {
const [internalInstance] = args;
if (getElementType(internalInstance) === ElementTypeOtherOrUnknown) {
return fn.apply(this, args);
}
const id = getID(internalInstance);
parentIDStack.push(id);
const prevChildren = getChildren(internalInstance);
try {
const result = fn.apply(this, args);
const nextChildren = getChildren(internalInstance);
if (!areEqualArrays(prevChildren, nextChildren)) {
// Push the operation
recordReorder(internalInstance, id, nextChildren);
}
parentIDStack.pop();
return result;
} catch (err) {
parentIDStack = [];
throw err;
} finally {
if (parentIDStack.length === 0) {
const rootID = internalInstanceToRootIDMap.get(internalInstance);
if (rootID === undefined) {
throw new Error('Expected to find root ID.');
}
flushPendingEvents(rootID);
}
}
},
receiveComponent(fn, args) {
const [internalInstance] = args;
if (getElementType(internalInstance) === ElementTypeOtherOrUnknown) {
return fn.apply(this, args);
}
const id = getID(internalInstance);
parentIDStack.push(id);
const prevChildren = getChildren(internalInstance);
try {
const result = fn.apply(this, args);
const nextChildren = getChildren(internalInstance);
if (!areEqualArrays(prevChildren, nextChildren)) {
// Push the operation
recordReorder(internalInstance, id, nextChildren);
}
parentIDStack.pop();
return result;
} catch (err) {
parentIDStack = [];
throw err;
} finally {
if (parentIDStack.length === 0) {
const rootID = internalInstanceToRootIDMap.get(internalInstance);
if (rootID === undefined) {
throw new Error('Expected to find root ID.');
}
flushPendingEvents(rootID);
}
}
},
unmountComponent(fn, args) {
const [internalInstance] = args;
if (getElementType(internalInstance) === ElementTypeOtherOrUnknown) {
return fn.apply(this, args);
}
const id = getID(internalInstance);
parentIDStack.push(id);
try {
const result = fn.apply(this, args);
parentIDStack.pop();
// Push the operation.
recordUnmount(internalInstance, id);
return result;
} catch (err) {
parentIDStack = [];
throw err;
} finally {
if (parentIDStack.length === 0) {
const rootID = internalInstanceToRootIDMap.get(internalInstance);
if (rootID === undefined) {
throw new Error('Expected to find root ID.');
}
flushPendingEvents(rootID);
}
}
},
});
}
function cleanup() {
if (oldReconcilerMethods !== null) {
if (renderer.Component) {
restoreMany(renderer.Component.Mixin, oldReconcilerMethods);
} else {
restoreMany(renderer.Reconciler, oldReconcilerMethods);
}
}
oldReconcilerMethods = null;
}
function recordMount(
internalInstance: InternalInstance,
id: number,
parentID: number
) {
const isRoot = parentID === 0;
if (__DEBUG__) {
console.log(
'%crecordMount()',
'color: green; font-weight: bold;',
id,
getData(internalInstance).displayName
);
}
if (isRoot) {
// TODO Is this right? For all versions?
const hasOwnerMetadata =
internalInstance._currentElement != null &&
internalInstance._currentElement._owner != null;
pushOperation(TREE_OPERATION_ADD);
pushOperation(id);
pushOperation(ElementTypeRoot);
pushOperation(0); // isProfilingSupported?
pushOperation(hasOwnerMetadata ? 1 : 0);
} else {
const { displayName, key, type } = getData(internalInstance);
const ownerID =
internalInstance._currentElement != null &&
internalInstance._currentElement._owner != null
? getID(internalInstance._currentElement._owner)
: 0;
let displayNameStringID = getStringID(displayName);
let keyStringID = getStringID(key);
pushOperation(TREE_OPERATION_ADD);
pushOperation(id);
pushOperation(type);
pushOperation(parentID);
pushOperation(ownerID);
pushOperation(displayNameStringID);
pushOperation(keyStringID);
}
}
function recordReorder(
internalInstance: InternalInstance,
id: number,
nextChildren: Array<InternalInstance>
) {
pushOperation(TREE_OPERATION_REORDER_CHILDREN);
pushOperation(id);
const nextChildIDs = nextChildren.map(getID);
pushOperation(nextChildIDs.length);
for (let i = 0; i < nextChildIDs.length; i++) {
pushOperation(nextChildIDs[i]);
}
}
function recordUnmount(internalInstance: InternalInstance, id: number) {
pendingUnmountedIDs.push(id);
idToInternalInstanceMap.delete(id);
}
function crawlAndRecordInitialMounts(id: number, parentID: number) {
const internalInstance = idToInternalInstanceMap.get(id);
if (__DEBUG__) {
console.group('crawlAndRecordInitialMounts() id:', id);
}
recordMount(internalInstance, id, parentID);
getChildren(internalInstance).forEach(child =>
crawlAndRecordInitialMounts(getID(child), id)
);
if (__DEBUG__) {
console.groupEnd();
}
}
function flushInitialOperations() {
// Crawl roots though and register any nodes that mounted before we were injected.
const roots =
renderer.Mount._instancesByReactRootID ||
renderer.Mount._instancesByContainerID;
for (let key in roots) {
const internalInstance = roots[key];
const id = getID(internalInstance);
crawlAndRecordInitialMounts(id, 0);
flushPendingEvents(id);
}
}
let pendingOperations: Array<number> = [];
let pendingStringTable: Map<string, number> = new Map();
let pendingUnmountedIDs: Array<number> = [];
let pendingStringTableLength: number = 0;
let pendingUnmountedRootID: number | null = null;
function flushPendingEvents(rootID: number) {
if (
pendingOperations.length === 0 &&
pendingUnmountedIDs.length === 0 &&
pendingUnmountedRootID === null
) {
return;
}
const numUnmountIDs =
pendingUnmountedIDs.length + (pendingUnmountedRootID === null ? 0 : 1);
const operations = new Uint32Array(
// Identify which renderer this update is coming from.
2 + // [rendererID, rootFiberID]
// How big is the string table?
1 + // [stringTableLength]
// Then goes the actual string table.
pendingStringTableLength +
// All unmounts are batched in a single message.
// [TREE_OPERATION_REMOVE, removedIDLength, ...ids]
(numUnmountIDs > 0 ? 2 + numUnmountIDs : 0) +
// Mount operations
pendingOperations.length
);
// Identify which renderer this update is coming from.
// This enables roots to be mapped to renderers,
// Which in turn enables fiber properations, states, and hooks to be inspected.
let i = 0;
operations[i++] = rendererID;
operations[i++] = rootID;
// Now fill in the string table.
// [stringTableLength, str1Length, ...str1, str2Length, ...str2, ...]
operations[i++] = pendingStringTableLength;
pendingStringTable.forEach((value, key) => {
operations[i++] = key.length;
operations.set(utfEncodeString(key), i);
i += key.length;
});
if (numUnmountIDs > 0) {
// All unmounts except roots are batched in a single message.
operations[i++] = TREE_OPERATION_REMOVE;
// The first number is how many unmounted IDs we're gonna send.
operations[i++] = numUnmountIDs;
// Fill in the unmounts
for (let j = 0; j < pendingUnmountedIDs.length; j++) {
operations[i++] = pendingUnmountedIDs[j];
}
// The root ID should always be unmounted last.
if (pendingUnmountedRootID !== null) {
operations[i] = pendingUnmountedRootID;
i++;
}
}
// Fill in the rest of the operations.
operations.set(pendingOperations, i);
i += pendingOperations.length;
if (__DEBUG__) {
printOperationsArray(operations);
}
// If we've already connected to the frontend, just pass the operations through.
hook.emit('operations', operations);
pendingOperations.length = 0;
pendingUnmountedIDs = [];
pendingUnmountedRootID = null;
pendingStringTable.clear();
pendingStringTableLength = 0;
}
function pushOperation(op: number): void {
if (__DEV__) {
if (!Number.isInteger(op)) {
console.error(
'pushOperation() was called but the value is not an integer.',
op
);
}
}
pendingOperations.push(op);
}
function getStringID(str: string | null): number {
if (str === null) {
return 0;
}
const existingID = pendingStringTable.get(str);
if (existingID !== undefined) {
return existingID;
}
const stringID = pendingStringTable.size + 1;
pendingStringTable.set(str, stringID);
// The string table total length needs to account
// both for the string length, and for the array item
// that contains the length itself. Hence + 1.
pendingStringTableLength += str.length + 1;
return stringID;
}
function inspectElement(id: number): InspectedElement | null {
let result = inspectElementRaw(id);
if (result === null) {
return null;
}
// TODO Review sanitization approach for the below inspectable values.
result.context = cleanForBridge(result.context);
result.props = cleanForBridge(result.props);
result.state = cleanForBridge(result.state);
return result;
}
function inspectElementRaw(id: number): InspectedElement | null {
const internalInstance = idToInternalInstanceMap.get(id);
const data = getData(internalInstance);
let context = null;
let owners = null;
let props = null;
let state = null;
let source = null;
if (internalInstance != null) {
const element = internalInstance._currentElement;
if (element !== null) {
props = element.props;
source = element._source != null ? element._source : null;
let owner = element._owner;
if (owner) {
owners = [];
while (owner != null) {
const ownerData = getData(owner);
owners.push({
displayName: ownerData.displayName || 'Unknown',
id: getID(owner),
type: ownerData.type,
});
owner = owner.owner;
}
}
}
context = internalInstance.context || null;
state = internalInstance.state || null;
}
return {
id,
// Hooks did not exist in legacy versions
canEditHooks: false,
// Does the current renderer support editable function props?
canEditFunctionProps: true,
// Suspense did not exist in legacy versions
canToggleSuspense: false,
// Can view component source location.
canViewSource:
data.type === ElementTypeClass || data.type === ElementTypeFunction,
displayName: data.displayName,
type: data.type,
// New events system did not exist in legacy versions
events: null,
// Inspectable properties.
context,
hooks: null,
props,
state,
// List of owners
owners,
// Location of component in source coude.
source,
};
}
function logElementToConsole(id: number): void {
const result = inspectElementRaw(id);
if (result === null) {
console.warn(`Could not find element with id "${id}"`);
return;
}
const supportsGroup = typeof console.groupCollapsed === 'function';
if (supportsGroup) {
console.groupCollapsed(
`[Click to expand] %c<${result.displayName || 'Component'} />`,
// --dom-tag-name-color is the CSS variable Chrome styles HTML elements with in the console.
'color: var(--dom-tag-name-color); font-weight: normal;'
);
}
if (result.props !== null) {
console.log('Props:', result.props);
}
if (result.state !== null) {
console.log('State:', result.state);
}
if (result.context !== null) {
console.log('State:', result.context);
}
const nativeNode = findNativeNodeForInternalID(id);
if (nativeNode !== null) {
console.log('Node:', nativeNode);
}
if (window.chrome || /firefox/i.test(navigator.userAgent)) {
console.log(
'Right-click any value to save it as a global variable for further inspection.'
);
}
if (supportsGroup) {
console.groupEnd();
}
}
function prepareViewElementSource(id: number): void {
const internalInstance = idToInternalInstanceMap.get(id);
if (internalInstance == null) {
console.warn(`Could not find instance with id "${id}"`);
return;
}
const element = internalInstance._currentElement;
if (element == null) {
console.warn(`Could not find element with id "${id}"`);
return;
}
global.$type = element.type;
}
function selectElement(id: number): void {
const internalInstance = idToInternalInstanceMap.get(id);
if (internalInstance == null) {
console.warn(`Could not find instance with id "${id}"`);
return;
}
switch (getElementType(internalInstance)) {
case ElementTypeClass:
case ElementTypeFunction:
const element = internalInstance._currentElement;
if (element == null) {
console.warn(`Could not find element with id "${id}"`);
return;
}
global.$r = {
props: element.props,
type: element.type,
};
break;
default:
break;
}
}
function setInProps(id: number, path: Array<string | number>, value: any) {
const internalInstance = idToInternalInstanceMap.get(id);
if (internalInstance != null) {
const element = internalInstance._currentElement;
internalInstance._currentElement = {
...element,
props: copyWithSet(element.props, path, value),
};
forceUpdate(internalInstance._instance);
}
}
function setInState(id: number, path: Array<string | number>, value: any) {
const internalInstance = idToInternalInstanceMap.get(id);
if (internalInstance != null) {
setIn(internalInstance.state, path, value);
internalInstance.forceUpdate();
}
}
function setInContext(id: number, path: Array<string | number>, value: any) {
const internalInstance = idToInternalInstanceMap.get(id);
if (internalInstance != null) {
setIn(internalInstance.context, path, value);
forceUpdate(internalInstance);
}
}
function setIn(obj: Object, path: Array<string | number>, value: any) {
const last = path.pop();
const parent = path.reduce(
// $FlowFixMe
(reduced, attr) => (reduced ? reduced[attr] : null),
obj
);
if (parent) {
// $FlowFixMe
parent[last] = value;
}
}
// v16+ only features
const getProfilingData = () => {
throw new Error('getProfilingData not supported by this renderer');
};
const handleCommitFiberRoot = () => {
throw new Error('handleCommitFiberRoot not supported by this renderer');
};
const handleCommitFiberUnmount = () => {
throw new Error('handleCommitFiberUnmount not supported by this renderer');
};
const overrideSuspense = () => {
throw new Error('overrideSuspense not supported by this renderer');
};
const setInHook = () => {
throw new Error('setInHook not supported by this renderer');
};
const startProfiling = () => {
throw new Error('startProfiling not supported by this renderer');
};
const stopProfiling = () => {
throw new Error('stopProfiling not supported by this renderer');
};
function getBestMatchForTrackedPath(): PathMatch | null {
// Not implemented.
return null;
}
function getPathForElement(id: number): Array<PathFrame> | null {
// Not implemented.
return null;
}
function updateComponentFilters(componentFilters: Array<ComponentFilter>) {
// Not implemented.
}
function setTrackedPath(path: Array<PathFrame> | null) {
// Not implemented.
}
function getOwnersList(id: number): Array<Owner> | null {
// Not implemented.
return null;
}
return {
cleanup,
flushInitialOperations,
getBestMatchForTrackedPath,
getFiberIDForNative: getInternalIDForNative,
findNativeNodesForFiberID: (id: number) => {
const nativeNode = findNativeNodeForInternalID(id);
return nativeNode == null ? null : [nativeNode];
},
getOwnersList,
getPathForElement,
getProfilingData,
handleCommitFiberRoot,
handleCommitFiberUnmount,
inspectElement,
logElementToConsole,
overrideSuspense,
prepareViewElementSource,
renderer,
selectElement,
setInContext,
setInHook,
setInProps,
setInState,
setTrackedPath,
startProfiling,
stopProfiling,
updateComponentFilters,
};
}
+39
View File
@@ -0,0 +1,39 @@
// @flow
import type { InternalInstance } from './renderer';
export function decorate(object: Object, attr: string, fn: Function): Function {
const old = object[attr];
object[attr] = function(instance: InternalInstance) {
return fn.call(this, old, arguments);
};
return old;
}
export function decorateMany(
source: Object,
fns: { [attr: string]: Function }
): Object {
const olds = {};
for (const name in fns) {
olds[name] = decorate(source, name, fns[name]);
}
return olds;
}
export function restoreMany(source: Object, olds: Object): void {
for (let name in olds) {
source[name] = olds[name];
}
}
export function forceUpdate(instance: InternalInstance): void {
if (typeof instance.forceUpdate === 'function') {
instance.forceUpdate();
} else if (
instance.updater != null &&
typeof instance.updater.enqueueForceUpdate === 'function'
) {
instance.updater.enqueueForceUpdate(this, () => {}, 'forceUpdate');
}
}
+9 -6
View File
@@ -79,11 +79,17 @@ export type FiberData = {|
type: ElementType,
|};
export type NativeType = {};
export type NativeType = Object;
export type RendererID = number;
type Dispatcher = any;
export type GetFiberIDForNative = (
component: NativeType,
findNearestUnfilteredAncestor?: boolean
) => number | null;
export type FindNativeNodesForFiberID = (id: number) => ?Array<NativeType>;
export type ReactRenderer = {
findFiberByHostInstance: (hostInstance: NativeType) => ?Fiber,
version: string,
@@ -208,13 +214,10 @@ export type InspectedElement = {|
export type RendererInterface = {
cleanup: () => void,
findNativeNodesForFiberID: (id: number) => ?Array<NativeType>,
findNativeNodesForFiberID: FindNativeNodesForFiberID,
flushInitialOperations: () => void,
getBestMatchForTrackedPath: () => PathMatch | null,
getFiberIDForNative: (
component: NativeType,
findNearestUnfilteredAncestor?: boolean
) => number | null,
getFiberIDForNative: GetFiberIDForNative,
getProfilingData(): ProfilingDataBackend,
getOwnersList: (id: number) => Array<Owner> | null,
getPathForElement: (id: number) => Array<PathFrame> | null,
+100
View File
@@ -1,6 +1,13 @@
// @flow
import LRU from 'lru-cache';
import {
TREE_OPERATION_ADD,
TREE_OPERATION_REMOVE,
TREE_OPERATION_REORDER_CHILDREN,
TREE_OPERATION_UPDATE_TREE_BASE_DURATION,
} from './constants';
import { ElementTypeRoot } from 'src/types';
import { LOCAL_STORAGE_FILTER_PREFERENCES_KEY } from './constants';
import { ComponentFilterElementType, ElementTypeHostComponent } from './types';
import {
@@ -71,6 +78,99 @@ function toCodePoint(string: string) {
return string.codePointAt(0);
}
export function printOperationsArray(operations: Uint32Array) {
// The first two values are always rendererID and rootID
const rendererID = operations[0];
const rootID = operations[1];
const logs = [`opertions for renderer:${rendererID} and root:${rootID}`];
let i = 2;
// Reassemble the string table.
const stringTable = [
null, // ID = 0 corresponds to the null string.
];
const stringTableSize = operations[i++];
const stringTableEnd = i + stringTableSize;
while (i < stringTableEnd) {
const nextLength = operations[i++];
const nextString = utfDecodeString(
(operations.slice(i, i + nextLength): any)
);
stringTable.push(nextString);
i += nextLength;
}
while (i < operations.length) {
const operation = operations[i];
switch (operation) {
case TREE_OPERATION_ADD: {
const id = ((operations[i + 1]: any): number);
const type = ((operations[i + 2]: any): ElementType);
i += 3;
if (type === ElementTypeRoot) {
logs.push(`Add new root node ${id}`);
i++; // supportsProfiling
i++; // hasOwnerMetadata
} else {
const parentID = ((operations[i]: any): number);
i++;
i++; // ownerID
const displayNameStringID = operations[i];
const displayName = stringTable[displayNameStringID];
i++;
i++; // key
logs.push(
`Add node ${id} (${displayName || 'null'}) as child of ${parentID}`
);
}
break;
}
case TREE_OPERATION_REMOVE: {
const removeLength = ((operations[i + 1]: any): number);
i += 2;
for (let removeIndex = 0; removeIndex < removeLength; removeIndex++) {
const id = ((operations[i]: any): number);
i += 1;
logs.push(`Remove node ${id}`);
}
break;
}
case TREE_OPERATION_REORDER_CHILDREN: {
const id = ((operations[i + 1]: any): number);
const numChildren = ((operations[i + 2]: any): number);
i += 3;
const children = operations.slice(i, i + numChildren);
i += numChildren;
logs.push(`Re-order node ${id} children ${children.join(',')}`);
break;
}
case TREE_OPERATION_UPDATE_TREE_BASE_DURATION:
// Base duration updates are only sent while profiling is in progress.
// We can ignore them at this point.
// The profiler UI uses them lazily in order to generate the tree.
i += 3;
break;
default:
throw Error(`Unsupported Bridge operation ${operation}`);
}
}
console.log(logs.join('\n '));
}
export function getDefaultComponentFilters(): Array<ComponentFilter> {
return [
{
+138 -7
View File
@@ -3646,6 +3646,15 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
safe-buffer "^5.0.1"
sha.js "^2.4.8"
create-react-class@^15.6.0:
version "15.6.3"
resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.3.tgz#2d73237fb3f970ae6ebe011a9e66f46dbca80036"
integrity sha512-M+/3Q6E6DLO6Yx3OwrWjwHBnvfXXYA7W+dFjt/ZDBemHO1DDZhsalX/NUtnTYclN6GfnBDRh4qRHjcDHmlJBJg==
dependencies:
fbjs "^0.8.9"
loose-envify "^1.3.1"
object-assign "^4.1.1"
cross-env@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.2.0.tgz#6ecd4c015d5773e614039ee529076669b9d126f2"
@@ -5243,6 +5252,19 @@ fbjs@0.5.1:
ua-parser-js "^0.7.9"
whatwg-fetch "^0.9.0"
fbjs@^0.8.9:
version "0.8.17"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd"
integrity sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=
dependencies:
core-js "^1.0.0"
isomorphic-fetch "^2.1.1"
loose-envify "^1.0.0"
object-assign "^4.1.0"
promise "^7.1.1"
setimmediate "^1.0.5"
ua-parser-js "^0.7.18"
fd-slicer@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
@@ -6162,6 +6184,17 @@ http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3:
setprototypeof "1.1.0"
statuses ">= 1.4.0 < 2"
http-errors@~1.7.2:
version "1.7.2"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
dependencies:
depd "~1.1.2"
inherits "2.0.3"
setprototypeof "1.1.1"
statuses ">= 1.5.0 < 2"
toidentifier "1.0.0"
http-parser-js@>=0.4.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.0.tgz#d65edbede84349d0dc30320815a15d39cc3cbbd8"
@@ -6751,7 +6784,7 @@ is-retry-allowed@^1.0.0:
resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34"
integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=
is-stream@^1.0.0, is-stream@^1.1.0:
is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
@@ -6826,6 +6859,14 @@ isobject@^3.0.0, isobject@^3.0.1:
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
isomorphic-fetch@^2.1.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=
dependencies:
node-fetch "^1.0.1"
whatwg-fetch ">=0.10.0"
isstream@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
@@ -7989,7 +8030,7 @@ loglevel@^1.6.1:
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa"
integrity sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
@@ -8262,6 +8303,11 @@ mime@1.4.1:
resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==
mime@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
mime@^2.3.1:
version "2.4.2"
resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.2.tgz#ce5229a5e99ffc313abac806b482c10e7ba6ac78"
@@ -8395,7 +8441,7 @@ ms@2.0.0:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
ms@^2.1.1:
ms@2.1.1, ms@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
@@ -8536,6 +8582,14 @@ nice-try@^1.0.4:
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
node-fetch@^1.0.1:
version "1.7.3"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==
dependencies:
encoding "^0.1.11"
is-stream "^1.0.1"
node-forge@0.7.5:
version "0.7.5"
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.5.tgz#6c152c345ce11c52f465c2abd957e8639cd674df"
@@ -9155,7 +9209,7 @@ parse5@^3.0.1:
dependencies:
"@types/node" "*"
parseurl@~1.3.2:
parseurl@~1.3.2, parseurl@~1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
@@ -9517,6 +9571,13 @@ promise@^7.0.3:
dependencies:
asap "~2.0.3"
promise@^7.1.1:
version "7.3.1"
resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==
dependencies:
asap "~2.0.3"
prompts@^2.0.1:
version "2.0.4"
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.0.4.tgz#179f9d4db3128b9933aa35f93a800d8fce76a682"
@@ -9683,6 +9744,11 @@ range-parser@^1.0.3, range-parser@~1.2.0:
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=
range-parser@~1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
raw-body@2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3"
@@ -9703,6 +9769,17 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.2.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
"react-15@npm:react@^15":
version "15.6.2"
resolved "https://registry.yarnpkg.com/react/-/react-15.6.2.tgz#dba0434ab439cfe82f108f0f511663908179aa72"
integrity sha1-26BDSrQ5z+gvEI8PURZjkIF5qnI=
dependencies:
create-react-class "^15.6.0"
fbjs "^0.8.9"
loose-envify "^1.1.0"
object-assign "^4.1.0"
prop-types "^15.5.10"
react-color@^2.11.7:
version "2.17.0"
resolved "https://registry.yarnpkg.com/react-color/-/react-color-2.17.0.tgz#e14b8a11f4e89163f65a34c8b43faf93f7f02aaa"
@@ -9715,6 +9792,16 @@ react-color@^2.11.7:
reactcss "^1.2.0"
tinycolor2 "^1.4.1"
"react-dom-15@npm:react-dom@^15":
version "15.6.2"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.6.2.tgz#41cfadf693b757faf2708443a1d1fd5a02bef730"
integrity sha1-Qc+t9pO3V/rycIRDodH9WgK+9zA=
dependencies:
fbjs "^0.8.9"
loose-envify "^1.1.0"
object-assign "^4.1.0"
prop-types "^15.5.10"
react-dom@^0.0.0-50b50c26f:
version "0.0.0-50b50c26f"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-0.0.0-50b50c26f.tgz#3cd8da0f2276ed4b7a926e1807d2675b2eb40227"
@@ -10497,6 +10584,25 @@ send@0.16.2:
range-parser "~1.2.0"
statuses "~1.4.0"
send@0.17.1:
version "0.17.1"
resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==
dependencies:
debug "2.6.9"
depd "~1.1.2"
destroy "~1.0.4"
encodeurl "~1.0.2"
escape-html "~1.0.3"
etag "~1.8.1"
fresh "0.5.2"
http-errors "~1.7.2"
mime "1.6.0"
ms "2.1.1"
on-finished "~2.3.0"
range-parser "~1.2.1"
statuses "~1.5.0"
serialize-javascript@^1.4.0:
version "1.6.1"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.6.1.tgz#4d1f697ec49429a847ca6f442a2a755126c4d879"
@@ -10525,6 +10631,16 @@ serve-static@1.13.2:
parseurl "~1.3.2"
send "0.16.2"
serve-static@^1.14.1:
version "1.14.1"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9"
integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==
dependencies:
encodeurl "~1.0.2"
escape-html "~1.0.3"
parseurl "~1.3.3"
send "0.17.1"
set-blocking@^2.0.0, set-blocking@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
@@ -10550,7 +10666,7 @@ set-value@^2.0.0:
is-plain-object "^2.0.3"
split-string "^3.0.1"
setimmediate@^1.0.4:
setimmediate@^1.0.4, setimmediate@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
@@ -10560,6 +10676,11 @@ setprototypeof@1.1.0:
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==
setprototypeof@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
sha.js@2.2.6:
version "2.2.6"
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.2.6.tgz#17ddeddc5f722fb66501658895461977867315ba"
@@ -10962,7 +11083,7 @@ static-extend@^0.1.1:
define-property "^0.2.5"
object-copy "^0.1.0"
"statuses@>= 1.4.0 < 2":
"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
@@ -11512,6 +11633,11 @@ to-regex@^3.0.1, to-regex@^3.0.2:
regex-not "^1.0.2"
safe-regex "^1.1.0"
toidentifier@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
tosource@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/tosource/-/tosource-1.0.0.tgz#42d88dd116618bcf00d6106dd5446f3427902ff1"
@@ -11613,7 +11739,7 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
ua-parser-js@^0.7.9:
ua-parser-js@^0.7.18, ua-parser-js@^0.7.9:
version "0.7.19"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.19.tgz#94151be4c0a7fb1d001af7022fdaca4642659e4b"
integrity sha512-T3PVJ6uz8i0HzPxOF9SWzWAlfN/DavlpQqepn22xgve/5QecC+XMCAtmUNnY7C9StehaV6exjUCI801lOI7QlQ==
@@ -12113,6 +12239,11 @@ whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3:
dependencies:
iconv-lite "0.4.19"
whatwg-fetch@>=0.10.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb"
integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==
whatwg-fetch@^0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-0.9.0.tgz#0e3684c6cb9995b43efc9df03e4c365d95fd9cc0"