* Remove redundant initial of isArray (#21163)
* Reapply prettier
* Type the isArray function with refinement support
This ensures that an argument gets refined just like it does if isArray is
used directly.
I'm not sure how to express with just a direct reference so I added a
function wrapper and confirmed that this does get inlined properly by
closure compiler.
* A few more
* Rename unit test to internal
This is not testing a bundle.
Co-authored-by: Behnam Mohammadi <itten@live.com>
* Implement DOM format config structure
* Styles
* Input warnings
* Textarea special cases
* Select special cases
* Option special cases
We read the currently selected value from the FormatContext.
* Warning for non-lower case HTML
We don't change to lower case at runtime anymore but keep the warning.
* Pre tags innerHTML needs to be prefixed
This is because if you do the equivalent on the client using innerHTML,
this is the effect you'd get.
* Extract errors
* Support nesting of startTransition and flushSync
* Unset transition before entering any special execution contexts
Co-authored-by: Andrew Clark <git@andrewclark.io>
The sync task queue is React-specific and doesn't really have anything
to do with Scheduler. We'd keep using it even once `postTask` exists.
By separating that part out, `SchedulerWithReactIntegration` is now
just a module that re-exports the Scheduler API. So I unforked it.
When we switch to ES Modules, we can remove this re-exporting module.
* Bump version number
* Remove Scheduler indirection
I originally kept the React PriorityLevel and Scheduler PriorityLevel
types separate in case there was a versioning mismatch between the two
modules. However, it looks like we're going to keep the Scheduler module
private in the short to medium term, and longer term the public
interface will match postTask. So, I've removed the extra indirection
(the switch statements that convert between the two types).
* Encode tables as a special insertion mode
The table modes are special in that its children can't be created outside
a table context so we need the segment container to be wrapped in a table.
* Move formatContext from Task to Segment
It works the same otherwise. It's just that this context needs to outlive
the task so that I can use it when writing the segment.
* Use template tag for placeholders and inserted dummy nodes with IDs
These can be used in any parent. At least outside IE11. Not sure yet what
happens in IE11 to these.
Not sure if these are bad for perf since they're special nodes.
* Add special wrappers around inserted segments depending on their insertion mode
* Allow the root namespace to be configured
This allows us to insert the correct wrappers when streaming into an
existing non-HTML tree.
* Add comment
This flag was meant to avoid flushing discrete updates unnecessarily,
if multiple discrete events were dispatched in response to the same
platform event.
But since we now flush all discrete events at the end of the task, in
a microtask, it no longer has any effect.
* Add format context
* Let the Work node hold all working state for the recursive loop
Stacks are nice and all but there's a cost to maintaining each frame
both in terms of stack size usage and writing to it.
* Move current format context into work
* Synchronously render children of a Suspense boundary
We don't have to spawn work and snapshot the context. Instead we can try
to render the boundary immediately in case it works.
* Lazily create the fallback work
Instead of eagerly create the fallback work and then immediately abort it.
We can just avoid creating it if we finish synchronously.
Instead of LanePriority. Internally, EventPriority is just a lane, so
this skips an extra conversion. Since EventPriority is a "public" (to
the host config) type, I was also able to remove some deep imports
of the Lane module.
This gets us most of the way to deleting the LanePriority entirely.
This is needed to avoid mutating the DOM during hydration. This *always*
adds it even when it's just text children.
We need to avoid this overhead but it's a somewhat tricky problem to solve
so we defer the optimization to later.
The event priority constants exports by the reconciler package are
meant to be used by the reconciler (host config) itself. So it doesn't
make sense to export them from a module that requires them.
To break the cycle, we can move them to a separate module and import
that. This looks like a "deep import" of an internal module, which we
try to avoid, but conceptually these are part of the public interface
of the reconciler module. So, no different than importing from the main
`react-reconciler`.
We do need to be careful about not mixing these types of imports with
implementation details. Those are the ones to really avoid.
An unintended benefit of the reconciler fork infra is that it makes
deep imports harder. Any module that we treat as "public", like this
one, needs to account for the `enableNewReconciler` flag and forward
to the correct implementation.
* Report errors to a global handler
This allows you to log errors or set things like status codes.
* Add complete callback
* onReadyToStream callback
This is typically not needed because if you want to stream when the
root is ready you can just start writing immediately.
* Rename onComplete -> onCompleteAll
* Add feature flag: enableStrongMemoryCleanup
Add a feature flag that will test doing a recursive clean of an unmount
node. This will disconnect the fiber graph making leaks less severe.
* Detach sibling pointers in old child list
When a fiber is deleted, it's still part of the previous (alternate)
parent fiber's list of children. Because children are a linked list, an
earlier sibling that's still alive will be connected to the deleted
fiber via its alternate:
live fiber
--alternate--> previous live fiber
--sibling--> deleted fiber
We can't disconnect `alternate` on nodes that haven't been deleted
yet, but we can disconnect the `sibling` and `child` pointers.
Will use this feature flag to test the memory impact.
* Combine into single enum flag
I combined `enableStrongMemoryCleanup` and `enableDetachOldChildList`
into a single enum flag. The flag has three possible values. Each level
is a superset of the previous one and performs more aggressive clean up.
We will use this to compare the memory impact of each level.
* Add Flow type to new host config method
* Re-use existing recursive clean up path
We already have a recursive loop that visits every deleted fiber. We
can re-use that one for clean up instead of adding another one.
Co-authored-by: Andrew Clark <git@andrewclark.io>
* Use identifierPrefix to avoid conflicts within the same response
identifierPrefix as an option exists to avoid useOpaqueIdentifier conflicting
when different renders are used within one HTML response.
This lets this be configured for the DOM renderer specifically since it's DOM
specific whether they will conflict across trees or not.
* Add test for using multiple containers in one HTML document
We use SyncLane everywhere we used to use InputDiscreteLane or
InputDiscreteHydrationLane. So we can delete them now, along with their
associated lane priority levels.
Discrete event hydration doesn't need to be interruptible, since
there's nothing higher priority than discrete events. So we can use
SyncLane instead of a special hydration lane.
We added this unstable feature a few years ago, as a way to opt out of
context updates, but it didn't prove useful in practice.
We have other proposals for how to address the same problem, like
context selectors.
Since it was prefixed with `unstable_`, we should be able to remove it
without consequence. The hook API already warned if you used it.
Even if someone is using it somewhere, it's meant to be an optimization
only, so if they are using the API properly, it should not have any
semantic impact.
* Track all suspended work while it's still pending
This allows us to abort work and put everything into client rendered mode
if we don't want to wait for further I/O.
It also allows us to cancel fallbacks if we complete the main content
before the fallback.
* Expose abort API to the browser streams
Since this API already returns a value, we need to use destructuring to
expose more options.
* Add a test including the client actually client rendering it
* Use AbortSignal option for W3C streams instead of external control
* Clean up listener after it's used once
* Don't delete any trailing nodes in the container during hydration error
* Warn when an error during hydration causes us to clear the container
* Encode unfortunate case in test
* Wrap the root for tests that are applicable to nested cases
* Now we can pipe Fizz into a container
* Grammatical fix
* Fix native event batching in concurrent mode
* Wrap DevTools test updates with act
These tests expect the `scheduleUpdate` DevTools hook to trigger a
synchronous re-render with legacy semantics, but flushing in a microtask
is fine. Wrapping the updates with `act` fixes it.
* Testing nits
* Nit: Check executionContext === NoContext first
In the common case it will be false and the binary expression will
short circuit.
Co-authored-by: Andrew Clark <git@andrewclark.io>
Some legacy environments can not encode non-strings. Those would specify
both as strings. They'll throw for binary data.
Some environments have to encode strings (like web streams). Those would
encode both as uint8array.
Some environments (like Node) can do either. It can be beneficial to leave
things as strings in case the native stream can do something smart with it.
* Move DOM/Native format configs to their respective packages
The streaming configs (Node/Browser) are different because they operate at
another dimension that exists in each package.
* Use escapeTextForBrowser to encode dynamic strings
We can now use local dependencies
* Destroy the stream with an error if the root throws
But not if the error happens inside a suspense boundary.
* Try rewriting the test to see if it works in other Node envs