From 12d7a8c227cd219abcfb733c6c3403f29395864c Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Thu, 19 Oct 2017 00:40:16 -0700 Subject: [PATCH 01/19] Authoritative brand checking library Can be used without any dependency on React. Plausible replacement for React.isValidElement. --- packages/react-is/README.md | 33 +++++++++++++++++ packages/react-is/index.js | 67 ++++++++++++++++++++++++++++++++++ packages/react-is/package.json | 12 ++++++ 3 files changed, 112 insertions(+) create mode 100644 packages/react-is/README.md create mode 100644 packages/react-is/index.js create mode 100644 packages/react-is/package.json diff --git a/packages/react-is/README.md b/packages/react-is/README.md new file mode 100644 index 0000000000000..05dca2624be01 --- /dev/null +++ b/packages/react-is/README.md @@ -0,0 +1,33 @@ +# `react-is` + +This package allows you to test arbitrary values and see if they're a particular React type, e.g. React Elements. + +## Usage + +```js +import React from 'react'; +import {isElement} from 'react-is'; +isElement(
); // true +``` + +```js +import React from 'react'; +import {isFragment} from 'react-is'; +isFragment(<>); // true +``` + +```js +import React from 'react'; +import {createPortal} from 'react-dom'; +import {isPortal} from 'react-is'; +isPortal(createPortal(
, document.body)); // true +``` + +```js +import React from 'react'; +import {createPortal} from 'react-dom'; +import {typeOf} from 'react-is'; +typeOf(
); // "ReactElement" +typeOf(<>); // "ReactFragment" +typeOf(createPortal(
, document.body)); // "ReactPortal" +``` diff --git a/packages/react-is/index.js b/packages/react-is/index.js new file mode 100644 index 0000000000000..670df04aa913a --- /dev/null +++ b/packages/react-is/index.js @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2014-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'; + +var REACT_ELEMENT_TYPE; +var REACT_COROUTINE_TYPE; +var REACT_YIELD_TYPE; +var REACT_PORTAL_TYPE; +var REACT_FRAGMENT_TYPE; +if (typeof Symbol === 'function' && Symbol.for) { + REACT_ELEMENT_TYPE = Symbol.for('react.element'); + REACT_COROUTINE_TYPE = Symbol.for('react.coroutine'); + REACT_YIELD_TYPE = Symbol.for('react.yield'); + REACT_PORTAL_TYPE = Symbol.for('react.portal'); + REACT_FRAGMENT_TYPE = Symbol.for('react.fragment'); +} else { + REACT_ELEMENT_TYPE = 0xeac7; + REACT_COROUTINE_TYPE = 0xeac8; + REACT_YIELD_TYPE = 0xeac9; + REACT_PORTAL_TYPE = 0xeaca; + REACT_FRAGMENT_TYPE = 0xeacb; +} + +function is(object, type) { + return ( + typeof object === 'object' && object !== null && object.$$typeof === type + ); +} + +module.exports = { + typeOf(object) { + switch (typeof object === 'object' && object !== null && object.$$typeof) { + case REACT_ELEMENT_TYPE: + return 'ReactElement'; + case REACT_COROUTINE_TYPE: + return 'ReactCoroutine'; + case REACT_YIELD_TYPE: + return 'ReactYield'; + case REACT_PORTAL_TYPE: + return 'ReactPortal'; + case REACT_FRAGMENT_TYPE: + return 'ReactFragment'; + default: + return undefined; + } + }, + isElement(object) { + return is(object, REACT_ELEMENT_TYPE); + }, + isCoroutine(object) { + return is(object, REACT_COROUTINE_TYPE); + }, + isYield(object) { + return is(object, REACT_YIELD_TYPE); + }, + isPortal(object) { + return is(object, REACT_PORTAL_TYPE); + }, + isFragment(object) { + return is(object, REACT_FRAGMENT_TYPE); + }, +}; diff --git a/packages/react-is/package.json b/packages/react-is/package.json new file mode 100644 index 0000000000000..b705d03941257 --- /dev/null +++ b/packages/react-is/package.json @@ -0,0 +1,12 @@ +{ + "name": "react-is", + "description": "Brand checking of React Elements.", + "keywords": ["react"], + "version": "1.0.0", + "homepage": "https://reactjs.org/", + "bugs": "https://github.com/facebook/react/issues", + "license": "MIT", + "files": ["index.js"], + "main": "index.js", + "repository": "facebook/react" +} From f44c66816111a5f25ce466abe7172d54a1df1bc2 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Fri, 9 Feb 2018 09:50:07 -0800 Subject: [PATCH 02/19] Patched up react-is and added some tests and docs --- packages/react-is/README.md | 62 ++++++++++--- packages/react-is/index.js | 63 +------------ packages/react-is/npm/index.js | 7 ++ packages/react-is/package.json | 24 +++-- packages/react-is/src/ReactIs.js | 90 +++++++++++++++++++ .../react-is/src/__tests__/ReactIs-test.js | 77 ++++++++++++++++ scripts/rollup/bundles.js | 10 +++ 7 files changed, 257 insertions(+), 76 deletions(-) create mode 100644 packages/react-is/npm/index.js create mode 100644 packages/react-is/src/ReactIs.js create mode 100644 packages/react-is/src/__tests__/ReactIs-test.js diff --git a/packages/react-is/README.md b/packages/react-is/README.md index 05dca2624be01..1af87184a233e 100644 --- a/packages/react-is/README.md +++ b/packages/react-is/README.md @@ -4,30 +4,72 @@ This package allows you to test arbitrary values and see if they're a particular ## Usage +### AsyncMode ```js import React from 'react'; -import {isElement} from 'react-is'; +import {isAsyncMode, typeOf} from 'react-is'; + +const AsyncMode = React.unstable_AsyncMode; + +typeOf(); // "ReactAsyncMode" + +isAsyncMode(); // true +``` + +### Context +```js +import React from 'react'; +import {isContextConsumer, isContextProvider, typeOf} from 'react-is'; + +const ThemeContext = React.createContext('blue'); + +typeOf(); // "ReactContextProvider" +typeOf(); // "ReactContextConsumer" + +isContextConsumer(); // true +isContextProvider(); // true +``` + +### Element +```js +import React from 'react'; +import {isElement, typeOf} from 'react-is'; + +typeOf(
); // "ReactElement" + isElement(
); // true ``` +### Fragment ```js import React from 'react'; -import {isFragment} from 'react-is'; +import {isFragment, typeOf} from 'react-is'; + +typeOf(<>); // "ReactFragment" + isFragment(<>); // true ``` +### Portal ```js import React from 'react'; import {createPortal} from 'react-dom'; -import {isPortal} from 'react-is'; -isPortal(createPortal(
, document.body)); // true +import {isPortal, typeOf} from 'react-is'; + +const div = document.createElement('div'); +const portal = createPortal(
, div); + +typeOf(portal); // "ReactPortal" + +isPortal(portal); // true ``` +### StrictMode ```js import React from 'react'; -import {createPortal} from 'react-dom'; -import {typeOf} from 'react-is'; -typeOf(
); // "ReactElement" -typeOf(<>); // "ReactFragment" -typeOf(createPortal(
, document.body)); // "ReactPortal" -``` +import {isStrictMode, typeOf} from 'react-is'; + +typeOf(); // "ReactStrictMode" + +isStrictMode(); // true +``` \ No newline at end of file diff --git a/packages/react-is/index.js b/packages/react-is/index.js index 670df04aa913a..53b825cfedd67 100644 --- a/packages/react-is/index.js +++ b/packages/react-is/index.js @@ -1,67 +1,12 @@ /** - * Copyright (c) 2014-present, Facebook, Inc. + * 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 */ 'use strict'; -var REACT_ELEMENT_TYPE; -var REACT_COROUTINE_TYPE; -var REACT_YIELD_TYPE; -var REACT_PORTAL_TYPE; -var REACT_FRAGMENT_TYPE; -if (typeof Symbol === 'function' && Symbol.for) { - REACT_ELEMENT_TYPE = Symbol.for('react.element'); - REACT_COROUTINE_TYPE = Symbol.for('react.coroutine'); - REACT_YIELD_TYPE = Symbol.for('react.yield'); - REACT_PORTAL_TYPE = Symbol.for('react.portal'); - REACT_FRAGMENT_TYPE = Symbol.for('react.fragment'); -} else { - REACT_ELEMENT_TYPE = 0xeac7; - REACT_COROUTINE_TYPE = 0xeac8; - REACT_YIELD_TYPE = 0xeac9; - REACT_PORTAL_TYPE = 0xeaca; - REACT_FRAGMENT_TYPE = 0xeacb; -} - -function is(object, type) { - return ( - typeof object === 'object' && object !== null && object.$$typeof === type - ); -} - -module.exports = { - typeOf(object) { - switch (typeof object === 'object' && object !== null && object.$$typeof) { - case REACT_ELEMENT_TYPE: - return 'ReactElement'; - case REACT_COROUTINE_TYPE: - return 'ReactCoroutine'; - case REACT_YIELD_TYPE: - return 'ReactYield'; - case REACT_PORTAL_TYPE: - return 'ReactPortal'; - case REACT_FRAGMENT_TYPE: - return 'ReactFragment'; - default: - return undefined; - } - }, - isElement(object) { - return is(object, REACT_ELEMENT_TYPE); - }, - isCoroutine(object) { - return is(object, REACT_COROUTINE_TYPE); - }, - isYield(object) { - return is(object, REACT_YIELD_TYPE); - }, - isPortal(object) { - return is(object, REACT_PORTAL_TYPE); - }, - isFragment(object) { - return is(object, REACT_FRAGMENT_TYPE); - }, -}; +module.exports = require('./src/ReactIs'); diff --git a/packages/react-is/npm/index.js b/packages/react-is/npm/index.js new file mode 100644 index 0000000000000..3ae098d078776 --- /dev/null +++ b/packages/react-is/npm/index.js @@ -0,0 +1,7 @@ +'use strict'; + +if (process.env.NODE_ENV === 'production') { + module.exports = require('./cjs/react-is.production.min.js'); +} else { + module.exports = require('./cjs/react-is.development.js'); +} diff --git a/packages/react-is/package.json b/packages/react-is/package.json index b705d03941257..9e88191dc320d 100644 --- a/packages/react-is/package.json +++ b/packages/react-is/package.json @@ -1,12 +1,22 @@ { "name": "react-is", + "version": "1.0.0", "description": "Brand checking of React Elements.", + "main": "index.js", + "repository": "facebook/react", "keywords": ["react"], - "version": "1.0.0", - "homepage": "https://reactjs.org/", - "bugs": "https://github.com/facebook/react/issues", "license": "MIT", - "files": ["index.js"], - "main": "index.js", - "repository": "facebook/react" -} + "bugs": { + "url": "https://github.com/facebook/react/issues" + }, + "homepage": "https://reactjs.org/", + "peerDependencies": { + "react": "^16.0.0 || 16.3.0-alpha.0" + }, + "files": [ + "LICENSE", + "README.md", + "index.js", + "cjs/" + ] +} \ No newline at end of file diff --git a/packages/react-is/src/ReactIs.js b/packages/react-is/src/ReactIs.js new file mode 100644 index 0000000000000..605a6bd2afb47 --- /dev/null +++ b/packages/react-is/src/ReactIs.js @@ -0,0 +1,90 @@ +/** + * 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 + */ + +'use strict'; + +import { + REACT_ASYNC_MODE_TYPE, + REACT_CONTEXT_TYPE, + REACT_ELEMENT_TYPE, + REACT_FRAGMENT_TYPE, + REACT_PORTAL_TYPE, + REACT_PROVIDER_TYPE, + REACT_STRICT_MODE_TYPE, +} from 'shared/ReactSymbols'; + +// e.g. Fragments, StrictMode +function getType(object: any) { + return typeof object === 'object' && object !== null ? object.type : null; +} + +// e.g. Elements, Portals +function getTypeOf(object: any) { + return typeof object === 'object' && object !== null ? object.$$typeof : null; +} + +// e.g. Context provider and consumer +function getTypeTypeOf(object: any) { + return typeof object === 'object' && + object !== null && + typeof object.type === 'object' && + object.type !== null + ? object.type.$$typeof + : null; +} + +const ReactIs = { + typeOf(object: any) { + switch (getType(object)) { + case REACT_ASYNC_MODE_TYPE: + return 'ReactAsyncMode'; + case REACT_FRAGMENT_TYPE: + return 'ReactFragment'; + case REACT_STRICT_MODE_TYPE: + return 'ReactStrictMode'; + } + + switch (getTypeTypeOf(object)) { + case REACT_CONTEXT_TYPE: + return 'ReactContextConsumer'; + case REACT_PROVIDER_TYPE: + return 'ReactContextProvider'; + } + + switch (getTypeOf(object)) { + case REACT_ELEMENT_TYPE: + return 'ReactElement'; + case REACT_PORTAL_TYPE: + return 'ReactPortal'; + } + }, + isAsyncMode(object: any) { + return getType(object) === REACT_ASYNC_MODE_TYPE; + }, + isContextConsumer(object: any) { + return getTypeTypeOf(object) === REACT_CONTEXT_TYPE; + }, + isContextProvider(object: any) { + return getTypeTypeOf(object) === REACT_PROVIDER_TYPE; + }, + isElement(object: any) { + return getTypeOf(object) === REACT_ELEMENT_TYPE; + }, + isFragment(object: any) { + return getType(object) === REACT_FRAGMENT_TYPE; + }, + isPortal(object: any) { + return getTypeOf(object) === REACT_PORTAL_TYPE; + }, + isStrictMode(object: any) { + return getType(object) === REACT_STRICT_MODE_TYPE; + }, +}; + +export default ReactIs; diff --git a/packages/react-is/src/__tests__/ReactIs-test.js b/packages/react-is/src/__tests__/ReactIs-test.js new file mode 100644 index 0000000000000..d01132668f4a3 --- /dev/null +++ b/packages/react-is/src/__tests__/ReactIs-test.js @@ -0,0 +1,77 @@ +/** + * 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. + * + * @emails react-core + */ + +'use strict'; + +let React; +let ReactDOM; +let ReactIs; + +describe('ReactIs', () => { + beforeEach(() => { + jest.resetModules(); + React = require('react'); + ReactDOM = require('react-dom'); + ReactIs = require('react-is'); + }); + + it('should identify async mode', () => { + expect(ReactIs.typeOf()).toBe('ReactAsyncMode'); + expect(ReactIs.isAsyncMode()).toBe(true); + expect(ReactIs.isAsyncMode()).toBe(false); + expect(ReactIs.isAsyncMode(
)).toBe(false); + }); + + it('should identify context consumers', () => { + const Context = React.createContext(false); + expect(ReactIs.typeOf()).toBe('ReactContextConsumer'); + expect(ReactIs.isContextConsumer()).toBe(true); + expect(ReactIs.isContextConsumer()).toBe(false); + expect(ReactIs.isContextConsumer(
)).toBe(false); + }); + + it('should identify context providers', () => { + const Context = React.createContext(false); + expect(ReactIs.typeOf()).toBe('ReactContextProvider'); + expect(ReactIs.isContextProvider()).toBe(true); + expect(ReactIs.isContextProvider()).toBe(false); + expect(ReactIs.isContextProvider(
)).toBe(false); + }); + + it('should identify elements', () => { + expect(ReactIs.typeOf(
)).toBe('ReactElement'); + expect(ReactIs.isElement(
)).toBe(true); + expect(ReactIs.isElement('div')).toBe(false); + expect(ReactIs.isElement(true)).toBe(false); + expect(ReactIs.isElement(123)).toBe(false); + }); + + it('should identify fragments', () => { + expect(ReactIs.typeOf()).toBe('ReactFragment'); + expect(ReactIs.isFragment()).toBe(true); + expect(ReactIs.isFragment('React.Fragment')).toBe(false); + expect(ReactIs.isFragment(
)).toBe(false); + expect(ReactIs.isFragment([])).toBe(false); + }); + + it('should identify portals', () => { + const div = document.createElement('div'); + const portal = ReactDOM.createPortal(
, div); + expect(ReactIs.typeOf(portal)).toBe('ReactPortal'); + expect(ReactIs.isPortal(portal)).toBe(true); + expect(ReactIs.isPortal(div)).toBe(false); + }); + + it('should identify strict mode', () => { + expect(ReactIs.typeOf()).toBe('ReactStrictMode'); + expect(ReactIs.isStrictMode()).toBe(true); + expect(ReactIs.isStrictMode()).toBe(false); + expect(ReactIs.isStrictMode(
)).toBe(false); + }); +}); diff --git a/scripts/rollup/bundles.js b/scripts/rollup/bundles.js index ff57b766998e0..785d47925c675 100644 --- a/scripts/rollup/bundles.js +++ b/scripts/rollup/bundles.js @@ -234,6 +234,16 @@ const bundles = [ global: 'ReactCallReturn', externals: [], }, + + /******* React Is *******/ + { + label: 'react-is', + bundleTypes: [UMD_DEV, UMD_PROD, NODE_DEV, NODE_PROD], + moduleType: ISOMORPHIC, + entry: 'react-is', + global: 'ReactIs', + externals: [], + }, ]; // Based on deep-freeze by substack (public domain) From 0f92bd3adb69cf7275c1e0bc77e1a6b26e714c77 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Fri, 9 Feb 2018 09:56:04 -0800 Subject: [PATCH 03/19] Updated react-is version number to mirror other packages --- packages/react-is/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-is/package.json b/packages/react-is/package.json index 9e88191dc320d..3c89f7306dbd8 100644 --- a/packages/react-is/package.json +++ b/packages/react-is/package.json @@ -1,6 +1,6 @@ { "name": "react-is", - "version": "1.0.0", + "version": "16.3.0-alpha.0", "description": "Brand checking of React Elements.", "main": "index.js", "repository": "facebook/react", From c91ef08aee277dc5309f1cc389deca621b61cbfb Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Fri, 9 Feb 2018 10:00:43 -0800 Subject: [PATCH 04/19] Fix export for tests --- packages/react-is/index.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/react-is/index.js b/packages/react-is/index.js index 53b825cfedd67..de0988705b36a 100644 --- a/packages/react-is/index.js +++ b/packages/react-is/index.js @@ -9,4 +9,10 @@ 'use strict'; -module.exports = require('./src/ReactIs'); +const ReactIs = require('./src/ReactIs'); + +// TODO: decide on the top-level export form. +// This is hacky but makes it work with both Rollup and Jest. +module.exports = ReactIs.default + ? ReactIs.default + : ReactIs; From 78c264d14acf8a273f1da51371a2e3c2766bdf08 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Fri, 9 Feb 2018 10:10:44 -0800 Subject: [PATCH 05/19] Prettier --- packages/react-is/index.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/react-is/index.js b/packages/react-is/index.js index de0988705b36a..c65e86ab53e5c 100644 --- a/packages/react-is/index.js +++ b/packages/react-is/index.js @@ -13,6 +13,4 @@ const ReactIs = require('./src/ReactIs'); // TODO: decide on the top-level export form. // This is hacky but makes it work with both Rollup and Jest. -module.exports = ReactIs.default - ? ReactIs.default - : ReactIs; +module.exports = ReactIs.default ? ReactIs.default : ReactIs; From cbffbd11af81c58059d91b8fe5bdc331f3d08cb7 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Fri, 9 Feb 2018 10:25:56 -0800 Subject: [PATCH 06/19] Add umd files to package --- packages/react-is/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/react-is/package.json b/packages/react-is/package.json index 3c89f7306dbd8..8fd899a90e05b 100644 --- a/packages/react-is/package.json +++ b/packages/react-is/package.json @@ -17,6 +17,7 @@ "LICENSE", "README.md", "index.js", - "cjs/" + "cjs/", + "umd/" ] } \ No newline at end of file From 88d1dd445c335825e38efa39444ec45d80f23545 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sat, 10 Feb 2018 17:24:09 -0800 Subject: [PATCH 07/19] typeOf returns symbols; symbols exported for switch/case --- packages/react-is/README.md | 14 +++++----- packages/react-is/src/ReactIs.js | 28 ++++++++++++------- .../react-is/src/__tests__/ReactIs-test.js | 16 ++++++----- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/packages/react-is/README.md b/packages/react-is/README.md index 1af87184a233e..58aa9d0c2676e 100644 --- a/packages/react-is/README.md +++ b/packages/react-is/README.md @@ -11,7 +11,7 @@ import {isAsyncMode, typeOf} from 'react-is'; const AsyncMode = React.unstable_AsyncMode; -typeOf(); // "ReactAsyncMode" +typeOf(); // ReactIs.AsyncMode isAsyncMode(); // true ``` @@ -23,8 +23,8 @@ import {isContextConsumer, isContextProvider, typeOf} from 'react-is'; const ThemeContext = React.createContext('blue'); -typeOf(); // "ReactContextProvider" -typeOf(); // "ReactContextConsumer" +typeOf(); // ReactIs.ContextProvider +typeOf(); // ReactIs.ContextConsumer isContextConsumer(); // true isContextProvider(); // true @@ -35,7 +35,7 @@ isContextProvider(); // true import React from 'react'; import {isElement, typeOf} from 'react-is'; -typeOf(
); // "ReactElement" +typeOf(
); // ReactIs.Element isElement(
); // true ``` @@ -45,7 +45,7 @@ isElement(
); // true import React from 'react'; import {isFragment, typeOf} from 'react-is'; -typeOf(<>); // "ReactFragment" +typeOf(<>); // ReactIs.Fragment isFragment(<>); // true ``` @@ -59,7 +59,7 @@ import {isPortal, typeOf} from 'react-is'; const div = document.createElement('div'); const portal = createPortal(
, div); -typeOf(portal); // "ReactPortal" +typeOf(portal); // ReactIs.Portal isPortal(portal); // true ``` @@ -69,7 +69,7 @@ isPortal(portal); // true import React from 'react'; import {isStrictMode, typeOf} from 'react-is'; -typeOf(); // "ReactStrictMode" +typeOf(); // ReactIs.StrictMode isStrictMode(); // true ``` \ No newline at end of file diff --git a/packages/react-is/src/ReactIs.js b/packages/react-is/src/ReactIs.js index 605a6bd2afb47..4dd1274a709d4 100644 --- a/packages/react-is/src/ReactIs.js +++ b/packages/react-is/src/ReactIs.js @@ -41,29 +41,37 @@ function getTypeTypeOf(object: any) { const ReactIs = { typeOf(object: any) { - switch (getType(object)) { + const type = getType(object); + switch (type) { case REACT_ASYNC_MODE_TYPE: - return 'ReactAsyncMode'; case REACT_FRAGMENT_TYPE: - return 'ReactFragment'; case REACT_STRICT_MODE_TYPE: - return 'ReactStrictMode'; + return type; } - switch (getTypeTypeOf(object)) { + const typeTypeOf = getTypeTypeOf(object); + switch (typeTypeOf) { case REACT_CONTEXT_TYPE: - return 'ReactContextConsumer'; case REACT_PROVIDER_TYPE: - return 'ReactContextProvider'; + return typeTypeOf; } - switch (getTypeOf(object)) { + const typeOf = getTypeOf(object); + switch (typeOf) { case REACT_ELEMENT_TYPE: - return 'ReactElement'; case REACT_PORTAL_TYPE: - return 'ReactPortal'; + return typeOf; } }, + + AsyncMode: REACT_ASYNC_MODE_TYPE, + ContextConsumer: REACT_CONTEXT_TYPE, + ContextProvider: REACT_PROVIDER_TYPE, + Element: REACT_ELEMENT_TYPE, + Fragment: REACT_FRAGMENT_TYPE, + Portal: REACT_PORTAL_TYPE, + StrictMode: REACT_STRICT_MODE_TYPE, + isAsyncMode(object: any) { return getType(object) === REACT_ASYNC_MODE_TYPE; }, diff --git a/packages/react-is/src/__tests__/ReactIs-test.js b/packages/react-is/src/__tests__/ReactIs-test.js index d01132668f4a3..6d4c4db896234 100644 --- a/packages/react-is/src/__tests__/ReactIs-test.js +++ b/packages/react-is/src/__tests__/ReactIs-test.js @@ -22,7 +22,9 @@ describe('ReactIs', () => { }); it('should identify async mode', () => { - expect(ReactIs.typeOf()).toBe('ReactAsyncMode'); + expect(ReactIs.typeOf()).toBe( + ReactIs.AsyncMode, + ); expect(ReactIs.isAsyncMode()).toBe(true); expect(ReactIs.isAsyncMode()).toBe(false); expect(ReactIs.isAsyncMode(
)).toBe(false); @@ -30,7 +32,7 @@ describe('ReactIs', () => { it('should identify context consumers', () => { const Context = React.createContext(false); - expect(ReactIs.typeOf()).toBe('ReactContextConsumer'); + expect(ReactIs.typeOf()).toBe(ReactIs.ContextConsumer); expect(ReactIs.isContextConsumer()).toBe(true); expect(ReactIs.isContextConsumer()).toBe(false); expect(ReactIs.isContextConsumer(
)).toBe(false); @@ -38,14 +40,14 @@ describe('ReactIs', () => { it('should identify context providers', () => { const Context = React.createContext(false); - expect(ReactIs.typeOf()).toBe('ReactContextProvider'); + expect(ReactIs.typeOf()).toBe(ReactIs.ContextProvider); expect(ReactIs.isContextProvider()).toBe(true); expect(ReactIs.isContextProvider()).toBe(false); expect(ReactIs.isContextProvider(
)).toBe(false); }); it('should identify elements', () => { - expect(ReactIs.typeOf(
)).toBe('ReactElement'); + expect(ReactIs.typeOf(
)).toBe(ReactIs.Element); expect(ReactIs.isElement(
)).toBe(true); expect(ReactIs.isElement('div')).toBe(false); expect(ReactIs.isElement(true)).toBe(false); @@ -53,7 +55,7 @@ describe('ReactIs', () => { }); it('should identify fragments', () => { - expect(ReactIs.typeOf()).toBe('ReactFragment'); + expect(ReactIs.typeOf()).toBe(ReactIs.Fragment); expect(ReactIs.isFragment()).toBe(true); expect(ReactIs.isFragment('React.Fragment')).toBe(false); expect(ReactIs.isFragment(
)).toBe(false); @@ -63,13 +65,13 @@ describe('ReactIs', () => { it('should identify portals', () => { const div = document.createElement('div'); const portal = ReactDOM.createPortal(
, div); - expect(ReactIs.typeOf(portal)).toBe('ReactPortal'); + expect(ReactIs.typeOf(portal)).toBe(ReactIs.Portal); expect(ReactIs.isPortal(portal)).toBe(true); expect(ReactIs.isPortal(div)).toBe(false); }); it('should identify strict mode', () => { - expect(ReactIs.typeOf()).toBe('ReactStrictMode'); + expect(ReactIs.typeOf()).toBe(ReactIs.StrictMode); expect(ReactIs.isStrictMode()).toBe(true); expect(ReactIs.isStrictMode()).toBe(false); expect(ReactIs.isStrictMode(
)).toBe(false); From b8f67c244a37a9f7c59ad688f777e09b998d3200 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sat, 10 Feb 2018 17:34:36 -0800 Subject: [PATCH 08/19] README tweaks --- packages/react-is/README.md | 59 ++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/packages/react-is/README.md b/packages/react-is/README.md index 58aa9d0c2676e..e7801e68da647 100644 --- a/packages/react-is/README.md +++ b/packages/react-is/README.md @@ -2,74 +2,79 @@ This package allows you to test arbitrary values and see if they're a particular React type, e.g. React Elements. +## Installation +```sh +# Yarn +yarn add react-is + +# NPM +npm install react-is --save +``` + ## Usage ### AsyncMode ```js import React from 'react'; -import {isAsyncMode, typeOf} from 'react-is'; +import ReactIs from 'react-is'; const AsyncMode = React.unstable_AsyncMode; -typeOf(); // ReactIs.AsyncMode - -isAsyncMode(); // true +ReactIs.isAsyncMode(); // true +ReactIs.typeOf() === ReactIs.AsyncMode; // true ``` ### Context ```js import React from 'react'; -import {isContextConsumer, isContextProvider, typeOf} from 'react-is'; +ReactIs ReactIs from 'react-is'; const ThemeContext = React.createContext('blue'); -typeOf(); // ReactIs.ContextProvider -typeOf(); // ReactIs.ContextConsumer - -isContextConsumer(); // true -isContextProvider(); // true +ReactIs.isContextConsumer(); // true +ReactIs.isContextProvider(); // true +ReactIs.typeOf() === ReactIs.ContextProvider; // true +ReactIs.typeOf() === ReactIs.ContextConsumer; // true ``` ### Element ```js import React from 'react'; -import {isElement, typeOf} from 'react-is'; - -typeOf(
); // ReactIs.Element +import ReactIs from 'react-is'; -isElement(
); // true +ReactIs.isElement(
); // true +ReactIs.typeOf(
) === ReactIs.Element; // true ``` ### Fragment ```js import React from 'react'; -import {isFragment, typeOf} from 'react-is'; +import ReactIs from 'react-is'; -typeOf(<>); // ReactIs.Fragment - -isFragment(<>); // true +ReactIs.isFragment(<>); // true +ReactIs.typeOf(<>) === ReactIs.Fragment; // true ``` ### Portal ```js import React from 'react'; -import {createPortal} from 'react-dom'; -import {isPortal, typeOf} from 'react-is'; +import ReactDOM from 'react-dom'; +import ReactIs from 'react-is'; const div = document.createElement('div'); -const portal = createPortal(
, div); - -typeOf(portal); // ReactIs.Portal +const portal = ReactDOM.createPortal(
, div); -isPortal(portal); // true +ReactIs.isPortal(portal); // true +ReactIs.typeOf(portal) === ReactIs.Portal; // true ``` ### StrictMode ```js import React from 'react'; -import {isStrictMode, typeOf} from 'react-is'; +import ReactIs from 'react-is'; -typeOf(); // ReactIs.StrictMode +const {StrictMode} = React; -isStrictMode(); // true +ReactIs.isStrictMode(); // true +ReactIs.typeOf() === ReactIs.StrictMode; // true ``` \ No newline at end of file From 784fffcc9d9e6eef4a945cc35a7ad19b965292c3 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sat, 10 Feb 2018 17:43:58 -0800 Subject: [PATCH 09/19] Added broader isElement() tests --- packages/react-is/src/__tests__/ReactIs-test.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/react-is/src/__tests__/ReactIs-test.js b/packages/react-is/src/__tests__/ReactIs-test.js index 6d4c4db896234..af5b2b5406f90 100644 --- a/packages/react-is/src/__tests__/ReactIs-test.js +++ b/packages/react-is/src/__tests__/ReactIs-test.js @@ -52,6 +52,14 @@ describe('ReactIs', () => { expect(ReactIs.isElement('div')).toBe(false); expect(ReactIs.isElement(true)).toBe(false); expect(ReactIs.isElement(123)).toBe(false); + + // It should also identify more specific types as elements + const Context = React.createContext(false); + expect(ReactIs.isElement()).toBe(true); + expect(ReactIs.isElement()).toBe(true); + expect(ReactIs.isElement()).toBe(true); + expect(ReactIs.isElement()).toBe(true); + expect(ReactIs.isElement()).toBe(true); }); it('should identify fragments', () => { From 7b060d3ed674745f8d45a1f8870fd6f53ed6d826 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sun, 11 Feb 2018 07:40:29 -0800 Subject: [PATCH 10/19] Replaced default exports with named exports --- packages/react-is/index.js | 6 +- packages/react-is/src/ReactIs.js | 102 +++++++++++++++---------------- 2 files changed, 50 insertions(+), 58 deletions(-) diff --git a/packages/react-is/index.js b/packages/react-is/index.js index c65e86ab53e5c..f8c9ffdcd287c 100644 --- a/packages/react-is/index.js +++ b/packages/react-is/index.js @@ -9,8 +9,4 @@ 'use strict'; -const ReactIs = require('./src/ReactIs'); - -// TODO: decide on the top-level export form. -// This is hacky but makes it work with both Rollup and Jest. -module.exports = ReactIs.default ? ReactIs.default : ReactIs; +export * from './src/ReactIs'; diff --git a/packages/react-is/src/ReactIs.js b/packages/react-is/src/ReactIs.js index 4dd1274a709d4..a56f41743b122 100644 --- a/packages/react-is/src/ReactIs.js +++ b/packages/react-is/src/ReactIs.js @@ -39,60 +39,56 @@ function getTypeTypeOf(object: any) { : null; } -const ReactIs = { - typeOf(object: any) { - const type = getType(object); - switch (type) { - case REACT_ASYNC_MODE_TYPE: - case REACT_FRAGMENT_TYPE: - case REACT_STRICT_MODE_TYPE: - return type; - } +export function typeOf(object: any) { + let maybeType = getType(object); + switch (maybeType) { + case REACT_ASYNC_MODE_TYPE: + case REACT_FRAGMENT_TYPE: + case REACT_STRICT_MODE_TYPE: + return maybeType; + } - const typeTypeOf = getTypeTypeOf(object); - switch (typeTypeOf) { - case REACT_CONTEXT_TYPE: - case REACT_PROVIDER_TYPE: - return typeTypeOf; - } + maybeType = getTypeTypeOf(object); + switch (maybeType) { + case REACT_CONTEXT_TYPE: + case REACT_PROVIDER_TYPE: + return maybeType; + } - const typeOf = getTypeOf(object); - switch (typeOf) { - case REACT_ELEMENT_TYPE: - case REACT_PORTAL_TYPE: - return typeOf; - } - }, - - AsyncMode: REACT_ASYNC_MODE_TYPE, - ContextConsumer: REACT_CONTEXT_TYPE, - ContextProvider: REACT_PROVIDER_TYPE, - Element: REACT_ELEMENT_TYPE, - Fragment: REACT_FRAGMENT_TYPE, - Portal: REACT_PORTAL_TYPE, - StrictMode: REACT_STRICT_MODE_TYPE, + maybeType = getTypeOf(object); + switch (maybeType) { + case REACT_ELEMENT_TYPE: + case REACT_PORTAL_TYPE: + return maybeType; + } +} - isAsyncMode(object: any) { - return getType(object) === REACT_ASYNC_MODE_TYPE; - }, - isContextConsumer(object: any) { - return getTypeTypeOf(object) === REACT_CONTEXT_TYPE; - }, - isContextProvider(object: any) { - return getTypeTypeOf(object) === REACT_PROVIDER_TYPE; - }, - isElement(object: any) { - return getTypeOf(object) === REACT_ELEMENT_TYPE; - }, - isFragment(object: any) { - return getType(object) === REACT_FRAGMENT_TYPE; - }, - isPortal(object: any) { - return getTypeOf(object) === REACT_PORTAL_TYPE; - }, - isStrictMode(object: any) { - return getType(object) === REACT_STRICT_MODE_TYPE; - }, -}; +export const AsyncMode = REACT_ASYNC_MODE_TYPE; +export const ContextConsumer = REACT_CONTEXT_TYPE; +export const ContextProvider = REACT_PROVIDER_TYPE; +export const Element = REACT_ELEMENT_TYPE; +export const Fragment = REACT_FRAGMENT_TYPE; +export const Portal = REACT_PORTAL_TYPE; +export const StrictMode = REACT_STRICT_MODE_TYPE; -export default ReactIs; +export function isAsyncMode(object: any) { + return getType(object) === REACT_ASYNC_MODE_TYPE; +} +export function isContextConsumer(object: any) { + return getTypeTypeOf(object) === REACT_CONTEXT_TYPE; +} +export function isContextProvider(object: any) { + return getTypeTypeOf(object) === REACT_PROVIDER_TYPE; +} +export function isElement(object: any) { + return getTypeOf(object) === REACT_ELEMENT_TYPE; +} +export function isFragment(object: any) { + return getType(object) === REACT_FRAGMENT_TYPE; +} +export function isPortal(object: any) { + return getTypeOf(object) === REACT_PORTAL_TYPE; +} +export function isStrictMode(object: any) { + return getType(object) === REACT_STRICT_MODE_TYPE; +} From 70bccd8a8b3334db6da9ce7bb655e644f2b378a5 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sun, 11 Feb 2018 07:53:30 -0800 Subject: [PATCH 11/19] Added results.json --- scripts/rollup/results.json | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/scripts/rollup/results.json b/scripts/rollup/results.json index 78fc29e1035e8..40b4157a0d36e 100644 --- a/scripts/rollup/results.json +++ b/scripts/rollup/results.json @@ -398,6 +398,34 @@ "packageName": "react-reconciler", "size": 41327, "gzip": 13133 + }, + { + "filename": "react-is.development.js", + "bundleType": "UMD_DEV", + "packageName": "react-is", + "size": 3760, + "gzip": 1086 + }, + { + "filename": "react-is.production.min.js", + "bundleType": "UMD_PROD", + "packageName": "react-is", + "size": 1641, + "gzip": 687 + }, + { + "filename": "react-is.development.js", + "bundleType": "NODE_DEV", + "packageName": "react-is", + "size": 3571, + "gzip": 1030 + }, + { + "filename": "react-is.production.min.js", + "bundleType": "NODE_PROD", + "packageName": "react-is", + "size": 1559, + "gzip": 624 } ] } \ No newline at end of file From b4ff653d92e82ba57ae898b2fed50f0a12d39202 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sun, 11 Feb 2018 07:54:17 -0800 Subject: [PATCH 12/19] Updated README --- packages/react-is/README.md | 81 ++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/packages/react-is/README.md b/packages/react-is/README.md index e7801e68da647..3b0ddc22d976d 100644 --- a/packages/react-is/README.md +++ b/packages/react-is/README.md @@ -3,6 +3,7 @@ This package allows you to test arbitrary values and see if they're a particular React type, e.g. React Elements. ## Installation + ```sh # Yarn yarn add react-is @@ -14,67 +15,75 @@ npm install react-is --save ## Usage ### AsyncMode -```js -import React from 'react'; -import ReactIs from 'react-is'; -const AsyncMode = React.unstable_AsyncMode; +```js +import React from "react"; +import { AsyncMode, isAsyncMode, typeOf } from "react-is"; -ReactIs.isAsyncMode(); // true -ReactIs.typeOf() === ReactIs.AsyncMode; // true +isAsyncMode(); // true +typeOf() === AsyncMode; // true ``` ### Context -```js -import React from 'react'; -ReactIs ReactIs from 'react-is'; - -const ThemeContext = React.createContext('blue'); -ReactIs.isContextConsumer(); // true -ReactIs.isContextProvider(); // true -ReactIs.typeOf() === ReactIs.ContextProvider; // true -ReactIs.typeOf() === ReactIs.ContextConsumer; // true +```js +import React from "react"; +import { + ContextConsumer, + ContextProvider, + isContextConsumer, + isContextProvider, + typeOf +} from "react-is"; + +const ThemeContext = React.createContext("blue"); + +isContextConsumer(); // true +isContextProvider(); // true +typeOf() === ContextProvider; // true +typeOf() === ContextConsumer; // true ``` ### Element + ```js -import React from 'react'; -import ReactIs from 'react-is'; +import React from "react"; +import { Element, isElement, typeOf } from "react-is"; -ReactIs.isElement(
); // true -ReactIs.typeOf(
) === ReactIs.Element; // true +isElement(
); // true +typeOf(
) === Element; // true ``` ### Fragment + ```js -import React from 'react'; -import ReactIs from 'react-is'; +import React from "react"; +import { Fragment, isFragment, typeOf } from "react-is"; -ReactIs.isFragment(<>); // true -ReactIs.typeOf(<>) === ReactIs.Fragment; // true +isFragment(<>); // true +typeOf(<>) === Fragment; // true ``` ### Portal + ```js -import React from 'react'; -import ReactDOM from 'react-dom'; -import ReactIs from 'react-is'; +import React from "react"; +import ReactDOM from "react-dom"; +import { isPortal, Portal, typeOf } from "react-is"; -const div = document.createElement('div'); +const div = document.createElement("div"); const portal = ReactDOM.createPortal(
, div); -ReactIs.isPortal(portal); // true -ReactIs.typeOf(portal) === ReactIs.Portal; // true +isPortal(portal); // true +typeOf(portal) === Portal; // true ``` ### StrictMode -```js -import React from 'react'; -import ReactIs from 'react-is'; -const {StrictMode} = React; +```js +import React from "react"; +import { isStrictMode, StrictMode, TypeOf } from "react-is"; -ReactIs.isStrictMode(); // true -ReactIs.typeOf() === ReactIs.StrictMode; // true -``` \ No newline at end of file +isStrictMode(); // true +typeOf() === StrictMode; // true +``` From 54588e4d0801c85f1f0ba1a517d0125135b5ad77 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sun, 11 Feb 2018 08:44:27 -0800 Subject: [PATCH 13/19] Removed UMD target from react-is bundle --- packages/react-is/package.json | 3 +-- scripts/rollup/bundles.js | 2 +- scripts/rollup/results.json | 14 -------------- 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/packages/react-is/package.json b/packages/react-is/package.json index 8fd899a90e05b..3c89f7306dbd8 100644 --- a/packages/react-is/package.json +++ b/packages/react-is/package.json @@ -17,7 +17,6 @@ "LICENSE", "README.md", "index.js", - "cjs/", - "umd/" + "cjs/" ] } \ No newline at end of file diff --git a/scripts/rollup/bundles.js b/scripts/rollup/bundles.js index 785d47925c675..a73d88779248e 100644 --- a/scripts/rollup/bundles.js +++ b/scripts/rollup/bundles.js @@ -238,7 +238,7 @@ const bundles = [ /******* React Is *******/ { label: 'react-is', - bundleTypes: [UMD_DEV, UMD_PROD, NODE_DEV, NODE_PROD], + bundleTypes: [NODE_DEV, NODE_PROD], moduleType: ISOMORPHIC, entry: 'react-is', global: 'ReactIs', diff --git a/scripts/rollup/results.json b/scripts/rollup/results.json index 40b4157a0d36e..4234263b4b04e 100644 --- a/scripts/rollup/results.json +++ b/scripts/rollup/results.json @@ -399,20 +399,6 @@ "size": 41327, "gzip": 13133 }, - { - "filename": "react-is.development.js", - "bundleType": "UMD_DEV", - "packageName": "react-is", - "size": 3760, - "gzip": 1086 - }, - { - "filename": "react-is.production.min.js", - "bundleType": "UMD_PROD", - "packageName": "react-is", - "size": 1641, - "gzip": 687 - }, { "filename": "react-is.development.js", "bundleType": "NODE_DEV", From 21a64bdbb797bb26b153aaf59cdc5bee8cc2cef4 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sun, 11 Feb 2018 09:44:51 -0800 Subject: [PATCH 14/19] Documentation nits --- packages/react-is/README.md | 46 ++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/packages/react-is/README.md b/packages/react-is/README.md index 3b0ddc22d976d..f744d7d1de708 100644 --- a/packages/react-is/README.md +++ b/packages/react-is/README.md @@ -18,50 +18,44 @@ npm install react-is --save ```js import React from "react"; -import { AsyncMode, isAsyncMode, typeOf } from "react-is"; +import * as ReactIs from 'react-is'; -isAsyncMode(); // true -typeOf() === AsyncMode; // true +ReactIs.isAsyncMode(); // true +ReactIs.typeOf() === ReactIs.AsyncMode; // true ``` ### Context ```js import React from "react"; -import { - ContextConsumer, - ContextProvider, - isContextConsumer, - isContextProvider, - typeOf -} from "react-is"; +import * as ReactIs from 'react-is'; const ThemeContext = React.createContext("blue"); -isContextConsumer(); // true -isContextProvider(); // true -typeOf() === ContextProvider; // true -typeOf() === ContextConsumer; // true +ReactIs.isContextConsumer(); // true +ReactIs.isContextProvider(); // true +ReactIs.typeOf() === ReactIs.ContextProvider; // true +ReactIs.typeOf() === ReactIs.ContextConsumer; // true ``` ### Element ```js import React from "react"; -import { Element, isElement, typeOf } from "react-is"; +import * as ReactIs from 'react-is'; -isElement(
); // true -typeOf(
) === Element; // true +ReactIs.isElement(
); // true +ReactIs.typeOf(
) === ReactIs.Element; // true ``` ### Fragment ```js import React from "react"; -import { Fragment, isFragment, typeOf } from "react-is"; +import * as ReactIs from 'react-is'; -isFragment(<>); // true -typeOf(<>) === Fragment; // true +ReactIs.isFragment(<>); // true +ReactIs.typeOf(<>) === ReactIs.Fragment; // true ``` ### Portal @@ -69,21 +63,21 @@ typeOf(<>) === Fragment; // true ```js import React from "react"; import ReactDOM from "react-dom"; -import { isPortal, Portal, typeOf } from "react-is"; +import * as ReactIs from 'react-is'; const div = document.createElement("div"); const portal = ReactDOM.createPortal(
, div); -isPortal(portal); // true -typeOf(portal) === Portal; // true +ReactIs.isPortal(portal); // true +ReactIs.typeOf(portal) === ReactIs.Portal; // true ``` ### StrictMode ```js import React from "react"; -import { isStrictMode, StrictMode, TypeOf } from "react-is"; +import * as ReactIs from 'react-is'; -isStrictMode(); // true -typeOf() === StrictMode; // true +ReactIs.isStrictMode(); // true +ReactIs.typeOf() === ReactIs.StrictMode; // true ``` From a06e6f738f6bdbb74f04bca5037e2a232eb7ebd5 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sun, 11 Feb 2018 09:49:47 -0800 Subject: [PATCH 15/19] Re-enabled UMD build for react-is --- packages/react-is/package.json | 3 ++- scripts/rollup/bundles.js | 2 +- scripts/rollup/results.json | 14 ++++++++++++++ scripts/rollup/validate/eslintrc.umd.js | 1 + 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/react-is/package.json b/packages/react-is/package.json index 3c89f7306dbd8..8fd899a90e05b 100644 --- a/packages/react-is/package.json +++ b/packages/react-is/package.json @@ -17,6 +17,7 @@ "LICENSE", "README.md", "index.js", - "cjs/" + "cjs/", + "umd/" ] } \ No newline at end of file diff --git a/scripts/rollup/bundles.js b/scripts/rollup/bundles.js index a73d88779248e..b29c382d51d15 100644 --- a/scripts/rollup/bundles.js +++ b/scripts/rollup/bundles.js @@ -238,7 +238,7 @@ const bundles = [ /******* React Is *******/ { label: 'react-is', - bundleTypes: [NODE_DEV, NODE_PROD], + bundleTypes: [NODE_DEV, NODE_PROD, UMD_DEV, UMD_PROD], moduleType: ISOMORPHIC, entry: 'react-is', global: 'ReactIs', diff --git a/scripts/rollup/results.json b/scripts/rollup/results.json index 4234263b4b04e..9745915368312 100644 --- a/scripts/rollup/results.json +++ b/scripts/rollup/results.json @@ -412,6 +412,20 @@ "packageName": "react-is", "size": 1559, "gzip": 624 + }, + { + "filename": "react-is.development.js", + "bundleType": "UMD_DEV", + "packageName": "react-is", + "size": 3760, + "gzip": 1086 + }, + { + "filename": "react-is.production.min.js", + "bundleType": "UMD_PROD", + "packageName": "react-is", + "size": 1641, + "gzip": 687 } ] } \ No newline at end of file diff --git a/scripts/rollup/validate/eslintrc.umd.js b/scripts/rollup/validate/eslintrc.umd.js index bfc5396ce52ec..7ee1e112f2b09 100644 --- a/scripts/rollup/validate/eslintrc.umd.js +++ b/scripts/rollup/validate/eslintrc.umd.js @@ -17,6 +17,7 @@ module.exports = { // UMD wrapper code // TODO: this is too permissive. // Ideally we should only allow these *inside* the UMD wrapper. + exports: true, module: true, define: true, require: true, From b22a7b78836d7d8252989c7a9a7522c40e7d2637 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sun, 11 Feb 2018 10:35:29 -0800 Subject: [PATCH 16/19] Made fragment/async/strict mode checks more strict --- packages/react-is/src/ReactIs.js | 19 +++++++++++++++---- .../react-is/src/__tests__/ReactIs-test.js | 3 +++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/react-is/src/ReactIs.js b/packages/react-is/src/ReactIs.js index a56f41743b122..b6d6c7fcb2da1 100644 --- a/packages/react-is/src/ReactIs.js +++ b/packages/react-is/src/ReactIs.js @@ -45,7 +45,9 @@ export function typeOf(object: any) { case REACT_ASYNC_MODE_TYPE: case REACT_FRAGMENT_TYPE: case REACT_STRICT_MODE_TYPE: - return maybeType; + if (getTypeOf(object) === REACT_ELEMENT_TYPE) { + return maybeType; + } } maybeType = getTypeTypeOf(object); @@ -72,7 +74,10 @@ export const Portal = REACT_PORTAL_TYPE; export const StrictMode = REACT_STRICT_MODE_TYPE; export function isAsyncMode(object: any) { - return getType(object) === REACT_ASYNC_MODE_TYPE; + return ( + getType(object) === REACT_ASYNC_MODE_TYPE && + getTypeOf(object) === REACT_ELEMENT_TYPE + ); } export function isContextConsumer(object: any) { return getTypeTypeOf(object) === REACT_CONTEXT_TYPE; @@ -84,11 +89,17 @@ export function isElement(object: any) { return getTypeOf(object) === REACT_ELEMENT_TYPE; } export function isFragment(object: any) { - return getType(object) === REACT_FRAGMENT_TYPE; + return ( + getType(object) === REACT_FRAGMENT_TYPE && + getTypeOf(object) === REACT_ELEMENT_TYPE + ); } export function isPortal(object: any) { return getTypeOf(object) === REACT_PORTAL_TYPE; } export function isStrictMode(object: any) { - return getType(object) === REACT_STRICT_MODE_TYPE; + return ( + getType(object) === REACT_STRICT_MODE_TYPE && + getTypeOf(object) === REACT_ELEMENT_TYPE + ); } diff --git a/packages/react-is/src/__tests__/ReactIs-test.js b/packages/react-is/src/__tests__/ReactIs-test.js index af5b2b5406f90..9f3e3b01a45b0 100644 --- a/packages/react-is/src/__tests__/ReactIs-test.js +++ b/packages/react-is/src/__tests__/ReactIs-test.js @@ -26,6 +26,7 @@ describe('ReactIs', () => { ReactIs.AsyncMode, ); expect(ReactIs.isAsyncMode()).toBe(true); + expect(ReactIs.isAsyncMode({type: ReactIs.AsyncMode})).toBe(false); expect(ReactIs.isAsyncMode()).toBe(false); expect(ReactIs.isAsyncMode(
)).toBe(false); }); @@ -65,6 +66,7 @@ describe('ReactIs', () => { it('should identify fragments', () => { expect(ReactIs.typeOf()).toBe(ReactIs.Fragment); expect(ReactIs.isFragment()).toBe(true); + expect(ReactIs.isFragment({type: ReactIs.Fragment})).toBe(false); expect(ReactIs.isFragment('React.Fragment')).toBe(false); expect(ReactIs.isFragment(
)).toBe(false); expect(ReactIs.isFragment([])).toBe(false); @@ -81,6 +83,7 @@ describe('ReactIs', () => { it('should identify strict mode', () => { expect(ReactIs.typeOf()).toBe(ReactIs.StrictMode); expect(ReactIs.isStrictMode()).toBe(true); + expect(ReactIs.isStrictMode({type: ReactIs.StrictMode})).toBe(false); expect(ReactIs.isStrictMode()).toBe(false); expect(ReactIs.isStrictMode(
)).toBe(false); }); From ef0a90099eb8304028d0564312791de10a5d89af Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sun, 11 Feb 2018 13:06:17 -0800 Subject: [PATCH 17/19] Adjusted typeOf() to be more efficient --- packages/react-is/src/ReactIs.js | 94 ++++++++----------- .../react-is/src/__tests__/ReactIs-test.js | 1 + scripts/rollup/results.json | 16 ++-- 3 files changed, 48 insertions(+), 63 deletions(-) diff --git a/packages/react-is/src/ReactIs.js b/packages/react-is/src/ReactIs.js index b6d6c7fcb2da1..87da4cbccfa83 100644 --- a/packages/react-is/src/ReactIs.js +++ b/packages/react-is/src/ReactIs.js @@ -19,50 +19,39 @@ import { REACT_STRICT_MODE_TYPE, } from 'shared/ReactSymbols'; -// e.g. Fragments, StrictMode -function getType(object: any) { - return typeof object === 'object' && object !== null ? object.type : null; -} +export function typeOf(object: any) { + if (typeof object === 'object' && object !== null) { + const $$typeof = object.$$typeof; -// e.g. Elements, Portals -function getTypeOf(object: any) { - return typeof object === 'object' && object !== null ? object.$$typeof : null; -} + switch ($$typeof) { + case REACT_ELEMENT_TYPE: + const type = object.type; -// e.g. Context provider and consumer -function getTypeTypeOf(object: any) { - return typeof object === 'object' && - object !== null && - typeof object.type === 'object' && - object.type !== null - ? object.type.$$typeof - : null; -} + switch (type) { + case REACT_ASYNC_MODE_TYPE: + case REACT_FRAGMENT_TYPE: + case REACT_STRICT_MODE_TYPE: + return type; + default: + const $$typeofType = + typeof type === 'object' && type !== null + ? type.$$typeof + : undefined; -export function typeOf(object: any) { - let maybeType = getType(object); - switch (maybeType) { - case REACT_ASYNC_MODE_TYPE: - case REACT_FRAGMENT_TYPE: - case REACT_STRICT_MODE_TYPE: - if (getTypeOf(object) === REACT_ELEMENT_TYPE) { - return maybeType; - } - } - - maybeType = getTypeTypeOf(object); - switch (maybeType) { - case REACT_CONTEXT_TYPE: - case REACT_PROVIDER_TYPE: - return maybeType; + switch ($$typeofType) { + case REACT_CONTEXT_TYPE: + case REACT_PROVIDER_TYPE: + return $$typeofType; + default: + return $$typeof; + } + } + case REACT_PORTAL_TYPE: + return $$typeof; + } } - maybeType = getTypeOf(object); - switch (maybeType) { - case REACT_ELEMENT_TYPE: - case REACT_PORTAL_TYPE: - return maybeType; - } + return undefined; } export const AsyncMode = REACT_ASYNC_MODE_TYPE; @@ -74,32 +63,27 @@ export const Portal = REACT_PORTAL_TYPE; export const StrictMode = REACT_STRICT_MODE_TYPE; export function isAsyncMode(object: any) { - return ( - getType(object) === REACT_ASYNC_MODE_TYPE && - getTypeOf(object) === REACT_ELEMENT_TYPE - ); + return typeOf(object) === REACT_ASYNC_MODE_TYPE; } export function isContextConsumer(object: any) { - return getTypeTypeOf(object) === REACT_CONTEXT_TYPE; + return typeOf(object) === REACT_CONTEXT_TYPE; } export function isContextProvider(object: any) { - return getTypeTypeOf(object) === REACT_PROVIDER_TYPE; + return typeOf(object) === REACT_PROVIDER_TYPE; } export function isElement(object: any) { - return getTypeOf(object) === REACT_ELEMENT_TYPE; -} -export function isFragment(object: any) { return ( - getType(object) === REACT_FRAGMENT_TYPE && - getTypeOf(object) === REACT_ELEMENT_TYPE + typeof object === 'object' && + object !== null && + object.$$typeof === REACT_ELEMENT_TYPE ); } +export function isFragment(object: any) { + return typeOf(object) === REACT_FRAGMENT_TYPE; +} export function isPortal(object: any) { - return getTypeOf(object) === REACT_PORTAL_TYPE; + return typeOf(object) === REACT_PORTAL_TYPE; } export function isStrictMode(object: any) { - return ( - getType(object) === REACT_STRICT_MODE_TYPE && - getTypeOf(object) === REACT_ELEMENT_TYPE - ); + return typeOf(object) === REACT_STRICT_MODE_TYPE; } diff --git a/packages/react-is/src/__tests__/ReactIs-test.js b/packages/react-is/src/__tests__/ReactIs-test.js index 9f3e3b01a45b0..6053b9f06aa7b 100644 --- a/packages/react-is/src/__tests__/ReactIs-test.js +++ b/packages/react-is/src/__tests__/ReactIs-test.js @@ -16,6 +16,7 @@ let ReactIs; describe('ReactIs', () => { beforeEach(() => { jest.resetModules(); + React = require('react'); ReactDOM = require('react-dom'); ReactIs = require('react-is'); diff --git a/scripts/rollup/results.json b/scripts/rollup/results.json index 9745915368312..f5a83d7aac006 100644 --- a/scripts/rollup/results.json +++ b/scripts/rollup/results.json @@ -403,29 +403,29 @@ "filename": "react-is.development.js", "bundleType": "NODE_DEV", "packageName": "react-is", - "size": 3571, - "gzip": 1030 + "size": 3414, + "gzip": 1029 }, { "filename": "react-is.production.min.js", "bundleType": "NODE_PROD", "packageName": "react-is", - "size": 1559, - "gzip": 624 + "size": 1470, + "gzip": 616 }, { "filename": "react-is.development.js", "bundleType": "UMD_DEV", "packageName": "react-is", - "size": 3760, - "gzip": 1086 + "size": 3603, + "gzip": 1084 }, { "filename": "react-is.production.min.js", "bundleType": "UMD_PROD", "packageName": "react-is", - "size": 1641, - "gzip": 687 + "size": 1552, + "gzip": 680 } ] } \ No newline at end of file From f111111ea932ad4ad01559abfb9396b82b32959c Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sun, 11 Feb 2018 13:12:49 -0800 Subject: [PATCH 18/19] Added a couple of additional tests --- packages/react-is/src/__tests__/ReactIs-test.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/react-is/src/__tests__/ReactIs-test.js b/packages/react-is/src/__tests__/ReactIs-test.js index 6053b9f06aa7b..6200388fd525d 100644 --- a/packages/react-is/src/__tests__/ReactIs-test.js +++ b/packages/react-is/src/__tests__/ReactIs-test.js @@ -22,6 +22,15 @@ describe('ReactIs', () => { ReactIs = require('react-is'); }); + it('should return undefined for unknown/invalid types', () => { + expect(ReactIs.typeOf('abc')).toBe(undefined); + expect(ReactIs.typeOf(true)).toBe(undefined); + expect(ReactIs.typeOf(123)).toBe(undefined); + expect(ReactIs.typeOf({})).toBe(undefined); + expect(ReactIs.typeOf(null)).toBe(undefined); + expect(ReactIs.typeOf(undefined)).toBe(undefined); + }); + it('should identify async mode', () => { expect(ReactIs.typeOf()).toBe( ReactIs.AsyncMode, @@ -54,6 +63,9 @@ describe('ReactIs', () => { expect(ReactIs.isElement('div')).toBe(false); expect(ReactIs.isElement(true)).toBe(false); expect(ReactIs.isElement(123)).toBe(false); + expect(ReactIs.isElement(null)).toBe(false); + expect(ReactIs.isElement(undefined)).toBe(false); + expect(ReactIs.isElement({})).toBe(false); // It should also identify more specific types as elements const Context = React.createContext(false); From 9c8385c3a68859046f804fb3a351ccb942688038 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sun, 11 Feb 2018 13:23:42 -0800 Subject: [PATCH 19/19] Removed unnecessary, nested not-null check --- packages/react-is/src/ReactIs.js | 5 +---- scripts/rollup/results.json | 16 ++++++++-------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/packages/react-is/src/ReactIs.js b/packages/react-is/src/ReactIs.js index 87da4cbccfa83..d26bc82f5e8c1 100644 --- a/packages/react-is/src/ReactIs.js +++ b/packages/react-is/src/ReactIs.js @@ -33,10 +33,7 @@ export function typeOf(object: any) { case REACT_STRICT_MODE_TYPE: return type; default: - const $$typeofType = - typeof type === 'object' && type !== null - ? type.$$typeof - : undefined; + const $$typeofType = type.$$typeof; switch ($$typeofType) { case REACT_CONTEXT_TYPE: diff --git a/scripts/rollup/results.json b/scripts/rollup/results.json index f5a83d7aac006..57d2013e37f29 100644 --- a/scripts/rollup/results.json +++ b/scripts/rollup/results.json @@ -403,29 +403,29 @@ "filename": "react-is.development.js", "bundleType": "NODE_DEV", "packageName": "react-is", - "size": 3414, - "gzip": 1029 + "size": 3358, + "gzip": 1015 }, { "filename": "react-is.production.min.js", "bundleType": "NODE_PROD", "packageName": "react-is", - "size": 1470, - "gzip": 616 + "size": 1433, + "gzip": 607 }, { "filename": "react-is.development.js", "bundleType": "UMD_DEV", "packageName": "react-is", - "size": 3603, - "gzip": 1084 + "size": 3547, + "gzip": 1071 }, { "filename": "react-is.production.min.js", "bundleType": "UMD_PROD", "packageName": "react-is", - "size": 1552, - "gzip": 680 + "size": 1515, + "gzip": 670 } ] } \ No newline at end of file