From 1cb6199d22af6f6ba2f55e4db18ed2f4216aaaf2 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Wed, 22 Nov 2017 18:08:22 +0000 Subject: [PATCH] Consolidate all symbols in a single file (#11629) * Consolidate all symbols in a single file This reduces the code duplication as we have quite a few now. * Record sizes --- .../react-call-return/src/ReactCallReturn.js | 14 +- .../src/server/ReactPartialRenderer.js | 7 +- .../react-reconciler/src/ReactChildFiber.js | 43 +---- packages/react-reconciler/src/ReactPortal.js | 8 +- packages/react/src/React.js | 7 +- packages/react/src/ReactChildren.js | 27 +-- packages/react/src/ReactElement.js | 7 +- packages/react/src/ReactElementValidator.js | 13 +- packages/shared/ReactSymbols.js | 42 +++++ scripts/rollup/results.json | 160 +++++++++--------- 10 files changed, 147 insertions(+), 181 deletions(-) create mode 100644 packages/shared/ReactSymbols.js diff --git a/packages/react-call-return/src/ReactCallReturn.js b/packages/react-call-return/src/ReactCallReturn.js index c39c71dcea..c6979dd436 100644 --- a/packages/react-call-return/src/ReactCallReturn.js +++ b/packages/react-call-return/src/ReactCallReturn.js @@ -7,19 +7,9 @@ * @flow */ -import type {ReactCall, ReactNodeList, ReactReturn} from 'shared/ReactTypes'; +import {REACT_CALL_TYPE, REACT_RETURN_TYPE} from 'shared/ReactSymbols'; -// The Symbol used to tag the special React types. If there is no native Symbol -// nor polyfill, then a plain number is used for performance. -var REACT_CALL_TYPE; -var REACT_RETURN_TYPE; -if (typeof Symbol === 'function' && Symbol.for) { - REACT_CALL_TYPE = Symbol.for('react.call'); - REACT_RETURN_TYPE = Symbol.for('react.return'); -} else { - REACT_CALL_TYPE = 0xeac8; - REACT_RETURN_TYPE = 0xeac9; -} +import type {ReactCall, ReactNodeList, ReactReturn} from 'shared/ReactTypes'; type CallHandler = (props: T, returns: Array) => ReactNodeList; diff --git a/packages/react-dom/src/server/ReactPartialRenderer.js b/packages/react-dom/src/server/ReactPartialRenderer.js index 5568ab504e..64ac4c8f4e 100644 --- a/packages/react-dom/src/server/ReactPartialRenderer.js +++ b/packages/react-dom/src/server/ReactPartialRenderer.js @@ -19,6 +19,7 @@ import warning from 'fbjs/lib/warning'; import checkPropTypes from 'prop-types/checkPropTypes'; import describeComponentFrame from 'shared/describeComponentFrame'; import {ReactDebugCurrentFrame} from 'shared/ReactGlobalSharedState'; +import {REACT_FRAGMENT_TYPE} from 'shared/ReactSymbols'; import { createMarkupForCustomAttribute, @@ -41,12 +42,6 @@ import {validateProperties as validateARIAProperties} from '../shared/ReactDOMIn import {validateProperties as validateInputProperties} from '../shared/ReactDOMNullInputValuePropHook'; import {validateProperties as validateUnknownProperties} from '../shared/ReactDOMUnknownPropertyHook'; -var REACT_FRAGMENT_TYPE = - (typeof Symbol === 'function' && - Symbol.for && - Symbol.for('react.fragment')) || - 0xeacb; - // Based on reading the React.Children implementation. TODO: type this somewhere? type ReactNode = string | number | ReactElement; type FlatReactChildren = Array; diff --git a/packages/react-reconciler/src/ReactChildFiber.js b/packages/react-reconciler/src/ReactChildFiber.js index 695e40c381..eb5bbed37f 100644 --- a/packages/react-reconciler/src/ReactChildFiber.js +++ b/packages/react-reconciler/src/ReactChildFiber.js @@ -14,6 +14,14 @@ import type {ExpirationTime} from 'react-reconciler/src/ReactFiberExpirationTime import {enableReactFragment} from 'shared/ReactFeatureFlags'; import {Placement, Deletion} from 'shared/ReactTypeOfSideEffect'; +import { + getIteratorFn, + REACT_ELEMENT_TYPE, + REACT_FRAGMENT_TYPE, + REACT_CALL_TYPE, + REACT_RETURN_TYPE, + REACT_PORTAL_TYPE, +} from 'shared/ReactSymbols'; import { FunctionalComponent, ClassComponent, @@ -27,7 +35,6 @@ import emptyObject from 'fbjs/lib/emptyObject'; import invariant from 'fbjs/lib/invariant'; import warning from 'fbjs/lib/warning'; -import {REACT_PORTAL_TYPE} from './ReactPortal'; import { createWorkInProgress, createFiberFromElement, @@ -87,40 +94,6 @@ if (__DEV__) { const isArray = Array.isArray; -const ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; -const FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec. - -// The Symbol used to tag the ReactElement-like types. If there is no native Symbol -// nor polyfill, then a plain number is used for performance. -var REACT_ELEMENT_TYPE; -var REACT_CALL_TYPE; -var REACT_RETURN_TYPE; -var REACT_FRAGMENT_TYPE; -if (typeof Symbol === 'function' && Symbol.for) { - REACT_ELEMENT_TYPE = Symbol.for('react.element'); - REACT_CALL_TYPE = Symbol.for('react.call'); - REACT_RETURN_TYPE = Symbol.for('react.return'); - REACT_FRAGMENT_TYPE = Symbol.for('react.fragment'); -} else { - REACT_ELEMENT_TYPE = 0xeac7; - REACT_CALL_TYPE = 0xeac8; - REACT_RETURN_TYPE = 0xeac9; - REACT_FRAGMENT_TYPE = 0xeacb; -} - -function getIteratorFn(maybeIterable: ?any): ?() => ?Iterator<*> { - if (maybeIterable === null || typeof maybeIterable === 'undefined') { - return null; - } - const iteratorFn = - (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL]) || - maybeIterable[FAUX_ITERATOR_SYMBOL]; - if (typeof iteratorFn === 'function') { - return iteratorFn; - } - return null; -} - function coerceRef(current: Fiber | null, element: ReactElement) { let mixedRef = element.ref; if (mixedRef !== null && typeof mixedRef !== 'function') { diff --git a/packages/react-reconciler/src/ReactPortal.js b/packages/react-reconciler/src/ReactPortal.js index fe46e71225..c20459c4b6 100644 --- a/packages/react-reconciler/src/ReactPortal.js +++ b/packages/react-reconciler/src/ReactPortal.js @@ -7,13 +7,9 @@ * @flow */ -import type {ReactNodeList, ReactPortal} from 'shared/ReactTypes'; +import {REACT_PORTAL_TYPE} from 'shared/ReactSymbols'; -// The Symbol used to tag the special React types. If there is no native Symbol -// nor polyfill, then a plain number is used for performance. -export const REACT_PORTAL_TYPE = - (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.portal')) || - 0xeaca; +import type {ReactNodeList, ReactPortal} from 'shared/ReactTypes'; export function createPortal( children: ReactNodeList, diff --git a/packages/react/src/React.js b/packages/react/src/React.js index f25181ea80..55c96f6d80 100644 --- a/packages/react/src/React.js +++ b/packages/react/src/React.js @@ -8,6 +8,7 @@ import assign from 'object-assign'; import ReactVersion from 'shared/ReactVersion'; import {enableReactFragment} from 'shared/ReactFeatureFlags'; +import {REACT_FRAGMENT_TYPE} from 'shared/ReactSymbols'; import {Component, PureComponent, AsyncComponent} from './ReactBaseClasses'; import {forEach, map, count, toArray, only} from './ReactChildren'; @@ -25,12 +26,6 @@ import { } from './ReactElementValidator'; import ReactDebugCurrentFrame from './ReactDebugCurrentFrame'; -const REACT_FRAGMENT_TYPE = - (typeof Symbol === 'function' && - Symbol.for && - Symbol.for('react.fragment')) || - 0xeacb; - var React = { Children: { map, diff --git a/packages/react/src/ReactChildren.js b/packages/react/src/ReactChildren.js index 44c65ae8cb..26bd88f8c6 100644 --- a/packages/react/src/ReactChildren.js +++ b/packages/react/src/ReactChildren.js @@ -8,26 +8,17 @@ import emptyFunction from 'fbjs/lib/emptyFunction'; import invariant from 'fbjs/lib/invariant'; import warning from 'fbjs/lib/warning'; +import { + getIteratorFn, + REACT_ELEMENT_TYPE, + REACT_CALL_TYPE, + REACT_RETURN_TYPE, + REACT_PORTAL_TYPE, +} from 'shared/ReactSymbols'; import {isValidElement, cloneAndReplaceKey} from './ReactElement'; import ReactDebugCurrentFrame from './ReactDebugCurrentFrame'; -var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; -var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec. -// The Symbol used to tag the ReactElement type. If there is no native Symbol -// nor polyfill, then a plain number is used for performance. -var REACT_ELEMENT_TYPE = - (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element')) || - 0xeac7; -const REACT_CALL_TYPE = - (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.call')) || - 0xeac8; -const REACT_RETURN_TYPE = - (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.return')) || - 0xeac9; -const REACT_PORTAL_TYPE = - (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.portal')) || - 0xeaca; var SEPARATOR = '.'; var SUBSEPARATOR = ':'; @@ -170,9 +161,7 @@ function traverseAllChildrenImpl( ); } } else { - var iteratorFn = - (ITERATOR_SYMBOL && children[ITERATOR_SYMBOL]) || - children[FAUX_ITERATOR_SYMBOL]; + var iteratorFn = getIteratorFn(children); if (typeof iteratorFn === 'function') { if (__DEV__) { // Warn about using Maps as children diff --git a/packages/react/src/ReactElement.js b/packages/react/src/ReactElement.js index ba3ba2c3a0..979494b3ab 100644 --- a/packages/react/src/ReactElement.js +++ b/packages/react/src/ReactElement.js @@ -6,17 +6,12 @@ */ import warning from 'fbjs/lib/warning'; +import {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols'; import ReactCurrentOwner from './ReactCurrentOwner'; var hasOwnProperty = Object.prototype.hasOwnProperty; -// The Symbol used to tag the ReactElement type. If there is no native Symbol -// nor polyfill, then a plain number is used for performance. -var REACT_ELEMENT_TYPE = - (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element')) || - 0xeac7; - var RESERVED_PROPS = { key: true, ref: true, diff --git a/packages/react/src/ReactElementValidator.js b/packages/react/src/ReactElementValidator.js index f4e4cf6eeb..f3f16f7649 100644 --- a/packages/react/src/ReactElementValidator.js +++ b/packages/react/src/ReactElementValidator.js @@ -15,6 +15,7 @@ import lowPriorityWarning from 'shared/lowPriorityWarning'; import describeComponentFrame from 'shared/describeComponentFrame'; import getComponentName from 'shared/getComponentName'; +import {getIteratorFn, REACT_FRAGMENT_TYPE} from 'shared/ReactSymbols'; import checkPropTypes from 'prop-types/checkPropTypes'; import warning from 'fbjs/lib/warning'; @@ -54,18 +55,9 @@ if (__DEV__) { return stack; }; - var REACT_FRAGMENT_TYPE = - (typeof Symbol === 'function' && - Symbol.for && - Symbol.for('react.fragment')) || - 0xeacb; - var VALID_FRAGMENT_PROPS = new Map([['children', true], ['key', true]]); } -var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; -var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec. - function getDeclarationErrorAddendum() { if (ReactCurrentOwner.current) { var name = getComponentName(ReactCurrentOwner.current); @@ -190,8 +182,7 @@ function validateChildKeys(node, parentType) { node._store.validated = true; } } else if (node) { - var iteratorFn = - (ITERATOR_SYMBOL && node[ITERATOR_SYMBOL]) || node[FAUX_ITERATOR_SYMBOL]; + var iteratorFn = getIteratorFn(node); if (typeof iteratorFn === 'function') { // Entry iterators used to provide implicit keys, // but now we print a separate warning for them later. diff --git a/packages/shared/ReactSymbols.js b/packages/shared/ReactSymbols.js new file mode 100644 index 0000000000..d914c0f25e --- /dev/null +++ b/packages/shared/ReactSymbols.js @@ -0,0 +1,42 @@ +/** + * 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. + * + * @flow + */ + +// The Symbol used to tag the ReactElement-like types. If there is no native Symbol +// nor polyfill, then a plain number is used for performance. +const hasSymbol = typeof Symbol === 'function' && Symbol.for; + +export const REACT_ELEMENT_TYPE = hasSymbol + ? Symbol.for('react.element') + : 0xeac7; +export const REACT_CALL_TYPE = hasSymbol ? Symbol.for('react.call') : 0xeac8; +export const REACT_RETURN_TYPE = hasSymbol + ? Symbol.for('react.return') + : 0xeac9; +export const REACT_PORTAL_TYPE = hasSymbol + ? Symbol.for('react.portal') + : 0xeaca; +export const REACT_FRAGMENT_TYPE = hasSymbol + ? Symbol.for('react.fragment') + : 0xeacb; + +const MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; +const FAUX_ITERATOR_SYMBOL = '@@iterator'; + +export function getIteratorFn(maybeIterable: ?any): ?() => ?Iterator<*> { + if (maybeIterable === null || typeof maybeIterable === 'undefined') { + return null; + } + const maybeIterator = + (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || + maybeIterable[FAUX_ITERATOR_SYMBOL]; + if (typeof maybeIterator === 'function') { + return maybeIterator; + } + return null; +} diff --git a/scripts/rollup/results.json b/scripts/rollup/results.json index 9599ee8922..6c1dbfea26 100644 --- a/scripts/rollup/results.json +++ b/scripts/rollup/results.json @@ -1,52 +1,52 @@ { "bundleSizes": { "react.development.js (UMD_DEV)": { - "size": 55240, - "gzip": 14948 + "size": 54810, + "gzip": 14962 }, "react.production.min.js (UMD_PROD)": { - "size": 6773, - "gzip": 2809 + "size": 6603, + "gzip": 2820 }, "react.development.js (NODE_DEV)": { - "size": 45656, - "gzip": 12650 + "size": 45226, + "gzip": 12653 }, "react.production.min.js (NODE_PROD)": { - "size": 5573, - "gzip": 2371 + "size": 5398, + "gzip": 2384 }, "React-dev.js (FB_DEV)": { - "size": 45456, - "gzip": 12326 + "size": 44902, + "gzip": 12309 }, "React-prod.js (FB_PROD)": { - "size": 12948, - "gzip": 3412 + "size": 12778, + "gzip": 3446 }, "react-dom.development.js (UMD_DEV)": { - "size": 569612, - "gzip": 132927 + "size": 569313, + "gzip": 132931 }, "react-dom.production.min.js (UMD_PROD)": { - "size": 94898, - "gzip": 30780 + "size": 94831, + "gzip": 30731 }, "react-dom.development.js (NODE_DEV)": { - "size": 551033, - "gzip": 128045 + "size": 550734, + "gzip": 128057 }, "react-dom.production.min.js (NODE_PROD)": { - "size": 93076, - "gzip": 30004 + "size": 93027, + "gzip": 29952 }, "ReactDOM-dev.js (FB_DEV)": { - "size": 576250, - "gzip": 132429 + "size": 575937, + "gzip": 132396 }, "ReactDOM-prod.js (FB_PROD)": { - "size": 273030, - "gzip": 51739 + "size": 272856, + "gzip": 51733 }, "react-dom-test-utils.development.js (NODE_DEV)": { "size": 36191, @@ -85,96 +85,96 @@ "gzip": 5327 }, "react-dom-server.browser.development.js (UMD_DEV)": { - "size": 94649, - "gzip": 25531 + "size": 94825, + "gzip": 25613 }, "react-dom-server.browser.production.min.js (UMD_PROD)": { - "size": 14787, - "gzip": 5859 + "size": 14785, + "gzip": 5865 }, "react-dom-server.browser.development.js (NODE_DEV)": { - "size": 83711, - "gzip": 22732 + "size": 83887, + "gzip": 22828 }, "react-dom-server.browser.production.min.js (NODE_PROD)": { - "size": 14265, - "gzip": 5749 + "size": 14263, + "gzip": 5748 }, "ReactDOMServer-dev.js (FB_DEV)": { - "size": 87438, - "gzip": 22988 + "size": 87596, + "gzip": 23087 }, "ReactDOMServer-prod.js (FB_PROD)": { - "size": 31679, - "gzip": 8157 + "size": 31671, + "gzip": 8156 }, "react-dom-server.node.development.js (NODE_DEV)": { - "size": 85679, - "gzip": 23240 + "size": 85855, + "gzip": 23337 }, "react-dom-server.node.production.min.js (NODE_PROD)": { - "size": 15090, - "gzip": 6057 + "size": 15088, + "gzip": 6052 }, "react-art.development.js (UMD_DEV)": { - "size": 359855, - "gzip": 79647 + "size": 359556, + "gzip": 79609 }, "react-art.production.min.js (UMD_PROD)": { - "size": 83726, - "gzip": 25768 + "size": 83658, + "gzip": 25785 }, "react-art.development.js (NODE_DEV)": { - "size": 283932, - "gzip": 60558 + "size": 283633, + "gzip": 60512 }, "react-art.production.min.js (NODE_PROD)": { - "size": 47681, - "gzip": 14930 + "size": 47631, + "gzip": 14903 }, "ReactART-dev.js (FB_DEV)": { - "size": 295166, - "gzip": 62418 + "size": 294853, + "gzip": 62366 }, "ReactART-prod.js (FB_PROD)": { - "size": 148338, - "gzip": 25339 + "size": 148156, + "gzip": 25307 }, "ReactNativeRenderer-dev.js (RN_DEV)": { - "size": 411706, - "gzip": 90261 + "size": 411393, + "gzip": 90175 }, "ReactNativeRenderer-prod.js (RN_PROD)": { - "size": 201332, - "gzip": 34709 + "size": 201148, + "gzip": 34670 }, "ReactRTRenderer-dev.js (RN_DEV)": { - "size": 289436, - "gzip": 61463 + "size": 289123, + "gzip": 61376 }, "ReactRTRenderer-prod.js (RN_PROD)": { - "size": 138320, - "gzip": 23287 + "size": 138136, + "gzip": 23262 }, "ReactCSRenderer-dev.js (RN_DEV)": { - "size": 279132, - "gzip": 58253 + "size": 278819, + "gzip": 58205 }, "ReactCSRenderer-prod.js (RN_PROD)": { - "size": 130641, - "gzip": 21857 + "size": 130459, + "gzip": 21823 }, "react-test-renderer.development.js (NODE_DEV)": { - "size": 280500, - "gzip": 59363 + "size": 280201, + "gzip": 59318 }, "react-test-renderer.production.min.js (NODE_PROD)": { - "size": 46036, - "gzip": 14212 + "size": 45987, + "gzip": 14196 }, "ReactTestRenderer-dev.js (FB_DEV)": { - "size": 291830, - "gzip": 61220 + "size": 291517, + "gzip": 61172 }, "react-test-renderer-shallow.development.js (NODE_DEV)": { "size": 9686, @@ -189,24 +189,24 @@ "gzip": 2596 }, "react-noop-renderer.development.js (NODE_DEV)": { - "size": 277191, - "gzip": 58354 + "size": 276892, + "gzip": 58307 }, "react-reconciler.development.js (NODE_DEV)": { - "size": 262361, - "gzip": 54978 + "size": 262062, + "gzip": 54933 }, "react-reconciler.production.min.js (NODE_PROD)": { - "size": 39353, - "gzip": 12233 + "size": 39304, + "gzip": 12212 }, "react-call-return.development.js (NODE_DEV)": { - "size": 2514, - "gzip": 924 + "size": 2463, + "gzip": 918 }, "react-call-return.production.min.js (NODE_PROD)": { - "size": 890, - "gzip": 507 + "size": 880, + "gzip": 499 }, "react-dom-test-utils.development.js (UMD_DEV)": { "size": 41456,