**what is the change?:**
Basically undoes 4b2e65d32e (diff-904ceabd8a1e9a07ab1d876d843d62e1)
**why make this change?:**
We rolled out this fix internally and in open source weeks ago, and now
we're cleaning up.
**test plan:**
Ran tests and lint, and really we have been testing this because the
flag is open internally as of last week or so.
**issue:**
Internal task T29948812 has some info.
* add legacy context APIs warning in strict mode
* refactor if statement and the warning message
* add other flags for type check
* add component stack tree and refactor wording
* fix the nits
* Extract base Jest config
This makes it easier to change the source config without affecting the build test config.
* Statically import the host config
This changes react-reconciler to import HostConfig instead of getting it through a function argument.
Rather than start with packages like ReactDOM that want to inline it, I started with React Noop and ensured that *custom* renderers using react-reconciler package still work. To do this, I'm making HostConfig module in the reconciler look at a global variable by default (which, in case of the react-reconciler npm package, ends up being the host config argument in the top-level scope).
This is still very broken.
* Add scaffolding for importing an inlined renderer
* Fix the build
* ES exports for renderer methods
* ES modules for host configs
* Remove closures from the reconciler
* Check each renderer's config with Flow
* Fix uncovered Flow issue
We know nextHydratableInstance doesn't get mutated inside this function, but Flow doesn't so it thinks it may be null.
Help Flow.
* Prettier
* Get rid of enable*Reconciler flags
They are not as useful anymore because for almost all cases (except third party renderers) we *know* whether it supports mutation or persistence.
This refactoring means react-reconciler and react-reconciler/persistent third-party packages now ship the same thing.
Not ideal, but this seems worth how simpler the code becomes. We can later look into addressing it by having a single toggle instead.
* Prettier again
* Fix Flow config creation issue
* Fix imprecise Flow typing
* Revert accidental changes
* Timeout component
Adds Timeout component. If a promise is thrown from inside a Timeout component,
React will suspend the in-progress render from committing. When the promise
resolves, React will retry. If the render is suspended for longer than the
maximum threshold, the Timeout switches to a placeholder state.
The timeout threshold is defined as the minimum of:
- The expiration time of the current render
- The `ms` prop given to each Timeout component in the ancestor path of the
thrown promise.
* Add a test for nested fallbacks
Co-authored-by: Andrew Clark <acdlite@fb.com>
* Resume on promise rejection
React should resume rendering regardless of whether it resolves
or rejects.
* Wrap Suspense code in feature flag
* Children of a Timeout must be strict mode compatible
Async is not required for Suspense, but strict mode is.
* Simplify list of pending work
Some of this was added with "soft expiration" in mind, but now with our revised
model for how soft expiration will work, this isn't necessary.
It would be nice to remove more of this, but I think the list itself is inherent
because we need a way to track the start times, for <Timeout ms={ms} />.
* Only use the Timeout update queue to store promises, not for state
It already worked this way in practice.
* Wrap more Suspense-only paths in the feature flag
* Attach promise listener immediately on suspend
Instead of waiting for commit phase.
* Infer approximate start time using expiration time
* Remove list of pending priority levels
We can replicate almost all the functionality by tracking just five
separate levels: the highest/lowest priority pending levels, the
highest/lowest priority suspended levels, and the lowest pinged level.
We lose a bit of granularity, in that if there are multiple levels of
pending updates, only the first and last ones are known. But in practice
this likely isn't a big deal.
These heuristics are almost entirely isolated to a single module and
can be adjusted later, without API changes, if necessary.
Non-IO-bound work is not affected at all.
* ReactFiberPendingWork -> ReactFiberPendingPriority
* Renaming method names from "pending work" to "pending priority"
* Get rid of SuspenseThenable module
Idk why I thought this was neccessary
* Nits based on Sebastian's feedback
* More naming nits + comments
* Add test for hiding a suspended tree to unblock
* Revert change to expiration time rounding
This means you have to account for the start time approximation
heuristic when writing Suspense tests, but that's going to be
true regardless.
When updating the tests, I also made a fix related to offscreen
priority. We should never timeout inside a hidden tree.
* palceholder -> placeholder
Add a new component type, Profiler, that can be used to collect new render time metrics. Since this is a new, experimental API, it will be exported as React.unstable_Profiler initially.
Most of the functionality for this component has been added behind a feature flag, enableProfileModeMetrics. When the feature flag is disabled, the component will just render its children with no additional behavior. When the flag is enabled, React will also collect timing information and pass it to the onRender function (as described below).
* Support using id to cancel scheduled callback
**what is the change?:**
see title
**why make this change?:**
Once we support multiple callbacks you will need to use the id to
specify which callback you mean.
**test plan:**
Added a test, ran all tests, lint, etc.
* ran prettier
* fix lint
* Use object for storing callback info in scheduler
* Wrap initial test in a describe block
* Support multiple callbacks in `ReactScheduler`
**what is the change?:**
We keep a queue of callbacks instead of just one at a time, and call
them in order first by their timeoutTime and then by the order which
they were scheduled in.
**why make this change?:**
We plan on using this module to coordinate JS outside of React, so we
will need to schedule more than one callback at a time.
**test plan:**
Added a boatload of shiny new tests. :)
Plus ran all the old ones.
NOTE: The tests do not yet cover the vital logic of callbacks timing
out, and later commits will add the missing test coverage.
* Heuristic to avoid looking for timed out callbacks when none timed out
**what is the change?:**
Tracks the current soonest timeOut time for all scheduled callbacks.
**why make this change?:**
We were checking every scheduled callback to see if it timed out on
every tick. It's more efficient to skip that O(n) check if we know that
none have timed out.
**test plan:**
Ran existing tests.
Will write new tests to cover timeout behavior in more detail soon.
* Put multiple callback support under a disabled feature flag
**what is the change?:**
See title
**why make this change?:**
We don't have error handling in place yet, so should maintain the old
behavior until that is in place.
But want to get this far to continue making incremental changes.
**test plan:**
Updated and ran tests.
* Hide support for multiple callbacks under a feature flag
**what is the change?:**
see title
**why make this change?:**
We haven't added error handling yet, so should not expose this feature.
**test plan:**
Ran all tests, temporarily split out the tests for multiple callbacks
into separate file. Will recombine once we remove the flag.
* Fix nits from code review
See comments on https://github.com/facebook/react/pull/12743
* update checklist in comments
* Remove nested loop which calls additional timed out callbacks
**what is the change?:**
We used to re-run any callbacks which time out whilst other callbacks
are running, but now we will only check once for timed out callbacks
then then run them.
**why make this change?:**
To simplify the code and the behavior of this module.
**test plan:**
Ran all existing tests.
* Remove feature flag
**what is the change?:**
see title
**why make this change?:**
Because only React is using this, and it sounds like async. rendering
won't hit any different behavior due to these changes.
**test plan:**
Existing tests pass, and this allowed us to recombine all tests to run
in both 'test' and 'test-build' modes.
* remove outdated file
* fix typo
* Remove the 'alwaysUseRequestIdleCallbackPolyfill' feature flag
**what is the change?:**
Removes the feature flag 'alwaysUseRequestIdleCallbackPolyfill', such
that we **always** use the polyfill for requestIdleCallback.
**why make this change?:**
We have been testing this feature flag at 100% for some time internally,
and determined it works better for React than the native implementation.
Looks like RN was overriding the flag to use the native when possible,
but since no RN products are using 'async' mode it should be safe to
switch this flag over for RN as well.
**test plan:**
We have already been testing this internally for some time.
**issue:**
internal task t28128480
* fix mistaken conditional
* Add mocking of rAF, postMessage, and initial test for ReactScheduler
**what is the change?:**
- In all tests where we previously mocked rIC or relied on native
mocking which no longer works, we are now mocking rAF and postMessage.
- Also adds a basic initial test for ReactScheduler.
NOTE -> we do plan to write headless browser tests for ReactScheduler!
This is just an initial test, to verify that it works with the mocked
out browser APIs as expected.
**why make this change?:**
We need to mock out the browser APIs more completely for the new
'ReactScheduler' to work in our tests. Many tests are depending on it,
since it's used at a low level.
By mocking the browser APIs rather than the 'react-scheduler' module, we
enable testing the production bundles. This approach is trading
isolation for accuracy. These tests will be closer to a real use.
**test plan:**
run the tests :)
**issue:**
internal task T28128480
We'll use this in www to test whether the polyfill is better at
scheduling high-pri async work than the native one. My preliminary tests
suggest "yes" but it's hard to say for certain, given how difficult it
is to consistently reproduce the starvation issues we've been seeing.
* Add stack unwinding phase for handling errors
A rewrite of error handling, with semantics that more closely match
stack unwinding.
Errors that are thrown during the render phase unwind to the nearest
error boundary, like before. But rather than synchronously unmount the
children before retrying, we restart the failed subtree within the same
render phase. The failed children are still unmounted (as if all their
keys changed) but without an extra commit.
Commit phase errors are different. They work by scheduling an error on
the update queue of the error boundary. When we enter the render phase,
the error is popped off the queue. The rest of the algorithm is
the same.
This approach is designed to work for throwing non-errors, too, though
that feature is not implemented yet.
* Add experimental getDerivedStateFromCatch lifecycle
Fires during the render phase, so you can recover from an error within the same
pass. This aligns error boundaries more closely with try-catch semantics.
Let's keep this behind a feature flag until a future release. For now, the
recommendation is to keep using componentDidCatch. Eventually, the advice will
be to use getDerivedStateFromCatch for handling errors and componentDidCatch
only for logging.
* Reconcile twice to remount failed children, instead of using a boolean
* Handle effect immediately after its thrown
This way we don't have to store the thrown values on the effect list.
* ReactFiberIncompleteWork -> ReactFiberUnwindWork
* Remove startTime
* Remove TypeOfException
We don't need it yet. We'll reconsider once we add another exception type.
* Move replay to outer catch block
This moves it out of the hot path.
* Switch to JSX API for context
80% sure this will be the final API. Merging this now so we can get this
into the next www sync in preparation for 16.3.
* Promote context to a stable API
* Replace unstable_AsyncComponent with Unstable_AsyncMode
Mirrors the StrictMode API and uses the new Mode type of work.
* internalContextTag -> mode
Change this now that we have a better name
* Unstable_ -> unstable_
A new feature flag has been added, debugRenderPhaseSideEffectsForStrictMode. When enabled, StrictMode subtrees will also double-invoke lifecycles in the same way as debugRenderPhaseSideEffects.
By default, this flag is enabled for __DEV__ only. Internally we can toggle it with a GK.
This breaks several of our incremental tests which make use of the noop-renderer. Updating the tests to account for the double-rendering in development mode makes them significantly more complicated. The most straight forward fix for this will be to convert them to be run as internal tests only. I believe this is reasonable since we are the only people making use of the noop renderer.
* New context API
Introduces a declarative context API that propagates updates even when
shouldComponentUpdate returns false.
* Fuzz tester for context
* Use ReactElement for provider and consumer children
* Unify more branches in createFiberFromElement
* Compare context values using Object.is
Same semantics as PureComponent/shallowEqual.
* Add support for Provider and Consumer to server-side renderer
* Store providers on global stack
Rather than using a linked list stored on the context type. The global
stack can be reset in case of an interruption or error, whereas with the
linked list implementation, you'd need to keep track of every
context type.
* Put new context API behind a feature flag
We'll enable this in www only for now.
* Store nearest provider on context object
* Handle reentrancy in server renderer
Context stack should be per server renderer instance.
* Bailout of consumer updates using bitmask
The context type defines an optional function that compares two context
values, returning a bitfield. A consumer may specify the bits it needs
for rendering. If a provider's context changes, and the consumer's bits
do not intersect with the changed bits, we can skip the consumer.
This is similar to how selectors are used in Redux but fast enough to do
while scanning the tree. The only user code involved is the function
that computes the changed bits. But that's only called once per provider
update, not for every consumer.
* Store current value and changed bits on context object
There are fewer providers than consumers, so better to do this work
at the provider.
* Use maximum of 31 bits for bitmask
This is the largest integer size in V8 on 32-bit systems. Warn in
development if too large a number is used.
* ProviderComponent -> ContextProvider, ConsumerComponent -> ContextConsumer
* Inline Object.is
* Warn if multiple renderers concurrently render the same context provider
Let's see if we can get away with not supporting this for now. If it
turns out that it's needed, we can fall back to backtracking the
fiber return path.
* Nits that came up during review
* Added unsafe_* lifecycles and deprecation warnings
If the old lifecycle hooks (componentWillMount, componentWillUpdate, componentWillReceiveProps) are detected, these methods will be called and a deprecation warning will be logged. (In other words, we do not check for both the presence of the old and new lifecycles.) This commit is expected to fail tests.
* Ran lifecycle hook codemod over project
This should handle the bulk of the updates. I will manually update TypeScript and CoffeeScript tests with another commit.
The actual command run with this commit was: jscodeshift --parser=flow -t ../react-codemod/transforms/rename-unsafe-lifecycles.js ./packages/**/src/**/*.js
* Manually migrated CoffeeScript and TypeScript tests
* Added inline note to createReactClassIntegration-test
Explaining why lifecycles hooks have not been renamed in this test.
* Udated NativeMethodsMixin with new lifecycle hooks
* Added static getDerivedStateFromProps to ReactPartialRenderer
Also added a new set of tests focused on server side lifecycle hooks.
* Added getDerivedStateFromProps to shallow renderer
Also added warnings for several cases involving getDerivedStateFromProps() as well as the deprecated lifecycles.
Also added tests for the above.
* Dedupe and DEV-only deprecation warning in server renderer
* Renamed unsafe_* prefix to UNSAFE_* to be more noticeable
* Added getDerivedStateFromProps to ReactFiberClassComponent
Also updated class component and lifecyle tests to cover the added functionality.
* Warn about UNSAFE_componentWillRecieveProps misspelling
* Added tests to createReactClassIntegration for new lifecycles
* Added warning for stateless functional components with gDSFP
* Added createReactClass test for static gDSFP
* Moved lifecycle deprecation warnings behind (disabled) feature flag
Updated tests accordingly, by temporarily splitting tests that were specific to this feature-flag into their own, internal tests. This was the only way I knew of to interact with the feature flag without breaking our build/dist tests.
* Tidying up
* Tweaked warning message wording slightly
Replaced 'You may may have returned undefined.' with 'You may have returned undefined.'
* Replaced truthy partialState checks with != null
* Call getDerivedStateFromProps via .call(null) to prevent type access
* Move shallow-renderer didWarn* maps off the instance
* Only call getDerivedStateFromProps if props instance has changed
* Avoid creating new state object if not necessary
* Inject state as a param to callGetDerivedStateFromProps
This value will be either workInProgress.memoizedState (for updates) or instance.state (for initialization).
* Explicitly warn about uninitialized state before calling getDerivedStateFromProps.
And added some new tests for this change.
Also:
* Improved a couple of falsy null/undefined checks to more explicitly check for null or undefined.
* Made some small tweaks to ReactFiberClassComponent WRT when and how it reads instance.state and sets to null.
* Improved wording for deprecation lifecycle warnings
* Fix state-regression for module-pattern components
Also add support for new static getDerivedStateFromProps method
Removes the `useSyncScheduling` option from the HostConfig, since it's
no longer needed. Instead of globally flipping between sync and async,
our strategy will be to opt-in specific trees and subtrees.
* Unify the way we fork modules
* Replace rollup-plugin-alias with our own plugin
This does exactly what we need and doesn't suffer from https://github.com/rollup/rollup-plugin-alias/issues/34.
* Move the new plugin to its own file
* Rename variable for consistency
I settled on calling them "forks" since we already have a different concept of "shims".
* Move fork config into its own file