useMutableSource hook
useMutableSource() enables React components to safely and efficiently read from a mutable external source in Concurrent Mode. The API will detect mutations that occur during a render to avoid tearing and it will automatically schedule updates when the source is mutated.
RFC: reactjs/rfcs#147
* Rename to clarify that it's client-only
* Rename FizzStreamer to FizzServer for consistency
* Rename react-flight to react-client/flight
For consistency with react-server. Currently this just includes flight
but it could be expanded to include the whole reconciler.
* Add Relay Flight Build
* Rename ReactServerHostConfig to ReactServerStreamConfig
This will be the config specifically for streaming purposes.
There will be other configs for other purposes.
* Require deep for reconcilers
* Delete inline* files
* Delete react-reconciler/persistent
This no longer makes any sense because it react-reconciler takes
supportsMutation or supportsPersistence as options. It's no longer based
on feature flags.
* Fix jest mocking
* Fix Flow strategy
We now explicitly list which paths we want to be checked by a renderer.
For every other renderer config we ignore those paths.
Nothing is "any" typed. So if some transitive dependency isn't reachable
it won't be accidentally "any" that leaks.
In CI, we run our test suite against multiple build configurations. For
example, we run our tests in both dev and prod, and in both the
experimental and stable release channels. This is to prevent accidental
deviations in behavior between the different builds. If there's an
intentional deviation in behavior, the test author must account
for them.
However, we currently don't run tests against the www builds. That's
a problem, because it's common for features to land in www before they
land anywhere else, including the experimental release channel.
Typically we do this so we can gradually roll out the feature behind
a flag before deciding to enable it.
The way we test those features today is by mutating the
`shared/ReactFeatureFlags` module. There are a few downsides to this
approach, though. The flag is only overridden for the specific tests or
test suites where you apply the override. But usually what you want is
to run *all* tests with the flag enabled, to protect against unexpected
regressions.
Also, mutating the feature flags module only works when running the
tests against source, not against the final build artifacts, because the
ReactFeatureFlags module is inlined by the build script.
Instead, we should run the test suite against the www configuration,
just like we do for prod, experimental, and so on. I've added a new
command, `yarn test-www`. It automatically runs in CI.
Some of the www feature flags are dynamic; that is, they depend on
a runtime condition (i.e. a GK). These flags are imported from an
external module that lives in www. Those flags will be enabled for some
clients and disabled for others, so we should run the tests against
*both* modes.
So I've added a new global `__VARIANT__`, and a new test command `yarn
test-www-variant`. `__VARIANT__` is set to false by default; when
running `test-www-variant`, it's set to true.
If we were going for *really* comprehensive coverage, we would run the
tests against every possible configuration of feature flags: 2 ^
numberOfFlags total combinations. That's not practical, though, so
instead we only run against two combinations: once with `__VARIANT__`
set to `true`, and once with it set to `false`. We generally assume that
flags can be toggled independently, so in practice this should
be enough.
You can also refer to `__VARIANT__` in tests to detect which mode you're
running in. Or, you can import `shared/ReactFeatureFlags` and read the
specific flag you can about. However, we should stop mutating that
module going forward. Treat it as read-only.
In this commit, I have only setup the www tests to run against source.
I'll leave running against build for a follow up.
Many of our tests currently assume they run only in the default
configuration, and break when certain flags are toggled. Rather than fix
these all up front, I've hard-coded the relevant flags to the default
values. We can incrementally migrate those tests later.
* This type is all wrong and nothing cares because it's all any
* Refine Flow types of Lazy Components
We can type each condition.
* Remove _ctor field from Lazy components
This field is not needed because it's only used before we've initialized,
and we don't have anything else to store before we've initialized.
* Check for _ctor in case it's an older isomorphic that created it
We try not to break across minors but it's no guarantee.
* Move types and constants from shared to isomorphic
The "react" package owns the data structure of the Lazy component. It
creates it and decides how any downstream renderer may use it.
* Move constants to shared
Apparently we can't depend on react/src/ because the whole package is
considered "external" as far as rollup is concerned.
Nothing interesting here except that ReactShallowRenderer currently exports
a class with a static method instead of an object.
I think the public API is probably just meant to be createRenderer but
currently the whole class is exposed. So this means that we have to keep
it as default export. We could potentially also expose a named export for
createRenderer but that's going to cause compatibility issues.
So I'm just going to make that export default.
Unfortunately Rollup and Babel (which powers Jest) disagree on how to
import this. So to make it work I had to move the jest tests to imports.
This doesn't work with module resetting. Some tests weren't doing that
anyway and the rest is just testing ReactShallowRenderer so meh.
* Add options for forked entry points
We currently fork .fb.js entry points. This adds a few more options.
.modern.fb.js - experimental FB builds
.classic.fb.js - stable FB builds
.fb.js - if no other FB build, use this for FB builds
.experimental.js - experimental builds
.stable.js - stable builds
.js - used if no other override exists
This will be used to have different ES exports for different builds.
* Switch React to named exports
* Export named exports from the export point itself
We need to re-export the Flow exported types so we can use them in our code.
We don't want to use the Flow types from upstream since it doesn't have the non-public APIs that we have.
This should be able to use export * but I don't know why it doesn't work.
This actually enables Flow typing of React which was just "any" before.
This exposed some Flow errors that needs fixing.
* Create forks for the react entrypoint
None of our builds expose all exports and they all differ in at least one
way, so we need four forks.
* Set esModule flag to false
We don't want to emit the esModule compatibility flag on our CommonJS
output. For now we treat our named exports as if they're CommonJS.
This is a potentially breaking change for scheduler (but all those apis
are unstable), react-is and use-subscription. However, it seems unlikely
that anyone would rely on this since these only have named exports.
* Remove unused Feature Flags
* Let jest observe the stable fork for stable tests
This lets it do the negative test by ensuring that the right tests fail.
However, this in turn will make other tests that are not behind
__EXPERIMENTAL__ fail. So I need to do that next.
* Put all tests that depend on exports behind __EXPERIMENTAL__
Since there's no way to override the exports using feature flags
in .intern.js anymore we can't use these APIs in stable.
The tradeoff here is that we can either enable the negative tests on
"stable" that means experimental are expected to fail, or we can disable
tests on stable. This is unfortunate since some of these APIs now run on
a "stable" config at FB instead of the experimental.
* Switch ReactDOM to named exports
Same strategy as React.
I moved the ReactDOMFB runtime injection to classic.fb.js
Since we only fork the entrypoint, the `/testing` entrypoint needs to
be forked too to re-export the same things plus `act`. This is a bit
unfortunate. If it becomes a pattern we can consider forking in the
module resolution deeply.
fix flow
* Fix ReactDOM Flow Types
Now that ReactDOM is Flow type checked we need to fix up its types.
* Configure jest to use stable entry for ReactDOM in non-experimental
* Remove additional FeatureFlags that are no longer needed
These are only flagging the exports and no implementation details so we
can control them fully through the export overrides.
Exports from ReactDOM represents React's public API. This include types
exported by React. At some point we'll start building Flow types from
these files.
The duplicate name between DOMContainer and Container seems confusing too
since it was used in the same files even though they're the same.
* import * as React from "react";
This is the correct way to import React from an ES module since the ES
module will not have a default export. Only named exports.
* import * as ReactDOM from "react-dom"
* Build both stable and experimental WWW builds
* Flip already experimental WWW flags to true
* Remove FB-specific internals from modern FB builds
We think we're not going to need these.
* Disable classic features in modern WWW builds
* Disable legacy ReactDOM API for modern WWW build
* Don’t include user timing in prod
* Fix bad copy paste and add missing flags to test renderer
* Add testing WWW feature flag file
We need it because WWW has a different meaning of experimental now.
The mock Scheduler that we use in our tests has its own fake timer
implementation. The `unstable_advanceTime` method advances the timeline.
Currently, a call to `unstable_advanceTime` will also flush any pending
expired work. But that's not how it works in the browser: when a timer
fires, the corresponding task is added to the Scheduler queue. However,
we will still wait until the next message event before flushing it.
This commit changes `unstable_advanceTime` to more closely resemble the
browser behavior, by removing the automatic flushing of expired work.
```js
// Before this commit
Scheduler.unstable_advanceTime(ms);
// Equivalent behavior after this commit
Scheduler.unstable_advanceTime(ms);
Scheduler.unstable_flushExpired();
```
The general principle is to prefer separate APIs for scheduling tasks
and flushing them.
This change does not affect any public APIs. `unstable_advanceTime` is
only used by our own test suite. It is not used by `act`.
However, we may need to update tests in www, like Relay's.
This PR introduces adds `react/testing` and `react-dom/testing`.
- changes infra to generate these builds
- exports act on ReactDOM in these testing builds
- uses the new test builds in fixtures/dom
In the next PR -
- I'll use the new builds for all our own tests
- I'll replace usages of TestUtils.act with ReactDOM.act.
* Simplify Continuous Hydration Targets
Let's use a constant priority for this. This helps us avoid restarting
a render when switching targets and simplifies the model.
The downside is that now we're not down-prioritizing the previous hover
target. However, we think that's ok because it'll only do one level too
much and then stop.
* Add test meant to show why it's tricky to merge both hydration levels
Having both levels co-exist works. However, if we deprioritize hydration
using a single level, we might deprioritize the wrong thing.
This adds a test that catches it if we ever try a naive deprioritization
in the future.
It also tests that we don't down-prioritize if we're changing the hover
in the middle of doing continuous priority work.
* Add test of Event Replaying using Flare
* Fix Event Replaying in Flare by Eagerly Adding Active Listeners
This effectively reverts part of https://github.com/facebook/react/pull/17513