* [schedule] Use linked list instead of queue and map for storing cbs
NOTE: This PR depends on https://github.com/facebook/react/pull/12880
and https://github.com/facebook/react/pull/12884
Please review those first, and after they land Flarnie will rebase on
top of them.
---
**what is the change?:**
See title
**why make this change?:**
This seems to make the code simpler, and potentially saves space of
having an array and object around holding references to the callbacks.
**test plan:**
Run existing tests
* minor style improvements
* refactor conditionals in cancelScheduledWork for increased clarity
* Remove 'canUseDOM' condition and fix some flow issues w/callbackID type
**what is the change?:**
- Removed conditional which fell back to 'setTimeout' when the
environment doesn't have DOM. This appears to be an old polyfill used
for test environments and we don't use it any more.
- Fixed type definitions around the callbackID to be more accurate in
the scheduler itself, and more loose in the React code.
**why make this change?:**
To get Flow passing, simplify the scheduler code, make things accurate.
**test plan:**
Run tests and flow.
* Rewrite 'cancelScheduledWork' so that Flow accepts it
**what is the change?:**
Adding verification that 'previousCallbackConfig' and
'nextCallbackConfig' are not null before accessing properties on them.
Slightly concerned because this implementation relies on these
properties being untouched and correct on the config which is passed to
'cancelScheduledWork' but I guess we already rely heavily on that for
this whole approach. :\
**why make this change?:**
To get Flow passing.
Not sure why it passed earlier and in CI, but now it's not.
**test plan:**
`yarn flow dom` and other flow tests, lint, tests, etc.
* ran prettier
* Put back the fallback implementation of scheduler for node environment
**what is the change?:**
We had tried removing the fallback implementation of `scheduler` but
tests reminded us that this is important for supporting isomorphic uses
of React.
Long term we will move this out of the `schedule` module but for now
let's keep things simple.
**why make this change?:**
Keep things working!
**test plan:**
Ran tests and flow
* Shorten properties stored in objects by sheduler
**what is the change?:**
`previousScheduledCallback` -> `prev`
`nextScheduledCallback` -> `next`
**why make this change?:**
We want this package to be smaller, and less letters means less code
means smaller!
**test plan:**
ran existing tests
* further remove extra lines in scheduler
* 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
* Support concurrent primary and secondary renderers.
As a workaround to support multiple concurrent renderers, we categorize
some renderers as primary and others as secondary. We only expect
there to be two concurrent renderers at most: React Native (primary) and
Fabric (secondary); React DOM (primary) and React ART (secondary).
Secondary renderers store their context values on separate fields.
* Add back concurrent renderer warning
Only warn for two concurrent primary or two concurrent secondary renderers.
* Change "_secondary" suffix to "2"
#EveryBitCounts
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).
These are based on the ReactNoop renderer, which we use to test React
itself. This gives library authors (Relay, Apollo, Redux, et al.) a way
to test their components for async compatibility.
- Pass `unstable_isAsync` to `TestRenderer.create` to create an async
renderer instance. This causes updates to be lazily flushed.
- `renderer.unstable_yield` tells React to yield execution after the
currently rendering component.
- `renderer.unstable_flushAll` flushes all pending async work, and
returns an array of yielded values.
- `renderer.unstable_flushThrough` receives an array of expected values,
begins rendering, and stops once those values have been yielded. It
returns the array of values that are actually yielded. The user should
assert that they are equal.
Although we've used this pattern successfully in our own tests, I'm not
sure if these are the final APIs we'll make public.
* Implemented new getSnapshotBeforeUpdate lifecycle
* Store snapshot value from Fiber to instance (__reactInternalSnapshotBeforeUpdate)
* Use commitAllHostEffects() traversal for getSnapshotBeforeUpdate()
* Added DEV warnings and tests for new lifecycle
* Don't invoke legacy lifecycles if getSnapshotBeforeUpdate() is defined. DEV warn about this.
* Converted did-warn objects to Sets in ReactFiberClassComponent
* Replaced redundant new lifecycle checks in a few methods
* Check for polyfill suppress flag on cWU as well before warning
* Added Snapshot bit to HostEffectMask
* Support ForwardRef type of work in TestRenderer and ShallowRenderer.
* Release script now updates inter-package dependencies too (e.g. react-test-renderer depends on react-is).
* 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.
* Invoke both legacy and UNSAFE_ lifecycles when both are present
This is to support edge cases with eg create-react-class where a mixin defines a legacy lifecycle but the component being created defines an UNSAFE one (or vice versa).
I did not warn about this case because the warning would be a bit redundant with the deprecation warning which we will soon be enabling. I could be convinced to change my stance here though.
* Added explicit function-type check to SS ReactPartialRenderer
* Suppress unsafe/deprecation warnings for polyfilled components.
* Don't invoke deprecated lifecycles if static gDSFP exists.
* Applied recent changes to server rendering also
* 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.