2016-11-14 06:00:07 +08:00
|
|
|
'use strict';
|
|
|
|
|
2018-11-09 01:56:35 +08:00
|
|
|
const {
|
|
|
|
es5Paths,
|
|
|
|
esNextPaths,
|
|
|
|
} = require('./scripts/shared/pathsByLanguageVersion');
|
|
|
|
|
2016-03-02 07:40:52 +08:00
|
|
|
const OFF = 0;
|
|
|
|
const ERROR = 2;
|
|
|
|
|
|
|
|
module.exports = {
|
2020-01-15 01:26:44 +08:00
|
|
|
extends: [
|
|
|
|
'fbjs',
|
|
|
|
'prettier'
|
|
|
|
],
|
2016-03-02 07:40:52 +08:00
|
|
|
|
2017-11-29 06:56:29 +08:00
|
|
|
// Stop ESLint from looking for a configuration file in parent folders
|
2019-08-10 03:59:02 +08:00
|
|
|
root: true,
|
2017-11-29 06:56:29 +08:00
|
|
|
|
2019-08-10 03:59:02 +08:00
|
|
|
plugins: ['jest', 'no-for-of-loops', 'react', 'react-internal'],
|
2016-03-02 07:40:52 +08:00
|
|
|
|
2019-08-10 03:59:02 +08:00
|
|
|
parser: 'babel-eslint',
|
2018-11-09 01:56:35 +08:00
|
|
|
parserOptions: {
|
2019-08-10 03:59:02 +08:00
|
|
|
ecmaVersion: 8,
|
2018-11-09 01:56:35 +08:00
|
|
|
sourceType: 'script',
|
|
|
|
ecmaFeatures: {
|
|
|
|
experimentalObjectRestSpread: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
2016-03-02 07:40:52 +08:00
|
|
|
// We're stricter than the default config, mostly. We'll override a few rules
|
|
|
|
// and then enable some React specific ones.
|
|
|
|
rules: {
|
|
|
|
'accessor-pairs': OFF,
|
|
|
|
'brace-style': [ERROR, '1tbs'],
|
2016-11-18 06:16:44 +08:00
|
|
|
'consistent-return': OFF,
|
2016-03-02 07:40:52 +08:00
|
|
|
'dot-location': [ERROR, 'property'],
|
2019-12-15 02:09:25 +08:00
|
|
|
// We use console['error']() as a signal to not transform it:
|
|
|
|
'dot-notation': [ERROR, {allowPattern: '^(error|warn)$'}],
|
2016-03-02 07:40:52 +08:00
|
|
|
'eol-last': ERROR,
|
2019-08-10 03:59:02 +08:00
|
|
|
eqeqeq: [ERROR, 'allow-null'],
|
|
|
|
indent: OFF,
|
2016-03-02 07:40:52 +08:00
|
|
|
'jsx-quotes': [ERROR, 'prefer-double'],
|
2016-11-18 06:16:44 +08:00
|
|
|
'keyword-spacing': [ERROR, {after: true, before: true}],
|
2016-03-02 07:40:52 +08:00
|
|
|
'no-bitwise': OFF,
|
2016-06-05 04:37:57 +08:00
|
|
|
'no-inner-declarations': [ERROR, 'functions'],
|
2016-03-02 07:40:52 +08:00
|
|
|
'no-multi-spaces': ERROR,
|
|
|
|
'no-restricted-syntax': [ERROR, 'WithStatement'],
|
|
|
|
'no-shadow': ERROR,
|
|
|
|
'no-unused-expressions': ERROR,
|
|
|
|
'no-unused-vars': [ERROR, {args: 'none'}],
|
2019-08-10 03:59:02 +08:00
|
|
|
'no-use-before-define': OFF,
|
2017-03-15 05:12:35 +08:00
|
|
|
'no-useless-concat': OFF,
|
2019-08-10 03:59:02 +08:00
|
|
|
quotes: [ERROR, 'single', {avoidEscape: true, allowTemplateLiterals: true}],
|
2016-03-02 07:40:52 +08:00
|
|
|
'space-before-blocks': ERROR,
|
2017-03-15 05:12:35 +08:00
|
|
|
'space-before-function-paren': OFF,
|
2018-08-21 00:28:04 +08:00
|
|
|
'valid-typeof': [ERROR, {requireStringLiterals: true}],
|
2016-03-02 07:40:52 +08:00
|
|
|
|
2018-11-09 01:56:35 +08:00
|
|
|
// We apply these settings to files that should run on Node.
|
|
|
|
// They can't use JSX or ES6 modules, and must be in strict mode.
|
|
|
|
// They can, however, use other ES6 features.
|
|
|
|
// (Note these rules are overridden later for source files.)
|
|
|
|
'no-var': ERROR,
|
|
|
|
strict: ERROR,
|
|
|
|
|
2019-08-10 03:59:02 +08:00
|
|
|
// Enforced by Prettier
|
|
|
|
// TODO: Prettier doesn't handle long strings or long comments. Not a big
|
|
|
|
// deal. But I turned it off because loading the plugin causes some obscure
|
|
|
|
// syntax error and it didn't seem worth investigating.
|
|
|
|
'max-len': OFF,
|
|
|
|
|
2016-03-02 07:40:52 +08:00
|
|
|
// React & JSX
|
|
|
|
// Our transforms set this automatically
|
|
|
|
'react/jsx-boolean-value': [ERROR, 'always'],
|
|
|
|
'react/jsx-no-undef': ERROR,
|
|
|
|
// We don't care to do this
|
|
|
|
'react/jsx-sort-prop-types': OFF,
|
2017-03-01 01:03:08 +08:00
|
|
|
'react/jsx-space-before-closing': ERROR,
|
2016-03-02 07:40:52 +08:00
|
|
|
'react/jsx-uses-react': ERROR,
|
2016-11-18 06:16:44 +08:00
|
|
|
'react/no-is-mounted': OFF,
|
2016-03-02 07:40:52 +08:00
|
|
|
// This isn't useful in our test code
|
|
|
|
'react/react-in-jsx-scope': ERROR,
|
|
|
|
'react/self-closing-comp': ERROR,
|
|
|
|
// We don't care to do this
|
2019-08-10 03:59:02 +08:00
|
|
|
'react/jsx-wrap-multilines': [
|
|
|
|
ERROR,
|
|
|
|
{declaration: false, assignment: false},
|
|
|
|
],
|
2016-03-02 07:40:52 +08:00
|
|
|
|
2018-02-10 00:11:22 +08:00
|
|
|
// Prevent for...of loops because they require a Symbol polyfill.
|
|
|
|
// You can disable this rule for code that isn't shipped (e.g. build scripts and tests).
|
|
|
|
'no-for-of-loops/no-for-of-loops': ERROR,
|
|
|
|
|
2016-03-02 07:40:52 +08:00
|
|
|
// CUSTOM RULES
|
|
|
|
// the second argument of warning/invariant should be a literal string
|
2017-03-01 07:59:45 +08:00
|
|
|
'react-internal/no-primitive-constructors': ERROR,
|
2018-08-21 22:43:02 +08:00
|
|
|
'react-internal/no-to-warn-dev-within-to-throw': ERROR,
|
2019-12-11 11:28:14 +08:00
|
|
|
'react-internal/invariant-args': ERROR,
|
|
|
|
'react-internal/warning-args': ERROR,
|
2019-12-07 02:25:54 +08:00
|
|
|
'react-internal/no-production-logging': ERROR,
|
2016-11-14 06:00:07 +08:00
|
|
|
},
|
|
|
|
|
2018-01-10 02:55:51 +08:00
|
|
|
overrides: [
|
2018-11-09 01:56:35 +08:00
|
|
|
{
|
|
|
|
// We apply these settings to files that we ship through npm.
|
|
|
|
// They must be ES5.
|
|
|
|
files: es5Paths,
|
|
|
|
parser: 'espree',
|
|
|
|
parserOptions: {
|
|
|
|
ecmaVersion: 5,
|
|
|
|
sourceType: 'script',
|
|
|
|
},
|
|
|
|
rules: {
|
|
|
|
'no-var': OFF,
|
|
|
|
strict: ERROR,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// We apply these settings to the source files that get compiled.
|
|
|
|
// They can use all features including JSX (but shouldn't use `var`).
|
|
|
|
files: esNextPaths,
|
|
|
|
parser: 'babel-eslint',
|
|
|
|
parserOptions: {
|
2019-08-10 03:59:02 +08:00
|
|
|
ecmaVersion: 8,
|
2018-11-09 01:56:35 +08:00
|
|
|
sourceType: 'module',
|
|
|
|
},
|
|
|
|
rules: {
|
|
|
|
'no-var': ERROR,
|
|
|
|
strict: OFF,
|
|
|
|
},
|
|
|
|
},
|
2018-01-10 02:55:51 +08:00
|
|
|
{
|
|
|
|
files: ['**/__tests__/*.js'],
|
|
|
|
rules: {
|
|
|
|
// https://github.com/jest-community/eslint-plugin-jest
|
|
|
|
'jest/no-focused-tests': ERROR,
|
2019-08-14 18:51:01 +08:00
|
|
|
'jest/valid-expect': ERROR,
|
|
|
|
'jest/valid-expect-in-promise': ERROR,
|
2019-08-10 03:59:02 +08:00
|
|
|
},
|
2019-04-30 05:31:16 +08:00
|
|
|
},
|
2019-12-15 02:09:25 +08:00
|
|
|
{
|
|
|
|
files: [
|
|
|
|
'**/__tests__/**/*.js',
|
|
|
|
'scripts/**/*.js',
|
|
|
|
'packages/*/npm/**/*.js',
|
2019-12-20 00:51:25 +08:00
|
|
|
'packages/dom-event-testing-library/**/*.js',
|
2019-12-15 02:09:25 +08:00
|
|
|
'packages/react-devtools*/**/*.js'
|
|
|
|
],
|
|
|
|
rules: {
|
|
|
|
'react-internal/no-production-logging': OFF,
|
|
|
|
'react-internal/warning-args': OFF,
|
|
|
|
},
|
|
|
|
},
|
2019-04-30 05:31:16 +08:00
|
|
|
{
|
|
|
|
files: ['packages/react-native-renderer/**/*.js'],
|
|
|
|
globals: {
|
|
|
|
nativeFabricUIManager: true,
|
2019-08-10 03:59:02 +08:00
|
|
|
},
|
|
|
|
},
|
2018-01-10 02:55:51 +08:00
|
|
|
],
|
|
|
|
|
2016-11-14 06:00:07 +08:00
|
|
|
globals: {
|
2019-08-23 04:58:12 +08:00
|
|
|
SharedArrayBuffer: true,
|
|
|
|
|
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 21:02:26 +08:00
|
|
|
spyOnDev: true,
|
2017-11-29 06:06:26 +08:00
|
|
|
spyOnDevAndProd: true,
|
|
|
|
spyOnProd: true,
|
2018-06-12 04:16:27 +08:00
|
|
|
__PROFILE__: true,
|
2018-09-02 03:00:00 +08:00
|
|
|
__UMD__: true,
|
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-15 01:46:42 +08:00
|
|
|
__EXPERIMENTAL__: true,
|
2019-09-16 20:43:22 +08:00
|
|
|
trustedTypes: true,
|
2016-11-14 06:00:07 +08:00
|
|
|
},
|
2016-03-02 07:40:52 +08:00
|
|
|
};
|