* react-test-renderer injects itself into DevTools if present
* Fibers are always opted into ProfileMode if DevTools is present
* Added simple test for DevTools + always profiling behavior
* Inline fbjs/lib/emptyObject
* Explicit naming
* Compare to undefined
* Another approach for detecting whether we can mutate
Each renderer would have its own local LegacyRefsObject function.
While in general we don't want `instanceof`, here it lets us do a simple check: did *we* create the refs object?
Then we can mutate it.
If the check didn't pass, either we're attaching ref for the first time (so we know to use the constructor),
or (unlikely) we're attaching a ref to a component owned by another renderer. In this case, to avoid "losing"
refs, we assign them onto the new object. Even in that case it shouldn't "hop" between renderers anymore.
* Clearer naming
* Add test case for strings refs across renderers
* Use a shared empty object for refs by reading it from React
* Remove string refs from ReactART test
It's not currently possible to resetModules() between several renderers
without also resetting the `React` module. However, that leads to losing
the referential identity of the empty ref object, and thus subsequent
checks in the renderers for whether it is pooled fail (and cause assignments
to a frozen object).
This has always been the case, but we used to work around it by shimming
fbjs/lib/emptyObject in tests and preserving its referential identity.
This won't work anymore because we've inlined it. And preserving referential
identity of React itself wouldn't be great because it could be confusing during
testing (although we might want to revisit this in the future by moving its
stateful parts into a separate package).
For now, I'm removing string ref usage from this test because only this is
the only place in our tests where we hit this problem, and it's only
related to string refs, and not just ref mechanism in general.
* Simplify the condition
* [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