mirror of
https://github.com/vercel/next.js.git
synced 2026-09-20 02:25:18 +08:00
4d2a793c4e
This is a hack that we need until we refactor everything to use the Node builds
of 'react-dom/server' and 'react-server-dom-{webpack,turbopack}' when running in
Node.
We're currently using the Edge builds of 'react-dom/server' and
'react-server-dom-{webpack,turbopack}' everywhere. But if we're in Node, we'd
like it to act more like the Node build, for performance and correctness reasons
(e.g. in DynamicIO). In particular, we want to change the implementation of
`scheduleWork` from
[the Edge one](https://github.com/facebook/react/blob/19bd26beb689e554fceb0b929dc5199be8cba594/packages/react-server/src/ReactServerStreamConfigEdge.js#L31-L33)
to [the Node one](https://github.com/facebook/react/blob/19bd26beb689e554fceb0b929dc5199be8cba594/packages/react-server/src/ReactServerStreamConfigNode.js#L25-L27).
Since `scheduleWork` is inlined, we have to convert `setTimeout` calls like this
```
setTimeout(() => ..., 0)
```
into this:
```
setImmediate(() => ...)
```
ReactDOM only ever calls `setTimeout` with `0` (and no further arguments), so we
can just naively replace `setTimeout` with `setImmediate`. Technically the `0`
will then be passed to the callback as an argument, but the callbacks will
always ignore it anyway.
64 lines
2.2 KiB
TypeScript
64 lines
2.2 KiB
TypeScript
import { nextTestSetup } from 'e2e-utils'
|
|
|
|
const LINK_HEADER_SIZE = 111
|
|
|
|
/**
|
|
* Calculates the minimum header length that will be emitted by the server. This
|
|
* is calculated by taking the maximum header length and dividing it by the
|
|
* average header size including joining `, ` characters.
|
|
*
|
|
* @param maxLength the maximum header length
|
|
* @returns the minimum header length
|
|
*/
|
|
function calculateMinHeaderLength(maxLength) {
|
|
const averageHeaderSize = LINK_HEADER_SIZE + 2
|
|
return Math.floor(maxLength / averageHeaderSize) * averageHeaderSize - 2
|
|
}
|
|
|
|
describe('react-max-headers-length', () => {
|
|
describe.each([0, 400, undefined, 10000])(
|
|
'reactMaxHeadersLength = %s',
|
|
(reactMaxHeadersLength) => {
|
|
const env: Record<string, string> = {}
|
|
if (typeof reactMaxHeadersLength === 'number') {
|
|
env.TEST_REACT_MAX_HEADERS_LENGTH = reactMaxHeadersLength.toString()
|
|
}
|
|
|
|
const { next } = nextTestSetup({ files: __dirname, env })
|
|
|
|
it('should respect reactMaxHeadersLength', async () => {
|
|
const res = await next.fetch('/')
|
|
expect(res.status).toBe(200)
|
|
|
|
// React currently only sets the `Link` header, so we should check to
|
|
// see that the length of the header has respected the configured
|
|
// value.
|
|
const header = res.headers.get('Link')
|
|
if (reactMaxHeadersLength === undefined) {
|
|
// This is the default case.
|
|
expect(header).not.toBeNull()
|
|
expect(header).toBeString()
|
|
|
|
expect(header.length).toBeGreaterThanOrEqual(
|
|
calculateMinHeaderLength(6000)
|
|
)
|
|
expect(header.length).toBeLessThanOrEqual(6000)
|
|
} else if (reactMaxHeadersLength === 0) {
|
|
// This is the case where the header is not emitted.
|
|
expect(header).toBeNull()
|
|
} else if (typeof reactMaxHeadersLength === 'number') {
|
|
// This is the case where the header is emitted and the length is
|
|
// respected.
|
|
expect(header).not.toBeNull()
|
|
expect(header).toBeString()
|
|
|
|
expect(header.length).toBeGreaterThanOrEqual(
|
|
calculateMinHeaderLength(reactMaxHeadersLength)
|
|
)
|
|
expect(header.length).toBeLessThanOrEqual(reactMaxHeadersLength)
|
|
}
|
|
})
|
|
}
|
|
)
|
|
})
|