* float enhance!!!
Support preinit as script
Support resources from async scripts
Support saving the precedence place when rendering the shell
There was a significant change to the flushing order of resources which follows the general principal of...
1. stuff that blocks display
2. stuff that we know will be used
3. stuff that was explicitly preloaded
As a consequence if you preinit a style now it won't automatically flush in the shell unless you actually depend on it in your tree. To avoid races with precedence order we now emit a tag that saves the place amongst the precedence hierarchy so late insertions still end up where they were intended
There is also a novel hydration pathway for certain tags. If you render an async script with an onLoad or onError it will always treat it like an insertion rather than a hydration.
* restore preinit style flushing behavior and nits
Fixes a bug that happens when you suspend in the shell (the part of the
tree that is not wrapped in a Suspense boundary) during a
discrete update.
There were two underyling issues. One was just a mistake:
RootDidNotComplete needs to be handled in both renderRootConcurrent and
renderRootSync, but it was only handled in renderRootConcurrent. I did
it this way because I thought this path was unreachable during a sync
update, but I neglected to consider that renderRootSync is sometimes
called for non-concurrent lanes, like when recovering from an error, or
patching up a mutation to an external store.
After I fixed that oversight, the other issue is that we intentionally
error if the shell suspends during a sync update. The idea was that you
should either wrap the tree in a Suspense boundary, or you should mark
the update as a transition to allow React to suspend.
However, this did not take into account selective hydration, which can
force a sync render before anything has even committed. There's no way
in that case to wrap the update in startTransition.
Our solution for now is to remove the error that happens when you
suspend in the shell during a sync update — even for discrete updates.
We will likely revisit this in the future. One appealing possibility is
to commit the whole root in an inert state, as if it were a hidden
Offscreen tree.
Co-authored-by: Sebastian Markbåge <sebastian@calyptus.eu>
Co-authored-by: Sebastian Markbåge <sebastian@calyptus.eu>
* Missing Hooks
* Remove www forks. These can use __SECRET... instead.
* Move cache to separate dispatcher
These will be available in more contexts than just render.
In #24967, I changed the behavior of Offscreen so that passive effects
are not fired when the tree is hidden. I accidentally applied this
behavior to the old LegacyHidden API, too, which is a deprecated
internal-only type that www has been using while they wait for Offscreen
to be ready.
This fixes LegacyHidden so that the effects do not get deferred, like
before. The new behavior still remains in the Offscreen API, which is
experimental and not currently in use in www.
* track resources in different roots separately
* flow types
* add test demonstrating portals deep into shadowRoots
* revert hostcontext changes
* lints
* funge style cache key a la ReactDOMComponentTree
* hide hacks in componentTree
The existential type `*` was deprecated and a codemod provided to replace it. Ran that and did some manual fixups:
```sh
node_modules/.bin/flow codemod replace-existentials --write .
```
ghstack-source-id: 4c98b8db6a
Pull Request resolved: https://github.com/facebook/react/pull/25416
- method unbinding is no longer supported in Flow for soundness, this added a bunch of suppressions
- Flow now prevents objects to be supertypes of interfaces/classes
ghstack-source-id: d7749cbad8
Pull Request resolved: https://github.com/facebook/react/pull/25412
This upgrade made more expressions invalidate refinements. In some
places this lead to a large number of suppressions that I automatically
suppressed and should be followed up on when the code is touched.
I think most of them might require either manual annotations or moving
a value into a const to allow refinement.
ghstack-source-id: a45b40abf0
Pull Request resolved: https://github.com/facebook/react/pull/25410
This was a large upgrade that removed "classic mode" and made "types first" the only option.
Most of the needed changes have been done in previous PRs, this just fixes up the last few instances.
ghstack-source-id: 9612d95ba4
Pull Request resolved: https://github.com/facebook/react/pull/25408
This contains one code change, renaming the local function `ChildReconciler` to `createChildReconciler` as it's called as a function, not a constructor and to free up the name for the return value.
* [Fizz/Float] Float for stylesheet resources
This commit implements Float in Fizz and on the Client. The initial set of supported APIs is roughly
1. Convert certain stylesheets into style Resources when opting in with precedence prop
2. Emit preloads for stylesheets and explicit preload tags
3. Dedupe all Resources by href
4. Implement ReactDOM.preload() to allow for imperative preloading
5. Implement ReactDOM.preinit() to allow for imperative preinitialization
Currently supports
1. style Resources (link rel "stylesheet")
2. font Resources (preload as "font")
later updates will include support for scripts and modules
* Refactor useEvent
Previously, the useEvent implementation made use of effect infra under
the hood. This was a lot of extra overhead for functionality we didn't
use (events have no deps, and no clean up functions). This PR refactors
the implementation to instead use a queue to ensure that the callback is
stable across renders.
Additionally, the function signature was updated to infer the callback's argument types and return value. While this doesn't affect anything internal it more accurately describes what's being passed.
This lets us share it with react-server-dom-webpack while still having a
dependency on react-dom. It also makes somewhat sense from a bundling
perspective since react-dom is an external to itself.
* Expose ref to Offscreen if mode is manual
* Prepend private fields on OffscreenInstance with underscore
* Schedule Ref effect unconditionally on Offscreen
* Make sure Offscreen's ref is detached when unmounted
* Make sure ref is mounted/unmounted in all scenarious
* Nit: pendingProps -> memoizedProps
Co-authored-by: Andrew Clark <git@andrewclark.io>
To enable the next Flow version, we need to annotate exported values. This adds a few automatically inferred types that didn't look huge or just `any`.
There's a global queue (`concurrentQueues` in the
ReactFiberConcurrentUpdates module) that is cleared at the beginning of
each render phase.
However, in the case of an eager `setState` bailout where the state is
updated to same value as the current one, we add the update to the queue
without scheduling a render. So the render phase never removes it from
the queue. This can lead to a memory leak if it happens repeatedly
without any other updates.
There's only one place where this ever happens, so the fix was pretty
straightforward.
Currently there's no great way to test this from a Jest test, so I
confirmed locally by checking in an existing test whether the array gets
reset. @sompylasar had an interesting suggestion for how to catch these
in the future: in the development build (perhaps behind a flag), use a
Babel plugin to instrument all module-level variables. Then periodically
sweep to confirm if something has leaked. The logic is that if there's
no React work scheduled, and a module-level variable points to an
object, it very likely indicates a memory leak.
* [Flight] Align Chunks with Thenable used with experimental_use
Use the field names used by the Thenable data structure passed to use().
These are considered public in this model.
This adds another field since we use a separate field name for "reason".
* Implement Thenable Protocol on Chunks
This doesn't just ping but resolves/rejects with the value.
* Subclass Promises
* Pass key through JSON parsing
* Wait for preloadModules before resolving module chunks
* Initialize lazy resolved values before reading the result
* Block a model from initializing if its direct dependencies are pending
If a module is blocked, then we can't complete initializing a model.
However, we can still let it parse, and then fill in the missing pieces
later.
We need to block it from resolving until all dependencies have filled in
which we can do with a ref count.
* Treat blocked modules or models as a special status
We currently loop over all chunks at the end to error them if they're
still pending. We shouldn't do this if they're pending because they're
blocked on an external resource like a module because the module might not
resolve before the Flight connection closes and that's not an error.
In an alternative solution I had a set that tracked pending chunks and
removed one at a time. While the loop at the end is faster it's more
work as we go.
I figured the extra status might also help debugging.
For modules we can probably assume no forward references, and the first
async module we can just use the promise as the chunk.
So we could probably get away with this only on models that are blocked by
modules.
* useMemoCache impl
* test for multiple calls in a component (from custom hook)
* Use array of arrays for multiple calls; use alternate/local as the backup
* code cleanup
* fix internal test
* oops we do not support nullable property access
* Simplify implementation, still have questions on some of the PR feedback though
* Gate all code based on the feature flag
* refactor to use updateQueue
* address feedback
* Try to eliminate size increase in prod bundle
* update to retrigger ci
add more accurate end time for transitions and update host configs with `requestPostPaintCallback` function and move post paint logic to another module and use it in the work loop
This update range includes:
- `types_first` ([blog](https://flow.org/en/docs/lang/types-first/), all exports need annotated types) is default. I disabled this for now to make that change incremental.
- Generics that escape the scope they are defined in are an error. I fixed some with explicit type annotations and some are suppressed that I didn't easily figure out.
Usually we complete workInProgress before yielding but if that's the
currently suspended one, we don't yet complete it in case we can
immediately unblock it.
If we get interrupted, however, we must unwind it. Where as we usually
assume that we've already completed it.
This shows up when the current work in progress was a Context that pushed
and then it suspends in its immediate children. If we don't unwind,
it won't pop and so we get an imbalance.
* Prevent infinite re-render in StrictMode + Offscreen
* Only fire effects for Offscreen when it is revealed
* Move setting debug fiber into if branch
* Move settings of debug fiber out of if branch