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.
The changes to the test code relate to changes in JSDOM that come with Jest 25:
* Several JSDOM workarounds are no longer needed.
* Several tests made assertions to match incorrect JSDOM behavior (e.g. setAttribute calls) that JSDOM has now patched to match browsers.
* https://codesandbox.io/s/resets-value-of-datetime-input-to-fix-bugs-in-ios-safari-1ppwh
* JSDOM no longer triggers default actions when dispatching click events.
* https://codesandbox.io/s/beautiful-cdn-ugn8f
* JSDOM fixed (jsdom/jsdom#2700) a bug so that calling focus() on an already focused element does not dispatch a FocusEvent.
* JSDOM now supports passive events.
* JSDOM has improved support for custom CSS properties.
* But requires jsdom/cssstyle#112 to land to support webkit prefixed properties.
* Update Flow to 0.84
* Fix violations
* Use inexact object syntax in files from fbsource
* Fix warning extraction to use a modern parser
* Codemod inexact objects to new syntax
* Tighten types that can be exact
* Revert unintentional formatting changes from codemod
* Updated DevTools local development instructions to mention experimental build step
* Added a command to download latest experimental release (for DevTools)
* Updated build instructions for clarity
* Added build-for-devtools package alias
* Skip abandoned project folders in Jest config
This fixes a problem that occurs after renaming a package.
* Fix test_build_devtools to run test-build-devtools
* Exclude console.error plugin for DevTools packages
* Use correct release channel for DevTools tests
This should fix the createRoot error.
* Fix TZ dependent test
* Change DT job dependencies
* Replace all warning/lowPriWarning with console calls
* Replace console.warn/error with a custom wrapper at build time
* Fail the build for console.error/warn() where we can't read the stack
* prep for codemod
* prep warnings
* rename lint rules
* codemod for ifs
* shim www functions
* Handle more cases in the transform
* Thanks De Morgan
* Run the codemod
* Delete the transform
* Fix up confusing conditions manually
* Fix up www shims to match expected API
* Also check for low-pri warning in the lint rule
* Replace Babel plugin with an ESLint plugin
* Fix ESLint rule violations
* Move shared conditions higher
* Test formatting nits
* Tweak ESLint rule
* Bugfix: inside else branch, 'if' tests are not satisfactory
* Use a stricter check for exactly if (__DEV__)
This makes it easier to see what's going on and matches dominant style in the codebase.
* Fix remaining files after stricter check
* Move Flight DOM to Webpack Specific Packagee
We'll have Webpack specific coupling so we need to ensure that it can be
versioned separately from various Webpack versions. We'll also have builds
for other bundlers in the future.
* Move to peerDep
* Move DOM Flight Tests
* Merge ReactFlightIntegration into ReactFlightDOM
This was an integration test. We can add to it.
* Fix fixture paths
* Rename ReactFlightStreamer -> ReactFlightServer
* Unify Browser/Node stream tests into one file and use the client reader
* Defer to the actual ReactDOM for HTML rendering for now
This will need to use a variant of Fizz to do inline SSR in Flight.
However, I don't want to build the whole impl right now but also don't
want to exclude the use case yet. So I outsource it to the existing
renderer. Ofc, this doesn't work with Suspense atm.
* Change demo to server
* Expose client in package.json
* Reorganize tests
We don't want unit tests but instead test how both server and clients work
together. So this merges server/client test files.
* Fill in the client implementation a bit
* Use new client in fixture
* Add Promise/Uint8Array to lint rule
I'll probably end up deleting these deps later but they're here for now.
* Add Flight Build and Unify HostFormat Config between Flight and Fizz
* Add basic resolution of models
* Add basic Flight fixture
Demonstrates the streaming protocol.
* Rename to flight-server to distinguish from the client parts
* Add Flight Client package and entry point
* Fix fixture
Special version of Jest's `it` for experimental tests. Tests marked as
experimental will run **both** stable and experimental modes. In
experimental mode, they work the same as the normal Jest methods. In
stable mode, they are **expected to fail**. This means we can detect
when a test previously marked as experimental can be un-marked when the
feature becomes stable. It also reduces the chances that we accidentally
add experimental APIs to the stable builds before we intend.
I added corresponding methods for the focus and skip APIs:
- `fit` -> `fit.experimental`
- `it.only` -> `it.only.experimental` or `it.experimental.only`
- `xit` -> `xit.experimental`
- `it.skip` -> `it.skip.experimental` or `it.experimental.skip`
Since `it` is an alias of `test`, `test.experimental` works, too.
`yarn build` defaults to building in experimental mode. To opt-out, set
the `RELEASE_CHANNEL` environment variable to `stable`. This is the same
as what we do when running tests via `yarn test`, to make local
development easier.
* 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
* Download correct artifacts for release channel
Experimental builds should pull artifacts from the
`process_artifacts_experimental` job.
I think instead of two separate CI workflows, a better approach might
be to build stable artifacts to the `build` directory and the
experimental artifacts to a `build_experimental` directory, and
generate both within the same workflow. This would take some work since
lots of things assume the output directory is `build`, but something
to consider in the future.
* Prevent experimental promotion to stable
Adds a check to the `prepare-stable` script to prevent experimental
builds from being published using stable semver versions.
* 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.
* Remove "Invariant Violation" from dev errors
When I made the change to compile `invariant` to throw expressions, I
left a small runtime to set the error's `name` property to "Invariant
Violation" to maintain the existing behavior.
I think we can remove it. The argument for keeping it is to preserve
continuity in error logs, but this only affects development errors,
anyway: production error messages are replaced with error codes.
* Pass prod error messages directly to constructor
Updates the `invariant` transform to pass an error message string
directly to the Error constructor, instead of mutating the
message property.
Turns this code:
```js
invariant(condition, 'A %s message that contains %s', adj, noun);
```
into this:
```js
if (!condition) {
throw Error(
__DEV__
? `A ${adj} message that contains ${noun}`
: formatProdErrorMessage(ERR_CODE, adj, noun)
);
}
```
The error transform works by replacing calls to `invariant` with
an `if` statement.
Since we're replacing a call expression with a statement, Babel wraps
the new statement in an immediately-invoked function expression (IIFE).
This wrapper is unnecessary in practice because our `invariant` calls
are always part of their own expression statement.
In the production bundle, the function wrappers are removed by Closure.
But they remain in the development bundles.
This commit updates the transform to confirm that an `invariant` call
expression's parent node is an expression statement. (If not, it throws
a transform error.)
Then, it replaces the expression statement instead of the expression
itself, effectively removing the extraneous IIFE wrapper.
* Rename lowPriorityWarning to lowPriorityWarningWithoutStack
This maintains parity with the other warning-like functions.
* Duplicate the toWarnDev tests to test toLowPriorityWarnDev
* Make a lowPriorityWarning version of warning.js
* Extract both variants in print-warning
Avoids parsing lowPriorityWarning.js itself as the way it forwards the
call to lowPriorityWarningWithoutStack is not analyzable.
* Idle updates should not be blocked by hidden work
Use the special `Idle` expiration time for updates that are triggered at
Scheduler's `IdlePriority`, instead of `Never`.
The key difference between Idle and Never¹ is that Never work can be
committed in an inconsistent state without tearing the UI. The main
example is offscreen content, like a hidden subtree.
¹ "Never" isn't the best name. I originally called it that because it
"never" expires, but neither does Idle. Since it's mostly used for
offscreen subtrees, we could call it "Offscreen." However, it's also
used for dehydrated Suspense boundaries, which are inconsistent in the
sense that they haven't finished yet, but aren't visibly inconsistent
because the server rendered HTML matches what the hydrated tree would
look like.
* Reset as early as possible using local variable
* Updates in a hidden effect should be Idle
I had made them Never to avoid an extra render when a hidden effect
updates the hidden component -- if they are Idle, we have to render once
at Idle, which bails out on the hidden subtree, then again at Never to
actually process the update -- but the problem of needing an extra
render pass to bail out hidden updates already exists and we should fix
that properly instead of adding yet another special case.
* Outline push/pop logic in `renderRoot`
I want to get rid of the the `isSync` argument to `renderRoot`, and
instead use separate functions for concurrent and synchronous render.
As a first step, this extracts the push/pop logic that happens before
and after the render phase into helper functions.
* Extract `catch` block into helper function
Similar to previous commit. Extract error handling logic into
a separate function so it can be reused.
* Fork `renderRoot` for sync and concurrent
Removes `isSync` argument in favor of separate functions.
* Extra "root completion" logic to separate function
Moving this out to avoid an accidental early return, which would
bypass the call to `ensureRootIsScheduled` and freeze the UI.
* Inline `renderRoot`
Inlines `renderRoot` into `performConcurrentWorkOnRoot` and
`performSyncWorkOnRoot`. This lets me remove the `isSync` argument
and also get rid of a redundant try-catch wrapper.
* [suspense][error handling] Add failing unit test
Covers an edge case where an error is thrown inside the complete phase
of a component that is in the return path of a component that suspends.
The second error should also be handled (i.e. able to be captured by
an error boundary.
The test is currently failing because there's a call to
`completeUnitOfWork` inside the main render phase `catch` block. That
call is not itself wrapped in try-catch, so anything that throws is
treated as a fatal/unhandled error.
I believe this bug is only observable if something in the host config
throws; and, only in legacy mode, because in concurrent/batched mode,
`completeUnitOfWork` on fiber that throws follows the "unwind" path
only, not the "complete" path, and the "unwind" path does not call
any host config methods.
* [scheduler][profiler] Start time of delayed tasks
Fixes a bug in the Scheduler profiler where the start time of a delayed
tasks is always 0.
* Remove ad hoc `throw`
Fatal errors (errors that are not captured by an error boundary) are
currently rethrown from directly inside the render phase's `catch`
block. This is a refactor hazard because the code in this branch has
to mirror the code that happens at the end of the function, when exiting
the render phase in the normal case.
This commit moves the throw to the end, using a new root exit status.
* Handle errors that occur on unwind
This is because the HostConfig can't be guaranteed to be consistent with
other code such as code that touches the DOM directly.
Ideally we'd have a more systemic solution to this since it will pop
up for other packages later too.
This implements 'usePress' in user-space as a combination of 'useKeyboard' and 'useTap'. The existing 'usePress' API is preserved for now. The previous 'usePress' implementation is moved to 'PressLegacy'.
* 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
If a Scheduler profile runs without stopping, the event log will grow
unbounded. Eventually it will run out of memory and the VM will throw
an error.
To prevent this from happening, let's automatically stop the profiler
once the log exceeds a certain limit. We'll also print a warning with
advice to call `stopLoggingProfilingEvents` explicitly.
* Don't invoke listeners on parent of dehydrated event target
* Move Suspense boundary check to getClosestInstanceFromNode
Now getClosestInstanceFromNode can return either a host component,
host text component or suspense component when the suspense
component is dehydrated.
We then use that to ignore events on a suspense component.
* Attach the HostRoot fiber to the DOM container
This lets us detect if an event happens on this root's subtree before it
has rendered something.
* Add todo
The approach of checking isFiberMounted answers if we might be in an
in-progress hydration but it doesn't answer which root or boundary
might be in-progress so we don't know what to wait for.
This needs some refactoring.
* Refactor isFiberMountedImpl to getNearestMountedFiber
We'll need the nearest boundary for event replaying so this prepares for
that.
This surfaced an issue that we attach Hydrating tag on the root but normally
this (and Placement) is attached on the child. This surfaced an issue
that this can lead to both Placement and Hydrating effects which is not
supported so we need to ensure that we only ever use one or the other.
* Add todo for bug I spotted
* Cache tags
* Check the ContainerInstanceKey before the InstanceKey
The container is inside the instance, so we must find it before the
instance, since otherwise we'll miss it.
This is a partial replacement for the 'Press' responder:
1. `useTap` is scoped to pointers (no keyboard support). Our current thinking is
that "responders" should be limited to working with pointers, and that they can
be combined with 'useKeyboard' in user-space. For example, we might create a
'usePress' hook in user-space that combines 'useTap' with 'useKeyboard' to react
to both pointers and keyboard interactions.
2. `useTap` cancels the gesture once the pointer moves over an element that is
not within the responder target's subtree. This differs from `usePress` (and
React Native), where the gesture remains active after the pointer exits the
target's subtree and is restarted once the pointer reenters. One of the
drawbacks with the `usePress` behavior is that it requires repeatedly measuring
DOM elements (which can cause jank) to perform hit region tests. `useTap` avoids
doing this and relies on `document.elementFromPoint` only to support the
TouchEvent fallbacks.
3. `useTap` calls `onTapUpdate` when the active gesture's state changes,
`onTapEnd` when the gesture successfully completes. and `onTapCancel` when it
fails. There is no `onTap` callback. `usePress` did not explicitly report back
when the gesture failed, and product developers were confused about the
difference between `onPress` and `onPressEnd`.
4. `useTap` explicitly separates the PointerEvent implementation from the
MouseEvent/TouchEvent fallback.
5. `useTap` has better unit test coverage . All pointer types and the fallback
environment are tested. The shape of the gesture state object is also defined
and tested.
* Revert "Revert "[Scheduler] Profiling features (#16145)" (#16392)"
This reverts commit 4ba1412305.
* Fix copy paste mistake
* Remove init path dependency on ArrayBuffer
* Add a regression test for cancelling multiple tasks
* Prevent deopt from adding isQueued later
* Remove pop() calls that were added for profiling
* Verify that Suspend/Unsuspend events match up in tests
This currently breaks tests.
* Treat Suspend and Resume as exiting and entering work loop
Their definitions used to be more fuzzy. For example, Suspend didn't always fire on exit, and sometimes fired when we did _not_ exit (such as at task enqueue).
I chatted to Boone, and he's saying treating Suspend and Resume as strictly exiting and entering the loop is fine for their use case.
* Revert "Prevent deopt from adding isQueued later"
This reverts commit 9c30b0b695.
Unnecessary because GCC
* Start counter with 1
* Group exports into unstable_Profiling namespace
* No catch in PROD codepath
* No label TODO
* No null checks
* [Scheduler] Mark user-timing events
Marks when Scheduler starts and stops running a task. Also marks when
a task is initially scheduled, and when Scheduler is waiting for a
callback, which can't be inferred from a sample-based JavaScript CPU
profile alone.
The plan is to use the user-timing events to build a Scheduler profiler
that shows how the lifetime of tasks interact with each other and
with unscheduled main thread work.
The test suite works by printing an text representation of a
Scheduler flamegraph.
* Expose shared array buffer with profiling info
Array contains
- the priority Scheduler is currently running
- the size of the queue
- the id of the currently running task
* Replace user-timing calls with event log
Events are written to an array buffer using a custom instruction format.
For now, this is only meant to be used during page start up, before the
profiler worker has a chance to start up. Once the worker is ready, call
`stopLoggingProfilerEvents` to return the log up to that point, then
send the array buffer to the worker.
Then switch to the sampling based approach.
* Record the current run ID
Each synchronous block of Scheduler work is given a unique run ID. This
is different than a task ID because a single task will have more than
one run if it yields with a continuation.
* Move dehydrated to be child of regular SuspenseComponent
We now store the comment node on SuspenseState instead and that indicates
that this SuspenseComponent is still dehydrated.
We also store a child but that is only used to represent the DOM node for
deletions and getNextHostSibling.
* Move logic from DehydratedSuspenseComponent to SuspenseComponent
Forked based on SuspenseState.dehydrated instead.
* Retry logic for dehydrated boundary
We can now simplify the logic for retrying dehydrated boundaries without
hydrating. This is becomes simply a reconciliation against the dehydrated
fragment which gets deleted, and the new children gets inserted.
* Remove dehydrated from throw
Instead we use the regular Suspense path. To save code, we attach retry
listeners in the commit phase even though technically we don't have to.
* Pop to nearest Suspense
I think this is right...?
* Popping hydration state should skip past the dehydrated instance
* Split mount from update and special case suspended second pass
The DidCapture flag isn't used consistently in the same way. We need
further refactor for this.
* Reorganize update path
If we remove the dehydration status in the first pass and then do a second
pass because we suspended, then we need to continue as if it didn't
previously suspend. Since there is no fragment child etc.
However, we must readd the deletion.
* Schedule context work on the boundary and not the child
* Warn for Suspense hydration in legacy mode
It does a two pass render that client renders the content.
* Rename DehydratedSuspenseComponent -> DehydratedFragment
This now doesn't represent a suspense boundary itself. Its parent does.
This Fiber represents the fragment around the dehydrated content.
* Refactor returns
Avoids the temporary mutable variables. I kept losing track of them.
* Add a comment explaining the type.
Placing it in the type since that's the central point as opposed to spread
out.
Upgraded from Babel 6 to Babel 7.
The only significant change seems to be the way `@babel/plugin-transform-classes` handles classes differently from `babel-plugin-transform-es2015-classes`. In regular mode, the former injects a `_createClass` function that increases the bundle size, and in the latter it removes the safeguard checks. However, this is okay because we don't all classes in new features, and we want to deprecate class usage in the future in the react repo.
Co-authored-by: Luna Ruan <luna@fb.com>
Co-authored-by: Abdul Rauf <abdulraufmujahid@gmail.com>
Co-authored-by: Maksim Markelov <maks-markel@mail.ru>
We have behaviour divergence for act() between prod and dev (specifically, act() + concurrent mode does not flush fallbacks in prod. This doesn't affect anyone in OSS yet)
We also don't have a good story for writing tests in prod (and what from what I gather, nobody really writes tests in prod mode).
We could have wiped out act() in prod builds, except that _we_ ourselves use act() for our tests when we run them in prod mode.
This PR is a compromise to all of this. We will log a warning if you try to use act() in prod mode, and we silence it in our test suites.
- redoes #15431 from scratch, taking on the feedback there
- unifies the messaging between "deprecated" and UNSAFE_ lifecycle messages. It reorganizes ReactStrictModeWarnings.js to capture and flush all the lifecycle warnings in one procedure each.
- matches the warning from ReactPartialRenderer to match the above change
- passes all the tests
- this also turns on `warnAboutDeprecatedLifecycles` for the test renderer. I think we missed doing so it previously. In a future PR, I'll remove the feature flag altogether.
- this DOES NOT do the same treatment for context warnings, I'll do that in another PR too
This commit is a follow-up to https://github.com/facebook/react/pull/15604, which explains more of the rationale behind moving React Native to path-based imports and the work needed in the React repository. In that linked PR, the generated renderers were updated but not the shims; this commit updates the shims.
The problem is that FB needs a different copy of the built renderers than the OSS versions so we need a way for FB code to import different modules than in OSS. This was previously done with Haste, but with the removal of Haste from RN, we need another mechanism. Talking with cpojer, we are using a `.fb.js` extension that Metro can be configured to prioritize over `.js`.
This commit generates FB's renderers with the `.fb.js` extension and OSS renderers with just `.js`. This way, FB can internally configure Metro to use the `.fb.js` implementations and OSS will use the `.js` ones, letting us swap out which implementation gets bundled.
Test Plan: Generated the renderers and shims with `yarn build` and then verified that the generated shims don't contain any Haste-style imports. Copied the renderers and shims into RN manually and launched the RNTester app to verify it loads end-to-end. Added `.fb.js` to the extensions in `metro.config.js` and verified that the FB-specific bundles loaded.
The previous naming scheme used the name of the resulting bundle file.
However, there are cases where multiple bundles have the same filename.
This meant whichever bundle finishes last overwrites the previous ones
with the same name.
The updated naming scheme is `bundle-sizes-<CI_NODE_INDEX>.json`.
Instead of generating a separate info file per bundle, it now creates
one per process.
* Write size info to separate file per bundle
`bundle-sizes.json` contains the combined size information for every
build. This makes it easier to store and process, but it prevents us
from parallelizing the build script, because each process would need to
write to the same file.
So I've updated the Rollup script to output individual files per build.
A downstream CI job consolidates them into a single file.
I have not parallelized the Rollup script yet. I'll do that next.
* Parallelize the build script
Uses CircleCI's `parallelism` config option to spin up multiple build
processes.
Removes `--extract-errors` argument from CI build script command.
Instead, the author is expected to run `yarn extract-errors` locally
or manually edit the error code map.
The lint rule should be sufficient to catch unminified errors, but
as an extra precaution, I added a post-build step that greps the
production bundles. The post-build step works even if someone disables
the lint rule for a specific line or file.
* Lint rule for unminified errors
Add a lint rule that fails if an invariant message is not part of the
error code map.
The goal is to be more disciplined about adding and modifiying
production error codes. Error codes should be consistent across releases
even if their wording changes, for continuity in logs.
Currently, error codes are added to the error code map via an automated
script that runs right before release. The problem with this approach is
that if someone modifies an error message in the source, but neglects to
modify the corresponding message in the error code map, then the message
will be assigned a new error code, instead of reusing the existing one.
Because the error extraction script only runs before a release, people
rarely modify the error code map in practice. By moving the extraction
step to the PR stage, it forces the author to consider whether the
message should be assigned a new error code. It also allows the reviewer
to review the changes.
The trade off is that it requires more effort and context to land new
error messages, or to modify existing ones, particular for new
contributors who are not familiar with our processes.
Since we already expect users to lint their code, I would argue the
additional burden is marginal. Even if they forget to run the lint
command locally, they will get quick feedback from the CI lint job,
which typically finishes within 2-3 minutes.
* Add unreleased error messages to map
* [react-native] Use path-based imports instead of Haste for the RN renderer
To move React Native to standard path-based imports instead of Haste, the RN renderer that is generated from the code in this repo needs to use path-based imports as well since the generated code is vendored by RN. This commit makes it so the interface between the generated renderers and RN does not rely on Haste and instead uses a private interface explicitly defined by RN. This inverts control of the abstraction so that RN decides the internals to export rather than React deciding what to import.
On RN's side, a new module named `react-native/Libraries/ReactPrivate/ReactNativePrivateInterface` explicitly exports the modules used by the renderers in this repo. (There is also a private module for InitializeCore so that we can import it just for the side effects.) On React's side, the various renderer modules access RN internals through the explicit private interface.
The Rollup configuration becomes slimmer since the only external package is now `react-native`, and the individual modules are instead listed out in `ReactNativePrivateInterface`.
Task description: https://github.com/facebook/react-native/issues/24770
Sister RN PR (needs to land before this one): https://github.com/facebook/react-native/pull/24782
Test Plan: Ran unit tests and Flow in this repo. Generated the renderers and manually copied them over to the RN repo. Ran the RN tests and launched the RNTester app.
* Access natively defined "nativeFabricUIManager" instead of importing it
Some places in the Fabric renderers access `nativeFabricUIManager` (a natively defined global) instead of importing UIManager. While this is coupling across repos that depends on the timing of events, it is necessary until we have a way to defer top-level imports to run after `nativeFabricUIManager` is defined. So for consistency we use `nativeFabricUIManager` everywhere (see the comment in https://github.com/facebook/react/pull/15604#pullrequestreview-236842223 for more context).
Updates the CircleCI config to use the workflows features to run jobs in
parallel, instead of the `parallelism` option. This change alone doesn't
improve the overall build time much, since almost all of the total time
is spent running the Rollup script, which runs entirely sequentially.
But it does improve reporting, and should make it easier to add
additional parallel jobs in the future.
* Add a stub for React Fresh Babel plugin package
* Move ReactFresh-test into ReactFresh top level directory
* Add a stub for React Fresh Runtime entry point
* Extract Fresh runtime from tests into its entry point
* 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
If React finishes rendering a tree, delays committing it (e.g.
Suspense), then subsequently starts over or renders a new tree, the
pending tree is no longer valid. That's because rendering a new work-in
progress mutates the old one in place.
The current structure of the work loop makes this hard to reason about
because, although `renderRoot` and `commitRoot` are separate functions,
they can't be interleaved. If they are interleaved by accident, it
either results in inconsistent render output or invariant violations
that are hard to debug.
This commit adds an invariant that throws if the new tree is the same as
the old one. This won't prevent all bugs of this class, but it should
catch the most common kind.
To implement the invariant, I store the finished tree on a field on the
root. We already had a field for this, but it was only being used for
the unstable `createBatch` feature.
A more rigorous way to address this type of problem could be to unify
`renderRoot` and `commitRoot` into a single function, so that it's
harder to accidentally interleave the two phases. I plan to do something
like this in a follow-up.
* [React Native] Inline calls to FabricUIManager in shared code
* Call global.nativeFabricUIManager directly as short term fix
* Add flow types
* Add nativeFabricUIManager global to eslint config
* Adding eslint global to bundle validation script
The React Native build does not minify error messages in production,
but it still needs to run the error messages transform to compile
`invariant` calls to `ReactError`. To do this, I added a `noMinify`
option to the Babel plugin. I also renamed it from
`minify-error-messages` to the more generic `transform-error-messages`.
* [React Native] Add tests to paper renderer for measure, measureLayout
* [React Native] measure calls will now call FabricUIManager
The Fabric renderer was previously calling the paper UIManager's measure calls and passing the react tag. This PR changes the renderer to now call FabricUIManager passing the node instead.
One of the parts of this that feels more controversial is making NativeMethodsMixin and ReactNative.NativeComponent warn when calling measureLayout in Fabric. As Seb and I decided in https://github.com/facebook/react/pull/15126, it doesn't make sense for a component created with one of these methods to require a native ref but not work the other way around. For example: a.measureLayout(b) might work but b.measureLayout(a) wouldn't. We figure we should keep these consistent and continue migrating things off of NativeMethodsMixin and NativeComponent.
If this becomes problematic for the Fabric rollout then we should revisit this.
* Fixing Flow
* Add FabricUIManager to externals for paper renderer
* import * as FabricUIManager from 'FabricUIManager';
* Update tests
* Shouldn't have removed UIManager import
* Update with the new tests
* Store FB bundles as CI artifacts
Updates the Circle CI config to store Facebook bundles as build
artifacts. We already do this for our npm packages.
* Might as well store everything in build/
* Store build directory as a tarball
So it's easy to download
* Rewrite ReactFiberScheduler
Adds a new implementation of ReactFiberScheduler behind a feature flag.
We will maintain both implementations in parallel until the new one
is proven stable enough to replace the old one.
The main difference between the implementations is that the new one is
integrated with the Scheduler package's priority levels.
* Conditionally add fields to FiberRoot
Some fields only used by the old scheduler, and some by the new.
* Add separate build that enables new scheduler
* Re-enable skipped test
If synchronous updates are scheduled by a passive effect, that work
should be flushed synchronously, even if flushPassiveEffects is
called inside batchedUpdates.
* Passive effects have same priority as render
* Revert ability to cancel the current callback
React doesn't need this anyway because it never schedules callbacks if
it's already rendering.
* Revert change to FiberDebugPerf
Turns out this isn't neccessary.
* Fix ReactFiberScheduler dead code elimination
Should initialize to nothing, then assign the exports conditionally,
instead of initializing to the old exports and then reassigning to the
new ones.
* Don't yield before commit during sync error retry
* Call Scheduler.flushAll unconditionally in tests
Instead of wrapping in enableNewScheduler flag.
This took a while, but I'm happy I went through it. Some key moments - recursively flushing effects, flushing microtasks on each async turn, and my team's uncompromising philosophy on code reuse. Really happy with this. I still want to expand test coverage, and I have some more small related todos, but this is good to land. On to the next one.
Soundtrack to landing this - https://open.spotify.com/track/0MF8I8OUo8kytiOo8aSHYq?si=gSWqUheKQbiQDXzptCXHTg
* hacked up act(async () => {...})
* move stuff around
* merge changes
* abstract .act warnings and stuff. all renderers. pass all tests.
* move testutils.act back into testutils
* move into scheduler, rename some bits
* smaller bundle
* a comment for why we don't do typeof === 'function'
* fix test
* pass tests - fire, prod
* lose actContainerElement
* tighter
* write a test for TestRenderer
it's an odd one, because not only does sync act not flush effects correctly, but the async one does (wut). verified it's fine with the dom version.
* lint
* rewrote to move flushing logic closer to the renderer
the scheduler's `flushPassiveEffects` didn't work as expected for the test renderer, so I decided to go back to the hack (rendering a dumb container) This also makes reactdom not as heavy (by a few bytes, but still).
* move it around so the delta isn't too bad
* cleanups
fix promise chaining
propagate errors correctly
test for thenable the 'right' way
more tests!
tidier!
ponies!
* Stray comment
* recursively flush effects
* fixed tests
* lint, move noop.act into react-reconciler
* microtasks when checking if called, s/called/calledLog, cleanup
* pass fb lint
we could have globally changed our eslint config to assume Promise is available, but that means we expect a promise polyfill on the page, and we don't yet. this code is triggered only in jest anyway, and we're fairly certain Promise will be available there. hence, the once-off disable for the check
* shorter timers, fix a test, test for Promise
* use global.Promise for existence check
* flush microtasks
* a version that works in browsers (that support postMessage)
I also added a sanity fixture inside fixtures/dom/ mostly for me.
* hoist flushEffectsAndMicroTasks
* pull out tick logic from ReactFiberScheduler
* fix await act (...sync) hanging
- fix a hang when awaiting sync logic
- a better async/await test for test renderer
* feedback changes
- use node's setImmediate if available
- a warning if MessageChannel isn't available
- rename some functions
* pass lint/flow checks (without requiring a Promise polyfill/exclusion)
* prettier
the prettiest, even.
* use globalPromise for the missed await warning
* __DEV__ check for didWarnAboutMessageChannel
* thenables and callbacks instead of promises, pass flow/lint
* tinier. better.
- pulled most bits out of FiberScheduler
- actedUpdates uses callbacks now
* pass build validation
* augh prettier
* golfing 7 more chars
* Test that effects are not flushed without also flushing microtasks
* export doesHavePendingPassiveEffects, nits
* createAct()
* dead code
* missed in merge?
* lose the preflushing bits
* ugh prettier
* removed `actedUpdates()`, created shared/actingUpdatesScopeDepth
* rearrange imports so builds work, remove the hack versions of flushPassiveEffects
* represent actingUpdatesScopeDepth as a tuple [number]
* use a shared flag on React.__SECRET...
* remove createAct, setup act for all relevant renderers
* review feedback
shared/enqueueTask
import ReactSharedInternals from 'shared/ReactSharedInternals';
simpler act() internals
ReactSharedInternals.ReactShouldWarnActingUpdates
* move act() implementation into createReactNoop
* warnIfNotCurrentlyActingUpdatesInDev condition check order
Adds a feature flag `enableNewScheduler` that toggles between two
implementations of ReactFiberScheduler. This will let us land changes in
master while preserving the ability to quickly rollback.
Ideally this will be a short-lived fork. Once we've tested the new
scheduler for a week or so without issues, we will get rid of it. Until
then, we'll need to maintain two parallel implementations and run tests
against both of them. We rarely land changes to ReactFiberScheduler, so
I don't expect this will be a huge burden.
This commit does not implement anything new. The flag is still off and
tests run against the existing implementation.
Use `yarn test-new-scheduler` to run tests against the new one.
* Transform invariant to custom error type
This transforms calls to the invariant module:
```js
invariant(condition, 'A %s message that contains %s', adj, noun);
```
Into throw statements:
```js
if (!condition) {
if (__DEV__) {
throw ReactError(`A ${adj} message that contains ${noun}`);
} else {
throw ReactErrorProd(ERR_CODE, adj, noun);
}
}
```
The only thing ReactError does is return an error whose name is set
to "Invariant Violation" to match the existing behavior.
ReactErrorProd is a special version used in production that throws
a minified error code, with a link to see to expanded form. This
replaces the reactProdInvariant module.
As a next step, I would like to replace our use of the invariant module
for user facing errors by transforming normal Error constructors to
ReactError and ReactErrorProd. (We can continue using invariant for
internal React errors that are meant to be unreachable, which was the
original purpose of invariant.)
* Use numbers instead of strings for error codes
* Use arguments instead of an array
I wasn't sure about this part so I asked Sebastian, and his rationale
was that using arguments will make ReactErrorProd slightly slower, but
using an array will likely make all the functions that throw slightly
slower to compile, so it's hard to say which way is better. But since
ReactErrorProd is in an error path, and fewer bytes is generally better,
no array is good.
* Casing nit
* Add command to run tests in persistent mode
* Convert Suspense fuzz tester to use noop renderer
So we can run it in persistent mode, too.
* Don't mutate stateNode in appendAllChildren
We can't mutate the stateNode in appendAllChildren because the children
could be current.
This is a bit weird because now the child that we append is different
from the one on the fiber stateNode. I think this makes conceptual
sense, but I suspect this likely breaks an assumption in Fabric.
With this approach, we no longer need to clone to unhide the children,
so I removed those host config methods.
Fixes bug surfaced by fuzz tester. (The test case that failed was the
one that's already hard coded.)
* In persistent mode, disable test that reads a ref
Refs behave differently in persistent mode. I added a TODO to write
a persistent mode version of this test.
* Run persistent mode tests in CI
* test-persistent should skip files without noop
If a file doesn't reference react-noop-renderer, we shouldn't bother
running it in persistent mode, since the results will be identical to
the normal test run.
* Remove module constructor from placeholder tests
We don't need this now that we have the ability to run any test file in
either mutation or persistent mode.
* Revert "test-persistent should skip files without noop"
Seb objected to adding shelljs as a dep and I'm too lazy to worry about
Windows support so whatever I'll just revert this.
* Delete duplicate file
* Swap expect(ReactNoop) for expect(Scheduler)
In the previous commits, I upgraded our custom Jest matchers for the
noop and test renderers to use Scheduler under the hood.
Now that all these matchers are using Scheduler, we can drop
support for passing ReactNoop and test roots and always pass
Scheduler directly.
* Externalize Scheduler in noop and test bundles
I also noticed we don't need to regenerator runtime in noop anymore.
* Replace test renderer's fake Scheduler implementation with mock build
The test renderer has its own mock implementation of the Scheduler
interface, with the ability to partially render work in tests. Now that
this functionality has been lifted into a proper mock Scheduler build,
we can use that instead.
* Fix Profiler tests in prod
* Replace noop's fake Scheduler implementation with mock Scheduler build
The noop renderer has its own mock implementation of the Scheduler
interface, with the ability to partially render work in tests. Now that
this functionality has been lifted into a proper mock Scheduler build,
we can use that instead.
Most of the existing noop tests were unaffected, but I did have to make
some changes. The biggest one involved passive effects: previously, they
were scheduled on a separate queue from the queue that handles
rendering. After this change, both rendering and effects are scheduled
in the Scheduler queue. I think this is a better approach because tests
no longer have to worry about the difference; if you call `flushAll`,
all the work is flushed, both rendering and effects. But for those few
tests that do care to flush the rendering without the effects, that's
still possible using the `yieldValue` API.
Follow-up: Do the same for test renderer.
* Fix import to scheduler/unstable_mock
* Add new mock build of Scheduler with flush, yield API
Test environments need a way to take control of the Scheduler queue and
incrementally flush work. Our current tests accomplish this either using
dynamic injection, or by using Jest's fake timers feature. Both of these
options are fragile and rely too much on implementation details.
In this new approach, we have a separate build of Scheduler that is
specifically designed for test environments. We mock the default
implementation like we would any other module; in our case, via Jest.
This special build has methods like `flushAll` and `yieldValue` that
control when work is flushed. These methods are based on equivalent
methods we've been using to write incremental React tests. Eventually
we may want to migrate the React tests to interact with the mock
Scheduler directly, instead of going through the host config like we
currently do.
For now, I'm using our custom static injection infrastructure to create
the two builds of Scheduler — a default build for DOM (which falls back
to a naive timer based implementation), and the new mock build. I did it
this way because it allows me to share most of the implementation, which
isn't specific to a host environment — e.g. everything related to the
priority queue. It may be better to duplicate the shared code instead,
especially considering that future environments (like React Native) may
have entirely forked implementations. I'd prefer to wait until the
implementation stabilizes before worrying about that, but I'm open to
changing this now if we decide it's important enough.
* Mock Scheduler in bundle tests, too
* Remove special case by making regex more restrictive
* Throw in tests if work is done before emptying log
Test renderer already does this. Makes it harder to miss unexpected
behavior by forcing you to assert on every logged value.
* Convert ReactNoop tests to use jest matchers
The matchers warn if work is flushed while the log is empty. This is
the pattern we already follow for test renderer. I've used the same APIs
as test renderer, so it should be easy to switch between the two.
* Improve release script process documentation
* Improved pre-publish instructions/message based on feedback
* Added reminder to attach build artifacts to GitHub release
* Memoize promise listeners to prevent exponential growth
Previously, React would attach a new listener every time a promise is
thrown, regardless of whether the same listener was already attached
during a previous render. Because React attempts to render every time
a promise resolves, the number of listeners grows quickly.
This was especially bad in synchronous mode because the renders that
happen when the promise pings are not batched together. So if a single
promise has multiple listeners for the same root, there will be multiple
renders, which in turn results in more listeners being added to the
remaining unresolved promises. This results in exponential growth in
the number of listeners with respect to the number of IO-bound
components in a single render.
Fixes#14220
* Memoize on the root and Suspense fiber instead of on the promise
* Add TODO to fix persistent mode tests
* [Fizz] Add Flow/Jest/Rollup build infra
Add a new package for react-stream which allows for custom server renderer
outputs. I picked the name because it's a reasonable name but also
because the npm name is currently owned by a friend of the project.
The react-dom build has its own inlined server renderer under the
name `react-dom/fizz`.
There is also a noop renderer to be used for testing. At some point
we might add a public one to test-renderer but for now I don't want to have
to think about public API design for the tests.
* Add FormatConfig too
We need to separate the format (DOM, React Native, etc) from the host
running the server (Node, Browser, etc).
* Basic wiring between Node, Noop and DOM configs
The Node DOM API is pipeToNodeStream which accepts a writable stream.
* Merge host and format config in dynamic react-stream entry point
Simpler API this way but also avoids having to fork the wrapper config.
Fixes noop builds.
* Add setImmediate/Buffer globals to lint config
Used by the server renderer
* Properly include fizz.node.js
Also use forwarding to it from fizz.js in builds so that tests covers
this.
* Make react-stream private since we're not ready to publish
or even name it yet
* Rename Renderer -> Streamer
* Prefix react-dom/fizz with react-dom/unstable-fizz
* Add Fizz Browser host config
This lets Fizz render to WHATWG streams. E.g. for rendering in a
Service Worker.
I added react-dom/unstable-fizz.browser as the entry point for this.
Since we now have two configurations of DOM. I had to add another
inlinedHostConfigs configuration called `dom-browser`. The reconciler
treats this configuration the same as `dom`. For stream it checks
against the ReactFizzHostConfigBrowser instead of the Node one.
* Add Fizz Browser Fixture
This is for testing server rendering - on the client.
* Lower version number to detach it from react-reconciler version
* BUG: ReactPartialRenderer / New Context polutes mutable global state
The new context API stores the provided values on the shared context instance. When used in a synchronous context, this is not an issue. However when used in an concurrent context this can cause a "push provider" from one react render to have an effect on an unrelated concurrent react render.
I've encountered this bug in production when using renderToNodeStream, which asks ReactPartialRenderer for bytes up to a high water mark before yielding. If two Node Streams are created and read from in parallel, the state of one can polute the other.
I wrote a failing test to illustrate the conditions under which this happens.
I'm also concerned that the experimental concurrent/async React rendering on the client could suffer from the same issue.
* Use unique thread ID for each partial render to access Context
This first adds an allocator that keeps track of a unique ThreadID index
for each currently executing partial renderer. IDs are not just growing
but are reused as streams are destroyed.
This ensures that IDs are kept nice and compact.
This lets us use an "array" for each Context object to store the current
values. The look up for these are fast because they're just looking up
an offset in a tightly packed "array".
I don't use an actual Array object to store the values. Instead, I rely
on that VMs (notably V8) treat storage of numeric index property access
as a separate "elements" allocation.
This lets us avoid an extra indirection.
However, we must ensure that these arrays are not holey to preserve this
feature.
To do that I store the _threadCount on each context (effectively it takes
the place of the .length property on an array).
This lets us first validate that the context has enough slots before we
access the slot. If not, we fill in the slots with the default value.
* Parse build script type and package names
This ensures that `yarn build core dom` includes DOM.
It also ensures that spaces like `yarn build "core, dom"` doesn't build EVERYTHING.
* Get rid of label in bundles config
Instead we just use the name from entry using fuzzy search.
There is one special case. If you put in `/index` or `/index.js`.
That allows to build things like `react/index` to only build isomorphic
where as `react` would build everything. Or `react-dom/index` to exclude
the server renderers.
* Instead of matching `/index.js` just append it to the search string
That way things like `yarn build react/` works too.
* Add debug tools package
* Add basic implementation
* Implement inspection of the current state of hooks using the fiber tree
* Support useContext hooks inspection by backtracking from the Fiber
I'm not sure this is safe because the return fibers may not be current
but close enough and it's fast.
We use this to set up the current values of the providers.
* rm copypasta
* Use lastIndexOf
Just in case. I don't know of any scenario where this can happen.
* Support ForwardRef
* Add test for memo and custom hooks
* Support defaultProps resolution
* [react-cache] Remove `cache` as argument to `read`
Updated is API is `Resource.read(key)` instead of
`Resource.read(cache, key)`.
The cache is read from context using `readContext`.
This also removes cache invalidation entirely (other than the default
LRU mechanism), as well as the ability to have multiple caches. We'll
add it back once `Context.write` lands and we can implement it the
right way.
Since there's now only a single cache (the global one), we don't
actually need to use context yet, but I've added a dummy context
anyway so the user gets an error if they attempt to read outside the
render phase.
* nits
* Add test for thenables that resolve multiple times
* Jest + test renderer helpers for concurrent mode
Most of our concurrent React tests use the noop renderer. But most
of those tests don't test the renderer API, and could instead be
written with the test renderer. We should switch to using the test
renderer whenever possible, because that's what we expect product devs
and library authors to do. If test renderer is sufficient for writing
most React core tests, it should be sufficient for others, too. (The
converse isn't true but we should aim to dogfood test renderer as much
as possible.)
This PR adds a new package, jest-react (thanks @cpojer). I've moved
our existing Jest matchers into that package and added some new ones.
I'm not expecting to figure out the final API in this PR. My goal is
to land something good enough that we can start dogfooding in www.
TODO: Continue migrating Suspense tests, decide on better API names
* Add additional invariants to prevent common errors
- Errors if user attempts to flush when log of yields is not empty
- Throws if argument passed to toClearYields is not ReactTestRenderer
* Better method names
- toFlushAll -> toFlushAndYield
- toFlushAndYieldThrough ->
- toClearYields -> toHaveYielded
Also added toFlushWithoutYielding
* Fix jest-react exports
* Tweak README
* Added UMD_PROFILING type to react-dom and scheduling package. Added UMD shim to schedule package.
* Added new schedule umd prod+prof bundle to API test
* 🔥 Stop syncing the value attribute on inputs
* Eliminate some additional checks
* Remove initialValue and initialWrapper from wrapperState flow type
* Update tests with new sync logic, reduce some operations
* Update tests, add some caveats for SSR mismatches
* Revert newline change
* Remove unused type
* Call toString to safely type string values
* Add disableInputAttributeSyncing feature flag
Reverts tests to original state, adds attribute sync feature flag,
then moves all affected tests to ReactFire-test.js.
* Revert position of types in toStringValues
* Invert flag on number input blur
* Add clarification why double blur is necessary
* Update ReactFire number cases to be more explicite about blur
* Move comments to reduce diff size
* Add comments to clarify behavior in each branch
* There is no need to assign a different checked behavior in Fire
* Use checked reference
* Format
* Avoid precomputing stringable values
* Revert getToStringValue comment
* Revert placement of undefined in getToStringValue
* Do not eagerly stringify value
* Unify Fire test cases with normal ones
* Revert toString change. Only assign unsynced values when not nully
* Remove injectComponentTree from unstable-native-dependencies, add
EventPluginHub
injectComponentTree was exposed for react-native-web, but wasn't
actually being used by the project. They were using EventPluginHub
through ReactDOM's secret internals, but that was removed in https://github.com/facebook/react/pull/13539
This removes the unused injectComponentTree export, refactors the
ResponderEventPlugin test so it doesn't depend on it, and also adds
EventPluginHub to the exports to unbreak react-native-web
* Re-export injectEventPluginsByName from ReactDOM internals
* Merged interaction-tracking package into react-scheduler
* Add tracking API to FB+www builds
* Added Rollup plugin to strip no-side-effect imports from Rollup bundles
* Re-bundle tracking and scheduling APIs on SECRET_INTERNALS object for UMD build (and provide lazy forwarding methods)
* Added some additional tests and fixtures
* Fixed broken UMD fixture in master (#13512)
* Updated suspense fixture to use new interaction-tracking API
* Integrated Profiler API with interaction-tracking API (and added tests)
* Pass interaction Set (rather than Array) to Profiler onRender callback
* Removed some :any casts for enableInteractionTracking fields in FiberRoot type
* Refactored threadID calculation into a helper method
* Errors thrown by interaction tracking hooks use unhandledError to rethrow more safely.
Reverted try/finally change to ReactTestRendererScheduling
* Added a $FlowFixMe above the FiberRoot :any cast
* Reduce overhead from calling work-started hook
* Remove interaction-tracking wrap() references from unwind work in favor of managing suspense/interaction continuations in the scheduler
* Moved the logic for calling work-started hook from performWorkOnRoot() to renderRoot()
* Add interaction-tracking to bundle externals. Set feature flag to __PROFILE__
* Renamed the freezeInteractionCount flag and replaced one use-case with a method param
* let -> const
* Updated suspense fixture to handle recent API changes
* Removed enableInteractionTrackingObserver as a separate flag; only enableInteractionTracking is used now
* Added interaction-tracking/subscriptions bundle and split tests
* Added multi-subscriber support
* Moved subscriptions behind feature flag
* Fixed bug with wrap() parameters and added test
* Replaced wrap arrow function
* Add a regression test for #13188
* Replace console.error() with a throw in setTimeout() as last resort
* Fix lint and comment
* Fix tests to check we throw after all
* Fix build tests
Adds custom Jest matchers that help with writing async tests:
- `toFlushThrough`
- `toFlushAll`
- `toFlushAndThrow`
- `toClearYields`
Each one accepts an array of expected yielded values, to prevent
false negatives.
Eventually I imagine we'll want to publish this on npm.
This is a leftover from #13161 that I forgot to include.
It ensures we don't accidentally write code in the old way and end up passing the stack twice.
* Use %s in the console calls
* Add shared/warningWithStack
* Convert some warning callsites to warningWithStack
* Use warningInStack in shared utilities and remove unnecessary checks
* Replace more warning() calls with warningWithStack()
* Fixes after rebase + use warningWithStack in react
* Make warning have stack by default; warningWithoutStack opts out
* Forbid builds that may not use internals
* Revert newly added stacks
I changed my mind and want to keep this PR without functional changes. So we won't "fix" any warnings that are already missing stacks. We'll do it in follow-ups instead.
* Fix silly find/replace mistake
* Reorder imports
* Add protection against warning argument count mismatches
* Address review
* 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
* Remove rAF fork
**what is the change?:**
Undid https://github.com/facebook/react/pull/12837
**why make this change?:**
We originally forked rAF because we needed to pull in a particular
version of rAF internally at Facebook, to avoid grabbing the default
polyfilled version.
The longer term solution, until we can get rid of the global polyfill
behavior, is to initialize 'schedule' before the polyfilling happens.
Now that we have landed and synced
https://github.com/facebook/react/pull/12900 successfully, we can
initialize 'schedule' before the polyfill runs.
So we can remove the rAF fork. Here is how it will work:
1. Land this PR on Github.
2. Flarnie will quickly run a sync getting this change into www.
3. We delete the internal forked version of
'requestAnimationFrameForReact'.
4. We require 'schedule' in the polyfill file itself, before the
polyfilling happens.
**test plan:**
Flarnie will manually try the above steps locally and verify that things
work.
**issue:**
Internal task T29442940
* fix nits
* fix tests, fix changes from rebasing
* fix lint
* Use local references to global things inside 'scheduler'
**what is the change?:**
See title
**why make this change?:**
We want to avoid initially calling one version of an API and then later
accessing a polyfilled version.
**test plan:**
Run existing tests.
* Shim ReactScheduler for www
**what is the change?:**
In 'www' we want to reference the separate build of ReactScheduler,
which allows treating it as a separate module internally.
**why make this change?:**
We need to require the ReactScheduler before our rAF polyfill activates,
in order to customize which custom behaviors we want.
This is also a step towards being able to experiment with using it
outside of React.
**test plan:**
Ran tests, ran the build, and ran `test-build`.
* Generate a bundle for fb-www
**what is the change?:**
See title
**why make this change?:**
Splitting out the 'schedule' module allows us to load it before
polyfills kick in for rAF and other APIs.
And long term we want to split this into a separate module anyway, this
is a step towards that.
**test plan:**
I'll run the sync next week and verify that this all works. :)
* ran prettier
* fix rebase issues
* Change names of variables used for holding globals
* add legacy context APIs warning in strict mode
* refactor if statement and the warning message
* add other flags for type check
* add component stack tree and refactor wording
* fix the nits
* 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
* Generate Flow config on install
We'll need to do pre-renderer Flow passes with different configs.
This is the first step to get it working. We only want the original version checked in.
* Create multiple Flow configs from a template
* Run Flow per renderer
* Lint
* Revert the environment consolidation
I thought this would be a bit cleaner at first because we now have non-environment files in this directory.
But Sebastian is changing these files at the same time so I want to avoid conflicts and keep the PR more tightly scoped. Undo.
* Misc
* Temporary fix for grabbing wrong rAF polyfill in ReactScheduler
**what is the change?:**
For now...
We need to grab a slightly different implementation of rAF internally at
FB than in Open Source. Making rAF a dependency of the ReactScheduler
module allows us to fork the dependency at FB.
NOTE: After this lands we have an alternative plan to make this module
separate from React and require it before our Facebook timer polyfills
are applied. But want to land this now to keep master in a working state
and fix bugs folks are seeing at Facebook.
Thanks @sebmarkbage @acdlite and @sophiebits for discussing the options
and trade-offs for solving this issue.
**why make this change?:**
This fixes a problem we're running into when experimenting with
ReactScheduler internally at Facebook, **and* it's part of our long term
plan to use dependency injection with the scheduler to make it easier to
test and adjust.
**test plan:**
Ran tests, lint, flow, and will manually test when syncing into
Facebook's codebase.
**issue:**
See internal task T29442940
* ran prettier
* Add TopLevelEventTypes
* Fix `ReactBrowserEventEmitter`
* Fix EventPluginUtils
* Fix TapEventPlugin
* Fix ResponderEventPlugin
* Update ReactDOMFiberComponent
* Fix BeforeInputEventPlugin
* Fix ChangeEventPlugin
* Fix EnterLeaveEventPlugin
* Add missing non top event type used in ChangeEventPlugin
* Fix SelectEventPlugin
* Fix SimpleEventPlugin
* Fix outstanding Flow issues and move TopLevelEventTypes
* Inline a list of all events in `ReactTestUtils`
* Fix tests
* Make it pretty
* Fix completly unrelated typo
* Don’t use map constructor because of IE11
* Update typings, revert changes to native code
* Make topLevelTypes in ResponderEventPlugin injectable and create DOM and ReactNative variant
* Set proper dependencies for DOMResponderEventPlugin
* Prettify
* Make some react dom tests no longer depend on internal API
* Use factories to create top level speific generic event modules
* Remove unused dependency
* Revert exposed module renaming, hide store creation, and inline dependency decleration
* Add Flow types to createResponderEventPlugin and its consumers
* Remove unused dependency
* Use opaque flow type for TopLevelType
* Add missing semis
* Use raw event names as top level identifer
* Upgrade baylon
This is required for parsing opaque flow types in our CI tests.
* Clean up flow types
* Revert Map changes of ReactBrowserEventEmitter
* Upgrade babel-* packages
Apparently local unit tests also have issues with parsing JavaScript
modules that contain opaque types (not sure why I didn't notice
earlier!?).
* Revert Map changes of SimpleEventPlugin
* Clean up ReactTestUtils
* Add missing semi
* Fix Flow issue
* Make TopLevelType clearer
* Favor for loops
* Explain the new DOMTopLevelEventTypes concept
* Use static injection for Responder plugin types
* Remove null check and rely on flow checks
* Add missing ResponderEventPlugin dependencies
* makes closure compiler threaded
* Dans PR with a closure compiler java version
* Remove unused dep
* Pin GCC
* Prettier
* Nit rename
* Fix error handling
* Name plugins consistently
* Fix lint
* Maybe this works?
* or this
* AppVeyor
* Fix lint
```
$ jest
FAIL scripts/jest/dont-run-jest-directly.js
● Test suite failed to run
Don't run `jest` directly. Run `yarn test` instead.
> 1 | throw new Error("Don't run `jest` directly. Run `yarn test` instead.");
2 |
at Object.<anonymous> (scripts/jest/dont-run-jest-directly.js:1:96)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 0.866s
Ran all test suites.
```
This is the first step - pulling the ReactDOMFrameScheduling module out
into a separate package.
Co-authored-by: Brandon Dail <aweary@users.noreply.github.com>
* 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).
* Don't download bundle stats from master on CI
This was temporarily necessary in the past because we didn't have the logic that downloads actual *merge base* stats.
We do have that now as part of the Danger script. So we can remove this.
* Use absolute threshold for whether to show a change
* Download master stats, but only for other master builds
* Rewrite sizes
* 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 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.
* 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).
* 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
* Revert "Replace danger token with a refreshed facebook-open-source-bot token (#12295)"
This reverts commit 2d511479c4.
* Revert "Temporarily disable Danger in CI (#12291)"
This reverts commit 925fc93389.
* [experimental] simple-cache-provider
Pushing an early version of this for testing and demonstration purposes.
* Change invariant to DEV-only warning
* Use function overloading for createResource type
Expresses that primitive keys do not require a hash function, but
non-primitive keys do.
* More tests
* Use export *
* Make Record type a disjoint union
* Pass miss argument separate from key to avoid a closure
* Additional release script options for publishing canary versions
- `branch` specifies a branch other than master
- `local` skips pulling from the remote branch and checking CircleCI
- `tag` specifies an npm dist tag other than `latest` or `next`
We may add a higher-level `canary` option in the future.
* Address Brian's feedback:
- Updated description of `local` option
- Throws if the `latest` tag is specified for a prerelease version
* [Danger] Use the PR's mergebase for a branch in the dangerfile instead of
the root commit's parent.
* [Danger] Get the full history to find the merge base
While writing tests for unsafe async warnings, I noticed that in certain cases, errors were swallowed by the toWarnDev matcher and resulted in confusing test failures. For example, if an error prevented the code being tested from logging an expected warning- the test would fail saying that the warning hadn't been logged rather than reporting the unexpected error. I think a better approach for this is to always treat caught errors as the highest-priority reason for failing a test.
I reran all of the test cases for this matcher that I originally ran with PR #11786 and ensured they all still pass.
* Adds danger_js with an initial rule for warning about large PRs
Signed-off-by: Anandaroop Roy <roop@artsymail.com>
* [WIP] Get the before and after for the build results
* [Dev] More work on the Dangerfile
* [Danger] Split the reports into sections based on their package
* Remove the --extract-errors on the circle build
* [Danger] Improve the lookup for previous -> current build to also include the environment
* Fix rebase
* Runs a lint rule on tests only that errors if it sees `fdescribe` or `fit` calls.
* Changes `file:` to `link:` for our custom, internal rules (just to simplify updating these in the future).
* Updates `eslint` from 3.10 -> 4.1 and `babel-eslint` from 7.1 -> 8.0 so that we can run this new rule only against tests.
* Warn about spying on the console
* Added suppress warning flag for spyOn(console)
* Nits
* Removed spy-on-console guard
* Fixed a potential source of false-positives in toWarnDev() matcher
Also updated (most of) ReactIncrementalErrorLogging-test.internal to use the new matcher
* Removed unused third param to spyOn
* Improved clarity of inline comments
* Removed unused normalizeCodeLocInfo() method
* Move build/packages/* to build/node_modules/*
This fixes Node resolution in that folder and lets us require() packages in it in Node shell for manual testing.
* Link fixtures to packages/node_modules
This updates the location and also uses link: instead of file: to avoid Yarn caching the folder contents.
* Bump deps to Jest 22
* Prevent jsdom from logging intentionally thrown errors
This relies on our existing special field that we use to mute errors.
Perhaps, it would be better to instead rely on preventDefault() directly.
I outlined a possible strategy here: https://github.com/facebook/react/issues/11098#issuecomment-355032539
* Update snapshots
* Mock out a method called by ReactART that now throws
* Calling .click() no longer works, dispatch event instead
* Fix incorrect SVG element creation in test
* Render SVG elements inside <svg> to avoid extra warnings
* Fix range input test to use numeric value
* Fix creating SVG element in test
* Replace brittle test that relied on jsdom behavior
The test passed in jsdom due to its implementation details.
The original intention was to test the mutation method, but it was removed a while ago.
Following @nhunzaker's suggestion, I moved the tests to ReactDOMInput and adjusted them to not rely on implementation details.
* Add a workaround for the expected extra client-side warning
This is a bit ugly but it's just two places. I think we can live with this.
* Only warn once for mismatches caused by bad attribute casing
We used to warn both about bad casing and about a mismatch.
The mismatch warning was a bit confusing. We didn't know we warned twice because jsdom didn't faithfully emulate SVG.
This changes the behavior to only leave the warning about bad casing if that's what caused the mismatch.
It also adjusts the test to have an expectation that matches the real world behavior.
* Add an expected warning per comment in the same test
* Added toWarnInDev matcher and connected to 1 test
* Added .toLowPriorityWarnDev() matcher
* Reply Jest spy with custom spy. Unregister spy after toWarnDev() so unexpected console.error/warn calls will fail tests.
* console warn/error throws immediately in tests by default (if not spied on)
* Pass-thru console message before erroring to make it easier to identify
* More robustly handle unexpected warnings within try/catch
* Error message includes remaining expected warnings in addition to unexpected warning
I'm running out of ideas to keep these commit messages entertaining. Thankfully this should keep the CI green and we can forget any of it ever happened.
We added this to Flow in v0.25 (about 2 years ago), but never actually
deprecated the legacy `declare var exports` syntax. Hoping to do that
soon, so clearing up uses that I can find.
Test Plan: flow
* use different eslint config for es6 and es5
* remove confusing eslint/baseConfig.js & add more eslint setting for es5, es6
* more clear way to run eslint on es5 & es6 file
* seperate ESNext, ES6, ES6 path, and use different lint config
* rename eslint config file & update eslint rules
* Undo yarn.lock changes
* Rename a file
* Remove unnecessary exceptions
* Refactor a little bit
* Refactor and tweak the logic
* Minor issues
* Remove EventListener fbjs utility
EventListener normalizes event subscription for <= IE8. This is no
longer necessary. element.addEventListener is sufficient.
* Remove an extra allocation for open source bundles
* Split into two functions to avoid extra runtime checks
* Revert unrelated changes
* Add a test-only transform to catch infinite loops
* Only track iteration count, not time
This makes the detection dramatically faster, and is okay in our case because we don't have tests that iterate so much.
* Use clearer naming
* Set different limits for tests
* Fail tests with infinite loops even if the error was caught
* Add a test
* Rewrite the build scripts
* Don't crash when doing FB-only builds
* Group sync imports under Sync.*
* Don't print known errors twice
* Use an exclamation that aligns vertically
* Change build process to include npm pack and unpacking generated packages to corresponding build directories.
* Update function name, change to use os's default temp directory
* appending uuid to temp npm packaging directory.
* Use `this` inside invokeGuardedCallback
It's slightly odd but that's exactly how our www fork works.
Might as well do it in the open source version to make it clear we rely on context here.
* Move invokeGuardedCallback into a separate file
This lets us introduce forks for it.
* Add a www fork for invokeGuardedCallback
* Fix Flow
* 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.
* Add rule to ignore default handling of not linting hidden files
* Undo changes
* Add function to validate warnings
* Use validateWarnings when reporting linc command
* Restore files
* Contain code to line file
* Add bundle linting and tests to the release script
- add yarn lint-build
- use yarn lint-build in circle ci build.sh
- add yarn lint-build, yarn test-prod, yarn test-build, and yarn test-build-prod to the realse script
* Improve readability of release test messages
* Run prettier
* Updating package versions for release 16.2.0
* Seperate bundle specific tests
- Moved the runYarnTask into utils since its being used two files now
- Uncomment out checks I mistakenly committed
* Revert a bunch of version bump changes
Mistakenly commited by release script
* .js for consistency
* 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).
* Remove global mocks
They are making it harder to test compiled bundles.
One of them (FeatureFlags) is not used. It is mocked in some specific test files (and that's fine).
The other (FiberErrorLogger) is mocked to silence its output. I'll look if there's some other way to achieve this.
* Add error.suppressReactErrorLogging and use it in tests
This adds an escape hatch to *not* log errors that go through React to the console.
We will enable it for our own tests.
* Move Jest setup files to /dev/ subdirectory
* Clone Jest /dev/ files into /prod/
* Move shared code into scripts/jest
* Move Jest config into the scripts folder
* Fix the equivalence test
It fails because the config is now passed to Jest explicitly.
But the test doesn't know about the config.
To fix this, we just run it via `yarn test` (which includes the config).
We already depend on Yarn for development anyway.
* Add yarn test-prod to run Jest with production environment
* Actually flip the production tests to run in prod environment
This produces a bunch of errors:
Test Suites: 64 failed, 58 passed, 122 total
Tests: 740 failed, 26 skipped, 1809 passed, 2575 total
Snapshots: 16 failed, 4 passed, 20 total
* Ignore expectDev() calls in production
Down from 740 to 175 failed.
Test Suites: 44 failed, 78 passed, 122 total
Tests: 175 failed, 26 skipped, 2374 passed, 2575 total
Snapshots: 16 failed, 4 passed, 20 total
* Decode errors so tests can assert on their messages
Down from 175 to 129.
Test Suites: 33 failed, 89 passed, 122 total
Tests: 129 failed, 1029 skipped, 1417 passed, 2575 total
Snapshots: 16 failed, 4 passed, 20 total
* Remove ReactDOMProduction-test
There is no need for it now. The only test that was special is moved into ReactDOM-test.
* Remove production switches from ReactErrorUtils
The tests now run in production in a separate pass.
* Add and use spyOnDev() for warnings
This ensures that by default we expect no warnings in production bundles.
If the warning *is* expected, use the regular spyOn() method.
This currently breaks all expectDev() assertions without __DEV__ blocks so we go back to:
Test Suites: 56 failed, 65 passed, 121 total
Tests: 379 failed, 1029 skipped, 1148 passed, 2556 total
Snapshots: 16 failed, 4 passed, 20 total
* Replace expectDev() with expect() in __DEV__ blocks
We started using spyOnDev() for console warnings to ensure we don't *expect* them to occur in production. As a consequence, expectDev() assertions on console.error.calls fail because console.error.calls doesn't exist. This is actually good because it would help catch accidental warnings in production.
To solve this, we are getting rid of expectDev() altogether, and instead introduce explicit expectation branches. We'd need them anyway for testing intentional behavior differences.
This commit replaces all expectDev() calls with expect() calls in __DEV__ blocks. It also removes a few unnecessary expect() checks that no warnings were produced (by also removing the corresponding spyOnDev() calls).
Some DEV-only assertions used plain expect(). Those were also moved into __DEV__ blocks.
ReactFiberErrorLogger was special because it console.error()'s in production too. So in that case I intentionally used spyOn() instead of spyOnDev(), and added extra assertions.
This gets us down to:
Test Suites: 21 failed, 100 passed, 121 total
Tests: 72 failed, 26 skipped, 2458 passed, 2556 total
Snapshots: 16 failed, 4 passed, 20 total
* Enable User Timing API for production testing
We could've disabled it, but seems like a good idea to test since we use it at FB.
* Test for explicit Object.freeze() differences between PROD and DEV
This is one of the few places where DEV and PROD behavior differs for performance reasons.
Now we explicitly test both branches.
* Run Jest via "yarn test" on CI
* Remove unused variable
* Assert different error messages
* Fix error handling tests
This logic is really complicated because of the global ReactFiberErrorLogger mock.
I understand it now, so I added TODOs for later.
It can be much simpler if we change the rest of the tests that assert uncaught errors to also assert they are logged as warnings.
Which mirrors what happens in practice anyway.
* Fix more assertions
* Change tests to document the DEV/PROD difference for state invariant
It is very likely unintentional but I don't want to change behavior in this PR.
Filed a follow up as https://github.com/facebook/react/issues/11618.
* Remove unnecessary split between DEV/PROD ref tests
* Fix more test message assertions
* Make validateDOMNesting tests DEV-only
* Fix error message assertions
* Document existing DEV/PROD message difference (possible bug)
* Change mocking assertions to be DEV-only
* Fix the error code test
* Fix more error message assertions
* Fix the last failing test due to known issue
* Run production tests on CI
* Unify configuration
* Fix coverage script
* Remove expectDev from eslintrc
* Run everything in band
We used to before, too. I just forgot to add the arguments after deleting the script.
* Forked ReactFeatureFlags for React Native to enable debugRenderPhaseSideEffects GK
* Changed debugRenderPhaseSideEffects in www feature flags to be runtime as well
* Improve formatting of errors when building
* Remove undefined from the header when error.plugin is undefined
* Add babel-code-frame and syntax highlighting in error message
* Run yarn prettier and fix code format
* 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.
* Added missing params object to execUnlessDry call
* Public package names are no longer hard-coded
* Added "v" prefix to git tag
* Show more accurate in-progress duration
* Properly bucket-bridage params
* Prettier
* Publish command logs stack with error
* Consolidate build process with GCC
* Record sizes
* Refactor header and footer wrapping
It is easier to understand if we just explicitly type them out.
* Add a timeout before querying npm right after publish
* Conditionally log some post publish steps
* Print ready-to-paste 'yarn add' instructions for CRA prerelease testing
* Enable User Timing API integration with a feature flag
* Expose a way to toggle user timing flag in www
* Update ReactNativeCSFeatureFlags.js
* Update ReactFeatureFlags.js
* Fix dead code elimination for feature flags
Turning flags into named exports fixes dead code elimination.
This required some restructuring of how we verify that flag types match up. I used the Check<> trick combined with import typeof, as suggested by @calebmer.
For www, we can no longer re-export `require('ReactFeatureFlags')` directly, and instead destructure it. This means flags have to be known at init time. This is already the case so it's not a problem. In fact it may be better since it removes extra property access in tight paths.
For things that we *want* to be dynamic on www (currently, only performance flag) we can export a function to toggle it, and then put it on the secret exports. In fact this is better than just letting everyone mutate the flag at arbitrary times since we can provide, e.g., a ref counting interface to it.
* Record sizes
* 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
* Update transforms to handle ES modules
* Update Jest to handle ES modules
* Convert react package to ES modules
* Convert react-art package to ES Modules
* Convert react-call-return package to ES Modules
* Convert react-test-renderer package to ES Modules
* Convert react-cs-renderer package to ES Modules
* Convert react-rt-renderer package to ES Modules
* Convert react-noop-renderer package to ES Modules
* Convert react-dom/server to ES modules
* Convert react-dom/{client,events,test-utils} to ES modules
* Convert react-dom/shared to ES modules
* Convert react-native-renderer to ES modules
* Convert react-reconciler to ES modules
* Convert events to ES modules
* Convert shared to ES modules
* Remove CommonJS support from transforms
* Move ReactDOMFB entry point code into react-dom/src
This is clearer because we can use ES imports in it.
* Fix Rollup shim configuration to work with ESM
* Fix incorrect comment
* Exclude external imports without side effects
* Fix ReactDOM FB build
* Remove TODOs I don’t intend to fix yet