use different eslint config for es6 and es5 (#11794)

* 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
This commit is contained in:
Jack Hou
2017-12-11 23:52:46 +08:00
committed by Dan Abramov
parent a5025b1610
commit e8e62ebb59
45 changed files with 9305 additions and 5147 deletions

View File

@@ -72,6 +72,7 @@
"jest-jasmine2": "^21.3.0-beta.4",
"jest-runtime": "^21.3.0-beta.4",
"merge-stream": "^1.0.0",
"minimatch": "^3.0.4",
"minimist": "^1.2.0",
"mkdirp": "^0.5.1",
"ncp": "^2.0.0",

View File

@@ -65,15 +65,16 @@ const _touchConfig = function(
) {
const allTouchObjects = allTouchHandles.map(touch);
const changedTouchObjects = subsequence(allTouchObjects, changedIndices);
const activeTouchObjects = topType === 'topTouchStart'
? allTouchObjects
: topType === 'topTouchMove'
const activeTouchObjects =
topType === 'topTouchStart'
? allTouchObjects
: topType === 'topTouchMove'
? allTouchObjects
: topType === 'topTouchEnd'
? antiSubsequence(allTouchObjects, changedIndices)
: topType === 'topTouchCancel'
? antiSubsequence(allTouchObjects, changedIndices)
: topType === 'topTouchCancel'
? antiSubsequence(allTouchObjects, changedIndices)
: null;
: null;
return {
nativeEvent: touchEvent(
@@ -234,19 +235,24 @@ const registerTestHandlers = function(eventTestConfig, readableIDToID) {
for (const readableID in eventTypeTestConfig) {
const nodeConfig = eventTypeTestConfig[readableID];
const id = readableIDToID[readableID];
const handler = nodeConfig.order === NA
? neverFire.bind(null, readableID, registrationName)
: // We partially apply readableID and nodeConfig, as they change in the
// parent closure across iterations.
function(rID, config, e) {
expect(
rID + '->' + registrationName + ' index:' + runs.dispatchCount++,
).toBe(rID + '->' + registrationName + ' index:' + config.order);
if (config.assertEvent) {
config.assertEvent(e);
}
return config.returnVal;
}.bind(null, readableID, nodeConfig);
const handler =
nodeConfig.order === NA
? neverFire.bind(null, readableID, registrationName)
: // We partially apply readableID and nodeConfig, as they change in the
// parent closure across iterations.
function(rID, config, e) {
expect(
rID +
'->' +
registrationName +
' index:' +
runs.dispatchCount++,
).toBe(rID + '->' + registrationName + ' index:' + config.order);
if (config.assertEvent) {
config.assertEvent(e);
}
return config.returnVal;
}.bind(null, readableID, nodeConfig);
putListener(getInstanceFromNode(id), registrationName, handler);
}
};
@@ -1362,7 +1368,7 @@ describe('ResponderEventPlugin', () => {
});
it('should determine the first common ancestor correctly', () => {
// This test was moved here from the ReactTreeTraversal test since only the
// This test was moved here from the ReactTreeTraversal test since only the
// ResponderEventPlugin uses `getLowestCommonAncestor`
const React = require('react');
const ReactTestUtils = require('react-dom/test-utils');
@@ -1379,7 +1385,7 @@ describe('ResponderEventPlugin', () => {
);
}
}
class ParentComponent extends React.Component {
render() {
return (
@@ -1443,7 +1449,9 @@ describe('ResponderEventPlugin', () => {
ReactDOMComponentTree.getInstanceFromNode(plan.one),
ReactDOMComponentTree.getInstanceFromNode(plan.two),
);
expect(firstCommon).toBe(ReactDOMComponentTree.getInstanceFromNode(plan.com));
expect(firstCommon).toBe(
ReactDOMComponentTree.getInstanceFromNode(plan.com),
);
}
});
});

View File

@@ -163,7 +163,7 @@ var Wedge = createReactClass({
var startAngle = this.props.startAngle;
var endAngle = this.props.endAngle;
if (startAngle - endAngle === 0) {
return;
return null;
}
// radii are provided in pixels

View File

@@ -443,10 +443,10 @@ describe('ReactDOMComponent', () => {
});
it('should not set null/undefined attributes', () => {
var container = document.createElement('div');
const container = document.createElement('div');
// Initial render.
ReactDOM.render(<img src={null} data-foo={undefined} />, container);
var node = container.firstChild;
const node = container.firstChild;
expect(node.hasAttribute('src')).toBe(false);
expect(node.hasAttribute('data-foo')).toBe(false);
// Update in one direction.
@@ -468,9 +468,9 @@ describe('ReactDOMComponent', () => {
});
it('should apply React-specific aliases to HTML elements', () => {
var container = document.createElement('div');
const container = document.createElement('div');
ReactDOM.render(<form acceptCharset="foo" />, container);
var node = container.firstChild;
const node = container.firstChild;
// Test attribute initialization.
expect(node.getAttribute('accept-charset')).toBe('foo');
expect(node.hasAttribute('acceptCharset')).toBe(false);
@@ -501,9 +501,9 @@ describe('ReactDOMComponent', () => {
});
it('should apply React-specific aliases to SVG elements', () => {
var container = document.createElement('div');
const container = document.createElement('div');
ReactDOM.render(<svg arabicForm="foo" />, container);
var node = container.firstChild;
const node = container.firstChild;
// Test attribute initialization.
expect(node.getAttribute('arabic-form')).toBe('foo');
expect(node.hasAttribute('arabicForm')).toBe(false);
@@ -543,9 +543,9 @@ describe('ReactDOMComponent', () => {
});
it('should not apply React-specific aliases to custom elements', () => {
var container = document.createElement('div');
const container = document.createElement('div');
ReactDOM.render(<some-custom-element arabicForm="foo" />, container);
var node = container.firstChild;
const node = container.firstChild;
// Should not get transformed to arabic-form as SVG would be.
expect(node.getAttribute('arabicForm')).toBe('foo');
expect(node.hasAttribute('arabic-form')).toBe(false);

View File

@@ -376,7 +376,7 @@ describe('ReactDOMServer', () => {
it('should not focus on either server or client with autofocus={false} even if there is a markup mismatch', () => {
spyOnDev(console, 'error');
var element = document.createElement('div');
const element = document.createElement('div');
element.innerHTML = ReactDOMServer.renderToString(
<button autoFocus={false}>server</button>,
);

View File

@@ -9,8 +9,8 @@
'use strict';
var React = require('react');
var ReactDOM = require('react-dom');
const React = require('react');
const ReactDOM = require('react-dom');
function normalizeCodeLocInfo(str) {
return str && str.replace(/at .+?:\d+/g, 'at **');

View File

@@ -7,7 +7,7 @@
* @flow
*/
var EventListenerWWW = require('EventListener');
const EventListenerWWW = require('EventListener');
import typeof * as EventListenerType from '../EventListener';
import typeof * as EventListenerShimType from './EventListener-www';

View File

@@ -4,6 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
describe('transform-prevent-infinite-loops', () => {
// Note: instead of testing the transform by applying it,

View File

@@ -26,14 +26,14 @@ module.exports = function autoImporter(babel) {
CallExpression: function(path, file) {
if (path.get('callee').matchesPattern('Object.assign')) {
// generate identifier and require if it hasn't been already
var id = getAssignIdent(path, file, this);
const id = getAssignIdent(path, file, this);
path.node.callee = id;
}
},
MemberExpression: function(path, file) {
if (path.matchesPattern('Object.assign')) {
var id = getAssignIdent(path, file, this);
const id = getAssignIdent(path, file, this);
path.replaceWith(id);
}
},

View File

@@ -17,96 +17,129 @@
return (url + '')
.replace('https://', '')
.replace('http://', '')
.split('/')[0]
.split('/')[0];
}
function HeaderBar() {
return e('tr', {
style: {
backgroundColor: '#222',
},
}, e('table', {
return e(
'tr',
{
style: {
padding: 4,
backgroundColor: '#222',
},
width: '100%',
cellSpacing: 0,
cellPadding: 0,
}, e('tbody', null,
e('tr', null,
e('td', {
},
e(
'table',
{
style: {
width: 18,
paddingRight: 4,
},
},
e('a', {
href: '#',
},
e('img', {
src: 'logo.png',
width: 16,
height: 16,
padding: 4,
},
width: '100%',
cellSpacing: 0,
cellPadding: 0,
},
e(
'tbody',
null,
e(
'tr',
null,
e(
'td',
{
style: {
border: '1px solid #00d8ff',
width: 18,
paddingRight: 4,
},
})
)
),
e('td', {
style: {
lineHeight: '12pt',
},
height: 10,
},
e('span', {
className: 'pagetop',
},
e('b', { className: 'hnname' }, 'React HN Benchmark'),
e('a', { href: '#' }, 'new'),
' | ',
e('a', { href: '#' }, 'comments'),
' | ',
e('a', { href: '#' }, 'show'),
' | ',
e('a', { href: '#' }, 'ask'),
' | ',
e('a', { href: '#' }, 'jobs'),
' | ',
e('a', { href: '#' }, 'submit')
},
e(
'a',
{
href: '#',
},
e('img', {
src: 'logo.png',
width: 16,
height: 16,
style: {
border: '1px solid #00d8ff',
},
})
)
),
e(
'td',
{
style: {
lineHeight: '12pt',
},
height: 10,
},
e(
'span',
{
className: 'pagetop',
},
e('b', {className: 'hnname'}, 'React HN Benchmark'),
e('a', {href: '#'}, 'new'),
' | ',
e('a', {href: '#'}, 'comments'),
' | ',
e('a', {href: '#'}, 'show'),
' | ',
e('a', {href: '#'}, 'ask'),
' | ',
e('a', {href: '#'}, 'jobs'),
' | ',
e('a', {href: '#'}, 'submit')
)
)
)
)
)
));
);
}
function Story({ story, rank }) {
function Story({story, rank}) {
return [
e('tr', {
className: 'athing',
},
e('td', {
style: {
verticalAlign: 'top',
textAlign: 'right',
},
className: 'title',
e(
'tr',
{
className: 'athing',
},
e('span', {
className: 'rank',
}, `${rank}.`)
),
e('td', {
className: 'votelinks',
style: {
verticalAlign: 'top',
},
},
e('center', null,
e('a', {
href: '#',
e(
'td',
{
style: {
verticalAlign: 'top',
textAlign: 'right',
},
className: 'title',
},
e(
'span',
{
className: 'rank',
},
`${rank}.`
)
),
e(
'td',
{
className: 'votelinks',
style: {
verticalAlign: 'top',
},
},
e(
'center',
null,
e(
'a',
{
href: '#',
},
e('div', {
className: 'votearrow',
title: 'upvote',
@@ -114,61 +147,95 @@
)
)
),
e('td', {
className: 'title',
},
e('a', {
href: '#',
className: 'storylink',
e(
'td',
{
className: 'title',
},
e(
'a',
{
href: '#',
className: 'storylink',
},
story.title
),
story.url ? (
e('span', {
className: 'sitebit comhead',
},
' (',
e('a', {
href: '#',
},
getHostUrl(story.url)
),
')'
)
) : null
story.url
? e(
'span',
{
className: 'sitebit comhead',
},
' (',
e(
'a',
{
href: '#',
},
getHostUrl(story.url)
),
')'
)
: null
)
),
e('tr', null,
e(
'tr',
null,
e('td', {
colSpan: 2,
}),
e('td', {
className: 'subtext',
},
e('span', {
className: 'score',
}, `${story.score} points`),
' by ',
e('a', {
href: '#',
className: 'hnuser',
}, story.by),
' ',
e('span', {
className: 'age',
e(
'td',
{
className: 'subtext',
},
e('a', {
e(
'span',
{
className: 'score',
},
`${story.score} points`
),
' by ',
e(
'a',
{
href: '#',
}, timeAge(story.time))
className: 'hnuser',
},
story.by
),
' ',
e(
'span',
{
className: 'age',
},
e(
'a',
{
href: '#',
},
timeAge(story.time)
)
),
' | ',
e('a', {
href: '#',
}, 'hide'),
e(
'a',
{
href: '#',
},
'hide'
),
' | ',
e('a', {
href: '#',
}, `${ story.descendants || 0 } comments`)
e(
'a',
{
href: '#',
},
`${story.descendants || 0} comments`
)
)
),
e('tr', {
@@ -176,21 +243,29 @@
height: 5,
},
className: 'spacer',
})
}),
];
}
function StoryList({ stories }) {
return e('tr', null,
e('td', null,
e('table', {
cellPadding: 0,
cellSpacing: 0,
classList: 'itemlist',
},
e('tbody', null,
stories.map((story, i) =>
e(Story, { story, rank: ++i, key: story.id })
function StoryList({stories}) {
return e(
'tr',
null,
e(
'td',
null,
e(
'table',
{
cellPadding: 0,
cellSpacing: 0,
classList: 'itemlist',
},
e(
'tbody',
null,
stories.map((story, i) =>
e(Story, {story, rank: ++i, key: story.id})
)
)
)
@@ -198,32 +273,43 @@
);
}
function App({ stories }) {
return e('center', null,
e('table', {
id: 'hnmain',
border: 0,
cellPadding: 0,
cellSpacing: 0,
width: '85%',
style: {
'background-color': '#f6f6ef',
function App({stories}) {
return e(
'center',
null,
e(
'table',
{
id: 'hnmain',
border: 0,
cellPadding: 0,
cellSpacing: 0,
width: '85%',
style: {
'background-color': '#f6f6ef',
},
},
}, e('tbody', null,
e(HeaderBar, null),
e('tr', { height: 10 }),
e(StoryList, {
stories,
})
))
e(
'tbody',
null,
e(HeaderBar, null),
e('tr', {height: 10}),
e(StoryList, {
stories,
})
)
)
);
}
const app = document.getElementById('app');
window.render = function render() {
ReactDOM.render(React.createElement(App, {
stories: window.stories
}), app);
}
})();
ReactDOM.render(
React.createElement(App, {
stories: window.stories,
}),
app
);
};
})();

View File

@@ -1,11 +1,9 @@
'use strict';
const {
join,
} = require('path');
const {join} = require('path');
async function build(reactPath, asyncCopyTo) {
// copy the UMD bundles
// copy the UMD bundles
await asyncCopyTo(
join(reactPath, 'build', 'dist', 'react.production.min.js'),
join(__dirname, 'react.production.min.js')

View File

@@ -1,16 +1,20 @@
'use strict';
const fetch = require('node-fetch');
const { writeFileSync } = require('fs');
const {writeFileSync} = require('fs');
const stories = 50;
async function getStory(id) {
const storyRes = await fetch(`https://hacker-news.firebaseio.com/v0/item/${id}.json`);
const storyRes = await fetch(
`https://hacker-news.firebaseio.com/v0/item/${id}.json`
);
return await storyRes.json();
}
async function getTopStories() {
const topStoriesRes = await fetch('https://hacker-news.firebaseio.com/v0/topstories.js');
const topStoriesRes = await fetch(
'https://hacker-news.firebaseio.com/v0/topstories.js'
);
const topStoriesIds = await topStoriesRes.json();
const topStories = [];
@@ -20,7 +24,10 @@ async function getTopStories() {
topStories.push(await getStory(topStoriesId));
}
writeFileSync('top-stories.json', `window.stories = ${JSON.stringify(topStories)}`);
writeFileSync(
'top-stories.json',
`window.stories = ${JSON.stringify(topStories)}`
);
}
getTopStories();
getTopStories();

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,9 @@
'use strict';
const {
join,
} = require('path');
const {join} = require('path');
async function build(reactPath, asyncCopyTo) {
// copy the UMD bundles
// copy the UMD bundles
await asyncCopyTo(
join(reactPath, 'build', 'dist', 'react.production.min.js'),
join(__dirname, 'react.production.min.js')

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,9 @@
'use strict';
const {
join,
} = require('path');
const {join} = require('path');
async function build(reactPath, asyncCopyTo) {
// copy the UMD bundles
// copy the UMD bundles
await asyncCopyTo(
join(reactPath, 'build', 'dist', 'react.production.min.js'),
join(__dirname, 'react.production.min.js')

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,9 @@
'use strict';
const {
join,
} = require('path');
const {join} = require('path');
async function build(reactPath, asyncCopyTo) {
// copy the UMD bundles
// copy the UMD bundles
await asyncCopyTo(
join(reactPath, 'build', 'dist', 'react.production.min.js'),
join(__dirname, 'react.production.min.js')

View File

@@ -47,7 +47,7 @@ describe('error codes transform', () => {
});
it('should only add `reactProdInvariant` once', () => {
var expectedInvariantTransformResult =
const expectedInvariantTransformResult =
'!condition ? ' +
'__DEV__ ? ' +
"invariant(false, 'Do not override existing functions.') : " +

View File

@@ -6,9 +6,9 @@
*/
'use strict';
var fs = require('fs');
var evalToString = require('../shared/evalToString');
var invertObject = require('./invertObject');
const fs = require('fs');
const evalToString = require('../shared/evalToString');
const invertObject = require('./invertObject');
module.exports = function(babel) {
const t = babel.types;

View File

@@ -9,9 +9,9 @@
'use strict';
var rule = require('../no-primitive-constructors');
var RuleTester = require('eslint').RuleTester;
var ruleTester = new RuleTester();
const rule = require('../no-primitive-constructors');
const RuleTester = require('eslint').RuleTester;
const ruleTester = new RuleTester();
ruleTester.run('eslint-rules/no-primitive-constructors', rule, {
valid: ['!!obj', "'' + obj", '+string'],

View File

@@ -9,9 +9,9 @@
'use strict';
var rule = require('../warning-and-invariant-args');
var RuleTester = require('eslint').RuleTester;
var ruleTester = new RuleTester();
const rule = require('../warning-and-invariant-args');
const RuleTester = require('eslint').RuleTester;
const ruleTester = new RuleTester();
ruleTester.run('eslint-rules/warning-and-invariant-args', rule, {
valid: [

View File

@@ -20,8 +20,8 @@ module.exports = function(context) {
if (node.type === 'Literal' && typeof node.value === 'string') {
return node.value;
} else if (node.type === 'BinaryExpression' && node.operator === '+') {
var l = getLiteralString(node.left);
var r = getLiteralString(node.right);
const l = getLiteralString(node.left);
const r = getLiteralString(node.right);
if (l !== null && r !== null) {
return l + r;
}
@@ -33,7 +33,7 @@ module.exports = function(context) {
CallExpression: function(node) {
// This could be a little smarter by checking context.getScope() to see
// how warning/invariant was defined.
var isWarningOrInvariant =
const isWarningOrInvariant =
node.callee.type === 'Identifier' &&
(node.callee.name === 'warning' || node.callee.name === 'invariant');
if (!isWarningOrInvariant) {
@@ -45,7 +45,7 @@ module.exports = function(context) {
});
return;
}
var format = getLiteralString(node.arguments[1]);
const format = getLiteralString(node.arguments[1]);
if (format === null) {
context.report(
node,
@@ -64,7 +64,7 @@ module.exports = function(context) {
return;
}
// count the number of formatting substitutions, plus the first two args
var expectedNArgs = (format.match(/%s/g) || []).length + 2;
const expectedNArgs = (format.match(/%s/g) || []).length + 2;
if (node.arguments.length !== expectedNArgs) {
context.report(
node,

View File

@@ -0,0 +1,31 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
const eslintrc = require('../../.eslintrc');
const ERROR = 2;
// 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.
module.exports = Object.assign({}, eslintrc, {
parser: 'espree',
parserOptions: {
ecmaVersion: 2017,
sourceType: 'script',
ecmaFeatures: {
experimentalObjectRestSpread: true,
},
},
rules: Object.assign({}, eslintrc.rules, {
'no-var': ERROR,
strict: ERROR,
}),
});

View File

@@ -0,0 +1,26 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
const eslintrc = require('../../.eslintrc');
const ERROR = 2;
// We apply these settings to files that we ship through npm.
// They must be ES5.
module.exports = Object.assign({}, eslintrc, {
parser: 'espree',
parserOptions: {
ecmaVersion: 5,
sourceType: 'script',
},
rules: {
strict: ERROR,
},
});

View File

@@ -0,0 +1,21 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
const eslintrc = require('../../.eslintrc');
const ERROR = 2;
// We apply these settings to the source files that get compiled.
// They can use all features including JSX (but shouldn't use `var`).
module.exports = Object.assign({}, eslintrc, {
rules: Object.assign({}, eslintrc.rules, {
'no-var': ERROR,
}),
});

View File

@@ -7,13 +7,85 @@
'use strict';
const minimatch = require('minimatch');
const CLIEngine = require('eslint').CLIEngine;
const cli = new CLIEngine();
const formatter = cli.getFormatter();
const listChangedFiles = require('../shared/listChangedFiles');
const {es5Paths, esNextPaths} = require('../shared/pathsByLanguageVersion');
module.exports = function lintOnFiles(filePatterns) {
const report = cli.executeOnFiles(filePatterns);
const formattedResults = formatter(report.results);
console.log(formattedResults);
return report;
};
const allPaths = ['**/*.js'];
let changedFiles = null;
function runESLintOnFilesWithOptions(filePatterns, onlyChanged, options) {
const cli = new CLIEngine(options);
const formatter = cli.getFormatter();
if (onlyChanged && changedFiles === null) {
// Calculate lazily.
changedFiles = [...listChangedFiles()];
}
const finalFilePatterns = onlyChanged
? intersect(changedFiles, filePatterns)
: filePatterns;
const report = cli.executeOnFiles(finalFilePatterns);
// When using `ignorePattern`, eslint will show `File ignored...` warnings for any ignores.
// We don't care because we *expect* some passed files will be ignores if `ignorePattern` is used.
const messages = report.results.filter(item => {
if (!onlyChanged) {
// Don't suppress the message on a full run.
// We only expect it to happen for "only changed" runs.
return true;
}
const ignoreMessage =
'File ignored because of a matching ignore pattern. Use "--no-ignore" to override.';
return !(item.messages[0] && item.messages[0].message === ignoreMessage);
});
const ignoredMessageCount = report.results.length - messages.length;
return {
output: formatter(messages),
errorCount: report.errorCount,
warningCount: report.warningCount - ignoredMessageCount,
};
}
function intersect(files, patterns) {
let intersection = [];
patterns.forEach(pattern => {
intersection = [
...intersection,
...minimatch.match(files, pattern, {matchBase: true}),
];
});
return [...new Set(intersection)];
}
function runESLint({onlyChanged}) {
if (typeof onlyChanged !== 'boolean') {
throw new Error('Pass options.onlyChanged as a boolean.');
}
let errorCount = 0;
let warningCount = 0;
let output = '';
[
runESLintOnFilesWithOptions(allPaths, onlyChanged, {
configFile: `${__dirname}/eslintrc.default.js`,
ignorePattern: [...es5Paths, ...esNextPaths],
}),
runESLintOnFilesWithOptions(esNextPaths, onlyChanged, {
configFile: `${__dirname}/eslintrc.esnext.js`,
}),
runESLintOnFilesWithOptions(es5Paths, onlyChanged, {
configFile: `${__dirname}/eslintrc.es5.js`,
}),
].forEach(result => {
errorCount += result.errorCount;
warningCount += result.warningCount;
output += result.output;
});
console.log(output);
return errorCount === 0 && warningCount === 0;
}
module.exports = runESLint;

View File

@@ -9,25 +9,25 @@
'use strict';
var fs = require('fs');
var path = require('path');
var execFileSync = require('child_process').execFileSync;
const fs = require('fs');
const path = require('path');
const execFileSync = require('child_process').execFileSync;
var cwd = null;
let cwd = null;
function exec(command, args) {
console.error('>', [command].concat(args));
var options = {};
const options = {};
if (cwd) {
options.cwd = cwd;
}
return execFileSync(command, args, options).toString();
}
var isCI = !!process.env.TRAVIS_REPO_SLUG;
const isCI = !!process.env.TRAVIS_REPO_SLUG;
if (isCI) {
var branch = process.env.TRAVIS_BRANCH || process.env.CIRCLE_BRANCH;
var isPullRequest =
const branch = process.env.TRAVIS_BRANCH || process.env.CIRCLE_BRANCH;
const isPullRequest =
(!!process.env.TRAVIS_PULL_REQUEST &&
process.env.TRAVIS_PULL_REQUEST !== 'false') ||
!!process.env.CI_PULL_REQUEST;
@@ -92,9 +92,9 @@ function getRepoSlug() {
return process.env.TRAVIS_REPO_SLUG;
}
var remotes = exec('git', ['remote', '-v']).split('\n');
for (var i = 0; i < remotes.length; ++i) {
var match = remotes[i].match(/^origin\t[^:]+:([^\.]+).+\(fetch\)/);
const remotes = exec('git', ['remote', '-v']).split('\n');
for (let i = 0; i < remotes.length; ++i) {
const match = remotes[i].match(/^origin\t[^:]+:([^\.]+).+\(fetch\)/);
if (match) {
return match[1];
}
@@ -104,17 +104,17 @@ function getRepoSlug() {
process.exit(1);
}
var repoSlug = getRepoSlug();
var currentCommitHash = exec('git', ['rev-parse', 'HEAD']).trim();
var currentTimestamp = new Date()
const repoSlug = getRepoSlug();
const currentCommitHash = exec('git', ['rev-parse', 'HEAD']).trim();
const currentTimestamp = new Date()
.toISOString()
.replace('T', ' ')
.replace(/\..+/, '');
function checkoutFactsFolder() {
var factsFolder = '../' + repoSlug.split('/')[1] + '-facts';
const factsFolder = '../' + repoSlug.split('/')[1] + '-facts';
if (!fs.existsSync(factsFolder)) {
var repoURL;
let repoURL;
if (isCI) {
repoURL =
'https://' +
@@ -146,9 +146,9 @@ function checkoutFactsFolder() {
}
checkoutFactsFolder();
for (var i = 2; i < process.argv.length; i += 2) {
var name = process.argv[i].trim();
var value = process.argv[i + 1];
for (let i = 2; i < process.argv.length; i += 2) {
const name = process.argv[i].trim();
const value = process.argv[i + 1];
if (value.indexOf('\n') !== -1) {
console.error(
'facts-tracker: skipping',
@@ -159,13 +159,14 @@ for (var i = 2; i < process.argv.length; i += 2) {
continue;
}
var filename = name + '.txt';
const filename = name + '.txt';
let lastLine;
try {
var lastLine = exec('tail', ['-n', '1', filename]);
lastLine = exec('tail', ['-n', '1', filename]);
} catch (e) {
// ignore error
}
var lastValue =
const lastValue =
lastLine && lastLine.replace(/^[^\t]+\t[^\t]+\t/, '').slice(0, -1); // commit hash \t timestamp \t // trailing \n
if (value !== lastValue) {

View File

@@ -39,7 +39,7 @@ declare module 'UIManager' {
reactTag: number,
viewName: string,
rootTag: number,
props: ?Object
props: ?Object,
): void;
declare function manageChildren(
containerTag: number,
@@ -47,30 +47,30 @@ declare module 'UIManager' {
moveToIndices: Array<number>,
addChildReactTags: Array<number>,
addAtIndices: Array<number>,
removeAtIndices: Array<number>
removeAtIndices: Array<number>,
): void;
declare function measure(hostComponent: mixed, callback: Function): void;
declare function measureInWindow(
nativeTag: ?number,
callback: Function
callback: Function,
): void;
declare function measureLayout(
nativeTag: mixed,
nativeNode: number,
onFail: Function,
onSuccess: Function
onSuccess: Function,
): void;
declare function removeRootView(containerTag: number): void;
declare function removeSubviewsFromContainerWithID(containerId: number): void;
declare function replaceExistingNonRootView(): void;
declare function setChildren(
containerTag: number,
reactTags: Array<number>
reactTags: Array<number>,
): void;
declare function updateView(
reactTag: number,
viewName: string,
props: ?Object
props: ?Object,
): void;
declare function __takeSnapshot(
view?: 'window' | Element<any> | number,
@@ -79,7 +79,7 @@ declare module 'UIManager' {
height?: number,
format?: 'png' | 'jpeg',
quality?: number,
}
},
): Promise<any>;
}
declare module 'View' {
@@ -90,14 +90,14 @@ declare module 'RTManager' {
declare function createNode(
tag: number,
classType: string,
props: ?Object
props: ?Object,
): void;
declare function beginUpdates(): void;
declare function appendChildToContext(
contextTag: number,
childTag: number
childTag: number,
): void;
declare function appendChild(parentTag: number, childTag: number): void;
declare function prependChild(childTag: number, beforeTag: number): void;

View File

@@ -1,29 +1,29 @@
'use strict';
var path = require('path');
const path = require('path');
var babel = require('babel-core');
var coffee = require('coffee-script');
const babel = require('babel-core');
const coffee = require('coffee-script');
var tsPreprocessor = require('./typescript/preprocessor');
var createCacheKeyFunction = require('fbjs-scripts/jest/createCacheKeyFunction');
const tsPreprocessor = require('./typescript/preprocessor');
const createCacheKeyFunction = require('fbjs-scripts/jest/createCacheKeyFunction');
// Use require.resolve to be resilient to file moves, npm updates, etc
var pathToBabel = path.join(
const pathToBabel = path.join(
require.resolve('babel-core'),
'..',
'package.json'
);
var pathToBabelPluginDevWithCode = require.resolve(
const pathToBabelPluginDevWithCode = require.resolve(
'../error-codes/replace-invariant-error-codes'
);
var pathToBabelPluginAsyncToGenerator = require.resolve(
const pathToBabelPluginAsyncToGenerator = require.resolve(
'babel-plugin-transform-async-to-generator'
);
var pathToBabelrc = path.join(__dirname, '..', '..', '.babelrc');
var pathToErrorCodes = require.resolve('../error-codes/codes.json');
const pathToBabelrc = path.join(__dirname, '..', '..', '.babelrc');
const pathToErrorCodes = require.resolve('../error-codes/codes.json');
var babelOptions = {
const babelOptions = {
plugins: [
// For Node environment only. For builds, Rollup takes care of ESM.
require.resolve('babel-plugin-transform-es2015-modules-commonjs'),
@@ -51,7 +51,7 @@ module.exports = {
if (!filePath.match(/\/third_party\//)) {
// for test files, we also apply the async-await transform, but we want to
// make sure we don't accidentally apply that transform to product code.
var isTestFile = !!filePath.match(/\/__tests__\//);
const isTestFile = !!filePath.match(/\/__tests__\//);
return babel.transform(
src,
Object.assign(

View File

@@ -5,8 +5,8 @@ if (process.env.REACT_CLASS_EQUIVALENCE_TEST) {
// require that instead.
require('./spec-equivalence-reporter/setupTests.js');
} else {
var env = jasmine.getEnv();
var errorMap = require('../error-codes/codes.json');
const env = jasmine.getEnv();
const errorMap = require('../error-codes/codes.json');
// TODO: Stop using spyOn in all the test since that seem deprecated.
// This is a legacy upgrade path strategy from:
@@ -56,8 +56,8 @@ if (process.env.REACT_CLASS_EQUIVALENCE_TEST) {
});
['error', 'warn'].forEach(methodName => {
var oldMethod = console[methodName];
var newMethod = function() {
const oldMethod = console[methodName];
const newMethod = function() {
newMethod.__callCount++;
oldMethod.apply(this, arguments);
};
@@ -90,7 +90,7 @@ if (process.env.REACT_CLASS_EQUIVALENCE_TEST) {
if (process.env.NODE_ENV === 'production') {
// In production, we strip error messages and turn them into codes.
// This decodes them back so that the test assertions on them work.
var decodeErrorMessage = function(message) {
const decodeErrorMessage = function(message) {
if (!message) {
return message;
}

View File

@@ -7,9 +7,9 @@
'use strict';
var expect = global.expect;
const expect = global.expect;
var numExpectations = 0;
let numExpectations = 0;
global.expect = function() {
numExpectations += 1;

View File

@@ -1,10 +1,10 @@
'use strict';
var fs = require('fs');
var path = require('path');
var ts = require('typescript');
const fs = require('fs');
const path = require('path');
const ts = require('typescript');
var tsOptions = {
const tsOptions = {
module: ts.ModuleKind.CommonJS,
jsx: ts.JsxEmit.React,
};
@@ -20,12 +20,12 @@ function formatErrorMessage(error) {
}
function compile(content, contentFilename) {
var output = null;
var compilerHost = {
let output = null;
const compilerHost = {
getSourceFile(filename, languageVersion) {
var source;
var jestRegex = /jest\.d\.ts/;
var reactRegex = /(?:React|ReactDOM|PropTypes)(?:\.d)?\.ts$/;
let source;
const jestRegex = /jest\.d\.ts/;
const reactRegex = /(?:React|ReactDOM|PropTypes)(?:\.d)?\.ts$/;
// `path.normalize` is used to turn forward slashes in
// the file path into backslashes on Windows.
@@ -78,13 +78,15 @@ function compile(content, contentFilename) {
return ts.sys.useCaseSensitiveFileNames;
},
};
var program = ts.createProgram(
const program = ts.createProgram(
['lib.d.ts', 'jest.d.ts', contentFilename],
tsOptions,
compilerHost
);
var emitResult = program.emit();
var errors = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
const emitResult = program.emit();
const errors = ts
.getPreEmitDiagnostics(program)
.concat(emitResult.diagnostics);
if (errors.length) {
throw new Error(errors.map(formatErrorMessage).join('\n'));
}

View File

@@ -14,6 +14,7 @@ const glob = require('glob');
const prettier = require('prettier');
const fs = require('fs');
const listChangedFiles = require('../shared/listChangedFiles');
const {esNextPaths} = require('../shared/pathsByLanguageVersion');
const mode = process.argv[2] || 'check';
const shouldWrite = mode === 'write' || mode === 'write-changed';
@@ -28,35 +29,24 @@ const defaultOptions = {
};
const config = {
default: {
patterns: [
// Internal forwarding modules
'packages/*/*.js',
// Source files
'packages/*/src/**/*.js',
'packages/shared/**/*.js',
],
ignore: ['**/node_modules/**'],
},
scripts: {
patterns: [
// Forwarding modules that get published to npm (must be ES5)
'packages/*/npm/**/*.js',
// Need to work on Node
'scripts/**/*.js',
'fixtures/**/*.js',
],
patterns: ['**/*.js'],
ignore: [
'**/node_modules/**',
// Built files and React repo clone
'scripts/bench/benchmarks/**',
// ESNext paths can have trailing commas.
// We'll handle them separately below.
...esNextPaths,
],
options: {
trailingComma: 'es5',
},
},
esNext: {
patterns: [...esNextPaths],
ignore: ['**/node_modules/**'],
},
};
var changedFiles = listChangedFiles();
const changedFiles = onlyChanged ? listChangedFiles() : null;
let didWarn = false;
let didError = false;
Object.keys(config).forEach(key => {

View File

@@ -17,11 +17,11 @@ function transform(input) {
}
function compare(input, output) {
var compiled = transform(input);
const compiled = transform(input);
expect(compiled).toEqual(output);
}
var oldEnv;
let oldEnv;
describe('wrap-warning-with-env-check', () => {
beforeEach(() => {

View File

@@ -7,17 +7,17 @@
'use strict';
module.exports = function(babel, options) {
var t = babel.types;
const t = babel.types;
var DEV_EXPRESSION = t.identifier('__DEV__');
const DEV_EXPRESSION = t.identifier('__DEV__');
var SEEN_SYMBOL = Symbol('expression.seen');
const SEEN_SYMBOL = Symbol('expression.seen');
return {
visitor: {
CallExpression: {
exit: function(path) {
var node = path.node;
const node = path.node;
// Ignore if it's already been processed
if (node[SEEN_SYMBOL]) {

View File

@@ -9,6 +9,6 @@
'use strict';
var ReactDOM = require('ReactDOM-fb');
const ReactDOM = require('ReactDOM-fb');
module.exports = ReactDOM.unstable_renderSubtreeIntoContainer;

View File

@@ -9,7 +9,7 @@
'use strict';
var ReactFeatureFlags = {
const ReactFeatureFlags = {
debugRenderPhaseSideEffects: false,
};

View File

@@ -6,12 +6,13 @@
*/
'use strict';
var evalToString = require('../evalToString');
var babylon = require('babylon');
const evalToString = require('../evalToString');
const babylon = require('babylon');
var parse = source => babylon.parse(`(${source});`).program.body[0].expression; // quick way to get an exp node
const parse = source =>
babylon.parse(`(${source});`).program.body[0].expression; // quick way to get an exp node
var parseAndEval = source => evalToString(parse(source));
const parseAndEval = source => evalToString(parse(source));
describe('evalToString', () => {
it('should support StringLiteral', () => {

View File

@@ -10,7 +10,7 @@ const execFileSync = require('child_process').execFileSync;
const exec = (command, args) => {
console.log('> ' + [command].concat(args).join(' '));
var options = {
const options = {
cwd: process.cwd(),
env: process.env,
stdio: 'pipe',
@@ -18,15 +18,15 @@ const exec = (command, args) => {
};
return execFileSync(command, args, options);
};
const execGitCmd = args =>
exec('git', args)
.trim()
.toString()
.split('\n');
const mergeBase = execGitCmd(['merge-base', 'HEAD', 'master']);
const listChangedFiles = () => {
const mergeBase = execGitCmd(['merge-base', 'HEAD', 'master']);
return new Set([
...execGitCmd(['diff', '--name-only', '--diff-filter=ACMRTUB', mergeBase]),
...execGitCmd(['ls-files', '--others', '--exclude-standard']),

View File

@@ -0,0 +1,28 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
// Files that are transformed and can use ES6/Flow/JSX.
const esNextPaths = [
// Internal forwarding modules
'packages/*/*.js',
// Source files
'packages/*/src/**/*.js',
'packages/events/**/*.js',
'packages/shared/**/*.js',
// Shims and Flow environment
'scripts/flow/*.js',
'scripts/rollup/shims/**/*.js',
];
// Files that we distribute on npm that should be ES5-only.
const es5Paths = ['packages/*/npm/**/*.js'];
module.exports = {
esNextPaths,
es5Paths,
};

View File

@@ -7,11 +7,16 @@
'use strict';
const lintOnFiles = require('../eslint');
const report = lintOnFiles(['.']);
if (report.errorCount > 0 || report.warningCount > 0) {
const runESLint = require('../eslint');
console.log('Linting all files...');
if (!process.CI) {
console.log('Hint: run `yarn linc` to only lint changed files.');
}
if (runESLint({onlyChanged: false})) {
console.log('Lint passed.');
} else {
console.log('Lint failed.');
process.exit(1);
} else {
console.log('Lint passed.');
}

View File

@@ -7,10 +7,10 @@
'use strict';
var path = require('path');
var spawn = require('child_process').spawn;
const path = require('path');
const spawn = require('child_process').spawn;
var extension = process.platform === 'win32' ? '.cmd' : '';
const extension = process.platform === 'win32' ? '.cmd' : '';
spawn(path.join('node_modules', '.bin', 'flow' + extension), ['check', '.'], {
// Allow colors to pass through

View File

@@ -7,24 +7,13 @@
'use strict';
const lintOnFiles = require('../eslint');
const listChangedFiles = require('../shared/listChangedFiles');
const runESLint = require('../eslint');
const changedFiles = [...listChangedFiles()];
const jsFiles = changedFiles.filter(file => file.match(/.js$/g));
console.log('Linting changed files...');
const report = lintOnFiles(jsFiles);
if (report.errorCount > 0 || getSourceCodeWarnings(report)) {
if (runESLint({onlyChanged: true})) {
console.log('Lint passed for changed files.');
} else {
console.log('Lint failed for changed files.');
process.exit(1);
} else {
console.log('Lint passed for changed files.');
}
// Prevents failing if the only warnings are about ignored files (#11615)
function getSourceCodeWarnings({warningCount, results}) {
const ignoreWanings = results.filter(
({messages}) => messages[0] && messages[0].message.includes('File ignored')
);
return warningCount > 0 ? warningCount !== ignoreWanings.length : false;
}