Commit Graph

28 Commits

Author SHA1 Message Date
Andrew Clark fe7163e73d Add unstable prefix to experimental APIs (#18825)
We've been shipping unprefixed experimental APIs (like `createRoot` and
`useTransition`) to the Experimental release channel, with the rationale
that because these APIs do not appear in any stable release, we're free
to change or remove them later without breaking any downstream projects.

What we didn't consider is that downstream projects might be tempted to
use feature detection:

```js
const useTransition = React.useTransition || fallbackUseTransition;
```

This pattern assumes that the version of `useTransition` that exists in
the Experimental channel today has the same API contract as the final
`useTransition` API that we'll eventually ship to stable.

To discourage feature detection, I've added an `unstable_` prefix to
all of our unstable APIs.

The Facebook builds still have the unprefixed APIs, though. We will
continue to support those; if we make any breaking changes, we'll
migrate the internal callers like we usually do. To make testing easier,
I added the `unstable_`-prefixed APIs to the www builds, too. That way
our tests can always use the prefixed ones without gating on the
release channel.
2020-05-04 22:25:41 -07:00
Brian Vaughn ea2af878cc Root API should clear non-empty roots before mounting (#18730)
* Root API should clear non-empty roots before mounting

Legacy render-into-subtree API removes children from a container before rendering into it. The root API did not do this previously, but just left the children around in the document.

This commit adds a new FiberRoot flag to clear a container's contents before mounting. This is done during the commit phase, to avoid multiple, observable mutations.
2020-04-28 13:07:42 -07:00
Dominic Gannaway 1662035852 Ensure createRoot warning parity with ReactDOM.render (#17937) 2020-01-30 17:17:42 +00:00
Brian Vaughn e26682a9f3 Removed Root API callback params and added warnings (#17916) 2020-01-27 12:35:08 -08:00
Dan Abramov 0b5a26a489 Rename toWarnDev -> toErrorDev, toLowPriorityWarnDev -> toWarnDev (#17605)
* Rename toWarnDev -> toErrorDev in tests

* Rename toWarnDev matcher implementation to toErrorDev

* Rename toLowPriorityWarnDev -> toWarnDev in tests and implementation
2019-12-16 12:48:16 +00:00
Dan Abramov b15bf36750 Add component stacks to (almost) all warnings (#17586) 2019-12-12 23:47:55 +00:00
Dan Abramov a7b4d51a20 Warn when doing createRoot twice on the same node (another approach) (#17329)
* Unify fields used for createRoot warning and event system

* Warn when doing createRoot twice on the same node

* Stricter check for modern roots

* Unmark asynchronously

* Fix Flow
2019-11-10 00:54:13 +00:00
Andrew Clark 30c5daf943 Remove concurrent apis from stable (#17088)
* 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
2019-10-15 15:09:19 -07:00
Andrew Clark d364d8555f Set up experimental builds (#17071)
* 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.
2019-10-14 10:46:42 -07:00
Andrew Clark 71d012ecd0 Remove dormant createBatch experiment (#17035)
* Remove dormant createBatch experiment

In a hybrid React app with multiple roots, `createBatch` is used to
coordinate an update to a root with its imperative container.

We've pivoted away from multi-root, hybrid React apps for now to focus
on single root apps.

This PR removes the API from the codebase. It's possible we'll add back
some version of this feature in the future.

* Remove unused export
2019-10-07 14:15:15 -07:00
Andrew Clark 4d307de458 Prefix mock Scheduler APIs with _unstable (#15999)
For now this is only meant to be consumed via `act`.
2019-06-26 12:16:08 -07:00
Andrew Clark 83fc258f29 Remove <ConcurrentMode /> (#15532)
Use createSyncRoot instead.
2019-05-13 16:10:00 -07:00
Andrew Clark 00748c53e1 Add new mock build of Scheduler with flush, yield API (#14964)
* 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
2019-02-26 20:51:17 -08:00
Sebastian Markbåge 1d48b4a684 Fix hydration with createRoot warning (#14808)
It's suggesting an API that doesn't exist. Fixed it to reference the actual
API.
2019-02-09 17:12:11 +00:00
Dan Abramov 17d70df919 Warn when mixing createRoot() and old APIs (#14615)
* Warn when mixing createRoot() and old APIs

* Move container checks to entry points

This way further warning check doesn't crash on bad inputs.

* Fix Flow

* Rename flag to be clearer

* managed by -> passed to

* Revert accidental change

* Fix Fire shim to match
2019-01-18 00:20:21 +00:00
Dominic Gannaway 0dc0ddc1ef Rename AsyncMode -> ConcurrentMode (#13732)
* Rename AsyncMode -> ConcurrentMode
2018-09-26 17:13:02 +01:00
Héctor Ramos b87aabdfe1 Drop the year from Facebook copyright headers and the LICENSE file. (#13593) 2018-09-07 15:11:23 -07:00
Brian Vaughn b92f947af1 Rename "react-scheduler" package to "schedule" (#13543)
* Git moved packages/react-scheduler -> packages/schedule

* Global find+replace 'react-scheduler' -> 'schedule'

* Global find+replace 'ReactScheduler' -> 'Scheduler'

* Renamed remaining files "ReactScheduler" -> "Schedule"

* Add thank-you note to schedule package README

* Replaced schedule package versions 0.1.0-alpha-1 -> 0.2.0

* Patched our local fixtures to work around Yarn install issue

* Removed some fixture hacks
2018-09-03 19:27:50 +01:00
Dan Abramov 840cb1a268 Add an invariant to createRoot() to validate containers (#13279) 2018-07-27 16:50:20 +02:00
Dan Abramov 467d139101 Enforce presence or absence of component stack in tests (#13215)
* Enforce presence or absence of stack in tests

* Rename expectNoStack to withoutStack

* Fix lint

* Add some tests for toWarnDev()
2018-07-16 20:20:18 +01:00
Flarnie Marchan 1e3cd332a0 Remove the 'alwaysUseRequestIdleCallbackPolyfill' feature flag (#12648)
* Remove the 'alwaysUseRequestIdleCallbackPolyfill' feature flag

**what is the change?:**
Removes the feature flag 'alwaysUseRequestIdleCallbackPolyfill', such
that we **always** use the polyfill for requestIdleCallback.

**why make this change?:**
We have been testing this feature flag at 100% for some time internally,
and determined it works better for React than the native implementation.
Looks like RN was overriding the flag to use the native when possible,
but since no RN products are using 'async' mode it should be safe to
switch this flag over for RN as well.

**test plan:**
We have already been testing this internally for some time.

**issue:**
internal task t28128480

* fix mistaken conditional

* Add mocking of rAF, postMessage, and initial test for ReactScheduler

**what is the change?:**
- In all tests where we previously mocked rIC or relied on native
mocking which no longer works, we are now mocking rAF and postMessage.
- Also adds a basic initial test for ReactScheduler.
NOTE -> we do plan to write headless browser tests for ReactScheduler!
This is just an initial test, to verify that it works with the mocked
out browser APIs as expected.

**why make this change?:**
We need to mock out the browser APIs more completely for the new
'ReactScheduler' to work in our tests. Many tests are depending on it,
since it's used at a low level.

By mocking the browser APIs rather than the 'react-scheduler' module, we
enable testing the production bundles. This approach is trading
isolation for accuracy. These tests will be closer to a real use.

**test plan:**
run the tests :)

**issue:**
internal task T28128480
2018-04-23 15:25:46 -07:00
Heaven b85c5cd188 remove duplicate code in test (#12620) 2018-04-16 16:36:49 +01:00
Brian Vaughn 6294b67a40 unstable_createRoot (#12487)
* Removed enableCreateRoot flag. Renamed createRoot to unstable_createRoot

* ReactDOMRoot test is no longer internal
2018-03-29 12:51:34 -07:00
Dan Abramov fa7a97fc46 Run 90% of tests on compiled bundles (both development and production) (#11633)
* 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).
2017-11-23 17:44:58 +00:00
Dan Abramov 6041f481b7 Run Jest in production mode (#11616)
* 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.
2017-11-22 13:02:26 +00:00
Clement Hoang 94f44aeba7 Update prettier to 1.8.1 (#10785)
* Change prettier dependency in package.json version 1.8.1

* Update yarn.lock

* Apply prettier changes

* Fix ReactDOMServerIntegration-test.js

* Fix test for ReactDOMComponent-test.js
2017-11-07 18:09:33 +00:00
Clement Hoang 1e35f2b282 Put createRoot export under a feature flag (#11426) 2017-11-02 15:21:06 -07:00
Dan Abramov 313611572b Reorganize code structure (#11288)
* Move files and tests to more meaningful places

* Fix the build

Now that we import reconciler via react-reconciler, I needed to make a few tweaks.

* Update sizes

* Move @preventMunge directive to FB header

* Revert unintentional change

* Fix Flow coverage

I forgot to @flow-ify those files. This uncovered some issues.

* Prettier, I love you but you're bringing me down
Prettier, I love you but you're bringing me down

Like a rat in a cage
Pulling minimum wage
Prettier, I love you but you're bringing me down

Prettier, you're safer and you're wasting my time
Our records all show you were filthy but fine
But they shuttered your stores
When you opened the doors
To the cops who were bored once they'd run out of crime

Prettier, you're perfect, oh, please don't change a thing
Your mild billionaire mayor's now convinced he's a king
So the boring collect
I mean all disrespect
In the neighborhood bars I'd once dreamt I would drink

Prettier, I love you but you're freaking me out
There's a ton of the twist but we're fresh out of shout
Like a death in the hall
That you hear through your wall
Prettier, I love you but you're freaking me out

Prettier, I love you but you're bringing me down
Prettier, I love you but you're bringing me down
Like a death of the heart
Jesus, where do I start?
But you're still the one pool where I'd happily drown

And oh! Take me off your mailing list
For kids who think it still exists
Yes, for those who think it still exists
Maybe I'm wrong and maybe you're right
Maybe I'm wrong and maybe you're right
Maybe you're right, maybe I'm wrong
And just maybe you're right

And oh! Maybe mother told you true
And there'll always be somebody there for you
And you'll never be alone
But maybe she's wrong and maybe I'm right
And just maybe she's wrong
Maybe she's wrong and maybe I'm right
And if so, here's this song!
2017-10-19 19:50:24 +01:00