mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Merge pull request #173 from bvaughn/legacy
Support legacy React versions
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
node_modules
|
||||
|
||||
flow-typed
|
||||
shells/browser/chrome/build
|
||||
shells/browser/firefox/build
|
||||
shells/browser/shared/build
|
||||
|
||||
+1
-3
@@ -12,6 +12,4 @@ yarn-error.log
|
||||
yarn-error.log
|
||||
.vscode
|
||||
.idea
|
||||
.watchmanconfig
|
||||
key.pem
|
||||
|
||||
.watchmanconfig
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
Executable
+16
@@ -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);
|
||||
@@ -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')
|
||||
);
|
||||
@@ -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;
|
||||
}
|
||||
Vendored
+5
@@ -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
@@ -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');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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 [
|
||||
{
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user