* 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.
Adds a feature flag for when React.jsx warns you about spreading a key into jsx. It's false for all builds, except as a dynamic flag for fb/www.
I also included the component name in the warning.
* Split recent passive effects changes into 2 flags
Separate flags can now be used to opt passive effects into:
1) Deferring destroy functions on unmount to subsequent passive effects flush
2) Running all destroy functions (for all fibers) before create functions
This allows us to test the less risky feature (2) separately from the more risky one.
* deferPassiveEffectCleanupDuringUnmount is ignored unless runAllPassiveEffectDestroysBeforeCreates is true
* 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.
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.
* Flush useEffect clean up functions in the passive effects phase
This is a change in behavior that may cause broken product code, so it has been added behind a killswitch (deferPassiveEffectCleanupDuringUnmount)
* Avoid scheduling unnecessary callbacks for cleanup effects
Updated enqueuePendingPassiveEffectDestroyFn() to check rootDoesHavePassiveEffects before scheduling a new callback. This way we'll only schedule (at most) one.
* Updated newly added test for added clarity.
* Cleaned up hooks effect tags
We previously used separate Mount* and Unmount* tags to track hooks work for each phase (snapshot, mutation, layout, and passive). This was somewhat complicated to trace through and there were man tag types we never even used (e.g. UnmountLayout, MountMutation, UnmountSnapshot). In addition to this, it left passive and layout hooks looking the same after renders without changed dependencies, which meant we were unable to reliably defer passive effect destroy functions until after the commit phase.
This commit reduces the effect tag types to only include Layout and Passive and differentiates between work and no-work with an HasEffect flag.
* Disabled deferred passive effects flushing in OSS builds for now
* Split up unmount and mount effects list traversal
* Add feature flags
* Add Chunk type and constructor
* Wire up Chunk support in the reconciler
* Update reconciler to reconcile Chunks against the render method
This allows the query and args to be updated.
* Drop the ref. Chunks cannot have refs anyway.
* Add Chunk checks in more missing cases
* Rename secondArg
* Add test and fix lazy chunks
Not really a supported use case but for consistency I guess.
* Fix fragment test
There are two similar flags, `debugRenderPhaseSideEffects` and
`debugRenderPhaseSideEffectsForStrictMode`. The strict mode one is the
only one that is actually used. I think originally the theory is that
we would one day turn it on for all components, even outside strict
mode. But what we'll do instead is migrate everyone to strict mode.
The only place `debugRenderPhaseSideEffects` was being used was in
an internal test file. I rewrote those tests to use public APIs.
* Tests run in experimental mode by default
For local development, you usually want experiments enabled. Unless
the release channel is set with an environment variable, tests will
run with __EXPERIMENTAL__ set to `true`.
* Remove concurrent APIs from stable builds
Those who want to try concurrent mode should use the experimental
builds instead.
I've left the `unstable_` prefixed APIs in the Facebook build so we
can continue experimenting with them internally without blessing them
for widespread use.
* Turn on SSR flags in experimental build
* Remove prefixed concurrent APIs from www build
Instead we'll use the experimental builds when syncing to www.
* Remove "canary" from internal React version string
* Don't bother including `unstable_` in error
The method names don't get stripped out of the production bundles
because they are passed as arguments to the error decoder.
Let's just always use the unprefixed APIs in the messages.
* Set up experimental builds
The experimental builds are packaged exactly like builds in the stable
release channel: same file structure, entry points, and npm package
names. The goal is to match what will eventually be released in stable
as closely as possible, but with additional features turned on.
Versioning and Releasing
------------------------
The experimental builds will be published to the same registry and
package names as the stable ones. However, they will be versioned using
a separate scheme. Instead of semver versions, experimental releases
will receive arbitrary version strings based on their content hashes.
The motivation is to thwart attempts to use a version range to match
against future experimental releases. The only way to install or depend
on an experimental release is to refer to the specific version number.
Building
--------
I did not use the existing feature flag infra to configure the
experimental builds. The reason is because feature flags are designed
to configure a single package. They're not designed to generate multiple
forks of the same package; for each set of feature flags, you must
create a separate package configuration.
Instead, I've added a new build dimension called the **release
channel**. By default, builds use the **stable** channel. There's
also an **experimental** release channel. We have the option to add more
in the future.
There are now two dimensions per artifact: build type (production,
development, or profiling), and release channel (stable or
experimental). These are separate dimensions because they are
combinatorial: there are stable and experimental production builds,
stable and experimental developmenet builds, and so on.
You can add something to an experimental build by gating on
`__EXPERIMENTAL__`, similar to how we use `__DEV__`. Anything inside
these branches will be excluded from the stable builds.
This gives us a low effort way to add experimental behavior in any
package without setting up feature flags or configuring a new package.
* Add trusted types to react on client side
* Implement changes according to review
* Remove support for trusted URLs, change TrustedTypes to trustedTypes
* Add support for deprecated trusted URLs
* Apply PR suggesstions
* Warn only once, remove forgotten check, put it behind a flag
* Move comment
* Fix PR comments
* Fix html toString concatenation
* Fix forgotten else branch
* Fix PR comments
When React schedules a rendering task, it passes a `timeout` option
based on its expiration time. This is intended to avoid starvation
by other React updates. However, it also affects the relative priority
of React tasks and other Scheduler tasks at the same level, like
data processing.
This adds a feature flag to disable passing a `timeout` option to
Scheduler. React tasks will always append themselves to the end of
the queue, without jumping ahead of already scheduled tasks.
This does not affect the order in which React updates within a single
root are processed, but it could affect updates across multiple roots.
This also doesn't remove the expiration from Scheduler. It only means
that React tasks are not given special treatment.
* Add a feature flag to disable legacy context
* Address review
- invariant -> warning
- Make this.context and context argument actually undefined
* Increase test coverage for lifecycles
* Also disable it on the server is flag is on
* Make this.context {} when disabled, but function context is undefined
* Move checks inside
In this PR, for tests (specifically, code inside an `act()` scope), we immediately trigger work that would have otherwise required a timeout. This makes it simpler to tests loading/spinner states, and makes tests resilient to changes in React.
For some of our tests(specifically, ReactSuspenseWithNoopRenderer-test.internal), we _don't_ want fallbacks to immediately trigger, because we're testing intermediate states and such. Added a feature flag `flushSuspenseFallbacksInTests` to disable this behaviour on a per case basis.
Concurrent/Batched mode tests should always be run with a mocked scheduler (v17 or not). This PR adds a warning for the same. I'll put up a separate PR to the docs with a page detailing how to mock the scheduler.
This adds a 'SuspenseCallback' feature flag. When the property is set on
a suspense component it will be called during the commit phase with a
set of the immediate thenable for this component. This will allow user
code to build runtime tracing of the cause for a suspense boundary.
* [Events] Add EventPriority enum
React DOM's DispatchConfig for synthetic events has an `isDiscrete`
field that affects how updates triggered by an event are scheduled.
Events are either discrete or continuous.
This commit adds an additional type of configuration where an event
has user-blocking priority, but is not discrete. E.g. updates triggered
by hover are more important than the default, but they don't need to
be processed serially. Because there are now three types of event
priority instead of two, I've replaced the `isDiscrete` boolean with an
enum: `eventPriority`.
This commit implements the new enum value but does not change any
behavior. I'll enable it behind a feature flag in the next commit.
I've only implemented this in the legacy event system. I'll leave Flare
for a follow-up.
* enableUserBlockingEvents feature flag
Adds a feature flag to increase the priority of events like `mouseover`,
without making them discrete.
* s/flushPassiveEffects/unstable_flushWithoutYielding
a first crack at flushing the scheduler manually from inside act(). uses unstable_flushWithoutYielding(). The tests that changed, mostly replaced toFlushAndYield(...) with toHaveYielded(). For some tests that tested the state of the tree before flushing effects (but still after updates), I replaced act() with bacthedUpdates().
* ugh lint
* pass build, flushPassiveEffects returns nothing now
* pass test-fire
* flush all work (not just effects), add a compatibility mode
of note, unstable_flushWithoutYielding now returns a boolean much like flushPassiveEffects
* umd build for scheduler/unstable_mock, pass the fixture with it
* add a comment to Shcduler.umd.js for why we're exporting unstable_flushWithoutYielding
* run testsutilsact tests in both sync/concurrent modes
* augh lint
* use a feature flag for the missing mock scheduler warning
I also tried writing a test for it, but couldn't get the scheduler to unmock. included the failing test.
* Update ReactTestUtilsAct-test.js
- pass the mock scheduler warning test,
- rewrite some tests to use Scheduler.yieldValue
- structure concurrent/legacy suites neatly
* pass failing tests in batchedmode-test
* fix pretty/lint/import errors
* pass test-build
* nit: pull .create(null) out of the act() call
PR #15650 is a bugfix but it's technically a semantic change that could
cause regressions. I don't think it will be an issue, since the
previous behavior was both broken and incoherent, but out of an
abundance of caution, let's wrap it in a flag so we can easily revert
it if necessary.