* 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
* Added new "native-fb" and "native-fabric-fb" bundles.
* Split RN_DEV and RN_PROD bundle types into RN_OSS_DEV, RN_OSS_PROD, RN_FB_DEV, and RN_FB_PROD. (This is a bit redundant but it seemed the least intrusive way of supporting a forked feature flags file for these bundles.)
* Renamed FB_DEV and FB_PROD bundle types to be more explicitly for www (FB_WWW_DEV and FB_WWW_PROD)
* Removed Haste @providesModule headers from the RB-specific RN renderer bundles to avoid a duplicate name conflicts.
* Remove dynamic values from OSS RN feature flags. (Leave them in FB RN feature flags.)
* Updated the sync script(s) to account for new renderer type.
* Move ReactFeatureFlags.js shim to FB bundle only (since OSS bundle no longer needs dynamic values).
* Move findNodeHandle into the renderers and use instantiation
This is just like ReactDOM does it. This also lets us get rid of injection
for findNodeHandle. Instead I move NativeMethodsMixin and ReactNativeComponent
to use instantiation.
* Refactor findHostInstance
The reconciler shouldn't expose the Fiber data structure. We should pass
the component instance to the reconciler, since the reconciler is the
thing that is supposed to be instancemap aware.
* Fix devtools injection
* Move view config registry to shims
This ensures that both Fabric and RN renderers share the same view config
registry since it is stateful.
I had to duplicate in the mocks for testing.
* Move createReactNativeComponentClass to shims and delete internal usage
Since createReactNativeComponentClass is just an alias for the register
there's no need to bundle it. This file should probably just move back
to RN too.
We already have one stateful module that contains all the view config.
We might as well store the event types there too. That way the shared
state is compartmentalized (and I can move it out in a follow up PR).
The view config registry also already has an appropriate place to call
processEventTypes so now we no longer have to do it in RN.
Will follow up with a PR to RN to remove that call.
These don't make much sense in Fabric, since Fabric will be async by default only.
And unmount+remove container is a sketchy API we should remove so we might
as well make sure modern containers enforce that.
This doesn't actually need to share any state because it goes through
the instance to the fiber structure. Since Fabric is on the same version
as RN, calling it on either renderer works.
There are no plans to enable async in the old renderer. In the new renderer
it only really makes sense to do from the main thread and probably from
native since it'll have to yield to native first.
This is not safe in general and therefore shouldn't be exposed to anything
other than React Native internals.
It will also need a different version in Fabric that will not have the
reactTag exposed.
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.
* Don't expose ReactGlobalSharedState on React Native renderer
We should just go through the "react" package if need access to this one.
Removed the dependencies in React Native.
* No longer used by InspectorUtils
If we have multiple RN renderers running simultaneously, we should be able to send a single event to all of them and only if it recognizes the event will it do anything with it. Crucially, this avoids the 'Unsupported top level event type "%s" dispatched' invariant in those cases.
* Disable DEV-only warnings for RN NativeMethodsMixin/create-react-class
* Tiny bit of cleanup
* Make strict-mode suppression check a little more robust
* Updates inside controlled events (onChange) are sync even in async mode
This guarantees the DOM is in a consistent state before we yield back
to the browser.
We'll need to figure out a separate strategy for other
interactive events.
* Don't rely on flushing behavior of public batchedUpdates implementation
Flush work as an explicit step at the end of the event, right before
restoring controlled state.
* Interactive updates
At the beginning of an interactive browser event (events that fire as
the result of a user interaction, like a click), check for pending
updates that were scheduled in a previous interactive event. Flush the
pending updates synchronously so that the event handlers are up-to-date
before responding to the current event.
We now have three classes of events:
- Controlled events. Updates are always flushed synchronously.
- Interactive events. Updates are async, unless another a subsequent
event is fired before it can complete, as described above. They are
also slightly higher priority than a normal async update.
- Non-interactive events. These are treated as normal, low-priority
async updates.
* Flush lowest pending interactive update time
Accounts for case when multiple interactive updates are scheduled at
different priorities. This can happen when an interactive event is
dispatched inside an async subtree, and there's an event handler on
an ancestor that is outside the subtree.
* Update comment about restoring controlled components
* 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.
* WIP:use public API
* ReactPortal shifted to shared:all passed
* wrote createPortal method for ReactNoop.(#11299)
* imported ReactNodeList type into ReactNoop.(#11299)
* createPortal method implemented.(#11299)
* exec yarn prettier-all.(#11299)
* 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
* Move ReactFiberTreeReflection to react-reconciler/reflection #11659
* Use * for react-reconciler
We don't know the latest local version, and release script currently doesn't bump deps automatically.
* Remove unused field
* Use CommonJS in entry point for consistency
* Undo the CommonJS change
I didn't realize it would break the build.
* Record sizes
* Remove reconciler fixtures
They're unnecessary now that we run real tests on reconciler bundles.
* Extract Jest config into a separate file
* Refactor Jest scripts directory structure
Introduces a more consistent naming scheme.
* Add yarn test-bundles and yarn test-prod-bundles
Only files ending with -test.public.js are opted in (so far we don't have any).
* Fix error decoding for production bundles
GCC seems to remove `new` from `new Error()` which broke our proxy.
* Build production version of react-noop-renderer
This lets us test more bundles.
* Switch to blacklist (exclude .private.js tests)
* Rename tests that are currently broken against bundles to *-test.internal.js
Some of these are using private APIs. Some have other issues.
* Add bundle tests to CI
* Split private and public ReactJSXElementValidator tests
* Remove internal deps from ReactServerRendering-test and make it public
* Only run tests directly in __tests__
This lets us share code between test files by placing them in __tests__/utils.
* Remove ExecutionEnvironment dependency from DOMServerIntegrationTest
It's not necessary since Stack.
* Split up ReactDOMServerIntegration into test suite and utilities
This enables us to further split it down. Good both for parallelization and extracting public parts.
* Split Fragment tests from other DOMServerIntegration tests
This enables them to opt other DOMServerIntegration tests into bundle testing.
* Split ReactDOMServerIntegration into different test files
It was way too slow to run all these in sequence.
* Don't reset the cache twice in DOMServerIntegration tests
We used to do this to simulate testing separate bundles.
But now we actually *do* test bundles. So there is no need for this, as it makes tests slower.
* Rename test-bundles* commands to test-build*
Also add test-prod-build as alias for test-build-prod because I keep messing them up.
* Use regenerator polyfill for react-noop
This fixes other issues and finally lets us run ReactNoop tests against a prod bundle.
* Run most Incremental tests against bundles
Now that GCC generator issue is fixed, we can do this.
I split ErrorLogging test separately because it does mocking. Other error handling tests don't need it.
* Update sizes
* Fix ReactMount test
* Enable ReactDOMComponent test
* Fix a warning issue uncovered by flat bundle testing
With flat bundles, we couldn't produce a good warning for <div onclick={}> on SSR
because it doesn't use the event system. However the issue was not visible in normal
Jest runs because the event plugins have been injected by the time the test ran.
To solve this, I am explicitly passing whether event system is available as an argument
to the hook. This makes the behavior consistent between source and bundle tests. Then
I change the tests to document the actual logic and _attempt_ to show a nice message
(e.g. we know for sure `onclick` is a bad event but we don't know the right name for it
on the server so we just say a generic message about camelCase naming convention).
* Forked ReactFeatureFlags for React Native to enable debugRenderPhaseSideEffects GK
* Changed debugRenderPhaseSideEffects in www feature flags to be runtime as well
* Don't call idle callback unless there's time remaining
* Expiration fixture
Fixture that demonstrates how async work expires after a certain interval.
The fixture clogs the main thread with animation work, so it only works if the
`timeout` option is provided to `requestIdleCallback`.
* Pass timeout option to requestIdleCallback
Forces `requestIdleCallback` to fire if too much time has elapsed, even if the
main thread is busy. Required to make expiration times work properly. Otherwise,
async work can expire, but React never has a chance to flush it because the
browser never calls into React.
* Update Flow
* Fix createElement() issue
The * type was too ambiguous. It's always a string so what's the point?
Suppression for missing Flow support for {is: ''} web component argument to createElement() didn't work for some reason.
I don't understand what the regex is testing for anyway (a task number?) so I just removed that, and suppression got fixed.
* Remove deleted $Abstract<> feature
* Expand the unsound isAsync check
Flow now errors earlier because it can't find .type on a portal.
* Add an unsafe cast for the null State in UpdateQueue
* Introduce "hydratable instance" type
The Flow error here highlighted a quirk in our typing of hydration.
React only really knows about a subset of all possible nodes that can
exist in a hydrated tree. Currently we assume that the host renderer
filters them out to be either Instance or TextInstance. We also assume
that those are different things which they might not be. E.g. it could
be fine for a renderer to render "text" as the same type as one of the
instances, with some default props.
We don't really know what it will be narrowed down to until we call
canHydrateInstance or canHydrateTextInstance. That's when the type is
truly refined.
So to solve this I use a different type for hydratable instance that is
used in that temporary stage between us reading it from the DOM and until
it gets refined by canHydrate(Text)Instance.
* Have the renderer refine Hydratable Instance to Instance or Text Instance
Currently we assume that if canHydrateInstance or canHydrateTextInstance
returns true, then the types also match up. But we don't tell that to Flow.
It just happens to work because `fiber.stateNode` is still `any`.
We could potentially use some kind of predicate typing but instead
of that I can just return null or instance from the "can" tests.
This ensures that the renderer has to do the refinement properly.
* Convert EventPlugin{Hub,Registry} to named exports
* Convert EventPluginUtils to named exports
* Convert EventPropagators to named exports
* Convert ReactControlledComponent to named exports
* Convert ReactGenericBatching to named exports
* Convert ReactDOMComponentTree to named exports
* Convert ReactNativeComponentTree to named exports
* Convert ReactNativeRTComponentTree to named exports
* Convert FallbackCompositionState to named exports
* Convert ReactEventEmitterMixin to named exports
* Convert ReactBrowserEventEmitter to named exports
* Convert ReactNativeEventEmitter to named exports
* Convert ReactDOMEventListener to named exports
* Convert DOMMarkupOperations to named exports
* Convert DOMProperty to named exports
* Add suppression for existing Flow violation
Flow didn't see it before.
* Update sizes