mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 00:20:04 +01:00
Stop creating Owner Stacks if many have been created recently (#32529)
Co-authored-by: Jack Pope <jackpope1@gmail.com>
This commit is contained in:
parent
da996a15be
commit
4a9df08157
23
fixtures/owner-stacks/.gitignore
vendored
Normal file
23
fixtures/owner-stacks/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
70
fixtures/owner-stacks/README.md
Normal file
70
fixtures/owner-stacks/README.md
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
# Getting Started with Create React App
|
||||
|
||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
||||
|
||||
## Available Scripts
|
||||
|
||||
In the project directory, you can run:
|
||||
|
||||
### `yarn start`
|
||||
|
||||
Runs the app in the development mode.\
|
||||
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
|
||||
|
||||
The page will reload when you make changes.\
|
||||
You may also see any lint errors in the console.
|
||||
|
||||
### `yarn test`
|
||||
|
||||
Launches the test runner in the interactive watch mode.\
|
||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
||||
|
||||
### `yarn build`
|
||||
|
||||
Builds the app for production to the `build` folder.\
|
||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
||||
|
||||
The build is minified and the filenames include the hashes.\
|
||||
Your app is ready to be deployed!
|
||||
|
||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
||||
|
||||
### `yarn eject`
|
||||
|
||||
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
|
||||
|
||||
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
||||
|
||||
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
|
||||
|
||||
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
|
||||
|
||||
## Learn More
|
||||
|
||||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
||||
|
||||
To learn React, check out the [React documentation](https://reactjs.org/).
|
||||
|
||||
### Code Splitting
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
|
||||
|
||||
### Analyzing the Bundle Size
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
|
||||
|
||||
### Making a Progressive Web App
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
|
||||
|
||||
### Advanced Configuration
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
|
||||
|
||||
### Deployment
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
|
||||
|
||||
### `yarn build` fails to minify
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
|
||||
36
fixtures/owner-stacks/package.json
Normal file
36
fixtures/owner-stacks/package.json
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"name": "owner-stacks",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"react": "experimental",
|
||||
"react-dom": "experimental",
|
||||
"react-scripts": "5.0.1",
|
||||
"web-vitals": "^2.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
"prestart": "cp -a ../../build/oss-experimental/. node_modules",
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
}
|
||||
BIN
fixtures/owner-stacks/public/favicon.ico
Normal file
BIN
fixtures/owner-stacks/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
43
fixtures/owner-stacks/public/index.html
Normal file
43
fixtures/owner-stacks/public/index.html
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
||||
BIN
fixtures/owner-stacks/public/logo192.png
Normal file
BIN
fixtures/owner-stacks/public/logo192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
BIN
fixtures/owner-stacks/public/logo512.png
Normal file
BIN
fixtures/owner-stacks/public/logo512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.4 KiB |
25
fixtures/owner-stacks/public/manifest.json
Normal file
25
fixtures/owner-stacks/public/manifest.json
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
3
fixtures/owner-stacks/public/robots.txt
Normal file
3
fixtures/owner-stacks/public/robots.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
||||
62
fixtures/owner-stacks/src/App.css
Normal file
62
fixtures/owner-stacks/src/App.css
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
.App-header {
|
||||
background-color: #282c34;
|
||||
min-height: 10vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.page {
|
||||
display: flex;
|
||||
height: 90vh;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 4;
|
||||
background-color: #f0f0f0;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.content.highlight {
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
flex: 1;
|
||||
background-color: #d0d0d0;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.line-number {
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
text-align: right;
|
||||
margin-right: 10px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.text-symbol {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.hovercard {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: -40px;
|
||||
left: 0;
|
||||
background-color: white;
|
||||
border: 1px solid #ccc;
|
||||
padding: 5px;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.text-symbol:hover .hovercard {
|
||||
display: block;
|
||||
}
|
||||
143
fixtures/owner-stacks/src/App.js
Normal file
143
fixtures/owner-stacks/src/App.js
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
import {useState} from 'react';
|
||||
import {flushSync} from 'react-dom';
|
||||
import './App.css';
|
||||
|
||||
const text = `
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
`;
|
||||
|
||||
const loremIpsum = text + text;
|
||||
|
||||
function TextSymbol({char, highlight}) {
|
||||
const randomColor = highlight
|
||||
? `#${Math.floor(Math.random() * 16777215).toString(16)}`
|
||||
: 'transparent';
|
||||
return (
|
||||
<span className="text-symbol" style={{backgroundColor: randomColor}}>
|
||||
{char}
|
||||
<div className="hovercard">
|
||||
<p>Character: {char}</p>
|
||||
<p>Color: {randomColor}</p>
|
||||
</div>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
function TextLine({sentence, highlight, lineNumber}) {
|
||||
const randomColor = highlight
|
||||
? `#${Math.floor(Math.random() * 16777215).toString(16)}`
|
||||
: 'transparent';
|
||||
return (
|
||||
<div style={{backgroundColor: randomColor}}>
|
||||
<span className="line-number">{lineNumber}</span>
|
||||
{sentence.split('').map((char, index) => (
|
||||
<TextSymbol key={index} char={char} highlight={highlight} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function App() {
|
||||
const [highlight, setHighlight] = useState(false);
|
||||
|
||||
const toggleHighlight = () => {
|
||||
console.time('toggleHighlight');
|
||||
flushSync(() => {
|
||||
setHighlight(!highlight);
|
||||
});
|
||||
console.timeEnd('toggleHighlight');
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
<header className="App-header">Owner Stacks Stress Test</header>
|
||||
<div className="page">
|
||||
<div className={`content ${highlight ? 'highlight' : ''}`}>
|
||||
{loremIpsum
|
||||
.trim()
|
||||
.split('\n')
|
||||
.map((sentence, index) => (
|
||||
<TextLine
|
||||
key={index}
|
||||
sentence={sentence.trim()}
|
||||
highlight={highlight}
|
||||
lineNumber={index + 1}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className="sidebar">
|
||||
<button onClick={toggleHighlight}>
|
||||
{highlight ? 'Remove Highlight' : 'Highlight Content'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
13
fixtures/owner-stacks/src/index.css
Normal file
13
fixtures/owner-stacks/src/index.css
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
||||
17
fixtures/owner-stacks/src/index.js
Normal file
17
fixtures/owner-stacks/src/index.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
// to log results (for example: reportWebVitals(console.log))
|
||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||
reportWebVitals();
|
||||
1
fixtures/owner-stacks/src/logo.svg
Normal file
1
fixtures/owner-stacks/src/logo.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
13
fixtures/owner-stacks/src/reportWebVitals.js
Normal file
13
fixtures/owner-stacks/src/reportWebVitals.js
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
const reportWebVitals = onPerfEntry => {
|
||||
if (onPerfEntry && onPerfEntry instanceof Function) {
|
||||
import('web-vitals').then(({getCLS, getFID, getFCP, getLCP, getTTFB}) => {
|
||||
getCLS(onPerfEntry);
|
||||
getFID(onPerfEntry);
|
||||
getFCP(onPerfEntry);
|
||||
getLCP(onPerfEntry);
|
||||
getTTFB(onPerfEntry);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default reportWebVitals;
|
||||
9688
fixtures/owner-stacks/yarn.lock
Normal file
9688
fixtures/owner-stacks/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -315,7 +315,7 @@ describe('ReactFlight', () => {
|
|||
expect(getDebugInfo(greeting)).toEqual(
|
||||
__DEV__
|
||||
? [
|
||||
{time: 11},
|
||||
{time: 12},
|
||||
{
|
||||
name: 'Greeting',
|
||||
env: 'Server',
|
||||
|
|
@ -327,7 +327,7 @@ describe('ReactFlight', () => {
|
|||
lastName: 'Smith',
|
||||
},
|
||||
},
|
||||
{time: 12},
|
||||
{time: 13},
|
||||
]
|
||||
: undefined,
|
||||
);
|
||||
|
|
@ -359,7 +359,7 @@ describe('ReactFlight', () => {
|
|||
expect(getDebugInfo(promise)).toEqual(
|
||||
__DEV__
|
||||
? [
|
||||
{time: 11},
|
||||
{time: 12},
|
||||
{
|
||||
name: 'Greeting',
|
||||
env: 'Server',
|
||||
|
|
@ -371,7 +371,7 @@ describe('ReactFlight', () => {
|
|||
lastName: 'Smith',
|
||||
},
|
||||
},
|
||||
{time: 12},
|
||||
{time: 13},
|
||||
]
|
||||
: undefined,
|
||||
);
|
||||
|
|
@ -2807,7 +2807,7 @@ describe('ReactFlight', () => {
|
|||
expect(getDebugInfo(promise)).toEqual(
|
||||
__DEV__
|
||||
? [
|
||||
{time: 18},
|
||||
{time: 20},
|
||||
{
|
||||
name: 'ServerComponent',
|
||||
env: 'Server',
|
||||
|
|
@ -2818,7 +2818,7 @@ describe('ReactFlight', () => {
|
|||
transport: expect.arrayContaining([]),
|
||||
},
|
||||
},
|
||||
{time: 19},
|
||||
{time: 21},
|
||||
]
|
||||
: undefined,
|
||||
);
|
||||
|
|
@ -2829,7 +2829,7 @@ describe('ReactFlight', () => {
|
|||
expect(getDebugInfo(thirdPartyChildren[0])).toEqual(
|
||||
__DEV__
|
||||
? [
|
||||
{time: 13},
|
||||
{time: 14},
|
||||
{
|
||||
name: 'ThirdPartyComponent',
|
||||
env: 'third-party',
|
||||
|
|
@ -2838,15 +2838,15 @@ describe('ReactFlight', () => {
|
|||
stack: ' in Object.<anonymous> (at **)',
|
||||
props: {},
|
||||
},
|
||||
{time: 14},
|
||||
{time: 21}, // This last one is when the promise resolved into the first party.
|
||||
{time: 15},
|
||||
{time: 23}, // This last one is when the promise resolved into the first party.
|
||||
]
|
||||
: undefined,
|
||||
);
|
||||
expect(getDebugInfo(thirdPartyChildren[1])).toEqual(
|
||||
__DEV__
|
||||
? [
|
||||
{time: 15},
|
||||
{time: 16},
|
||||
{
|
||||
name: 'ThirdPartyLazyComponent',
|
||||
env: 'third-party',
|
||||
|
|
@ -2855,14 +2855,14 @@ describe('ReactFlight', () => {
|
|||
stack: ' in myLazy (at **)\n in lazyInitializer (at **)',
|
||||
props: {},
|
||||
},
|
||||
{time: 16},
|
||||
{time: 17},
|
||||
]
|
||||
: undefined,
|
||||
);
|
||||
expect(getDebugInfo(thirdPartyChildren[2])).toEqual(
|
||||
__DEV__
|
||||
? [
|
||||
{time: 11},
|
||||
{time: 12},
|
||||
{
|
||||
name: 'ThirdPartyFragmentComponent',
|
||||
env: 'third-party',
|
||||
|
|
@ -2871,7 +2871,7 @@ describe('ReactFlight', () => {
|
|||
stack: ' in Object.<anonymous> (at **)',
|
||||
props: {},
|
||||
},
|
||||
{time: 12},
|
||||
{time: 13},
|
||||
]
|
||||
: undefined,
|
||||
);
|
||||
|
|
@ -2936,7 +2936,7 @@ describe('ReactFlight', () => {
|
|||
expect(getDebugInfo(promise)).toEqual(
|
||||
__DEV__
|
||||
? [
|
||||
{time: 14},
|
||||
{time: 16},
|
||||
{
|
||||
name: 'ServerComponent',
|
||||
env: 'Server',
|
||||
|
|
@ -2947,7 +2947,7 @@ describe('ReactFlight', () => {
|
|||
transport: expect.arrayContaining([]),
|
||||
},
|
||||
},
|
||||
{time: 15},
|
||||
{time: 17},
|
||||
]
|
||||
: undefined,
|
||||
);
|
||||
|
|
@ -2956,7 +2956,7 @@ describe('ReactFlight', () => {
|
|||
expect(getDebugInfo(thirdPartyFragment)).toEqual(
|
||||
__DEV__
|
||||
? [
|
||||
{time: 16},
|
||||
{time: 18},
|
||||
{
|
||||
name: 'Keyed',
|
||||
env: 'Server',
|
||||
|
|
@ -2967,7 +2967,7 @@ describe('ReactFlight', () => {
|
|||
children: {},
|
||||
},
|
||||
},
|
||||
{time: 17},
|
||||
{time: 19},
|
||||
]
|
||||
: undefined,
|
||||
);
|
||||
|
|
@ -2975,7 +2975,7 @@ describe('ReactFlight', () => {
|
|||
expect(getDebugInfo(thirdPartyFragment.props.children)).toEqual(
|
||||
__DEV__
|
||||
? [
|
||||
{time: 11},
|
||||
{time: 12},
|
||||
{
|
||||
name: 'ThirdPartyAsyncIterableComponent',
|
||||
env: 'third-party',
|
||||
|
|
@ -2984,7 +2984,7 @@ describe('ReactFlight', () => {
|
|||
stack: ' in Object.<anonymous> (at **)',
|
||||
props: {},
|
||||
},
|
||||
{time: 12},
|
||||
{time: 13},
|
||||
]
|
||||
: undefined,
|
||||
);
|
||||
|
|
@ -3132,7 +3132,7 @@ describe('ReactFlight', () => {
|
|||
expect(getDebugInfo(greeting)).toEqual(
|
||||
__DEV__
|
||||
? [
|
||||
{time: 11},
|
||||
{time: 12},
|
||||
{
|
||||
name: 'Component',
|
||||
env: 'A',
|
||||
|
|
@ -3144,7 +3144,7 @@ describe('ReactFlight', () => {
|
|||
{
|
||||
env: 'B',
|
||||
},
|
||||
{time: 12},
|
||||
{time: 13},
|
||||
]
|
||||
: undefined,
|
||||
);
|
||||
|
|
@ -3332,9 +3332,9 @@ describe('ReactFlight', () => {
|
|||
},
|
||||
};
|
||||
expect(getDebugInfo(greeting)).toEqual([
|
||||
{time: 11},
|
||||
greetInfo,
|
||||
{time: 12},
|
||||
greetInfo,
|
||||
{time: 13},
|
||||
{
|
||||
name: 'Container',
|
||||
env: 'Server',
|
||||
|
|
@ -3350,7 +3350,7 @@ describe('ReactFlight', () => {
|
|||
}),
|
||||
},
|
||||
},
|
||||
{time: 13},
|
||||
{time: 14},
|
||||
]);
|
||||
// The owner that created the span was the outer server component.
|
||||
// We expect the debug info to be referentially equal to the owner.
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ import {
|
|||
enableViewTransition,
|
||||
enableSwipeTransition,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
import {resetOwnerStackLimit} from 'shared/ReactOwnerStackReset';
|
||||
import ReactSharedInternals from 'shared/ReactSharedInternals';
|
||||
import is from 'shared/objectIs';
|
||||
|
||||
|
|
@ -1984,6 +1985,8 @@ function prepareFreshStack(root: FiberRoot, lanes: Lanes): Fiber {
|
|||
finishQueueingConcurrentUpdates();
|
||||
|
||||
if (__DEV__) {
|
||||
resetOwnerStackLimit();
|
||||
|
||||
ReactStrictModeWarnings.discardPendingWarnings();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,15 +11,43 @@
|
|||
|
||||
let React;
|
||||
let ReactNoop;
|
||||
let ReactNoopServer;
|
||||
let Scheduler;
|
||||
let act;
|
||||
let advanceTimersByTime;
|
||||
let assertLog;
|
||||
let serverAct;
|
||||
let waitFor;
|
||||
|
||||
describe('ReactOwnerStacks', () => {
|
||||
beforeEach(function () {
|
||||
jest.resetModules();
|
||||
let time = 10;
|
||||
advanceTimersByTime = timeMS => {
|
||||
jest.advanceTimersByTime(timeMS);
|
||||
time += timeMS;
|
||||
};
|
||||
|
||||
const now = jest.fn().mockImplementation(() => {
|
||||
return time++;
|
||||
});
|
||||
Object.defineProperty(performance, 'timeOrigin', {
|
||||
value: time,
|
||||
configurable: true,
|
||||
});
|
||||
Object.defineProperty(performance, 'now', {
|
||||
value: now,
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
jest.resetModules();
|
||||
React = require('react');
|
||||
ReactNoop = require('react-noop-renderer');
|
||||
ReactNoopServer = require('react-noop-renderer/server');
|
||||
Scheduler = require('scheduler');
|
||||
act = require('internal-test-utils').act;
|
||||
assertLog = require('internal-test-utils').assertLog;
|
||||
serverAct = require('internal-test-utils').serverAct;
|
||||
waitFor = require('internal-test-utils').waitFor;
|
||||
});
|
||||
|
||||
function normalizeCodeLocInfo(str) {
|
||||
|
|
@ -85,4 +113,311 @@ describe('ReactOwnerStacks', () => {
|
|||
expect(React.captureOwnerStack()).toBe(null);
|
||||
}
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('cuts off at the owner stack limit', async () => {
|
||||
function App({siblingsBeforeStackOne}) {
|
||||
const children = [];
|
||||
for (
|
||||
let i = 0;
|
||||
i <
|
||||
siblingsBeforeStackOne -
|
||||
// <App /> callsite
|
||||
1 -
|
||||
// Stop so that OwnerStackOne will be right before cutoff
|
||||
1;
|
||||
i++
|
||||
) {
|
||||
children.push(<Component key={i} />);
|
||||
}
|
||||
children.push(<OwnerStackOne key="stackOne" />);
|
||||
children.push(<OwnerStackTwo key="stackTwo" />);
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
function Component() {
|
||||
return null;
|
||||
}
|
||||
|
||||
let stackOne;
|
||||
function OwnerStackOne() {
|
||||
stackOne = React.captureOwnerStack();
|
||||
}
|
||||
|
||||
let stackTwo;
|
||||
function OwnerStackTwo() {
|
||||
stackTwo = React.captureOwnerStack();
|
||||
}
|
||||
|
||||
await act(() => {
|
||||
ReactNoop.render(
|
||||
<App
|
||||
key="one"
|
||||
// Should be the value with of `ownerStackLimit` with `__VARIANT__` so that we see the cutoff
|
||||
siblingsBeforeStackOne={500}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
|
||||
expect({
|
||||
pendingTimers: jest.getTimerCount(),
|
||||
stackOne: normalizeCodeLocInfo(stackOne),
|
||||
stackTwo: normalizeCodeLocInfo(stackTwo),
|
||||
}).toEqual({
|
||||
pendingTimers: 0,
|
||||
stackOne: '\n in App (at **)',
|
||||
stackTwo: __VARIANT__
|
||||
? // captured right after cutoff
|
||||
'\n in UnknownOwner (at **)'
|
||||
: // We never hit the limit outside __VARIANT__
|
||||
'\n in App (at **)',
|
||||
});
|
||||
|
||||
await act(() => {
|
||||
ReactNoop.render(
|
||||
<App
|
||||
// TODO: Owner Stacks should update on re-render.
|
||||
key="two"
|
||||
siblingsBeforeStackOne={0}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
|
||||
expect({
|
||||
pendingTimers: jest.getTimerCount(),
|
||||
stackOne: normalizeCodeLocInfo(stackOne),
|
||||
stackTwo: normalizeCodeLocInfo(stackTwo),
|
||||
}).toEqual({
|
||||
pendingTimers: 0,
|
||||
stackOne: __VARIANT__
|
||||
? // We re-rendered immediately so not enough time has ellapsed to reset the limit.
|
||||
'\n in UnknownOwner (at **)'
|
||||
: // We never hit the limit outside __VARIANT__
|
||||
'\n in App (at **)',
|
||||
stackTwo: __VARIANT__
|
||||
? // We re-rendered immediately so not enough time has ellapsed to reset the limit.
|
||||
'\n in UnknownOwner (at **)'
|
||||
: // We never hit the limit outside __VARIANT__
|
||||
'\n in App (at **)',
|
||||
});
|
||||
|
||||
// advance time so that we reset the limit
|
||||
advanceTimersByTime(1001);
|
||||
|
||||
await act(() => {
|
||||
ReactNoop.render(
|
||||
<App
|
||||
// TODO: Owner Stacks should update on re-render.
|
||||
key="three"
|
||||
// We reset after <App /> so we need to render one more
|
||||
// to have similar cutoff as the initial render (key="one")
|
||||
siblingsBeforeStackOne={501}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
|
||||
expect({
|
||||
pendingTimers: jest.getTimerCount(),
|
||||
stackOne: normalizeCodeLocInfo(stackOne),
|
||||
stackTwo: normalizeCodeLocInfo(stackTwo),
|
||||
}).toEqual({
|
||||
pendingTimers: 0,
|
||||
stackOne: '\n in App (at **)',
|
||||
stackTwo: __VARIANT__
|
||||
? // captured right after cutoff
|
||||
'\n in UnknownOwner (at **)'
|
||||
: // We never hit the limit outside __VARIANT__
|
||||
'\n in App (at **)',
|
||||
});
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('Fiber: resets the owner stack limit periodically', async () => {
|
||||
function App({siblingsBeforeStackOne, timeout}) {
|
||||
const children = [];
|
||||
for (
|
||||
let i = 0;
|
||||
i <
|
||||
siblingsBeforeStackOne -
|
||||
// <App /> callsite
|
||||
1 -
|
||||
// Stop so that OwnerStackOne will be right before cutoff
|
||||
1;
|
||||
i++
|
||||
) {
|
||||
children.push(<Component key={i} />);
|
||||
}
|
||||
children.push(<OwnerStackOne key="stackOne" />);
|
||||
children.push(<OwnerStackDelayed key="stackTwo" timeout={timeout} />);
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
function Component() {
|
||||
return null;
|
||||
}
|
||||
|
||||
let stackOne;
|
||||
function OwnerStackOne() {
|
||||
Scheduler.log('render OwnerStackOne');
|
||||
stackOne = React.captureOwnerStack();
|
||||
}
|
||||
|
||||
let stackTwo;
|
||||
function OwnerStackTwo() {
|
||||
Scheduler.log('render OwnerStackTwo');
|
||||
stackTwo = React.captureOwnerStack();
|
||||
}
|
||||
function OwnerStackDelayed({timeout}) {
|
||||
Scheduler.log('render OwnerStackDelayed');
|
||||
React.use(timeout);
|
||||
return <OwnerStackTwo />;
|
||||
}
|
||||
|
||||
React.startTransition(() => {
|
||||
ReactNoop.render(
|
||||
<App
|
||||
key="one"
|
||||
// Should be the value with of `ownerStackLimit` with `__VARIANT__` so that we see the cutoff
|
||||
siblingsBeforeStackOne={500}
|
||||
timeout={
|
||||
new Promise(resolve =>
|
||||
setTimeout(
|
||||
resolve,
|
||||
// Must be greater or equal then the reset interval
|
||||
1000,
|
||||
),
|
||||
)
|
||||
}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
|
||||
await waitFor(['render OwnerStackOne', 'render OwnerStackDelayed']);
|
||||
|
||||
expect({
|
||||
pendingTimers: jest.getTimerCount(),
|
||||
stackOne: normalizeCodeLocInfo(stackOne),
|
||||
stackTwo: normalizeCodeLocInfo(stackTwo),
|
||||
}).toEqual({
|
||||
// 1 for the timeout
|
||||
pendingTimers: 1,
|
||||
stackOne: '\n in App (at **)',
|
||||
stackTwo: undefined,
|
||||
});
|
||||
|
||||
// resolve `timeout` Promise
|
||||
advanceTimersByTime(1000);
|
||||
|
||||
await waitFor(['render OwnerStackDelayed', 'render OwnerStackTwo']);
|
||||
|
||||
expect({
|
||||
pendingTimers: jest.getTimerCount(),
|
||||
stackOne: normalizeCodeLocInfo(stackOne),
|
||||
stackTwo: normalizeCodeLocInfo(stackTwo),
|
||||
}).toEqual({
|
||||
pendingTimers: 0,
|
||||
stackOne: '\n in App (at **)',
|
||||
stackTwo: __VARIANT__
|
||||
? // We don't reset in Fiber until we start a new render.
|
||||
// Here we just continued after a ping.
|
||||
'\n in UnknownOwner (at **)' + '\n in UnknownOwner (at **)'
|
||||
: // We never hit the limit outside __VARIANT__
|
||||
'\n in OwnerStackDelayed (at **)' + '\n in App (at **)',
|
||||
});
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('Fizz: resets the owner stack limit periodically', async () => {
|
||||
function App({siblingsBeforeStackOne, timeout}) {
|
||||
const children = [];
|
||||
for (
|
||||
let i = 0;
|
||||
i <
|
||||
siblingsBeforeStackOne -
|
||||
// <App /> callsite
|
||||
1 -
|
||||
// Stop so that OwnerStackOne will be right before cutoff
|
||||
1;
|
||||
i++
|
||||
) {
|
||||
children.push(<Component key={i} />);
|
||||
}
|
||||
children.push(<OwnerStackOne key="stackOne" />);
|
||||
children.push(<OwnerStackDelayed key="stackTwo" timeout={timeout} />);
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
function Component() {
|
||||
return null;
|
||||
}
|
||||
|
||||
let stackOne;
|
||||
function OwnerStackOne() {
|
||||
Scheduler.log('render OwnerStackOne');
|
||||
stackOne = React.captureOwnerStack();
|
||||
}
|
||||
|
||||
let stackTwo;
|
||||
function OwnerStackTwo() {
|
||||
Scheduler.log('render OwnerStackTwo');
|
||||
stackTwo = React.captureOwnerStack();
|
||||
}
|
||||
function OwnerStackDelayed({timeout}) {
|
||||
Scheduler.log('render OwnerStackDelayed');
|
||||
React.use(timeout);
|
||||
return <OwnerStackTwo />;
|
||||
}
|
||||
|
||||
ReactNoopServer.render(
|
||||
<App
|
||||
key="one"
|
||||
// Should be the value with of `ownerStackLimit` with `__VARIANT__` so that we see the cutoff
|
||||
siblingsBeforeStackOne={500}
|
||||
timeout={
|
||||
new Promise(resolve =>
|
||||
setTimeout(
|
||||
resolve,
|
||||
// Must be greater or equal then the reset interval
|
||||
1000,
|
||||
),
|
||||
)
|
||||
}
|
||||
/>,
|
||||
);
|
||||
|
||||
assertLog(['render OwnerStackOne', 'render OwnerStackDelayed']);
|
||||
|
||||
expect({
|
||||
pendingTimers: jest.getTimerCount(),
|
||||
stackOne: normalizeCodeLocInfo(stackOne),
|
||||
stackTwo: normalizeCodeLocInfo(stackTwo),
|
||||
}).toEqual({
|
||||
// 1 for the timeout
|
||||
pendingTimers: 1,
|
||||
stackOne: '\n in App (at **)',
|
||||
stackTwo: undefined,
|
||||
});
|
||||
|
||||
await serverAct(() => {
|
||||
advanceTimersByTime(1000);
|
||||
});
|
||||
|
||||
expect({
|
||||
pendingTimers: jest.getTimerCount(),
|
||||
stackOne: normalizeCodeLocInfo(stackOne),
|
||||
stackTwo: normalizeCodeLocInfo(stackTwo),
|
||||
}).toEqual({
|
||||
pendingTimers: 0,
|
||||
stackOne: '\n in App (at **)',
|
||||
stackTwo: __VARIANT__
|
||||
? // We don't reset in Fiber until we start a new render.
|
||||
// Here we just continued after a ping.
|
||||
'\n in UnknownOwner (at **)' + '\n in UnknownOwner (at **)'
|
||||
: // We never hit the limit outside __VARIANT__
|
||||
'\n in OwnerStackDelayed (at **)' + '\n in App (at **)',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1050,15 +1050,15 @@ describe('ReactFlightDOMEdge', () => {
|
|||
owner: null,
|
||||
});
|
||||
expect(lazyWrapper._debugInfo).toEqual([
|
||||
{time: 11},
|
||||
greetInfo,
|
||||
{time: 12},
|
||||
greetInfo,
|
||||
{time: 13},
|
||||
expect.objectContaining({
|
||||
name: 'Container',
|
||||
env: 'Server',
|
||||
owner: greetInfo,
|
||||
}),
|
||||
{time: 13},
|
||||
{time: 14},
|
||||
]);
|
||||
// The owner that created the span was the outer server component.
|
||||
// We expect the debug info to be referentially equal to the owner.
|
||||
|
|
|
|||
10
packages/react-server/src/ReactFizzServer.js
vendored
10
packages/react-server/src/ReactFizzServer.js
vendored
|
|
@ -133,6 +133,7 @@ import {
|
|||
callRenderInDEV,
|
||||
} from './ReactFizzCallUserSpace';
|
||||
|
||||
import {resetOwnerStackLimit} from 'shared/ReactOwnerStackReset';
|
||||
import {
|
||||
getIteratorFn,
|
||||
ASYNC_ITERATOR,
|
||||
|
|
@ -473,6 +474,10 @@ export function createRequest(
|
|||
onPostpone: void | ((reason: string, postponeInfo: PostponeInfo) => void),
|
||||
formState: void | null | ReactFormState<any, any>,
|
||||
): Request {
|
||||
if (__DEV__) {
|
||||
resetOwnerStackLimit();
|
||||
}
|
||||
|
||||
// $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors
|
||||
const request: Request = new RequestInstance(
|
||||
resumableState,
|
||||
|
|
@ -571,6 +576,10 @@ export function resumeRequest(
|
|||
onFatalError: void | ((error: mixed) => void),
|
||||
onPostpone: void | ((reason: string, postponeInfo: PostponeInfo) => void),
|
||||
): Request {
|
||||
if (__DEV__) {
|
||||
resetOwnerStackLimit();
|
||||
}
|
||||
|
||||
// $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors
|
||||
const request: Request = new RequestInstance(
|
||||
postponedState.resumableState,
|
||||
|
|
@ -4616,6 +4625,7 @@ export function performWork(request: Request): void {
|
|||
fatalError(request, error, errorInfo, null);
|
||||
} finally {
|
||||
setCurrentResumableState(prevResumableState);
|
||||
|
||||
ReactSharedInternals.H = prevDispatcher;
|
||||
ReactSharedInternals.A = prevAsyncDispatcher;
|
||||
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ import {DefaultAsyncDispatcher} from './flight/ReactFlightAsyncDispatcher';
|
|||
import {resolveOwner, setCurrentOwner} from './flight/ReactFlightCurrentOwner';
|
||||
|
||||
import {getOwnerStackByComponentInfoInDev} from 'shared/ReactComponentInfoStack';
|
||||
import {resetOwnerStackLimit} from 'shared/ReactOwnerStackReset';
|
||||
|
||||
import {
|
||||
callComponentInDEV,
|
||||
|
|
@ -552,6 +553,10 @@ export function createRequest(
|
|||
environmentName: void | string | (() => string), // DEV-only
|
||||
filterStackFrame: void | ((url: string, functionName: string) => boolean), // DEV-only
|
||||
): Request {
|
||||
if (__DEV__) {
|
||||
resetOwnerStackLimit();
|
||||
}
|
||||
|
||||
// $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors
|
||||
return new RequestInstance(
|
||||
RENDER,
|
||||
|
|
@ -580,6 +585,10 @@ export function createPrerenderRequest(
|
|||
environmentName: void | string | (() => string), // DEV-only
|
||||
filterStackFrame: void | ((url: string, functionName: string) => boolean), // DEV-only
|
||||
): Request {
|
||||
if (__DEV__) {
|
||||
resetOwnerStackLimit();
|
||||
}
|
||||
|
||||
// $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors
|
||||
return new RequestInstance(
|
||||
PRERENDER,
|
||||
|
|
|
|||
178
packages/react-server/src/__tests__/ReactFlightServer-test.js
vendored
Normal file
178
packages/react-server/src/__tests__/ReactFlightServer-test.js
vendored
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @emails react-core
|
||||
* @jest-environment node
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
if (typeof Blob === 'undefined') {
|
||||
global.Blob = require('buffer').Blob;
|
||||
}
|
||||
if (typeof File === 'undefined' || typeof FormData === 'undefined') {
|
||||
global.File = require('undici').File;
|
||||
global.FormData = require('undici').FormData;
|
||||
}
|
||||
|
||||
function normalizeCodeLocInfo(str) {
|
||||
return (
|
||||
str &&
|
||||
str.replace(/^ +(?:at|in) ([\S]+)[^\n]*/gm, function (m, name) {
|
||||
const dot = name.lastIndexOf('.');
|
||||
if (dot !== -1) {
|
||||
name = name.slice(dot + 1);
|
||||
}
|
||||
return ' in ' + name + (/\d/.test(m) ? ' (at **)' : '');
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
let ReactServer;
|
||||
let ReactNoopFlightServer;
|
||||
let Scheduler;
|
||||
let advanceTimersByTime;
|
||||
let assertLog;
|
||||
|
||||
describe('ReactFlight', () => {
|
||||
beforeEach(() => {
|
||||
// Mock performance.now for timing tests
|
||||
let time = 0;
|
||||
advanceTimersByTime = timeMS => {
|
||||
time += timeMS;
|
||||
jest.advanceTimersByTime(timeMS);
|
||||
};
|
||||
const now = jest.fn().mockImplementation(() => {
|
||||
return time++;
|
||||
});
|
||||
Object.defineProperty(performance, 'timeOrigin', {
|
||||
value: time,
|
||||
configurable: true,
|
||||
});
|
||||
Object.defineProperty(performance, 'now', {
|
||||
value: now,
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => require('react/react.react-server'));
|
||||
ReactServer = require('react');
|
||||
ReactNoopFlightServer = require('react-noop-renderer/flight-server');
|
||||
Scheduler = require('scheduler');
|
||||
const InternalTestUtils = require('internal-test-utils');
|
||||
assertLog = InternalTestUtils.assertLog;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('resets the owner stack limit periodically', async () => {
|
||||
function App({siblingsBeforeStackOne, timeout}) {
|
||||
const children = [];
|
||||
for (
|
||||
let i = 0;
|
||||
i <
|
||||
siblingsBeforeStackOne -
|
||||
// <App /> callsite
|
||||
1 -
|
||||
// Stop so that OwnerStackOne will be right before cutoff
|
||||
1;
|
||||
i++
|
||||
) {
|
||||
children.push(ReactServer.createElement(Component, {key: i}));
|
||||
}
|
||||
children.push(
|
||||
ReactServer.createElement(OwnerStackOne, {key: 'stackOne'}),
|
||||
);
|
||||
children.push(
|
||||
ReactServer.createElement(OwnerStackDelayed, {
|
||||
key: 'stackTwo',
|
||||
timeout,
|
||||
}),
|
||||
);
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
function Component() {
|
||||
return null;
|
||||
}
|
||||
|
||||
let stackOne;
|
||||
function OwnerStackOne() {
|
||||
Scheduler.log('render OwnerStackOne');
|
||||
stackOne = ReactServer.captureOwnerStack();
|
||||
}
|
||||
|
||||
let stackTwo;
|
||||
function OwnerStackTwo() {
|
||||
Scheduler.log('render OwnerStackTwo');
|
||||
stackTwo = ReactServer.captureOwnerStack();
|
||||
}
|
||||
function OwnerStackDelayed({timeout}) {
|
||||
Scheduler.log('render OwnerStackDelayed');
|
||||
|
||||
// Owner Stacks start fresh after `await`.
|
||||
// We need to sync delay to observe the reset limit behavior.
|
||||
// TODO: Is that the right behavior? If you do stack + Ownst Stack you'd get `OwnerStackTwo` twice.
|
||||
jest.advanceTimersByTime(timeout);
|
||||
|
||||
return ReactServer.createElement(OwnerStackTwo, {});
|
||||
}
|
||||
|
||||
ReactNoopFlightServer.render(
|
||||
ReactServer.createElement(App, {
|
||||
key: 'one',
|
||||
// Should be the value with of `ownerStackLimit` with `__VARIANT__` so that we see the cutoff
|
||||
siblingsBeforeStackOne: 500,
|
||||
// Must be greater or equal then the reset interval
|
||||
timeout: 1000,
|
||||
}),
|
||||
);
|
||||
|
||||
assertLog([
|
||||
'render OwnerStackOne',
|
||||
'render OwnerStackDelayed',
|
||||
'render OwnerStackTwo',
|
||||
]);
|
||||
|
||||
expect({
|
||||
pendingTimers: jest.getTimerCount(),
|
||||
stackOne: normalizeCodeLocInfo(stackOne),
|
||||
stackTwo: normalizeCodeLocInfo(stackTwo),
|
||||
}).toEqual({
|
||||
pendingTimers: 0,
|
||||
stackOne: '\n in App (at **)',
|
||||
stackTwo: __VARIANT__
|
||||
? // Didn't advance timers yet to reset
|
||||
'\n in UnknownOwner (at **)' + '\n in UnknownOwner (at **)'
|
||||
: // We never hit the limit outside __VARIANT__
|
||||
'\n in OwnerStackDelayed (at **)' + '\n in App (at **)',
|
||||
});
|
||||
|
||||
// Ensure we reset the limit after the timeout
|
||||
advanceTimersByTime(1000);
|
||||
ReactNoopFlightServer.render(
|
||||
ReactServer.createElement(App, {
|
||||
key: 'two',
|
||||
siblingsBeforeStackOne: 0,
|
||||
timeout: 0,
|
||||
}),
|
||||
);
|
||||
|
||||
expect({
|
||||
pendingTimers: jest.getTimerCount(),
|
||||
stackOne: normalizeCodeLocInfo(stackOne),
|
||||
stackTwo: normalizeCodeLocInfo(stackTwo),
|
||||
}).toEqual({
|
||||
pendingTimers: 0,
|
||||
stackOne: '\n in App (at **)',
|
||||
stackTwo: '\n in OwnerStackDelayed (at **)' + '\n in App (at **)',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -38,6 +38,9 @@ export type SharedStateClient = {
|
|||
|
||||
// ReactDebugCurrentFrame
|
||||
getCurrentStack: null | (() => string),
|
||||
|
||||
// ReactOwnerStackReset
|
||||
recentlyCreatedOwnerStacks: 0,
|
||||
};
|
||||
|
||||
export type RendererTask = boolean => RendererTask | null;
|
||||
|
|
@ -58,6 +61,7 @@ if (__DEV__) {
|
|||
ReactSharedInternals.thrownErrors = [];
|
||||
// Stack implementation injected by the current renderer.
|
||||
ReactSharedInternals.getCurrentStack = (null: null | (() => string));
|
||||
ReactSharedInternals.recentlyCreatedOwnerStacks = 0;
|
||||
}
|
||||
|
||||
export default ReactSharedInternals;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,9 @@ export type SharedStateServer = {
|
|||
|
||||
// ReactDebugCurrentFrame
|
||||
getCurrentStack: null | (() => string),
|
||||
|
||||
// ReactOwnerStackReset
|
||||
recentlyCreatedOwnerStacks: 0,
|
||||
};
|
||||
|
||||
export type RendererTask = boolean => RendererTask | null;
|
||||
|
|
@ -59,6 +62,7 @@ if (enableTaint) {
|
|||
if (__DEV__) {
|
||||
// Stack implementation injected by the current renderer.
|
||||
ReactSharedInternals.getCurrentStack = (null: null | (() => string));
|
||||
ReactSharedInternals.recentlyCreatedOwnerStacks = 0;
|
||||
}
|
||||
|
||||
export default ReactSharedInternals;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,10 @@ import {
|
|||
} from 'shared/ReactSymbols';
|
||||
import {checkKeyStringCoercion} from 'shared/CheckStringCoercion';
|
||||
import isArray from 'shared/isArray';
|
||||
import {disableDefaultPropsExceptForClasses} from 'shared/ReactFeatureFlags';
|
||||
import {
|
||||
disableDefaultPropsExceptForClasses,
|
||||
ownerStackLimit,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
|
||||
const createTask =
|
||||
// eslint-disable-next-line react-internal/no-production-logging
|
||||
|
|
@ -57,12 +60,32 @@ function getOwner() {
|
|||
return null;
|
||||
}
|
||||
|
||||
/** @noinline */
|
||||
function UnknownOwner() {
|
||||
/** @noinline */
|
||||
return (() => Error('react-stack-top-frame'))();
|
||||
}
|
||||
const createFakeCallStack = {
|
||||
'react-stack-bottom-frame': function (callStackForError) {
|
||||
return callStackForError();
|
||||
},
|
||||
};
|
||||
|
||||
let specialPropKeyWarningShown;
|
||||
let didWarnAboutElementRef;
|
||||
let didWarnAboutOldJSXRuntime;
|
||||
let unknownOwnerDebugStack;
|
||||
let unknownOwnerDebugTask;
|
||||
|
||||
if (__DEV__) {
|
||||
didWarnAboutElementRef = {};
|
||||
|
||||
// We use this technique to trick minifiers to preserve the function name.
|
||||
unknownOwnerDebugStack = createFakeCallStack['react-stack-bottom-frame'].bind(
|
||||
createFakeCallStack,
|
||||
UnknownOwner,
|
||||
)();
|
||||
unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
|
||||
}
|
||||
|
||||
function hasValidRef(config) {
|
||||
|
|
@ -373,6 +396,9 @@ export function jsxProdSignatureRunningInDevWithDynamicChildren(
|
|||
) {
|
||||
if (__DEV__) {
|
||||
const isStaticChildren = false;
|
||||
const trackActualOwner =
|
||||
__DEV__ &&
|
||||
ReactSharedInternals.recentlyCreatedOwnerStacks++ < ownerStackLimit;
|
||||
return jsxDEVImpl(
|
||||
type,
|
||||
config,
|
||||
|
|
@ -380,8 +406,14 @@ export function jsxProdSignatureRunningInDevWithDynamicChildren(
|
|||
isStaticChildren,
|
||||
source,
|
||||
self,
|
||||
__DEV__ && Error('react-stack-top-frame'),
|
||||
__DEV__ && createTask(getTaskName(type)),
|
||||
__DEV__ &&
|
||||
(trackActualOwner
|
||||
? Error('react-stack-top-frame')
|
||||
: unknownOwnerDebugStack),
|
||||
__DEV__ &&
|
||||
(trackActualOwner
|
||||
? createTask(getTaskName(type))
|
||||
: unknownOwnerDebugTask),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -395,6 +427,9 @@ export function jsxProdSignatureRunningInDevWithStaticChildren(
|
|||
) {
|
||||
if (__DEV__) {
|
||||
const isStaticChildren = true;
|
||||
const trackActualOwner =
|
||||
__DEV__ &&
|
||||
ReactSharedInternals.recentlyCreatedOwnerStacks++ < ownerStackLimit;
|
||||
return jsxDEVImpl(
|
||||
type,
|
||||
config,
|
||||
|
|
@ -402,8 +437,14 @@ export function jsxProdSignatureRunningInDevWithStaticChildren(
|
|||
isStaticChildren,
|
||||
source,
|
||||
self,
|
||||
__DEV__ && Error('react-stack-top-frame'),
|
||||
__DEV__ && createTask(getTaskName(type)),
|
||||
__DEV__ &&
|
||||
(trackActualOwner
|
||||
? Error('react-stack-top-frame')
|
||||
: unknownOwnerDebugStack),
|
||||
__DEV__ &&
|
||||
(trackActualOwner
|
||||
? createTask(getTaskName(type))
|
||||
: unknownOwnerDebugTask),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -417,6 +458,9 @@ const didWarnAboutKeySpread = {};
|
|||
* @param {string} key
|
||||
*/
|
||||
export function jsxDEV(type, config, maybeKey, isStaticChildren, source, self) {
|
||||
const trackActualOwner =
|
||||
__DEV__ &&
|
||||
ReactSharedInternals.recentlyCreatedOwnerStacks++ < ownerStackLimit;
|
||||
return jsxDEVImpl(
|
||||
type,
|
||||
config,
|
||||
|
|
@ -424,8 +468,14 @@ export function jsxDEV(type, config, maybeKey, isStaticChildren, source, self) {
|
|||
isStaticChildren,
|
||||
source,
|
||||
self,
|
||||
__DEV__ && Error('react-stack-top-frame'),
|
||||
__DEV__ && createTask(getTaskName(type)),
|
||||
__DEV__ &&
|
||||
(trackActualOwner
|
||||
? Error('react-stack-top-frame')
|
||||
: unknownOwnerDebugStack),
|
||||
__DEV__ &&
|
||||
(trackActualOwner
|
||||
? createTask(getTaskName(type))
|
||||
: unknownOwnerDebugTask),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -692,7 +742,9 @@ export function createElement(type, config, children) {
|
|||
defineKeyPropWarningGetter(props, displayName);
|
||||
}
|
||||
}
|
||||
|
||||
const trackActualOwner =
|
||||
__DEV__ &&
|
||||
ReactSharedInternals.recentlyCreatedOwnerStacks++ < ownerStackLimit;
|
||||
return ReactElement(
|
||||
type,
|
||||
key,
|
||||
|
|
@ -700,8 +752,14 @@ export function createElement(type, config, children) {
|
|||
undefined,
|
||||
getOwner(),
|
||||
props,
|
||||
__DEV__ && Error('react-stack-top-frame'),
|
||||
__DEV__ && createTask(getTaskName(type)),
|
||||
__DEV__ &&
|
||||
(trackActualOwner
|
||||
? Error('react-stack-top-frame')
|
||||
: unknownOwnerDebugStack),
|
||||
__DEV__ &&
|
||||
(trackActualOwner
|
||||
? createTask(getTaskName(type))
|
||||
: unknownOwnerDebugTask),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -268,3 +268,5 @@ export const enableUpdaterTracking = __PROFILE__;
|
|||
|
||||
// Internal only.
|
||||
export const enableDO_NOT_USE_disableStrictPassiveEffect = false;
|
||||
|
||||
export const ownerStackLimit = 1e4;
|
||||
|
|
|
|||
42
packages/shared/ReactOwnerStackReset.js
Normal file
42
packages/shared/ReactOwnerStackReset.js
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import ReactSharedInternals from 'shared/ReactSharedInternals';
|
||||
|
||||
let lastResetTime = 0;
|
||||
|
||||
let getCurrentTime: () => number | DOMHighResTimeStamp;
|
||||
const hasPerformanceNow =
|
||||
// $FlowFixMe[method-unbinding]
|
||||
typeof performance === 'object' && typeof performance.now === 'function';
|
||||
|
||||
if (hasPerformanceNow) {
|
||||
const localPerformance = performance;
|
||||
getCurrentTime = () => localPerformance.now();
|
||||
} else {
|
||||
const localDate = Date;
|
||||
getCurrentTime = () => localDate.now();
|
||||
}
|
||||
|
||||
export function resetOwnerStackLimit() {
|
||||
if (__DEV__) {
|
||||
const now = getCurrentTime();
|
||||
const timeSinceLastReset = now - lastResetTime;
|
||||
if (timeSinceLastReset > 1000) {
|
||||
ReactSharedInternals.recentlyCreatedOwnerStacks = 0;
|
||||
lastResetTime = now;
|
||||
}
|
||||
} else {
|
||||
// These errors should never make it into a build so we don't need to encode them in codes.json
|
||||
// eslint-disable-next-line react-internal/prod-error-codes
|
||||
throw new Error(
|
||||
'resetOwnerStackLimit should never be called in production mode. This is a bug in React.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -29,3 +29,7 @@ export const enableUseEffectCRUDOverload = __VARIANT__;
|
|||
export const enableFastAddPropertiesInDiffing = __VARIANT__;
|
||||
export const enableLazyPublicInstanceInFabric = __VARIANT__;
|
||||
export const renameElementSymbol = __VARIANT__;
|
||||
export const ownerStackLimit: number = __VARIANT__
|
||||
? // Some value that doesn't impact existing tests
|
||||
500
|
||||
: 1e4;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ export const {
|
|||
enableFastAddPropertiesInDiffing,
|
||||
enableLazyPublicInstanceInFabric,
|
||||
renameElementSymbol,
|
||||
ownerStackLimit,
|
||||
} = dynamicFlags;
|
||||
|
||||
// The rest of the flags are static for better dead code elimination.
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ export const enableSwipeTransition = false;
|
|||
export const enableFastAddPropertiesInDiffing = false;
|
||||
export const enableLazyPublicInstanceInFabric = false;
|
||||
export const enableScrollEndPolyfill = true;
|
||||
export const ownerStackLimit = 1e4;
|
||||
|
||||
export const enableFragmentRefs = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ export const enableSwipeTransition = false;
|
|||
export const enableFastAddPropertiesInDiffing = true;
|
||||
export const enableLazyPublicInstanceInFabric = false;
|
||||
export const enableScrollEndPolyfill = true;
|
||||
export const ownerStackLimit = 1e4;
|
||||
|
||||
export const enableFragmentRefs = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ export const enableFastAddPropertiesInDiffing = false;
|
|||
export const enableLazyPublicInstanceInFabric = false;
|
||||
export const enableScrollEndPolyfill = true;
|
||||
export const enableFragmentRefs = false;
|
||||
export const ownerStackLimit = 1e4;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
((((null: any): ExportsType): FeatureFlagsType): ExportsType);
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ export const enableLazyPublicInstanceInFabric = false;
|
|||
export const enableScrollEndPolyfill = true;
|
||||
|
||||
export const enableFragmentRefs = false;
|
||||
export const ownerStackLimit = 1e4;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
((((null: any): ExportsType): FeatureFlagsType): ExportsType);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,11 @@ export const enableComponentPerformanceTrack = __VARIANT__;
|
|||
export const enableScrollEndPolyfill = __VARIANT__;
|
||||
export const enableFragmentRefs = __VARIANT__;
|
||||
|
||||
export const ownerStackLimit: number = __VARIANT__
|
||||
? // Some value that doesn't impact existing tests
|
||||
500
|
||||
: 1e4;
|
||||
|
||||
// TODO: These flags are hard-coded to the default values used in open source.
|
||||
// Update the tests so that they pass in either mode, then set these
|
||||
// to __VARIANT__.
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ export const {
|
|||
enableComponentPerformanceTrack,
|
||||
enableScrollEndPolyfill,
|
||||
enableFragmentRefs,
|
||||
ownerStackLimit,
|
||||
} = dynamicFeatureFlags;
|
||||
|
||||
// On WWW, __EXPERIMENTAL__ is used for a new modern build.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user