From 7e52e2f3a8e64daf49d933d0f731cba209fa47df Mon Sep 17 00:00:00 2001 From: Dan Date: Sun, 9 Sep 2018 19:04:34 +0100 Subject: [PATCH] Enable no-use-before-define rule --- .eslintrc.js | 1 + packages/react-dom/src/client/ReactDOM.js | 28 ++-- .../src/ReactFabricHostConfig.js | 2 + .../src/createReactNoop.js | 2 + .../react-reconciler/src/ReactFiberRoot.js | 2 + .../src/ReactShallowRenderer.js | 132 +++++++++--------- .../src/ReactTestHostConfig.js | 2 + .../src/ReactTestRenderer.js | 28 ++-- packages/shared/ReactTypes.js | 6 +- 9 files changed, 109 insertions(+), 94 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 4f085721abe28..4444c643eab89 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -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}], 'no-useless-concat': OFF, 'quotes': [ERROR, 'single', {avoidEscape: true, allowTemplateLiterals: true }], 'space-before-blocks': ERROR, diff --git a/packages/react-dom/src/client/ReactDOM.js b/packages/react-dom/src/client/ReactDOM.js index d8e955b88b104..80029c4fcc983 100644 --- a/packages/react-dom/src/client/ReactDOM.js +++ b/packages/react-dom/src/client/ReactDOM.js @@ -126,6 +126,7 @@ if (__DEV__) { ReactControlledComponent.setRestoreImplementation(restoreControlledState); +/* eslint-disable no-use-before-define */ type DOMContainer = | (Element & { _reactRootContainer: ?Root, @@ -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, + 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; @@ -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, - 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; diff --git a/packages/react-native-renderer/src/ReactFabricHostConfig.js b/packages/react-native-renderer/src/ReactFabricHostConfig.js index a3be7a3cb9afa..8d66c97b44ec5 100644 --- a/packages/react-native-renderer/src/ReactFabricHostConfig.js +++ b/packages/react-native-renderer/src/ReactFabricHostConfig.js @@ -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; @@ -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) { diff --git a/packages/react-noop-renderer/src/createReactNoop.js b/packages/react-noop-renderer/src/createReactNoop.js index e761e0b353958..1d71bd8ab55d5 100644 --- a/packages/react-noop-renderer/src/createReactNoop.js +++ b/packages/react-noop-renderer/src/createReactNoop.js @@ -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}; type Props = {prop: any, hidden?: boolean, children?: mixed}; type Instance = {| @@ -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 = {}; diff --git a/packages/react-reconciler/src/ReactFiberRoot.js b/packages/react-reconciler/src/ReactFiberRoot.js index 9c35ceede17ad..0065f841d0363 100644 --- a/packages/react-reconciler/src/ReactFiberRoot.js +++ b/packages/react-reconciler/src/ReactFiberRoot.js @@ -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, @@ -98,6 +99,7 @@ export type FiberRoot = { ...BaseFiberRootProperties, ...ProfilingOnlyFiberRootProperties, }; +/* eslint-enable no-use-before-define */ export function createFiberRoot( containerInfo: any, diff --git a/packages/react-test-renderer/src/ReactShallowRenderer.js b/packages/react-test-renderer/src/ReactShallowRenderer.js index e20fd9a604ea6..9bf373d033caf 100644 --- a/packages/react-test-renderer/src/ReactShallowRenderer.js +++ b/packages/react-test-renderer/src/ReactShallowRenderer.js @@ -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(); @@ -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) { diff --git a/packages/react-test-renderer/src/ReactTestHostConfig.js b/packages/react-test-renderer/src/ReactTestHostConfig.js index 57eb83ec11fc5..20131dfc74a97 100644 --- a/packages/react-test-renderer/src/ReactTestHostConfig.js +++ b/packages/react-test-renderer/src/ReactTestHostConfig.js @@ -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 = {| @@ -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'; diff --git a/packages/react-test-renderer/src/ReactTestRenderer.js b/packages/react-test-renderer/src/ReactTestRenderer.js index 5563ca5745536..4b0c50df69d2e 100644 --- a/packages/react-test-renderer/src/ReactTestRenderer.js +++ b/packages/react-test-renderer/src/ReactTestRenderer.js @@ -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, unstable_isAsync: boolean, @@ -57,6 +58,7 @@ type FindOptions = $Shape<{ }>; export type Predicate = (node: ReactTestInstance) => ?boolean; +/* eslint-enable no-use-before-define */ const defaultTestOptions = { createNodeMock: function() { @@ -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, @@ -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: (() => { diff --git a/packages/shared/ReactTypes.js b/packages/shared/ReactTypes.js index bd4a47ed9e68d..4beed2224b314 100644 --- a/packages/shared/ReactTypes.js +++ b/packages/shared/ReactTypes.js @@ -7,6 +7,7 @@ * @flow */ +/* eslint-disable no-use-before-define */ export type ReactNode = | React$Element | ReactPortal @@ -14,6 +15,9 @@ export type ReactNode = | ReactFragment | ReactProvider | ReactConsumer; +/* eslint-enable no-use-before-define */ + +export type ReactEmpty = null | void | boolean; export type ReactFragment = ReactEmpty | Iterable; @@ -21,8 +25,6 @@ export type ReactNodeList = ReactEmpty | React$Node; export type ReactText = string | number; -export type ReactEmpty = null | void | boolean; - export type ReactProvider = { $$typeof: Symbol | number, type: ReactProviderType,