* [Fizz] Add Flow/Jest/Rollup build infra
Add a new package for react-stream which allows for custom server renderer
outputs. I picked the name because it's a reasonable name but also
because the npm name is currently owned by a friend of the project.
The react-dom build has its own inlined server renderer under the
name `react-dom/fizz`.
There is also a noop renderer to be used for testing. At some point
we might add a public one to test-renderer but for now I don't want to have
to think about public API design for the tests.
* Add FormatConfig too
We need to separate the format (DOM, React Native, etc) from the host
running the server (Node, Browser, etc).
* Basic wiring between Node, Noop and DOM configs
The Node DOM API is pipeToNodeStream which accepts a writable stream.
* Merge host and format config in dynamic react-stream entry point
Simpler API this way but also avoids having to fork the wrapper config.
Fixes noop builds.
* Add setImmediate/Buffer globals to lint config
Used by the server renderer
* Properly include fizz.node.js
Also use forwarding to it from fizz.js in builds so that tests covers
this.
* Make react-stream private since we're not ready to publish
or even name it yet
* Rename Renderer -> Streamer
* Prefix react-dom/fizz with react-dom/unstable-fizz
* Add Fizz Browser host config
This lets Fizz render to WHATWG streams. E.g. for rendering in a
Service Worker.
I added react-dom/unstable-fizz.browser as the entry point for this.
Since we now have two configurations of DOM. I had to add another
inlinedHostConfigs configuration called `dom-browser`. The reconciler
treats this configuration the same as `dom`. For stream it checks
against the ReactFizzHostConfigBrowser instead of the Node one.
* Add Fizz Browser Fixture
This is for testing server rendering - on the client.
* Lower version number to detach it from react-reconciler version
* Fixes#14360 and adds a test for mixed priority dispatches.
It was broken because `cloneHook` assigned `memoizedState` instead of
`baseState` from the original hook to `baseState` of the clone.
* tweak comments
* Add a test for current defaultProps behavior in lazy
* Add a warning against definining defaultProps on the outer wrapper
* Warn about setting propTypes too
* Remove redundant async
* Validate propTypes for resolved lazy types
Note this only works for elements created after resolving. So it's not ideal. But it provides the best stack trace for those cases.
* Add a test for lazy(forwardRef()) propTypes check
* Validate memo() inner propTypes and warn about shadowing
* Add test verifying nested lazy is unsupported
* Change error wording to remove "Promise elements"
* Improve error message for nested lazy() and add tests
* Validate propTypes for memo in the reconciler when necessary
* Add comments for why we're calling checkPropTypes
* Fix Flow and lint
* Undo unintentional formatting changes
* Remove unnecessary case (it is handled by function code path)
* Add test coverage for memo(fn.defaultProps).propTypes
* Test should be agnostic of where resolving happens
That's an implementation detail and we might want to change it later. Let's keep it easy by making tests just check that validation happened, not at which stage.
* Unify traversal logic in createElement
This moves all type traversal into createElement. When lazy resolves, we call createElement once to re-check.
* Match prod behavior for propTypes/defaultProps shims closer
* Revert "Unify traversal logic in createElement"
This reverts commit 2e77ca47fe80ebe6595333542a8c5c138c68643f.
See https://github.com/facebook/react/pull/14298#issuecomment-442687775
* Undo unnecessary change to getComponentName
useMutationEffect has problems (namely, refs aren't attached at the time that it runs) and we're not positive it's necessary. useLayoutEffect runs at the same time as componentDidMount/Update so it's sufficient for all existing use cases; it can be used in any case that useEffect happens too late. Until we figure out what we want to do, let's delete it.
Regression introduced in #14182 resulted in errors no longer being emitted on streams, breaking many consumers.
Co-authored-by: Elliot Jalgard <elliot.j@live.se>
* Add failing test for defaultProps between lazy() and memo()
* Add another regression test for defaultProps resolution order
* Resolve outer props for MemoComponent
Whenever we do this, Rollup needs to materialize this as an object.
This causes it to also add the Babel compatibility property which is
unnecessary bloat. However, since when we use these, we leak the object
this often also deopts any compiler optimizations.
If we really need an object we should export default an object.
Currently there is an exception for DOMTopLevelEventTypes since
listing out the imports is a PITA and it doesn't escape so it should
get properly inlined. We should probably move to a different pattern
to avoid this for consistency though.
In the process of switching to MessageChannel, it seems the postMessage call was modified to pass `"*"` (originally the target origin value from `window.postMessage`). This actually ends up triggering serialization, whereas passing `undefined` bypasses.
To save some investigation, passing a Number like `0` still incurs serialization overhead - `undefined` has special behavior.
Disables the recently introduced (#14181) warning for shorthand
CSS property collisions by wrapping in a feature flag. Let's hold off
shipping this until at least the next minor.
* Add a checkbox to fixtures UI to choose React production build
* Assign header__label class name to label directly, instead of using a separate span
* center the production checkbox vertically
Scheduler needs to schedule a task that fires after paint. To do this,
it currently posts a message event to `window`. This happens on every
frame until the queue is empty. An unfortunate consequence is that every
other message event handler also gets called on every frame; even if
they exit immediately, this adds up to significant per-frame overhead.
Instead, we'll create a MessageChannel and post to that, with a
fallback to the old behavior if MessageChannel does not exist.
I figured out a simpler way to do #14181. It does allocate some but I think that's OK. Time complexity might even be better since we avoid the nested loops the old one had.
* BUG: ReactPartialRenderer / New Context polutes mutable global state
The new context API stores the provided values on the shared context instance. When used in a synchronous context, this is not an issue. However when used in an concurrent context this can cause a "push provider" from one react render to have an effect on an unrelated concurrent react render.
I've encountered this bug in production when using renderToNodeStream, which asks ReactPartialRenderer for bytes up to a high water mark before yielding. If two Node Streams are created and read from in parallel, the state of one can polute the other.
I wrote a failing test to illustrate the conditions under which this happens.
I'm also concerned that the experimental concurrent/async React rendering on the client could suffer from the same issue.
* Use unique thread ID for each partial render to access Context
This first adds an allocator that keeps track of a unique ThreadID index
for each currently executing partial renderer. IDs are not just growing
but are reused as streams are destroyed.
This ensures that IDs are kept nice and compact.
This lets us use an "array" for each Context object to store the current
values. The look up for these are fast because they're just looking up
an offset in a tightly packed "array".
I don't use an actual Array object to store the values. Instead, I rely
on that VMs (notably V8) treat storage of numeric index property access
as a separate "elements" allocation.
This lets us avoid an extra indirection.
However, we must ensure that these arrays are not holey to preserve this
feature.
To do that I store the _threadCount on each context (effectively it takes
the place of the .length property on an array).
This lets us first validate that the context has enough slots before we
access the slot. If not, we fill in the slots with the default value.
This is one of the most insidious quirks of React DOM that people run into. Now we warn when we think an update is dangerous.
We still allow rendering `{background, backgroundSize}` with unchanging values, for example. But once you remove either one or change `background` (without changing `backgroundSize` at the same time), that's bad news. So we warn.
Fixes#6348.