Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable no-use-before-define rule #13606

Merged
merged 1 commit into from
Sep 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ module.exports = {
'no-shadow': ERROR,
'no-unused-expressions': ERROR,
'no-unused-vars': [ERROR, {args: 'none'}],
'no-use-before-define': [ERROR, {functions: false, variables: false}],
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming of these options is confusing. It basically means "still allow to rely on function hoisting, and don't complain about variables unless they are in the same scope".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming of these options is confusing. It basically means "still allow to rely on function hoisting, and don't complain about variables unless they are in the same scope".

If .eslintrc.js is a .js would it make sense to put this explanation in a comment next to the added option?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, but then we almost never change the config so I don't think it's that helpful. Can always blame to a PR if necessary.

'no-useless-concat': OFF,
'quotes': [ERROR, 'single', {avoidEscape: true, allowTemplateLiterals: true }],
'space-before-blocks': ERROR,
Expand Down
28 changes: 15 additions & 13 deletions packages/react-dom/src/client/ReactDOM.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ if (__DEV__) {

ReactControlledComponent.setRestoreImplementation(restoreControlledState);

/* eslint-disable no-use-before-define */
type DOMContainer =
| (Element & {
_reactRootContainer: ?Root,
Expand All @@ -150,6 +151,20 @@ type Batch = FiberRootBatch & {
_didComplete: boolean,
};

type Root = {
render(children: ReactNodeList, callback: ?() => mixed): Work,
unmount(callback: ?() => mixed): Work,
legacy_renderSubtreeIntoContainer(
parentComponent: ?React$Component<any, any>,
children: ReactNodeList,
callback: ?() => mixed,
): Work,
createBatch(): Batch,

_internalRoot: FiberRoot,
};
/* eslint-enable no-use-before-define */

function ReactBatch(root: ReactRoot) {
const expirationTime = DOMRenderer.computeUniqueAsyncExpiration();
this._expirationTime = expirationTime;
Expand Down Expand Up @@ -317,19 +332,6 @@ ReactWork.prototype._onCommit = function(): void {
}
};

type Root = {
render(children: ReactNodeList, callback: ?() => mixed): Work,
unmount(callback: ?() => mixed): Work,
legacy_renderSubtreeIntoContainer(
parentComponent: ?React$Component<any, any>,
children: ReactNodeList,
callback: ?() => mixed,
): Work,
createBatch(): Batch,

_internalRoot: FiberRoot,
};

function ReactRoot(container: Container, isAsync: boolean, hydrate: boolean) {
const root = DOMRenderer.createContainer(container, isAsync, hydrate);
this._internalRoot = root;
Expand Down
2 changes: 2 additions & 0 deletions packages/react-native-renderer/src/ReactFabricHostConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import UIManager from 'UIManager';
// This means that they never overlap.
let nextReactTag = 2;

/* eslint-disable no-use-before-define */
type Node = Object;
export type Type = string;
export type Props = Object;
Expand All @@ -71,6 +72,7 @@ export type UpdatePayload = Object;

export type TimeoutHandle = TimeoutID;
export type NoTimeout = -1;
/* eslint-enable no-use-before-define */

// TODO: Remove this conditional once all changes have propagated.
if (registerEventHandler) {
Expand Down
2 changes: 2 additions & 0 deletions packages/react-noop-renderer/src/createReactNoop.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import type {ReactNodeList} from 'shared/ReactTypes';
import * as ReactPortal from 'shared/ReactPortal';
import expect from 'expect';

/* eslint-disable no-use-before-define */
type Container = {rootID: string, children: Array<Instance | TextInstance>};
type Props = {prop: any, hidden?: boolean, children?: mixed};
type Instance = {|
Expand All @@ -30,6 +31,7 @@ type Instance = {|
prop: any,
|};
type TextInstance = {|text: string, id: number|};
/* eslint-enable no-use-before-define */

const NO_CONTEXT = {};
const UPDATE_SIGNAL = {};
Expand Down
2 changes: 2 additions & 0 deletions packages/react-reconciler/src/ReactFiberRoot.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {NoWork} from './ReactFiberExpirationTime';
import {enableSchedulerTracking} from 'shared/ReactFeatureFlags';
import {unstable_getThreadID} from 'schedule/tracking';

/* eslint-disable no-use-before-define */
// TODO: This should be lifted into the renderer.
export type Batch = {
_defer: boolean,
Expand Down Expand Up @@ -98,6 +99,7 @@ export type FiberRoot = {
...BaseFiberRootProperties,
...ProfilingOnlyFiberRootProperties,
};
/* eslint-enable no-use-before-define */

export function createFiberRoot(
containerInfo: any,
Expand Down
132 changes: 66 additions & 66 deletions packages/react-test-renderer/src/ReactShallowRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,72 @@ if (__DEV__) {
Object.freeze(emptyObject);
}

class Updater {
constructor(renderer) {
this._renderer = renderer;
this._callbacks = [];
}

_enqueueCallback(callback, publicInstance) {
if (typeof callback === 'function' && publicInstance) {
this._callbacks.push({
callback,
publicInstance,
});
}
}

_invokeCallbacks() {
const callbacks = this._callbacks;
this._callbacks = [];

callbacks.forEach(({callback, publicInstance}) => {
callback.call(publicInstance);
});
}

isMounted(publicInstance) {
return !!this._renderer._element;
}

enqueueForceUpdate(publicInstance, callback, callerName) {
this._enqueueCallback(callback, publicInstance);
this._renderer._forcedUpdate = true;
this._renderer.render(this._renderer._element, this._renderer._context);
}

enqueueReplaceState(publicInstance, completeState, callback, callerName) {
this._enqueueCallback(callback, publicInstance);
this._renderer._newState = completeState;
this._renderer.render(this._renderer._element, this._renderer._context);
}

enqueueSetState(publicInstance, partialState, callback, callerName) {
this._enqueueCallback(callback, publicInstance);
const currentState = this._renderer._newState || publicInstance.state;

if (typeof partialState === 'function') {
partialState = partialState.call(
publicInstance,
currentState,
publicInstance.props,
);
}

// Null and undefined are treated as no-ops.
if (partialState === null || partialState === undefined) {
return;
}

this._renderer._newState = {
...currentState,
...partialState,
};

this._renderer.render(this._renderer._element, this._renderer._context);
}
}

class ReactShallowRenderer {
static createRenderer = function() {
return new ReactShallowRenderer();
Expand Down Expand Up @@ -263,72 +329,6 @@ class ReactShallowRenderer {
}
}

class Updater {
constructor(renderer) {
this._renderer = renderer;
this._callbacks = [];
}

_enqueueCallback(callback, publicInstance) {
if (typeof callback === 'function' && publicInstance) {
this._callbacks.push({
callback,
publicInstance,
});
}
}

_invokeCallbacks() {
const callbacks = this._callbacks;
this._callbacks = [];

callbacks.forEach(({callback, publicInstance}) => {
callback.call(publicInstance);
});
}

isMounted(publicInstance) {
return !!this._renderer._element;
}

enqueueForceUpdate(publicInstance, callback, callerName) {
this._enqueueCallback(callback, publicInstance);
this._renderer._forcedUpdate = true;
this._renderer.render(this._renderer._element, this._renderer._context);
}

enqueueReplaceState(publicInstance, completeState, callback, callerName) {
this._enqueueCallback(callback, publicInstance);
this._renderer._newState = completeState;
this._renderer.render(this._renderer._element, this._renderer._context);
}

enqueueSetState(publicInstance, partialState, callback, callerName) {
this._enqueueCallback(callback, publicInstance);
const currentState = this._renderer._newState || publicInstance.state;

if (typeof partialState === 'function') {
partialState = partialState.call(
publicInstance,
currentState,
publicInstance.props,
);
}

// Null and undefined are treated as no-ops.
if (partialState === null || partialState === undefined) {
return;
}

this._renderer._newState = {
...currentState,
...partialState,
};

this._renderer.render(this._renderer._element, this._renderer._context);
}
}

let currentlyValidatingElement = null;

function getDisplayName(element) {
Expand Down
2 changes: 2 additions & 0 deletions packages/react-test-renderer/src/ReactTestHostConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import warning from 'shared/warning';
import * as TestRendererScheduling from './ReactTestRendererScheduling';

/* eslint-disable no-use-before-define */
export type Type = string;
export type Props = Object;
export type Container = {|
Expand All @@ -35,6 +36,7 @@ export type UpdatePayload = Object;
export type ChildSet = void; // Unused
export type TimeoutHandle = TimeoutID;
export type NoTimeout = -1;
/* eslint-enable no-use-before-define */

export * from 'shared/HostConfigWithNoPersistence';
export * from 'shared/HostConfigWithNoHydration';
Expand Down
28 changes: 15 additions & 13 deletions packages/react-test-renderer/src/ReactTestRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import ReactVersion from 'shared/ReactVersion';
import * as ReactTestHostConfig from './ReactTestHostConfig';
import * as TestRendererScheduling from './ReactTestRendererScheduling';

/* eslint-disable no-use-before-define */
type TestRendererOptions = {
createNodeMock: (element: React$Element<any>) => any,
unstable_isAsync: boolean,
Expand All @@ -57,6 +58,7 @@ type FindOptions = $Shape<{
}>;

export type Predicate = (node: ReactTestInstance) => ?boolean;
/* eslint-enable no-use-before-define */

const defaultTestOptions = {
createNodeMock: function() {
Expand Down Expand Up @@ -209,19 +211,6 @@ function toTree(node: ?Fiber) {
}
}

const fiberToWrapper = new WeakMap();
function wrapFiber(fiber: Fiber): ReactTestInstance {
let wrapper = fiberToWrapper.get(fiber);
if (wrapper === undefined && fiber.alternate !== null) {
wrapper = fiberToWrapper.get(fiber.alternate);
}
if (wrapper === undefined) {
wrapper = new ReactTestInstance(fiber);
fiberToWrapper.set(fiber, wrapper);
}
return wrapper;
}

const validWrapperTypes = new Set([
FunctionalComponent,
FunctionalComponentLazy,
Expand Down Expand Up @@ -543,6 +532,19 @@ const ReactTestRendererFiber = {
unstable_setNowImplementation: TestRendererScheduling.setNowImplementation,
};

const fiberToWrapper = new WeakMap();
function wrapFiber(fiber: Fiber): ReactTestInstance {
let wrapper = fiberToWrapper.get(fiber);
if (wrapper === undefined && fiber.alternate !== null) {
wrapper = fiberToWrapper.get(fiber.alternate);
}
if (wrapper === undefined) {
wrapper = new ReactTestInstance(fiber);
fiberToWrapper.set(fiber, wrapper);
}
return wrapper;
}

// Enable ReactTestRenderer to be used to test DevTools integration.
TestRenderer.injectIntoDevTools({
findFiberByHostInstance: (() => {
Expand Down
6 changes: 4 additions & 2 deletions packages/shared/ReactTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,24 @@
* @flow
*/

/* eslint-disable no-use-before-define */
export type ReactNode =
| React$Element<any>
| ReactPortal
| ReactText
| ReactFragment
| ReactProvider<any>
| ReactConsumer<any>;
/* eslint-enable no-use-before-define */

export type ReactEmpty = null | void | boolean;

export type ReactFragment = ReactEmpty | Iterable<React$Node>;

export type ReactNodeList = ReactEmpty | React$Node;

export type ReactText = string | number;

export type ReactEmpty = null | void | boolean;

export type ReactProvider<T> = {
$$typeof: Symbol | number,
type: ReactProviderType<T>,
Expand Down